185 lines
5.5 KiB
TypeScript
185 lines
5.5 KiB
TypeScript
"use client";
|
|
|
|
import { CheckCircle } from "lucide-react";
|
|
|
|
import { AspectRatio } from "@/components/ui/aspect-ratio";
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@/components/ui/dialog";
|
|
import { Separator } from "@/components/ui/separator";
|
|
|
|
interface OrderItem {
|
|
id: string;
|
|
name: string;
|
|
image: string;
|
|
price: number;
|
|
quantity: number;
|
|
}
|
|
|
|
interface OrderSummaryData {
|
|
orderNumber: string;
|
|
items: OrderItem[];
|
|
subtotal: number;
|
|
shipping: number;
|
|
total: number;
|
|
/** ISO 8601 date range for estimated delivery */
|
|
estimatedDeliveryFrom: string;
|
|
estimatedDeliveryTo?: string;
|
|
}
|
|
|
|
const currencyFormatter = new Intl.NumberFormat("fa-IR", {
|
|
style: "currency",
|
|
currency: "IRR",
|
|
});
|
|
|
|
const dateFormatter = new Intl.DateTimeFormat("fa-IR", {
|
|
year: "numeric",
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
|
|
const formatOrderDate = (isoDate: string) =>
|
|
dateFormatter.format(new Date(isoDate + "T12:00:00"));
|
|
|
|
const formatDeliveryEstimate = (from: string, to?: string) => {
|
|
if (to && to !== from) {
|
|
return `${formatOrderDate(from)} تا ${formatOrderDate(to)}`;
|
|
}
|
|
return formatOrderDate(from);
|
|
};
|
|
|
|
const DEFAULT_ORDER: OrderSummaryData = {
|
|
orderNumber: "ORD-2024-78432",
|
|
items: [
|
|
{
|
|
id: "1",
|
|
name: "کفش بژ مینیمال",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/Minimalist-Beige-Sneakers-2.png",
|
|
price: 120.0,
|
|
quantity: 1,
|
|
},
|
|
{
|
|
id: "2",
|
|
name: "تاپ آبی گلدوزی",
|
|
image:
|
|
"/block-media/shadcnblocks/block/ecommerce/clothes/Woman-in-Embroidered-Blue-Top-2.png",
|
|
price: 140.0,
|
|
quantity: 2,
|
|
},
|
|
],
|
|
subtotal: 400.0,
|
|
shipping: 12.0,
|
|
total: 412.0,
|
|
estimatedDeliveryFrom: "2024-12-18",
|
|
estimatedDeliveryTo: "2024-12-20",
|
|
};
|
|
|
|
interface OrderSummary6Props {
|
|
order?: OrderSummaryData;
|
|
}
|
|
|
|
const OrderSummary6 = ({ order = DEFAULT_ORDER }: OrderSummary6Props) => {
|
|
return (
|
|
<div
|
|
dir="rtl"
|
|
lang="fa"
|
|
className="flex min-h-[400px] items-center justify-center p-8"
|
|
>
|
|
<Dialog>
|
|
<DialogTrigger asChild>
|
|
<Button size="lg">مشاهده تأیید سفارش</Button>
|
|
</DialogTrigger>
|
|
<DialogContent dir="rtl" lang="fa" className="sm:max-w-md">
|
|
<DialogHeader className="text-center sm:text-center">
|
|
<div className="mx-auto mb-2 flex size-12 items-center justify-center rounded-full bg-emerald-500">
|
|
<CheckCircle className="size-6 text-white" aria-hidden="true" />
|
|
</div>
|
|
<DialogTitle className="text-xl">سفارش تأیید شد!</DialogTitle>
|
|
<DialogDescription>
|
|
سفارش{" "}
|
|
<span dir="rtl" className="font-medium">
|
|
{order.orderNumber}
|
|
</span>{" "}
|
|
· تحویل{" "}
|
|
{formatDeliveryEstimate(
|
|
order.estimatedDeliveryFrom,
|
|
order.estimatedDeliveryTo,
|
|
)}
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="space-y-3 py-2">
|
|
{order.items.map((item) => (
|
|
<div key={item.id} className="flex gap-3">
|
|
<div className="w-12 shrink-0">
|
|
<AspectRatio
|
|
ratio={1}
|
|
className="overflow-hidden rounded-md bg-muted"
|
|
>
|
|
<img
|
|
src={item.image}
|
|
alt={item.name}
|
|
className="size-full object-cover"
|
|
/>
|
|
</AspectRatio>
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<p className="truncate text-sm font-medium">{item.name}</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
تعداد: {item.quantity.toLocaleString("fa-IR")}
|
|
</p>
|
|
</div>
|
|
<p className="text-sm font-semibold tabular-nums">
|
|
{currencyFormatter.format(item.price * item.quantity)}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
<Separator />
|
|
|
|
<div className="space-y-1.5 text-sm">
|
|
<div className="flex justify-between">
|
|
<span className="text-muted-foreground">جمع جزء</span>
|
|
<span className="tabular-nums">
|
|
{currencyFormatter.format(order.subtotal)}
|
|
</span>
|
|
</div>
|
|
<div className="flex justify-between">
|
|
<span className="text-muted-foreground">هزینه ارسال</span>
|
|
<span className="tabular-nums">
|
|
{order.shipping === 0
|
|
? "رایگان"
|
|
: currencyFormatter.format(order.shipping)}
|
|
</span>
|
|
</div>
|
|
<div className="flex justify-between pt-2 text-base font-bold">
|
|
<span>مجموع</span>
|
|
<span className="tabular-nums">
|
|
{currencyFormatter.format(order.total)}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<DialogFooter className="flex-col gap-2 sm:flex-col">
|
|
<Button className="w-full">پیگیری سفارش</Button>
|
|
<Button variant="ghost" className="w-full">
|
|
ادامه خرید
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { OrderSummary6 };
|