Files
website/src/components/home/ProductCard.tsx
T

134 lines
5.0 KiB
TypeScript

"use client";
import Image from "next/image";
import Link from "next/link";
import type { Product } from "@/data/home";
import { productPath } from "@/lib/product-path";
const FALLBACK_DESC =
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.";
type ProductCardProps = {
product: Product;
className?: string;
};
export default function ProductCard({ product, className = "" }: ProductCardProps) {
const href = product.href ?? productPath(product);
const hoverSrc = product.imageHover;
const colors = product.colors ?? [];
const sizes = product.sizes ?? [];
const hasVars = colors.length > 0 || sizes.length > 0;
const description = product.description?.trim() || FALLBACK_DESC;
return (
<article
dir="rtl"
className={`group relative flex h-[491px] w-full flex-col rounded-[5px] border border-[#8e8e8e]/30 bg-white transition-colors duration-300 ease-out hover:border-ink ${className}`}
>
<Link href={href} className="flex min-h-0 flex-1 flex-col">
{/* Clip media only — keep border on the outer box so it never gets cut off */}
<span className="relative block min-h-0 flex-1 overflow-hidden rounded-t-[4px] p-2.5">
<span className="relative block h-full w-full overflow-hidden rounded-[5px]">
<Image
src={product.image}
alt={product.nameFa}
fill
sizes="(max-width: 768px) 50vw, 324px"
className={`object-cover object-top transition-transform duration-500 ease-out ${
hoverSrc ? "group-hover:translate-x-full" : "group-hover:scale-[1.04]"
}`}
/>
{hoverSrc ? (
<Image
src={hoverSrc}
alt=""
fill
sizes="(max-width: 768px) 50vw, 324px"
className="object-cover object-top -translate-x-full transition-transform duration-500 ease-out group-hover:translate-x-0"
aria-hidden
/>
) : null}
</span>
</span>
<span className="flex shrink-0 flex-col gap-1.5 px-3.5 pb-3.5 pt-1">
<span className="w-full text-right">
<span className="line-clamp-1 block text-[15px] font-medium text-ink">
{product.nameFa}
</span>
<span
dir="ltr"
className="mt-0.5 line-clamp-1 block w-full text-right font-montserrat text-[9px] font-light uppercase tracking-[0.2em] text-[#afafaf]"
>
{product.nameEn}
</span>
</span>
{hasVars ? (
<span className="flex flex-wrap items-center justify-start gap-2">
{sizes.length > 0 ? (
<span className="flex items-center gap-1" aria-label="سایزها" dir="ltr">
{sizes.slice(0, 5).map((size) => (
<span
key={size.id}
title={size.labelFa}
className="inline-flex h-5 min-w-5 items-center justify-center rounded-[3px] border border-ink/20 px-1 font-montserrat text-[9px] font-medium uppercase leading-none text-ink"
>
{size.labelFa}
</span>
))}
</span>
) : null}
{colors.length > 0 ? (
<span className="flex items-center gap-1" aria-label="رنگ‌های موجود">
{colors.slice(0, 6).map((color) => (
<span
key={color.id}
title={color.labelFa}
className="inline-block size-3.5 shrink-0 rounded-full border border-black/10"
style={{ background: color.swatch || "#ccc" }}
/>
))}
</span>
) : null}
</span>
) : null}
<span
aria-hidden
className="mt-0.5 block h-px w-full bg-ink/10 transition-colors duration-300 ease-out group-hover:bg-ink/35"
/>
{/* Vars occupy ~1 line — clamp desc to 1 so the image height stays even */}
<span
className={`${
hasVars ? "line-clamp-1" : "line-clamp-2"
} text-right text-[11px] font-light leading-relaxed text-[#6e6e6e]`}
>
{description}
</span>
</span>
</Link>
<button
type="button"
aria-label="افزودن به علاقه‌مندی"
className="absolute end-3 top-4 z-10 transition-opacity hover:opacity-70"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<Image
src="/images/home/icons/bookmark.svg"
alt=""
width={24}
height={24}
unoptimized
/>
</button>
</article>
);
}