// Agora Browse — dense filter rail + product grid. const Browse = ({ route, setRoute, watchlist, toggleWatch }) => { const data = window.AG_DATA; const [sort, setSort] = useState('newest'); const [view, setView] = useState('grid'); const [activeCat, setActiveCat] = useState(route.cat || 'all'); const [activeBrands, setActiveBrands] = useState(new Set(route.brand ? [route.brand] : [])); const [conds, setConds] = useState(new Set()); const [cities, setCities] = useState(new Set()); const [priceRange, setPriceRange] = useState([0, 20000]); const [offersOnly, setOffersOnly] = useState(false); const [newOnly, setNewOnly] = useState(false); useEffect(()=>{ setActiveCat(route.cat || 'all'); }, [route.cat]); const cat = data.categories.find(c => c.id === activeCat); // Filter let items = data.items; if (activeCat !== 'all') items = items.filter(i => i.cat === activeCat); if (activeBrands.size) items = items.filter(i => activeBrands.has(i.brand)); if (conds.size) items = items.filter(i => conds.has(i.cond)); if (cities.size) items = items.filter(i => cities.has(i.city)); if (offersOnly) items = items.filter(i => i.acceptOffers); if (newOnly) items = items.filter(i => i.new); items = items.filter(i => i.eur >= priceRange[0] && i.eur <= priceRange[1]); // Sort const sorted = [...items].sort((a,b)=>{ if (sort==='price-low') return a.eur - b.eur; if (sort==='price-high') return b.eur - a.eur; if (sort==='watched') return b.watchers - a.watchers; return 0; // newest = original order }); const allCities = [...new Set(data.items.map(i => i.city))]; const allConds = ['New','Excellent','Very Good','Good']; return (
{/* ============== LEFT FILTER RAIL ============== */} {/* ============== MAIN ============== */}
{cat?.label || 'Everything'}
· {sorted.length} of {data.items.length} listings

{cat?.label || 'Everything'}

{cat?.id === 'bags' ? 'Authenticated handbags from 1,284 private sellers worldwide. Every piece inspected at one of three hubs before it ships.' : cat?.id === 'vintage' ? 'Archive and runway pieces with documented provenance.' : 'Curated, authenticated, shipped DDP.'}
{/* Active filter chips + sort row */}
{activeBrands.size > 0 && [...activeBrands].map(b => ( {b} { const ns = new Set(activeBrands); ns.delete(b); setActiveBrands(ns); }}/> ))} {newOnly && New this week setNewOnly(false)}/>} {offersOnly && Accepts offers setOffersOnly(false)}/>} {(activeBrands.size > 0 || newOnly || offersOnly) && ( { setActiveBrands(new Set()); setNewOnly(false); setOffersOnly(false); }}>Clear all )}
Sort
setView('grid')} style={{ width: 30, height: 30, display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer', color: view==='grid' ? 'var(--ag-ink)':'var(--ap-fg-faint)' }}> setView('large')} style={{ width: 30, height: 30, display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer', color: view==='large' ? 'var(--ag-ink)':'var(--ap-fg-faint)' }}> setView('list')} style={{ width: 30, height: 30, display:'flex', alignItems:'center', justifyContent:'center', cursor:'pointer', color: view==='list' ? 'var(--ag-ink)':'var(--ap-fg-faint)' }}>
{/* GRID */} {view === 'list' ? (
{sorted.map(it => ( setRoute({ name:'product', id: it.id })} watched={watchlist.has(it.id)} onToggleWatch={()=>toggleWatch(it.id)}/> ))}
) : (
{sorted.map(it => (
setRoute({ name:'product', id: it.id })}> toggleWatch(it.id)} large={view==='large'}/>
))}
)}
); }; const FilterGroup = ({ title, children }) => { const [open, setOpen] = useState(true); return (
setOpen(!open)} style={{ cursor:'pointer' }}>
{title}
{open && children}
); }; const Check = ({ on, onToggle }) => ( {on && } ); const GridCard = ({ item, watched, onToggleWatch, large = false }) => { const [hover, setHover] = useState(false); return (
setHover(true)} onMouseLeave={()=>setHover(false)} style={{ cursor:'pointer' }}>
{item.new && New} {item.acceptOffers && Offers}
{ e.stopPropagation(); onToggleWatch(); }}>
 Auth {item.watchers > 30 && ( {item.watchers} watching )}
{item.brand}
€{item.eur.toLocaleString()}
{item.title}
{item.cond}
); }; const ListRow = ({ item, onClick, watched, onToggleWatch }) => (
{item.brand}
{item.new && New}  Auth
{item.title}
Condition · {item.cond} Year · {item.year} {item.watchers} watching
€{item.eur.toLocaleString()}
{item.acceptOffers &&
Or make an offer
}
); window.Browse = Browse;