235 lines
7.1 KiB
TypeScript
235 lines
7.1 KiB
TypeScript
"use client";
|
||
|
||
import { CheckCircle, Package } from "lucide-react";
|
||
|
||
import { AspectRatio } from "@/components/ui/aspect-ratio";
|
||
import { Button } from "@/components/ui/button";
|
||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||
import { Separator } from "@/components/ui/separator";
|
||
import {
|
||
Sheet,
|
||
SheetContent,
|
||
SheetDescription,
|
||
SheetFooter,
|
||
SheetHeader,
|
||
SheetTitle,
|
||
SheetTrigger,
|
||
} from "@/components/ui/sheet";
|
||
|
||
interface OrderItem {
|
||
id: string;
|
||
name: string;
|
||
image: string;
|
||
price: number;
|
||
quantity: number;
|
||
}
|
||
|
||
interface OrderSummaryData {
|
||
orderNumber: string;
|
||
items: OrderItem[];
|
||
subtotal: number;
|
||
shipping: number;
|
||
tax: number;
|
||
discount?: 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,
|
||
},
|
||
{
|
||
id: "3",
|
||
name: "کلاه فدورا کلاسیک",
|
||
image:
|
||
"/block-media/shadcnblocks/block/ecommerce/accessories/Classic-Fedora-Hat-2.png",
|
||
price: 84.0,
|
||
quantity: 1,
|
||
},
|
||
],
|
||
subtotal: 484.0,
|
||
shipping: 12.0,
|
||
tax: 38.72,
|
||
discount: 50.0,
|
||
total: 484.72,
|
||
estimatedDeliveryFrom: "2024-12-18",
|
||
estimatedDeliveryTo: "2024-12-20",
|
||
};
|
||
|
||
interface OrderSummary5Props {
|
||
order?: OrderSummaryData;
|
||
}
|
||
|
||
const OrderSummary5 = ({ order = DEFAULT_ORDER }: OrderSummary5Props) => {
|
||
return (
|
||
<div
|
||
dir="rtl"
|
||
lang="fa"
|
||
className="flex min-h-[400px] items-center justify-center p-8"
|
||
>
|
||
<Sheet>
|
||
<SheetTrigger asChild>
|
||
<Button size="lg">مشاهده خلاصه سفارش</Button>
|
||
</SheetTrigger>
|
||
<SheetContent
|
||
dir="rtl"
|
||
lang="fa"
|
||
side="right"
|
||
className="flex w-full flex-col px-6 sm:max-w-md"
|
||
>
|
||
<SheetHeader className="px-0 text-start">
|
||
<div className="flex items-center gap-3">
|
||
<div className="flex size-10 items-center justify-center rounded-full bg-emerald-500">
|
||
<CheckCircle
|
||
className="size-5 text-white"
|
||
aria-hidden="true"
|
||
/>
|
||
</div>
|
||
<div>
|
||
<SheetTitle>سفارش تأیید شد</SheetTitle>
|
||
<SheetDescription dir="rtl">
|
||
{order.orderNumber}
|
||
</SheetDescription>
|
||
</div>
|
||
</div>
|
||
</SheetHeader>
|
||
|
||
<ScrollArea className="-mx-6 flex-1 px-6">
|
||
<div className="space-y-3 py-4">
|
||
{order.items.map((item) => (
|
||
<div key={item.id} className="flex gap-3">
|
||
<div className="w-16 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 font-medium">{item.name}</p>
|
||
<p className="text-sm text-muted-foreground">
|
||
تعداد: {item.quantity.toLocaleString("fa-IR")}
|
||
</p>
|
||
</div>
|
||
<p className="font-semibold tabular-nums">
|
||
{currencyFormatter.format(item.price * item.quantity)}
|
||
</p>
|
||
</div>
|
||
))}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
<div className="space-y-2 py-4 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">
|
||
<span className="text-muted-foreground">مالیات</span>
|
||
<span className="tabular-nums">
|
||
{currencyFormatter.format(order.tax)}
|
||
</span>
|
||
</div>
|
||
{order.discount && order.discount > 0 && (
|
||
<div className="flex justify-between text-emerald-600">
|
||
<span>تخفیف</span>
|
||
<span className="tabular-nums">
|
||
−{currencyFormatter.format(order.discount)}
|
||
</span>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<Separator />
|
||
|
||
<div className="flex items-center justify-between py-4">
|
||
<span className="text-lg font-bold">مجموع</span>
|
||
<span className="text-xl font-bold tabular-nums">
|
||
{currencyFormatter.format(order.total)}
|
||
</span>
|
||
</div>
|
||
|
||
<div className="flex items-center gap-2 rounded-lg bg-muted p-3 text-sm">
|
||
<Package
|
||
className="size-4 shrink-0 text-muted-foreground"
|
||
aria-hidden="true"
|
||
/>
|
||
<span>
|
||
تحویل تقریبی:{" "}
|
||
{formatDeliveryEstimate(
|
||
order.estimatedDeliveryFrom,
|
||
order.estimatedDeliveryTo,
|
||
)}
|
||
</span>
|
||
</div>
|
||
</ScrollArea>
|
||
|
||
<SheetFooter className="flex-col gap-2 px-0 sm:flex-col">
|
||
<Button className="w-full">پیگیری سفارش</Button>
|
||
<Button variant="outline" className="w-full">
|
||
ادامه خرید
|
||
</Button>
|
||
</SheetFooter>
|
||
</SheetContent>
|
||
</Sheet>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export { OrderSummary5 };
|