// pages-shop.jsx — Home, Shop, PDP — all wired to FF_API const { useState: useStateP, useEffect: useEffectP, useMemo: useMemoP } = React; // ─── HOME PAGE ──────────────────────────────────────────────────────────────── function HomePage({ goto, addToCart, cardStyle, wishIds, toggleWishlist }) { const [viral, setViral] = useStateP([]); const [featured, setFeatured] = useStateP([]); const [cats, setCats] = useStateP([]); const [loading, setLoading] = useStateP(true); useEffectP(() => { if (typeof FF_API === 'undefined') { setLoading(false); return; } Promise.all([ FF_API.products.list({ tag: 'viral', limit: 4 }), FF_API.products.list({ sort: 'sold', limit: 8 }), FF_API.products.categories(), ]).then(([v, f, c]) => { setViral(v.products || []); setFeatured(f.products || []); setCats(c || []); }).catch(console.error) .finally(() => setLoading(false)); }, []); // Collage uses first 4 featured products const col = featured.slice(0, 4); return (
{/* ── HERO — mobile-first, product-first ── */}
{/* Mobile hero — full bleed product strip + hook */}
{/* Product image strip — scrollable, shows goods immediately */} {col.length > 0 && (
{[...col, ...viral.slice(0, 4)].filter(Boolean).filter((p, i, a) => a.findIndex(x => x.id === p.id) === i).slice(0, 6).map((p, i) => (
goto({ page: 'pdp', id: p.id })} style={{ flexShrink: 0, width: 180, borderRadius: 16, overflow: 'hidden', position: 'relative', cursor: 'pointer', boxShadow: '0 4px 20px rgba(0,0,0,.12)', transform: i % 2 === 0 ? 'rotate(-1deg)' : 'rotate(1deg)', }}> {/* Price badge */}
{fmtINR(p.price)}
{/* Discount badge */} {p.compare > p.price && (
-{Math.round((1 - p.price / p.compare) * 100)}%
)}
))} {/* Trailing CTA card */}
goto({ page: 'shop' })} style={{ flexShrink: 0, width: 140, borderRadius: 16, background: 'var(--ff-accent)', cursor: 'pointer', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', gap: 8, padding: 20, color: '#fff', height: 220, }}> See all finds
)} {/* Hook text + CTA */}
{/* Trust badges row */}
{[ { icon: '⚡', text: '48h shipping' }, { icon: '❤️', text: 'With love' }, { icon: '💳', text: 'Secure checkout' }, { icon: '⭐', text: '4.8 avg rating' }, ].map(b => (
{b.icon} {b.text}
))}

The internet's
most obsessed-over
products. Delivered.

Viral finds from across the web — tested, curated, shipped to your door in 48h.

{/* Desktop hero — original layout, improved */}
{[ { icon: '⚡', text: '48h shipping' }, { icon: '❤️', text: 'With love' }, { icon: '💳', text: 'Secure checkout' }, { icon: '⭐', text: '4.8 avg rating' }, ].map(b => (
{b.icon} {b.text}
))}

The internet's
most obsessed-over
products. Delivered.

We hunt viral finds from across the internet, test them, and ship the good ones to your door in 48 hours. No fluff.

{/* Desktop collage */}
{col[0] &&
} {col[1] &&
} {col[2] &&
} {col[3] &&
}
As seen 6M+ times ✦
{/* Press marquee */}
{[...FF_PRESS, ...FF_PRESS, ...FF_PRESS].map((p, i) => ( AS SEEN ON {p} ))}
{/* Viral row */}
TRENDING NOW

The viral wall ✦

{loading ? : (
{viral.map(p => goto({ page: 'pdp', id: p.id })} cardStyle={cardStyle} wishlisted={wishIds?.has(p.id)} onWishlist={toggleWishlist} />)}
)}
{/* ── Social proof bar ── */}
{[ { n: '127K+', l: 'Happy customers', icon: '😊' }, { n: '4.8★', l: 'Average rating', icon: '⭐' }, { n: '48h', l: 'Ship time', icon: '⚡' }, { n: 'COD', l: 'Cash on delivery', icon: '💳' }, { n: 'Easy', l: 'Returns', icon: '🔄' }, ].map((s, i) => (
{s.icon}
{s.n}
{s.l}
))}
{/* ── UGC strip — customer photos & videos ── */} {/* Category grid — from API */}

Pick your rabbit hole

{cats.filter(c => c.id !== 'all').map((c, i) => { const catColors = ['var(--ff-lime)', 'var(--ff-lav)', 'var(--ff-sky)', 'var(--ff-sun)', 'var(--ff-pink)', 'var(--ff-mint)']; return ( ); })}
{/* Blog strip */} {/* How we work */}
{[ { t: 'We hunt', d: "Our team scrolls so you don't have to. 800+ products screened every week." }, { t: 'We test', d: 'Every item we list is put through 30 days of real use. Fails get cut.' }, { t: 'We ship', d: 'Fulfilled from our warehouse in 48 hours. Free over ₹999.' }, ].map((f, i) => (
0{i + 1}

{f.t}

{f.d}

))}
{/* All products — live from DB */}

Everything in stock

{loading ? : (
{featured.slice(0, 8).map(p => goto({ page: 'pdp', id: p.id })} cardStyle={cardStyle} wishlisted={wishIds?.has(p.id)} onWishlist={toggleWishlist} />)}
)}
{/* Reviews strip — static, marketing copy */}

Real reviews, fussy people

{[ { q: "My sister thought I spent a fortune. I did not.", n: 'Priya · Bangalore', s: 5 }, { q: 'They said 48h shipping. It was 31.', n: 'Rahul · Delhi', s: 5 }, { q: "Finally a site that doesn't lie about sizes.", n: 'Aisha · Mumbai', s: 4 }, ].map((r, i) => (

"{r.q}"

{r.n}
))}
); } function Stat({ n, l }) { return (
{n}
{l}
); } // Loading grid skeleton function LoadingGrid({ count = 4 }) { return (
{Array.from({ length: count }).map((_, i) => (
))}
); } // ─── SHOP PAGE ──────────────────────────────────────────────────────────────── // ── ReviewForm — text only (no uploads) ───────────────────────────────────── function ReviewForm({ productId, onDone }) { const [name, setName] = useStateP(''); const [stars, setStars] = useStateP(5); const [title, setTitle] = useStateP(''); const [body, setBody] = useStateP(''); const [saving, setSaving] = useStateP(false); const [error, setError] = useStateP(''); const submit = async () => { if (!name.trim() || !body.trim()) { setError('Name and review are required'); return; } setSaving(true); setError(''); const { ok } = await FF_API.products.addReview(productId, { name: name.trim(), stars, title: title.trim(), body: body.trim(), }); setSaving(false); if (ok) onDone(true); else setError('Could not submit. Please try again.'); }; return (
{error &&
{error}
} setName(e.target.value)} style={{ marginBottom: 10 }} /> setTitle(e.target.value)} style={{ marginBottom: 10 }} />
{[1, 2, 3, 4, 5].map(s => ( ))} {['', 'Terrible', 'Poor', 'OK', 'Good', 'Excellent!'][stars]}