From c830ab854165d05dedd99332954bdf677fb88e9f Mon Sep 17 00:00:00 2001 From: bender Date: Sun, 8 Mar 2026 02:06:53 +0000 Subject: [PATCH] Switch to version 1: modified src/components/sections/product/ProductCardTwo.tsx --- .../sections/product/ProductCardTwo.tsx | 312 +++++++++++++++--- 1 file changed, 261 insertions(+), 51 deletions(-) diff --git a/src/components/sections/product/ProductCardTwo.tsx b/src/components/sections/product/ProductCardTwo.tsx index 3080ae4..fe4a562 100644 --- a/src/components/sections/product/ProductCardTwo.tsx +++ b/src/components/sections/product/ProductCardTwo.tsx @@ -1,57 +1,267 @@ -import React from "react"; +"use client"; -interface ProductCard { - id: string; - name: string; - price: string; - imageSrc: string; - imageAlt?: string; - onProductClick?: () => void; - isFavorited?: boolean; - onFavorite?: () => void; -} +import { memo, useCallback } from "react"; +import { useRouter } from "next/navigation"; +import { Star } from "lucide-react"; +import CardStack from "@/components/cardStack/CardStack"; +import ProductImage from "@/components/shared/ProductImage"; +import { cls, shouldUseInvertedText } from "@/lib/utils"; +import { useTheme } from "@/providers/themeProvider/ThemeProvider"; +import { useProducts } from "@/hooks/useProducts"; +import type { Product } from "@/lib/api/product"; +import type { LucideIcon } from "lucide-react"; +import type { ButtonConfig, GridVariant, CardAnimationType, TitleSegment, ButtonAnimationType } from "@/components/cardStack/types"; +import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants"; -interface ProductCardTwoProps { - products?: ProductCard[]; - title?: string; - description?: string; - className?: string; -} +type ProductCardTwoGridVariant = Exclude; -export const ProductCardTwo: React.FC = ({ - products = [], - title = "Products", description = "Our collection", className, -}) => { - return ( -
-

{title}

-

{description}

-
- {products.map((product) => ( -
-
- {product.imageAlt - -
-

{product.name}

-

{product.price}

- -
- ))} -
-
- ); +type ProductCard = Product & { + brand: string; + rating: number; + reviewCount: string; }; +interface ProductCardTwoProps { + products?: ProductCard[]; + carouselMode?: "auto" | "buttons"; + gridVariant: ProductCardTwoGridVariant; + uniformGridCustomHeightClasses?: string; + animationType: CardAnimationType; + title: string; + titleSegments?: TitleSegment[]; + description: string; + tag?: string; + tagIcon?: LucideIcon; + tagAnimation?: ButtonAnimationType; + buttons?: ButtonConfig[]; + buttonAnimation?: ButtonAnimationType; + textboxLayout: TextboxLayout; + useInvertedBackground: InvertedBackground; + ariaLabel?: string; + className?: string; + containerClassName?: string; + cardClassName?: string; + imageClassName?: string; + textBoxTitleClassName?: string; + textBoxTitleImageWrapperClassName?: string; + textBoxTitleImageClassName?: string; + textBoxDescriptionClassName?: string; + cardBrandClassName?: string; + cardNameClassName?: string; + cardPriceClassName?: string; + cardRatingClassName?: string; + actionButtonClassName?: string; + gridClassName?: string; + carouselClassName?: string; + controlsClassName?: string; + textBoxClassName?: string; + textBoxTagClassName?: string; + textBoxButtonContainerClassName?: string; + textBoxButtonClassName?: string; + textBoxButtonTextClassName?: string; +} + +interface ProductCardItemProps { + product: ProductCard; + shouldUseLightText: boolean; + cardClassName?: string; + imageClassName?: string; + cardBrandClassName?: string; + cardNameClassName?: string; + cardPriceClassName?: string; + cardRatingClassName?: string; + actionButtonClassName?: string; +} + +const ProductCardItem = memo(({ + product, + shouldUseLightText, + cardClassName = "", + imageClassName = "", + cardBrandClassName = "", + cardNameClassName = "", + cardPriceClassName = "", + cardRatingClassName = "", + actionButtonClassName = "", +}: ProductCardItemProps) => { + return ( +
+ + +
+

+ {product.brand} +

+
+

+ {product.name} +

+
+
+ {[...Array(5)].map((_, i) => ( + + ))} +
+ + ({product.reviewCount}) + +
+
+

+ {product.price} +

+
+
+ ); +}); + +ProductCardItem.displayName = "ProductCardItem"; + +const ProductCardTwo = ({ + products: productsProp, + carouselMode = "buttons", + gridVariant, + uniformGridCustomHeightClasses = "min-h-95 2xl:min-h-105", + animationType, + title, + titleSegments, + description, + tag, + tagIcon, + tagAnimation, + buttons, + buttonAnimation, + textboxLayout, + useInvertedBackground, + ariaLabel = "Product section", + className = "", + containerClassName = "", + cardClassName = "", + imageClassName = "", + textBoxTitleClassName = "", + textBoxTitleImageWrapperClassName = "", + textBoxTitleImageClassName = "", + textBoxDescriptionClassName = "", + cardBrandClassName = "", + cardNameClassName = "", + cardPriceClassName = "", + cardRatingClassName = "", + actionButtonClassName = "", + gridClassName = "", + carouselClassName = "", + controlsClassName = "", + textBoxClassName = "", + textBoxTagClassName = "", + textBoxButtonContainerClassName = "", + textBoxButtonClassName = "", + textBoxButtonTextClassName = "", +}: ProductCardTwoProps) => { + const theme = useTheme(); + const router = useRouter(); + const { products: fetchedProducts, isLoading } = useProducts(); + const isFromApi = fetchedProducts.length > 0; + const products = (fetchedProducts.length > 0 ? fetchedProducts : productsProp) as ProductCard[]; + const shouldUseLightText = shouldUseInvertedText(useInvertedBackground, theme.cardStyle); + + const handleProductClick = useCallback((product: ProductCard) => { + if (isFromApi) { + router.push(`/shop/${product.id}`); + } else { + product.onProductClick?.(); + } + }, [isFromApi, router]); + + const customGridRows = (gridVariant === "bento-grid" || gridVariant === "bento-grid-inverted") + ? "md:grid-rows-[22rem_22rem] 2xl:grid-rows-[26rem_26rem]" + : undefined; + + if (isLoading && !productsProp) { + return ( +
+

Loading products...

+
+ ); + } + + if (!products || products.length === 0) { + return null; + } + + return ( + + {products?.map((product, index) => ( + handleProductClick(product) }} + shouldUseLightText={shouldUseLightText} + cardClassName={cardClassName} + imageClassName={imageClassName} + cardBrandClassName={cardBrandClassName} + cardNameClassName={cardNameClassName} + cardPriceClassName={cardPriceClassName} + cardRatingClassName={cardRatingClassName} + actionButtonClassName={actionButtonClassName} + /> + ))} + + ); +}; + +ProductCardTwo.displayName = "ProductCardTwo"; + export default ProductCardTwo;