From c106c1384b0b53fa614a5ffbc16b02dc9c1615a1 Mon Sep 17 00:00:00 2001 From: bender Date: Thu, 12 Mar 2026 03:57:09 +0000 Subject: [PATCH 1/3] Update src/components/cardStack/hooks/useCardAnimation.ts --- .../cardStack/hooks/useCardAnimation.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/cardStack/hooks/useCardAnimation.ts b/src/components/cardStack/hooks/useCardAnimation.ts index cc0f8f4..4848f0e 100644 --- a/src/components/cardStack/hooks/useCardAnimation.ts +++ b/src/components/cardStack/hooks/useCardAnimation.ts @@ -1,18 +1,28 @@ 'use client'; -import { useEffect, useState } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { useDepth3DAnimation } from './useDepth3DAnimation'; interface CardAnimationConfig { + isAnimating?: boolean; + transform?: string; duration?: number; delay?: number; easing?: string; + itemRefs?: React.MutableRefObject[]; + containerRef?: React.MutableRefObject; + perspectiveRef?: React.MutableRefObject; + bottomContentRef?: React.MutableRefObject; } -const useCardAnimation = (config: CardAnimationConfig = {}) => { +const useCardAnimation = (config: CardAnimationConfig = {}): CardAnimationConfig => { const { duration = 0.6, delay = 0, easing = 'ease-out' } = config; const [isAnimating, setIsAnimating] = useState(false); const { transform } = useDepth3DAnimation({ rotateX: 0, rotateY: 0, scale: 1 }); + const itemRefs = useRef(null); + const containerRef = useRef(null); + const perspectiveRef = useRef(null); + const bottomContentRef = useRef(null); useEffect(() => { setIsAnimating(true); @@ -24,6 +34,10 @@ const useCardAnimation = (config: CardAnimationConfig = {}) => { duration, delay, easing, + itemRefs: [itemRefs], + containerRef, + perspectiveRef, + bottomContentRef, }; }; -- 2.49.1 From 1d629a470bf55aae1d9c33600ae2f70be0b14991 Mon Sep 17 00:00:00 2001 From: bender Date: Thu, 12 Mar 2026 03:57:09 +0000 Subject: [PATCH 2/3] Update src/components/ecommerce/productCatalog/ProductCatalog.tsx --- .../productCatalog/ProductCatalog.tsx | 198 +++++------------- 1 file changed, 52 insertions(+), 146 deletions(-) diff --git a/src/components/ecommerce/productCatalog/ProductCatalog.tsx b/src/components/ecommerce/productCatalog/ProductCatalog.tsx index fc04961..e5d19c4 100644 --- a/src/components/ecommerce/productCatalog/ProductCatalog.tsx +++ b/src/components/ecommerce/productCatalog/ProductCatalog.tsx @@ -1,156 +1,62 @@ -"use client"; +'use client'; -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"; +import React, { useState } from 'react'; +import { useProducts } from '@/hooks/useProducts'; +import ProductCatalogItem from './ProductCatalogItem'; interface ProductCatalogProps { - 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; + className?: string; + gridClassName?: string; + itemClassName?: string; + ariaLabel?: string; } -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 ProductCatalog: React.FC = ({ + className = '', + gridClassName = 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6', + itemClassName = '', + ariaLabel = 'Product catalog', +}) => { + const { products, loading, error } = useProducts(); + const [favorites, setFavorites] = useState>(new Set()); - const handleProductClick = useCallback((productId: string) => { - router.push(`/shop/${productId}`); - }, [router]); + const handleFavorite = (productId: string) => { + setFavorites((prev) => { + const updated = new Set(prev); + if (updated.has(productId)) { + updated.delete(productId); + } else { + updated.add(productId); + } + return updated; + }); + }; - const products: CatalogProduct[] = useMemo(() => { - if (productsProp && productsProp.length > 0) { - return productsProp; - } + if (loading) return
Loading products...
; + if (error) return
Error: {error}
; - 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) => ( - - ))} -
- )} -
- ); + return ( +
+
+ {products.map((product) => ( + handleFavorite(product.id), + isFavorited: favorites.has(product.id), + }} + className={itemClassName} + /> + ))} +
+
+ ); }; -ProductCatalog.displayName = "ProductCatalog"; - -export default memo(ProductCatalog); \ No newline at end of file +export default ProductCatalog; \ No newline at end of file -- 2.49.1 From 3ca082eef29bfba9359ac126c94f0e6da23b4c9a Mon Sep 17 00:00:00 2001 From: bender Date: Thu, 12 Mar 2026 03:57:10 +0000 Subject: [PATCH 3/3] Update src/hooks/useProducts.ts --- src/hooks/useProducts.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hooks/useProducts.ts b/src/hooks/useProducts.ts index 07af22b..f0357d2 100644 --- a/src/hooks/useProducts.ts +++ b/src/hooks/useProducts.ts @@ -27,4 +27,5 @@ const useProducts = () => { return { products, loading, error }; }; +export { useProducts }; export default useProducts; \ No newline at end of file -- 2.49.1