fix(ux): map empty state; marketplace-aware CreateListing return

- Map view now shows a 'No spots match / Clear filters' overlay when the active
  filters hide everything (it previously looked blank/unloaded)
- 'List Gear' passes returnTo=/marketplace, so the back link and the post-publish
  redirect return to Marketplace instead of dumping users on the map
This commit is contained in:
SkateSpots 2026-09-26 19:03:29 +07:00
parent 18d2af6366
commit c0ee70b8bb
3 changed files with 21 additions and 4 deletions

View file

@ -85,6 +85,8 @@ export default function CreateListingPage() {
// Check if coming from stash
const fromStash = searchParams.get('fromStash') === 'true';
// Where to return after publishing / when going back (e.g. /marketplace).
const returnTo = searchParams.get('returnTo') || '';
const stashId = searchParams.get('stashId');
// Form state - initialize from URL params if coming from stash
@ -353,7 +355,7 @@ export default function CreateListingPage() {
if (selectedSpot) {
navigate(`/spot/${selectedSpot.pubkey}/${selectedSpot.identifier}`);
} else {
navigate('/map');
navigate(returnTo || '/map');
}
} catch (error) {
toast({
@ -386,11 +388,11 @@ export default function CreateListingPage() {
<div className="container px-4 sm:px-6 py-6 sm:py-8 max-w-2xl">
<div className="mb-6">
<Link
to={fromStash ? '/stash' : (selectedSpot ? `/spot/${selectedSpot.pubkey}/${selectedSpot.identifier}` : '/map')}
to={fromStash ? '/stash' : (selectedSpot ? `/spot/${selectedSpot.pubkey}/${selectedSpot.identifier}` : (returnTo || '/map'))}
className="inline-flex items-center text-gray-400 hover:text-white transition-colors mb-4"
>
<ArrowLeft className="h-4 w-4 mr-2" />
{fromStash ? 'Back to Stash' : (selectedSpot ? `Back to ${selectedSpot.title}` : 'Back to Map')}
{fromStash ? 'Back to Stash' : (selectedSpot ? `Back to ${selectedSpot.title}` : (returnTo === '/marketplace' ? 'Back to Marketplace' : 'Back to Map'))}
</Link>
<h1
className="text-3xl font-black uppercase neon-orange"

View file

@ -207,7 +207,7 @@ export default function GearSwapPage() {
</p>
</div>
<Link to="/create-listing">
<Link to="/create-listing?returnTo=/marketplace">
<Button
size="lg"
className="gap-2 bg-orange-500 hover:bg-orange-600 text-white font-bold uppercase shadow-[0_0_20px_rgba(255,102,0,0.3)]"

View file

@ -1691,6 +1691,21 @@ export default function MapPage() {
{/* Empty state — the active filters hid everything. Without this
the map just looks blank/unloaded. Only shown when the
spot/shop layers are on (other layers have their own markers). */}
{!isLoading && (showSpots || showShops) && filteredSpots.length === 0 && (
<div className="pointer-events-none absolute inset-0 z-[1001] flex items-center justify-center px-4">
<div className="pointer-events-auto max-w-xs rounded-2xl border border-white/10 bg-black/85 p-5 text-center shadow-2xl backdrop-blur-md">
<p className="font-black uppercase tracking-wide text-white">No spots match</p>
<p className="mt-1 text-xs text-gray-400">Try a different search or clear your filters.</p>
<Button size="sm" className="mt-3" onClick={clearFilters}>
Clear filters
</Button>
</div>
</div>
)}
{/* Map attribution — bottom-left, sits ABOVE the mobile bottom
nav so it never covers the Shops & Spots buttons. Tiny + subtle. */}
<div