پیگیریِ چندمرسولهای
پیشنمایش تمامصفحهسفارشِ چندبستهای از چند فروشنده: هر بسته وضعیت، زمانِ تحویل، عکسِ اقلام، شرکتِ حمل و کدِ رهگیری با کپی و ثبتِ نظر برای تحویلشده.
۱. نصب کامپوننتها
این بلاک از ۶ آیتم دیگ استفاده میکند: badgebuttoncontrol-sizeiconspersiantoast
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/toast.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/toast.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/toast.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/badge.json https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/toast.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
order-tracking-packages.tsx
"use client"
import * as React from "react"
import { CheckIcon, ClockIcon, TruckIcon } from "@/components/icons"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { toast } from "@/components/ui/toast"
import { toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"
const PACKAGES: { id: string; seller: string; status: "delivered" | "shipping" | "preparing"; eta: string; items: StockImageName[]; carrier: string; tracking: string }[] = [
{ id: "1", seller: "خانهٔ سفال", status: "delivered", eta: "تحویل شد، دیروز ۱۶:۲۰", items: ["productVase"], carrier: "پیک", tracking: "PK-48812" },
{ id: "2", seller: "نوشتافزارِ مهر", status: "shipping", eta: "فردا تا ساعتِ ۱۸", items: ["coverNotebook", "coverOfficeSupplies"], carrier: "پستِ پیشتاز", tracking: "PST-221045" },
{ id: "3", seller: "کارگاهِ میبد", status: "preparing", eta: "ارسال تا ۲ روزِ دیگر", items: ["studioSunlit"], carrier: "هنوز تعیین نشده", tracking: "" },
]
const STATUS = {
delivered: { label: "تحویل شد", color: "success" as const, icon: <CheckIcon /> },
shipping: { label: "در راه", color: "info" as const, icon: <TruckIcon /> },
preparing: { label: "در حالِ آمادهسازی", color: "warning" as const, icon: <ClockIcon /> },
}
/**
* پیگیری سفارشِ چندمرسولهای: سفارشی که از چند فروشنده رسیده در چند بسته؛ هر بسته وضعیت،
* زمانِ تحویل، عکسِ اقلام، شرکتِ حمل و کدِ رهگیری با کپی دارد و بستهٔ تحویلشده «ثبتِ نظر».
*/
export default function OrderTrackingPackagesBlock() {
return (
<ControlSizeProvider size="xl" asChild>
<main className="mx-auto flex w-full max-w-3xl flex-col gap-8 p-4 sm:p-6">
<header className="flex flex-col gap-1">
<h1 className="text-2xl font-bold">سفارشِ {toFaDigits("8821042")}</h1>
<p className="text-muted-foreground">
در {toFaDigits(PACKAGES.length)} بسته ارسال میشود · {toFaDigits(PACKAGES.filter((item) => item.status === "delivered").length)} بسته تحویل شده
</p>
</header>
<ol className="flex flex-col gap-4">
{PACKAGES.map((pkg, index) => (
<li key={pkg.id} className="flex flex-col gap-4 rounded-xl border border-border bg-card p-5">
<div className="flex flex-wrap items-center justify-between gap-3">
<span className="flex flex-col">
<span className="text-sm text-muted-foreground">بستهٔ {toFaDigits(index + 1)} · {pkg.seller}</span>
<span className="font-bold">{pkg.eta}</span>
</span>
<Badge variant="soft" color={STATUS[pkg.status].color} className="gap-1 [&>svg]:size-3.5">
{STATUS[pkg.status].icon}
{STATUS[pkg.status].label}
</Badge>
</div>
<div className="flex flex-wrap items-center justify-between gap-4">
<div className="flex gap-2">
{pkg.items.map((image) => (
// eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ
<img key={image} src={stockImages[image].src} alt={stockImages[image].alt} className="size-16 rounded-lg object-cover" />
))}
</div>
{pkg.tracking ? (
<div className="flex items-center gap-2 text-sm">
<span className="text-muted-foreground">{pkg.carrier}</span>
<Button
variant="outline"
onClick={() => {
void navigator.clipboard?.writeText(pkg.tracking)
toast.success("کدِ رهگیری کپی شد.")
}}
>
<bdi dir="ltr">{pkg.tracking}</bdi>
</Button>
</div>
) : (
<span className="text-sm text-muted-foreground">کدِ رهگیری بعد از ارسال میآید.</span>
)}
</div>
{pkg.status === "delivered" && (
<Button variant="ghost" className="self-start">
ثبتِ نظر دربارهٔ این بسته
</Button>
)}
</li>
))}
</ol>
</main>
</ControlSizeProvider>
)
}