"use client"; import { SlidersHorizontal, X } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { ProductCard } from "@/components/product/product-card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import type { Product } from "@/lib/headless/types"; type CatalogClientProps = { products: Product[]; initialCategory?: string; initialCollection?: string; initialQuery?: string; }; export function CatalogClient({ products, initialCategory = "Todos", initialCollection = "", initialQuery = "", }: CatalogClientProps) { const [query, setQuery] = useState(initialQuery); const [category, setCategory] = useState(initialCategory); const [collection, setCollection] = useState(initialCollection); const [brand, setBrand] = useState("Todas"); const [age, setAge] = useState("Todas"); const [sort, setSort] = useState("featured"); const categories = ["Todos", ...new Set(products.map((product) => product.category))]; const brands = ["Todas", ...new Set(products.map((product) => product.brand))]; const ages = ["Todas", ...new Set(products.map((product) => product.ageRange))]; const pricedProducts = products.filter((product) => product.price !== null); const maxCatalogPrice = pricedProducts.length ? Math.max(...pricedProducts.map((product) => product.price ?? 0)) : 0; const [maxPrice, setMaxPrice] = useState(maxCatalogPrice); // Next.js conserva la instancia del componente cuando solo cambia el query string. // Sin esta sincronización, el catálogo anterior permanece visible hasta presionar F5. useEffect(() => { setQuery(initialQuery); setCategory(initialCategory || "Todos"); setCollection(initialCollection || ""); setBrand("Todas"); setAge("Todas"); setSort("featured"); setMaxPrice(maxCatalogPrice); }, [initialCategory, initialCollection, initialQuery, maxCatalogPrice]); const filtered = useMemo( () => products .filter((product) => { const search = [ product.name, product.category, product.collection, product.brand, ] .join(" ") .toLowerCase(); return ( (!query || search.includes(query.toLowerCase())) && (category === "Todos" || product.category === category) && (!collection || product.collection === collection) && (brand === "Todas" || product.brand === brand) && (age === "Todas" || product.ageRange === age) && (product.price === null || maxPrice === 0 || product.price <= maxPrice) ); }) .sort((a, b) => sort === "name" ? a.name.localeCompare(b.name, "es") : sort === "new" ? Number(b.isNew) - Number(a.isNew) : Number(b.featured) - Number(a.featured), ), [age, brand, category, collection, maxPrice, products, query, sort], ); const reset = () => { setQuery(""); setCategory("Todos"); setCollection(""); setBrand("Todas"); setAge("Todas"); setMaxPrice(maxCatalogPrice); setSort("featured"); }; return (
Filtra por categoría, marca o edad sin recargar la página.
{filtered.length} productos
No encontramos productos