// ============================================================
// Browse.html — filterable listing grid with sticky QC map.
// Apple-Maps-meets-Airbnb-Explore: chips to filter, list+map split.
// ============================================================
const ALL_TAGS = ["River View", "Patio", "Date Night", "Hidden Gem", "Free", "Live Music", "Family Friendly", "Outdoors"];
function Browse() {
const initialCat = param("cat") || "all";
const [cat, setCat] = React.useState(initialCat);
const [tag, setTag] = React.useState(null);
const [sort, setSort] = React.useState("featured");
const [view, setView] = React.useState("grid"); // split | grid
const [hover, setHover] = React.useState(null);
const [dataVersion, setDataVersion] = React.useState(0);
// Re-render when live data loads from fetch
React.useEffect(() => {
const handler = () => setDataVersion((v) => v + 1);
window.addEventListener("qc:data-loaded", handler);
return () => window.removeEventListener("qc:data-loaded", handler);
}, []);
const CATEGORIES = window.QC.CATEGORIES;
const LISTINGS = window.QC.LISTINGS;
let results = LISTINGS.filter((l) => (cat === "all" || l.categoryId === cat));
if (tag) results = results.filter((l) => l.tags.includes(tag));
if (sort === "az") results = [...results].sort((a, b) => a.name.localeCompare(b.name));
if (sort === "city") results = [...results].sort((a, b) => a.city.localeCompare(b.city));
const catName = cat === "all" ? "Everything" : (CATEGORIES.find((c) => c.id === cat)?.name || "Everything");
return (
<>
Browse {catName} in the QC
Try clearing a filter — the QC is bigger than this prototype’s sample data.