165 lines
4.7 KiB
TypeScript
165 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { X } from "lucide-react";
|
|
|
|
import { Price } from "@/components/shadcnblocks/price";
|
|
import { AspectRatio } from "@/components/ui/aspect-ratio";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Carousel,
|
|
CarouselContent,
|
|
CarouselItem,
|
|
CarouselNext,
|
|
CarouselPrevious,
|
|
} from "@/components/ui/carousel";
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogTitle,
|
|
} from "@/components/ui/dialog";
|
|
|
|
type Image = {
|
|
alt: string;
|
|
src: string;
|
|
};
|
|
|
|
interface ProductPrice {
|
|
regular: number;
|
|
sale?: number;
|
|
currency: string;
|
|
}
|
|
|
|
type Product = {
|
|
images: Image[];
|
|
price: ProductPrice;
|
|
name: string;
|
|
description: string;
|
|
};
|
|
|
|
type ProductQuickView8Props = Product;
|
|
|
|
interface ProductImagesProps {
|
|
images: Image[];
|
|
}
|
|
|
|
const formatCurrency = (
|
|
value: number,
|
|
currency: string = "ریال",
|
|
locale: string = "fa-IR",
|
|
) => {
|
|
return `${value.toLocaleString(locale)} ${currency}`;
|
|
};
|
|
|
|
const PRODUCT_DETAILS: Product = {
|
|
images: [
|
|
{
|
|
src: "/block-media/shadcnblocks/block/ecommerce/electronics/turntable/modern-audio-device.png",
|
|
alt: "دستگاه صوتی مدرن",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/ecommerce/electronics/turntable/modern-audio-panel.png",
|
|
alt: "پنل صوتی مدرن",
|
|
},
|
|
{
|
|
src: "/block-media/shadcnblocks/block/ecommerce/electronics/turntable/elegant-turntable-scene.png",
|
|
alt: "صحنه گرامافون شیک",
|
|
},
|
|
],
|
|
price: {
|
|
regular: 1299000.0,
|
|
currency: "ریال",
|
|
},
|
|
name: "گرامافون دقیق پرو",
|
|
description:
|
|
"وینیل را همانگونه بشنوید که باید شنیده شود. موتور دایرکتدرایو دقیق، بازوی صوتی قابل تنظیم و شاسی ضدلرزش برای بازتولید صدایی پاکیزه.",
|
|
};
|
|
|
|
const ProductQuickView8 = ({
|
|
images = PRODUCT_DETAILS.images,
|
|
price = PRODUCT_DETAILS.price,
|
|
name = PRODUCT_DETAILS.name,
|
|
description = PRODUCT_DETAILS.description,
|
|
}: ProductQuickView8Props) => {
|
|
const { regular, sale, currency } = price;
|
|
|
|
return (
|
|
<Dialog defaultOpen>
|
|
<DialogContent showCloseButton={false} className="p-4 sm:max-w-168">
|
|
<div className="absolute top-5 end-5 z-50">
|
|
<DialogClose asChild>
|
|
<Button className="rounded-full" size="icon-sm" variant="secondary">
|
|
<X />
|
|
</Button>
|
|
</DialogClose>
|
|
</div>
|
|
<div className="hide-scrollbar max-h-[calc(100dvh-8rem)] overflow-auto">
|
|
<ProductImages images={images} />
|
|
<div className="pt-4 pb-20">
|
|
<div className="space-y-6">
|
|
<div className="space-y-1">
|
|
<Price
|
|
onSale={sale != null}
|
|
className="items-end gap-x-1 text-base font-medium"
|
|
>
|
|
{sale != null && (
|
|
<span className="leading-tight text-foreground">
|
|
{formatCurrency(sale, currency)}
|
|
</span>
|
|
)}
|
|
<span
|
|
className={
|
|
sale != null
|
|
? "leading-tight text-muted-foreground line-through"
|
|
: "leading-tight text-foreground"
|
|
}
|
|
>
|
|
{formatCurrency(regular, currency)}
|
|
</span>
|
|
</Price>
|
|
<DialogTitle className="text-xl font-medium">
|
|
{name}
|
|
</DialogTitle>
|
|
</div>
|
|
<DialogDescription className="text-base leading-relaxed">
|
|
{description}
|
|
</DialogDescription>
|
|
</div>
|
|
<DialogFooter className="fixed inset-x-0 bottom-0">
|
|
<div className="w-full rounded-b-lg bg-background p-4">
|
|
<Button className="w-full">افزودن به سبد</Button>
|
|
</div>
|
|
</DialogFooter>
|
|
</div>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
};
|
|
|
|
const ProductImages = ({ images }: ProductImagesProps) => {
|
|
return (
|
|
<Carousel>
|
|
<CarouselContent>
|
|
{images.map((img) => (
|
|
<CarouselItem key={crypto.randomUUID()}>
|
|
<AspectRatio ratio={1.4} className="overflow-hidden rounded-sm">
|
|
<img
|
|
src={img.src}
|
|
alt={img.alt}
|
|
className="block size-full object-cover object-center"
|
|
/>
|
|
</AspectRatio>
|
|
</CarouselItem>
|
|
))}
|
|
</CarouselContent>
|
|
<CarouselPrevious className="start-1" />
|
|
<CarouselNext className="end-1" />
|
|
</Carousel>
|
|
);
|
|
};
|
|
|
|
export { ProductQuickView8 };
|