/* 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.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;