بلاک‌ها · فروشگاهی

پیگیریِ چندمرسوله‌ای

پیش‌نمایش تمام‌صفحه

سفارشِ چندبسته‌ای از چند فروشنده: هر بسته وضعیت، زمانِ تحویل، عکسِ اقلام، شرکتِ حمل و کدِ رهگیری با کپی و ثبتِ نظر برای تحویل‌شده.

۱. نصب کامپوننت‌ها

این بلاک از ۶ آیتم دیگ استفاده می‌کند: 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.json
pnpm 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.json
yarn 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.json
bunx --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>
  )
}