diff --git a/src/components/ecommerce/productCatalog/ProductCatalog.tsx b/src/components/ecommerce/productCatalog/ProductCatalog.tsx index 09a6aa3..fc04961 100644 --- a/src/components/ecommerce/productCatalog/ProductCatalog.tsx +++ b/src/components/ecommerce/productCatalog/ProductCatalog.tsx @@ -1,31 +1,156 @@ -'use client'; +"use client"; -import React from 'react'; -import { Product } from '@/lib/api/product'; +import { memo, useMemo, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import Input from "@/components/form/Input"; +import ProductDetailVariantSelect from "@/components/ecommerce/productDetail/ProductDetailVariantSelect"; +import type { ProductVariant } from "@/components/ecommerce/productDetail/ProductDetailCard"; +import { cls } from "@/lib/utils"; +import { useProducts } from "@/hooks/useProducts"; +import ProductCatalogItem from "./ProductCatalogItem"; +import type { CatalogProduct } from "./ProductCatalogItem"; interface ProductCatalogProps { - products?: Product[]; - loading?: boolean; - className?: string; + layout: "page" | "section"; + products?: CatalogProduct[]; + searchValue?: string; + onSearchChange?: (value: string) => void; + searchPlaceholder?: string; + filters?: ProductVariant[]; + emptyMessage?: string; + className?: string; + gridClassName?: string; + cardClassName?: string; + imageClassName?: string; + searchClassName?: string; + filterClassName?: string; + toolbarClassName?: string; } -const ProductCatalog: React.FC = ({ products = [], loading = false, className = '' }) => { - return ( -
- {loading ? ( -
Loading...
- ) : ( -
- {products.map((product) => ( -
-

{product.name}

-

{product.price}

-
- ))} -
- )} -
- ); +const ProductCatalog = ({ + layout, + products: productsProp, + searchValue = "", + onSearchChange, + searchPlaceholder = "Search products...", + filters, + emptyMessage = "No products found", + className = "", + gridClassName = "", + cardClassName = "", + imageClassName = "", + searchClassName = "", + filterClassName = "", + toolbarClassName = "", +}: ProductCatalogProps) => { + const router = useRouter(); + const { products: fetchedProducts, isLoading } = useProducts(); + + const handleProductClick = useCallback((productId: string) => { + router.push(`/shop/${productId}`); + }, [router]); + + const products: CatalogProduct[] = useMemo(() => { + if (productsProp && productsProp.length > 0) { + return productsProp; + } + + 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), + })); + }, [productsProp, fetchedProducts, handleProductClick]); + + if (isLoading && (!productsProp || productsProp.length === 0)) { + return ( +
+

+ Loading products... +

+
+ ); + } + + return ( +
+ {(onSearchChange || (filters && filters.length > 0)) && ( +
+ {onSearchChange && ( + + )} + {filters && filters.length > 0 && ( +
+ {filters.map((filter) => ( + + ))} +
+ )} +
+ )} + + {products.length === 0 ? ( +

+ {emptyMessage} +

+ ) : ( +
+ {products.map((product) => ( + + ))} +
+ )} +
+ ); }; -export default ProductCatalog; +ProductCatalog.displayName = "ProductCatalog"; + +export default memo(ProductCatalog); \ No newline at end of file