Files
reui-blocks/blocks/product-list10.tsx
T

550 lines
20 KiB
TypeScript

import { Eye, ShoppingCart } from "lucide-react";
import { AspectRatio } from "@/components/ui/aspect-ratio";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { cn } from "@/lib/utils";
const STOCK_STATUS = {
IN_STOCK: "IN_STOCK",
OUT_OF_STOCK: "OUT_OF_STOCK",
} as const;
type StockStatusCode = keyof typeof STOCK_STATUS;
interface ProductPrice {
regular: number;
sale?: number;
currency: string;
}
interface Product {
name: string;
image: {
src: string;
srcset?: string;
sizes?: string;
alt: string;
};
link: string;
price: ProductPrice;
stockStatusCode: StockStatusCode;
badges?: Array<{
text: string;
color?: string;
}>;
}
type ProductCardProps = Product;
interface FeaturedPromotion {
kicker: string;
title: string;
cta: {
link: string;
label: string;
};
link: string;
image: string;
}
type FeaturedPromotionCardProps = FeaturedPromotion;
type ProductList = Array<{
featuredPromotion: FeaturedPromotion;
products: Array<Product>;
}>;
const PRODUCTS_LIST: ProductList = [
{
featuredPromotion: {
image:
"/block-media/shadcnblocks/block/ecommerce/other/linh-le-giP0e750Dr8-unsplash-1.jpg",
title: "قطعاتی ماندگار (کلاسیک) که برای راحتی و سبک طراحی شده‌اند.",
kicker: "فضاهای روزمره‌تان را ارتقا دهید.",
cta: {
label: "خرید مبلمان و موارد دیگر",
link: "#",
},
link: "#",
},
products: [
{
name: "مبل چرمی",
price: {
regular: 899000.0,
sale: 799000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112729-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112729-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112729-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112729-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "ماگ سرامیکی",
price: {
regular: 59900.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-20710970-15362198-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-20710970-15362198-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-20710970-15362198-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-20710970-15362198-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "کتری چای",
price: {
regular: 920000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "OUT_OF_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-nicola-barts-7937498-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-nicola-barts-7937498-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-nicola-barts-7937498-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-nicola-barts-7937498-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "شمع‌های معطر",
price: {
regular: 500000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-sueda-gln-327513956-20081033-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-sueda-gln-327513956-20081033-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-sueda-gln-327513956-20081033-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-sueda-gln-327513956-20081033-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: 'قاب چوبی ۵×۷ اینچ',
price: {
regular: 200000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-4207785-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-4207785-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-4207785-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-4207785-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "آباژور کره‌ای",
price: {
regular: 199000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-6825308-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-6825308-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-6825308-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-6825308-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "صندلی چرمی",
price: {
regular: 899000.0,
sale: 799000.0,
currency: "ریال",
},
link: "#",
badges: [
{
text: "بهترین انتخاب!",
color: "oklch(54.6% 0.245 262.881)",
},
{
text: "حراج",
color: "oklch(57.7% 0.245 27.325)",
},
],
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/furniture/pexels-mathilde-14792096-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/furniture/pexels-mathilde-14792096-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-mathilde-14792096-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-mathilde-14792096-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "فنجان سرامیکی",
price: {
regular: 190000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "OUT_OF_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-bWlbcvFMUh4-unsplash-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-bWlbcvFMUh4-unsplash-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-bWlbcvFMUh4-unsplash-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-bWlbcvFMUh4-unsplash-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
],
},
{
featuredPromotion: {
image:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-karolina-grabowska-4207892-1.jpg",
title: "از شمع تا قاب؛ جزئیات کوچک، اثر بزرگ.",
kicker: "جزئیاتی که خانه می‌سازند",
cta: {
label: "کاوش اکسسوری‌های خانه",
link: "#",
},
link: "#",
},
products: [
{
name: "صندلی ناهارخوری",
price: {
regular: 299000.0,
sale: 199000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "OUT_OF_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/furniture/pexels-cottonbro-6626409-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/furniture/pexels-cottonbro-6626409-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-cottonbro-6626409-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-cottonbro-6626409-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "ساعت دیواری",
price: {
regular: 159000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-cottonbro-5185169-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-cottonbro-5185169-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-cottonbro-5185169-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-cottonbro-5185169-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "بشقاب سرامیکی",
price: {
regular: 990000.0,
sale: 890000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
badges: [
{
text: "حراج",
color: "oklch(57.7% 0.245 27.325)",
},
],
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-micheile-10410297-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-micheile-10410297-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-micheile-10410297-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-micheile-10410297-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "کابینت چوبی",
price: {
regular: 699000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112749-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112749-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112749-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112749-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "صندلی چوبی",
price: {
regular: 490000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112738-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112738-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112738-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-kseniachernaya-11112738-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "فنجان سرامیکی",
price: {
regular: 190000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/pexels-anna-nekrashevich-8533748-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/pexels-anna-nekrashevich-8533748-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/pexels-anna-nekrashevich-8533748-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/pexels-anna-nekrashevich-8533748-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "فنجان سرامیکی",
price: {
regular: 190000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-L2r9L6Llyp4-unsplash-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-L2r9L6Llyp4-unsplash-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-L2r9L6Llyp4-unsplash-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/other/cafeconcetto-L2r9L6Llyp4-unsplash-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
{
name: "صندلی چوبی",
price: {
regular: 490000.0,
currency: "ریال",
},
link: "#",
stockStatusCode: "IN_STOCK",
image: {
src: "/block-media/shadcnblocks/block/ecommerce/furniture/pexels-karolina-grabowska-7193566-3.jpg",
srcset:
"/block-media/shadcnblocks/block/ecommerce/furniture/pexels-karolina-grabowska-7193566-3.jpg 1920w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-karolina-grabowska-7193566-2.jpg 1280w, /block-media/shadcnblocks/block/ecommerce/furniture/pexels-karolina-grabowska-7193566-1.jpg 640w",
alt: "تصویر محصول",
sizes:
"(min-width: 1920px) 1920px, (min-width: 1280px) 1280px, 100vw",
},
},
],
},
];
interface ProductList10Props {
className?: string;
}
const ProductList10 = ({ className }: ProductList10Props) => {
return (
<section className={cn("py-32", className)}>
<div className="container">
<div className="flex flex-col gap-5">
{PRODUCTS_LIST.map((item, index) => (
<div
className="flex flex-col gap-5 lg:flex-row lg:even:flex-row-reverse"
key={`product-list-10-featured-promo-${index}`}
>
<div className="flex-1/3">
<FeaturedPromotionCard {...item.featuredPromotion} />
</div>
<div className="flex-2/3">
<div className="grid grid-cols-2 gap-5 md:grid-cols-4">
{item.products.map((product, index) => (
<ProductCard
{...product}
key={`product-10-list-card-${index}`}
/>
))}
</div>
</div>
</div>
))}
</div>
</div>
</section>
);
};
const ProductCard = ({
link,
image,
name,
price,
stockStatusCode,
}: ProductCardProps) => {
const { regular, sale, currency } = price;
return (
<Card className="group relative block rounded-none border-none bg-background p-0 shadow-none">
<a href={link} className="absolute inset-0 z-10 size-full"></a>
<CardContent className="p-0">
<div className="relative overflow-hidden">
<AspectRatio
ratio={0.749767365}
className="overflow-hidden rounded-xl"
>
<img
srcSet={image.srcset}
alt={image.alt}
sizes={image.sizes}
className="block size-full origin-center object-cover object-center transition-transform duration-700 group-hover:scale-110"
/>
</AspectRatio>
{stockStatusCode === STOCK_STATUS.OUT_OF_STOCK && (
<div className="absolute start-2.5 top-2.5 z-60">
<Badge>فروخته شد</Badge>
</div>
)}
{stockStatusCode === STOCK_STATUS.IN_STOCK && price.sale && (
<div className="absolute start-2.5 top-2.5 z-60">
<Badge variant="destructive">حراج</Badge>
</div>
)}
<div className="absolute inset-x-5 top-1/2 z-60 hidden -translate-y-1/2 md:block">
<div className="flex flex-col gap-2 opacity-0 duration-700 lg:translate-y-4 lg:group-hover:translate-y-0 lg:group-hover:opacity-100">
<Button
disabled={stockStatusCode === STOCK_STATUS.OUT_OF_STOCK}
className="w-full"
>
<ShoppingCart />
افزودن به سبد
</Button>
<Button variant="secondary" className="w-full">
<Eye />
مشاهده سریع
</Button>
</div>
</div>
</div>
<div className="flex flex-col gap-1 pt-3">
<CardTitle className="leading-normal font-normal underline-offset-3 group-hover:underline">
{name}
</CardTitle>
<ProductCardPrice regular={regular} sale={sale} currency={currency} />
</div>
</CardContent>
</Card>
);
};
const FeaturedPromotionCard = ({
kicker,
title,
cta,
link,
image,
}: FeaturedPromotionCardProps) => {
return (
<Card
style={{
backgroundImage: `url(${image})`,
}}
className="relative h-full min-h-160 border-none bg-cover bg-center bg-no-repeat p-10 shadow-none md:min-h-100"
>
<a href={link} className="absolute inset-0 z-10 size-full"></a>
<CardHeader className="gap-2.5 p-0">
<p>{kicker}</p>
<CardTitle className="text-xl font-medium">{title}</CardTitle>
<div className="relative z-20 mt-5">
<Button size="lg" asChild>
<a href={cta.link}>{cta.label}</a>
</Button>
</div>
</CardHeader>
</Card>
);
};
const formatCurrency = (
value: number,
currency: string = "ریال",
locale: string = "fa-IR",
) => {
return `${value.toLocaleString(locale)} ${currency}`;
};
const ProductCardPrice = ({
regular,
sale,
currency,
}: {
regular: number;
sale?: number;
currency: string;
}) => {
const onSale = sale != null;
return (
<div className="flex flex-wrap items-center gap-x-2 text-sm leading-normal font-bold">
{onSale ? (
<span className="leading-tight text-red-700">
{formatCurrency(sale, currency)}
</span>
) : null}
<span
className={cn(
"leading-tight",
onSale
? "text-muted-foreground line-through"
: "text-foreground",
)}
>
{formatCurrency(regular, currency)}
</span>
</div>
);
};
export { ProductList10 };