Files
sent-shop/components/ui/ProductCard.tsx
2026-01-19 20:21:14 +01:00

157 lines
5.3 KiB
TypeScript

'use client';
import { AddToBoxButton } from '@/components/products/AddToBoxButton';
import { ColorVariant, getProductColorVariants } from '@/components/products/utils/colorUtils';
import { Product } from 'lib/shopify/types';
import Image from "next/image";
import Link from "next/link";
import { usePathname } from 'next/navigation';
import { useEffect, useState } from 'react';
import { AddToCartButton } from './AddToCartButton';
import { ColorSelector } from './ColorSelector';
interface ProductCardProps {
title: string;
variant: string;
price: number;
imageSrc: string;
slug: string;
product?: Product;
colors?: string[]; // Array of color hex codes
}
export function ProductCard({ title, variant, price: defaultPrice, imageSrc, slug, product, colors }: ProductCardProps) {
const pathname = usePathname();
const isBuildBoxPage = pathname.includes('/build-box');
const [colorVariants, setColorVariants] = useState<ColorVariant[] | undefined>(undefined);
const [selectedColorHex, setSelectedColorHex] = useState<string | null>(null);
const [selectedVariant, setSelectedVariant] = useState<ColorVariant | undefined>(undefined);
const [currentPrice, setCurrentPrice] = useState<number>(defaultPrice);
const [isHovered, setIsHovered] = useState(false);
// Initialize color variants and selected color
useEffect(() => {
if (product) {
const variants = getProductColorVariants(product);
setColorVariants(variants);
if (variants && variants.length > 0) {
// Only set these values if we have valid variants
if (variants[0]?.color) {
setSelectedColorHex(variants[0].color);
}
setSelectedVariant(variants[0]);
if (typeof variants[0]?.price === 'number') {
setCurrentPrice(variants[0].price);
}
}
} else if (colors && colors.length > 0) {
// If we only have color hex codes without variants
const firstColor = colors[0];
if (firstColor) {
setSelectedColorHex(firstColor);
}
}
}, [product, colors]);
// Handle color selection
const handleColorSelect = (color: string) => {
setSelectedColorHex(color);
if (colorVariants) {
const variant = colorVariants.find(v => v.color === color);
if (variant) {
setSelectedVariant(variant);
setCurrentPrice(variant.price);
}
}
};
return (
<div className="flex flex-col h-full">
{/* Image container with fixed height and hover effect */}
<div
className="relative w-full h-[480px] bg-gray-100 mb-5 overflow-hidden"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<Link href={`/product/${slug}`}>
<Image
src={imageSrc}
alt={title}
fill
className="object-cover transition-opacity duration-300"
sizes="(max-width: 768px) 280px, 405px"
/>
</Link>
{/* Button - always visible on mobile, hover effect on desktop */}
{product && (
<>
{/* Mobile button - always visible */}
<div className="absolute bottom-6 left-5 right-5 md:hidden">
{isBuildBoxPage ? (
<AddToBoxButton
productId={product.id}
name={product.title}
price={currentPrice}
image={imageSrc}
variantId={selectedVariant?.variantId}
color={selectedColorHex || undefined}
/>
) : (
<AddToCartButton
product={product}
variantId={selectedVariant?.variantId}
/>
)}
</div>
{/* Desktop button - visible on hover */}
<div className={`absolute bottom-6 left-5 right-5 hidden md:block transition-opacity duration-300 ${isHovered ? 'opacity-100' : 'opacity-0'}`}>
{isBuildBoxPage ? (
<AddToBoxButton
productId={product.id}
name={product.title}
price={currentPrice}
image={imageSrc}
variantId={selectedVariant?.variantId}
color={selectedColorHex || undefined}
/>
) : (
<AddToCartButton
product={product}
variantId={selectedVariant?.variantId}
/>
)}
</div>
</>
)}
</div>
<div className="flex justify-between items-start">
<h3 className="font-bold text-[18px] leading-[28px]">{title}</h3>
<span className="font-bold text-[20px] leading-[28px] ml-2">{currentPrice} </span>
</div>
{variant && (
<p className="text-[16px] leading-[26px] text-gray-600 mb-auto">{variant}</p>
)}
{colorVariants && colorVariants.length > 0 ? (
<ColorSelector
colors={colorVariants}
selectedColor={selectedColorHex}
onColorSelect={handleColorSelect}
/>
) : colors && colors.length > 0 ? (
<ColorSelector
colors={colors}
selectedColor={selectedColorHex}
onColorSelect={setSelectedColorHex}
/>
) : null}
</div>
);
}