import React from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { ShoppingCart, Heart } from 'lucide-react'; import { formatPrice, formatDiscount } from '@/lib/currency'; import { Button } from './ui/button'; import { useShopSettings } from '@/hooks/useAppearanceSettings'; import { useWishlist } from '@/hooks/useWishlist'; import { useModules } from '@/hooks/useModules'; interface ProductCardProps { product: { id: number; name: string; slug: string; price: string; regular_price?: string; sale_price?: string; image?: string; on_sale?: boolean; stock_status?: string; type?: string; }; onAddToCart?: (product: any) => void; } export function ProductCard({ product, onAddToCart }: ProductCardProps) { const navigate = useNavigate(); const { layout, elements, addToCart, saleBadge, isLoading } = useShopSettings(); const { isEnabled: wishlistEnabled, isInWishlist, toggleWishlist } = useWishlist(); const { isEnabled: isModuleEnabled } = useModules(); const showWishlist = isModuleEnabled('wishlist') && wishlistEnabled; const inWishlist = showWishlist && isInWishlist(product.id); const handleWishlistClick = async (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); await toggleWishlist(product.id); }; // Aspect ratio classes const aspectRatioClass = { 'square': 'aspect-square', 'portrait': 'aspect-[3/4]', 'landscape': 'aspect-[4/3]', }[layout.aspect_ratio] || 'aspect-square'; const isVariable = product.type === 'variable'; const handleAddToCart = (e: React.MouseEvent) => { e.preventDefault(); e.stopPropagation(); // Variable products need to go to product page for attribute selection if (isVariable) { navigate(`/product/${product.slug}`); return; } onAddToCart?.(product); }; // Calculate discount if on sale const discount = product.on_sale && product.regular_price && product.sale_price ? formatDiscount(parseFloat(product.regular_price), parseFloat(product.sale_price)) : null; // Show skeleton while settings are loading to prevent layout shift if (isLoading) { return (
); } // Determine button variant and position based on settings const buttonVariant = addToCart.style === 'outline' ? 'outline' : addToCart.style === 'text' ? 'ghost' : 'default'; const showButtonOnHover = addToCart.position === 'overlay'; const isTextOnly = addToCart.style === 'text'; // Card style variations - adapt to column count const gridCols = parseInt(layout.grid_columns) || 3; // More columns = cleaner styling const getCardClasses = () => { const cardStyle = layout.card_style || 'card'; if (cardStyle === 'minimal') { return gridCols >= 4 ? 'overflow-hidden hover:opacity-90 transition-opacity' : 'overflow-hidden hover:opacity-80 transition-opacity border-b border-border pb-4'; } if (cardStyle === 'overlay') { return gridCols >= 4 ? 'relative overflow-hidden group-hover:shadow-lg transition-all rounded-md' : 'relative overflow-hidden group-hover:shadow-xl transition-all rounded-lg bg-card'; } // Default 'card' style return gridCols >= 4 ? 'border border-border rounded-md overflow-hidden hover:shadow-md transition-shadow bg-card' : 'border border-border rounded-lg overflow-hidden hover:shadow-lg transition-shadow bg-card'; }; const cardClasses = getCardClasses(); // Text alignment class const textAlignClass = { 'left': 'text-left', 'center': 'text-center', 'right': 'text-right', }[layout.card_text_align || 'left'] || 'text-left'; // Unified card render — adapts via card_style (card / minimal / overlay) + shop settings return (
{/* Image */}
{product.image ? ( {product.name} ) : (
No Image
)} {/* Sale Badge */} {elements.sale_badges && product.on_sale && discount && (
{discount}
)} {/* Wishlist Button */} {showWishlist && (
)} {/* Hover/Overlay Button */} {showButtonOnHover && (
)}
{/* Content */}

{product.name}

{/* Price */}
{product.on_sale && product.regular_price ? ( <> {formatPrice(product.sale_price || product.price)} {formatPrice(product.regular_price)} ) : ( {formatPrice(product.price)} )}
{/* Add to Cart Button */} {!showButtonOnHover && ( )}
); }