diff --git a/src/hooks/useProductCatalog.ts b/src/hooks/useProductCatalog.ts index 771793a..c4ae5cf 100644 --- a/src/hooks/useProductCatalog.ts +++ b/src/hooks/useProductCatalog.ts @@ -1,35 +1,115 @@ -import { useState, useEffect } from "react"; +"use client"; -export interface Product { - id: string; - name: string; - price: number; - category: string; - description?: string; +import { useState, useMemo, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import { useProducts } from "./useProducts"; +import type { Product } from "@/lib/api/product"; +import type { CatalogProduct } from "@/components/ecommerce/productCatalog/ProductCatalogItem"; +import type { ProductVariant } from "@/components/ecommerce/productDetail/ProductDetailCard"; + +export type SortOption = "Newest" | "Price: Low-High" | "Price: High-Low"; + +interface UseProductCatalogOptions { + basePath?: string; } -export const useProductCatalog = () => { - const [products, setProducts] = useState([]); - const [isLoading, setIsLoading] = useState(true); - const [error, setError] = useState(null); +export function useProductCatalog(options: UseProductCatalogOptions = {}) { + const { basePath = "/shop" } = options; + const router = useRouter(); + const { products: fetchedProducts, isLoading } = useProducts(); - useEffect(() => { - const fetchProducts = async () => { - try { - setIsLoading(true); - // Simulate API call - await new Promise((resolve) => setTimeout(resolve, 500)); - // Mock data would be loaded here - setProducts([]); - } catch (err) { - setError(err instanceof Error ? err.message : "Failed to load products"); - } finally { - setIsLoading(false); - } + const [search, setSearch] = useState(""); + const [category, setCategory] = useState("All"); + const [sort, setSort] = useState("Newest"); + + const handleProductClick = useCallback((productId: string) => { + router.push(`${basePath}/${productId}`); + }, [router, basePath]); + + const catalogProducts: CatalogProduct[] = useMemo(() => { + if (fetchedProducts.length === 0) return []; + + return fetchedProducts.map((product) => ({ + id: product.id, + name: product.name, + price: product.price, + imageSrc: product.imageSrc, + imageAlt: product.imageAlt || product.name, + rating: product.rating || 0, + reviewCount: product.reviewCount, + category: product.brand, + onProductClick: () => handleProductClick(product.id), + })); + }, [fetchedProducts, handleProductClick]); + + const categories = useMemo(() => { + const categorySet = new Set(); + catalogProducts.forEach((product) => { + if (product.category) { + categorySet.add(product.category); + } + }); + return Array.from(categorySet).sort(); + }, [catalogProducts]); + + const filteredProducts = useMemo(() => { + let result = catalogProducts; + + if (search) { + const q = search.toLowerCase(); + result = result.filter( + (p) => + p.name.toLowerCase().includes(q) || + (p.category?.toLowerCase().includes(q) ?? false) + ); + } + + if (category !== "All") { + result = result.filter((p) => p.category === category); + } + + if (sort === "Price: Low-High") { + result = [...result].sort( + (a, b) => + parseFloat(a.price.replace("$", "").replace(",", "")) - + parseFloat(b.price.replace("$", "").replace(",", "")) + ); + } else if (sort === "Price: High-Low") { + result = [...result].sort( + (a, b) => + parseFloat(b.price.replace("$", "").replace(",", "")) - + parseFloat(a.price.replace("$", "").replace(",", "")) + ); + } + + return result; + }, [catalogProducts, search, category, sort]); + + const filters: ProductVariant[] = useMemo(() => [ + { + label: "Category", + options: ["All", ...categories], + selected: category, + onChange: setCategory, + }, + { + label: "Sort", + options: ["Newest", "Price: Low-High", "Price: High-Low"] as SortOption[], + selected: sort, + onChange: (value) => setSort(value as SortOption), + }, + ], [categories, category, sort]); + + return { + products: filteredProducts, + isLoading, + search, + setSearch, + category, + setCategory, + sort, + setSort, + filters, + categories, }; - - fetchProducts(); - }, []); - - return { products, isLoading, error }; -}; +}