diff --git a/src/components/CategoryHero.tsx b/src/components/CategoryHero.tsx index 77848a5..91b3600 100644 --- a/src/components/CategoryHero.tsx +++ b/src/components/CategoryHero.tsx @@ -35,7 +35,7 @@ export function CategoryHero({ {limited && ( - This week in {content.title} + Filter on · This week only )} @@ -51,6 +51,7 @@ export function CategoryHero({ {' '} · {productCount} {productCount === 1 ? 'piece' : 'pieces'} + {limited ? ' this week' : ''} ) : null}

diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index aa751c0..10a30b2 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,4 +1,4 @@ -import { Link, Outlet, useLocation } from 'react-router-dom' +import { Link, Outlet, useLocation, useSearchParams } from 'react-router-dom' import { Menu, X } from 'lucide-react' import { useState } from 'react' import { formatExpiry, limitedTimeCopy } from '../data/catalog' @@ -24,26 +24,48 @@ function navClass(active: boolean) { export function Layout() { const [open, setOpen] = useState(false) const { pathname } = useLocation() - const limited = limitedTimeCopy() - const until = formatExpiry(limited.expiresAt ?? undefined) + const [searchParams] = useSearchParams() + const drop = limitedTimeCopy() + const until = formatExpiry(drop.expiresAt ?? undefined) + const onShop = pathname === '/shop' || pathname.startsWith('/shop') + const limitedMode = onShop && searchParams.get('limited') === '1' + // When already filtering to this week, offer escape — not another trap door + const weekCta = limitedMode + ? { to: '/shop', label: 'Full collection', primary: false as const } + : { to: '/shop?limited=1', label: 'This week', primary: true as const } return (
-
- - This week’s selection - {limited.count > 0 ? ` · ${limited.count} pieces` : ''} - {until ? ` · Until ${until}` : ''} - - {' '} - · {BRAND.mottoEn} - - -
+ {limitedMode ? ( +
+ Filter on · This week only + {drop.count > 0 ? ` · ${drop.count} pieces` : ''} + · not the full house + {' · '} + + Show full collection + +
+ ) : ( +
+ + This week’s selection + {drop.count > 0 ? ` · ${drop.count} pieces` : ''} + {until ? ` · Until ${until}` : ''} + + {' '} + · {BRAND.mottoEn} + + +
+ )}
@@ -74,10 +96,14 @@ export function Layout() {
- This week + {weekCta.label} +
+ )} + + {/* Active filter chips */} + {hasFilters && ( +
+ + Filtering + + {limited && ( + updateParams({ limited: null })} + /> )} - + {catLabel && ( + updateParams({ cat: null })} + /> + )} + {q && ( + updateParams({ q: null })} + /> + )} + +
)}
- updateParams({ q: e.target.value || null })} - placeholder="Search products…" - className="w-full max-w-md rounded-2xl border border-line bg-card px-4 py-3.5 text-sm font-medium outline-none focus:border-focus:ring-2 focus:ring-bamboo/15" - /> +
+ + updateParams({ q: e.target.value || null })} + placeholder="Search the house…" + className="w-full rounded-2xl border border-line bg-card pl-10 pr-4 py-3.5 text-sm font-medium outline-none focus:border-bamboo focus:ring-2 focus:ring-bamboo/15" + /> +
@@ -166,7 +241,7 @@ export function Shop() { : 'bg-card border border-line hover:border-bamboo/40' }`} > - All categories + All rooms {CATEGORY_OPTIONS.map((c) => ( )}
@@ -214,16 +303,29 @@ export function Shop() { {filtered.length === 0 ? (

No matches

-

- Try another room or clear search / limited filter. +

+ {limited + ? 'Nothing in this week’s list matches. Turn off “This week” or clear filters to see the full house.' + : 'Try another room or clear search.'}

- +
+ {limited && ( + + )} + +
) : ( ) } + +function FilterChip({ + label, + onRemove, + tone = 'default', +}: { + label: string + onRemove: () => void + tone?: 'default' | 'limited' +}) { + const limited = tone === 'limited' + return ( + + ) +}