/* global React, CATALOGO, CAT_LABELS, CAT_TOTALS, PATRONES, detectarPatron, ICONOS_INFO, Placeholder, Eyebrow, Arr, HeartIcon, Reveal, useWishlist, useUI, waLink */ const { useState, useMemo, useEffect } = React; /* Una tarjeta de producto para listados (cat / categoría / modelo). */ function CatProd({ p, onOpen, onModelo }) { const wl = useWishlist(); const isOn = wl.has(p.id); return (
onOpen(p)}>
{p.foto ? ( {p.nombre} ) : ( )}

{p.nombre}

$ {p.precio.toLocaleString("es-CO")}
{p.variante ?
{p.variante}
: null}
); } function Catalog({ initialFilter, setPage, openModelo, openFicha }) { const initial = { cat: "all", modelo: "all", patron: "all", q: "", sort: "destacado", ...(initialFilter || {}) }; const [f, setF] = useState(initial); const [drawerOpen, setDrawerOpen] = useState(false); const set = (k, v) => setF((x) => ({ ...x, [k]: v })); // Bloqueo scroll cuando drawer abierto useEffect(() => { document.body.style.overflow = drawerOpen ? "hidden" : ""; return () => { document.body.style.overflow = ""; }; }, [drawerOpen]); useEffect(() => { window.scrollTo({ top: 0, behavior: "instant" }); }, [initialFilter?.cat]); // Modelos derivados del catálogo const modelos = useMemo(() => { const counts = {}; CATALOGO.forEach((p) => { counts[p.nombre] = (counts[p.nombre] || 0) + 1; }); return Object.entries(counts).sort((a, b) => b[1] - a[1]).map(([name, n]) => ({ name, n })); }, []); // Filtrado const filtered = useMemo(() => { let out = CATALOGO.slice(); if (f.cat !== "all") out = out.filter((p) => p.categoria === f.cat); if (f.modelo !== "all") out = out.filter((p) => p.nombre === f.modelo); if (f.patron !== "all") out = out.filter((p) => detectarPatron(p.variante) === f.patron); if (f.q) { const q = f.q.toLowerCase(); out = out.filter((p) => p.nombre.toLowerCase().includes(q) || (p.variante || "").toLowerCase().includes(q) || p.id.toLowerCase().includes(q) ); } if (f.sort === "destacado") out.sort((a, b) => (b.destacado - a.destacado)); if (f.sort === "precio-asc") out.sort((a, b) => a.precio - b.precio); if (f.sort === "precio-desc") out.sort((a, b) => b.precio - a.precio); if (f.sort === "nombre") out.sort((a, b) => a.nombre.localeCompare(b.nombre)); return out; }, [f]); const activeChips = []; if (f.cat !== "all") activeChips.push({ key: "cat", label: CAT_LABELS[f.cat], kind: "Categoría" }); if (f.modelo !== "all") activeChips.push({ key: "modelo", label: f.modelo, kind: "Modelo" }); if (f.patron !== "all") activeChips.push({ key: "patron", label: f.patron, kind: "Patrón" }); if (f.q) activeChips.push({ key: "q", label: `"${f.q}"`, kind: "Buscar" }); const clearAll = () => setF({ cat: "all", modelo: "all", patron: "all", q: "", sort: "destacado" }); return (
Inicio · Catálogo

{filtered.length}
piezas.

Tejido a mano · entrega en 15 días

Filtra por categoría, modelo o patrón. Toca cualquier pieza para verla en grande y pedirla por WhatsApp.

Filtros activos: {activeChips.length === 0 ? ( — ninguno · mostrando todo el catálogo ) : ( <> {activeChips.map((c) => ( ))} )}
{filtered.length} resultados Ordenar
{filtered.length === 0 ? (
— Sin resultados con esos filtros.
) : (
{filtered.map((p) => ( ))}
)}
{/* MOBILE: FAB de filtros */} {/* MOBILE: drawer de filtros */}
setDrawerOpen(false)} />
); } window.Catalog = Catalog; window.CatProd = CatProd;