/* store-app.jsx — top-level state (cart, wishlist, quick view), cart drawer, cursor glow, and page assembly. */ const { Button: ABtn } = window.FluvexDesignsDesignSystem_072666; const { CursorGlow: ACursorGlow, StoreIcon: AIcon } = window; const { Hero, TrustBar, Marquee, BestSellers, Shop, Categories, Bundle, Gallery, Why, HowItWorks, Reviews, FAQ, FinalCTA, Footer, QuickView, } = window; /* ---- Cart drawer ---- */ function CartDrawer({ open, items, onClose, onQty, onRemove }) { React.useEffect(() => { if (open) document.body.style.overflow = "hidden"; else document.body.style.overflow = ""; return () => { document.body.style.overflow = ""; }; }, [open]); // Escape closes the drawer (desktop). Listener lives only while open, so // no duplicate handlers accumulate. React.useEffect(() => { if (!open) return; const onKey = (e) => { if (e.key === "Escape") onClose(); }; window.addEventListener("keydown", onKey); return () => window.removeEventListener("keydown", onKey); }, [open, onClose]); const total = items.reduce((s, it) => s + it.product.price * it.qty, 0); return ( <>
); } /* ---- Toast ---- */ function Toast({ msg }) { return (
{msg}
); } function App() { // Cart persists across refreshes via localStorage. Read is defensive: // any parse/shape error falls back to an empty cart instead of throwing. const [cart, setCart] = React.useState(() => { try { const raw = localStorage.getItem("fx_cart_v1"); const parsed = raw ? JSON.parse(raw) : []; return Array.isArray(parsed) ? parsed.filter((it) => it && it.product && it.product.id) : []; } catch (e) { return []; } }); React.useEffect(() => { try { localStorage.setItem("fx_cart_v1", JSON.stringify(cart)); } catch (e) {} }, [cart]); const [wishes, setWishes] = React.useState(new Set()); const [quick, setQuick] = React.useState(null); const [cartOpen, setCartOpen] = React.useState(false); const [toast, setToast] = React.useState(""); const toastTimer = React.useRef(null); const showToast = (m) => { setToast(m); clearTimeout(toastTimer.current); toastTimer.current = setTimeout(() => setToast(""), 1800); }; const addToCart = (p) => { setCart((c) => { const found = c.find((it) => it.product.id === p.id); if (found) return c.map((it) => it.product.id === p.id ? { ...it, qty: it.qty + 1 } : it); return [...c, { product: p, qty: 1 }]; }); showToast(`Added “${p.title}” to cart`); if (window.FluvexTracking) window.FluvexTracking.trackAddToCart(p); }; const changeQty = (id, d) => setCart((c) => c.map((it) => it.product.id === id ? { ...it, qty: Math.max(1, it.qty + d) } : it)); const removeItem = (id) => { if (window.FluvexTracking) { const found = cart.find((it) => it.product.id === id); if (found) window.FluvexTracking.trackRemoveFromCart(found.product); } setCart((c) => c.filter((it) => it.product.id !== id)); }; const openQuick = (p) => { setQuick(p); if (window.FluvexTracking) window.FluvexTracking.trackQuickView(p); }; const toggleWish = (id) => setWishes((w) => { const n = new Set(w); n.has(id) ? n.delete(id) : n.add(id); return n; }); const cartCount = cart.reduce((s, it) => s + it.qty, 0); const openCart = () => setCartOpen(true); const pickFilter = () => {}; // filter handled inside Shop; anchor scroll is enough return (