خرید بدونِ ثبتنام
پیشنمایش تمامصفحهفرمِ کوتاهِ گیرنده و نشانی، «وارد شو» برای مشتریِ قبلی و ساختِ حسابِ تیکخوردنی در پایان؛ خلاصهٔ سفارش با عکس.
۱. نصب کامپوننتها
این بلاک از ۸ آیتم دیگ استفاده میکند: buttoncheckboxcontrol-sizelabellinkpersiantext-fieldtextarea
پکیجمنیجر پیشفرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیجمنیجر Bun
npx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/checkbox.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/label.json https://docs.digdesign.ir/r/link.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/textarea.jsonpnpm dlx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/checkbox.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/label.json https://docs.digdesign.ir/r/link.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/textarea.jsonyarn dlx digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/checkbox.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/label.json https://docs.digdesign.ir/r/link.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/textarea.jsonbunx --bun digdesign@latest add https://docs.digdesign.ir/r/button.json https://docs.digdesign.ir/r/checkbox.json https://docs.digdesign.ir/r/control-size.json https://docs.digdesign.ir/r/label.json https://docs.digdesign.ir/r/link.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/text-field.json https://docs.digdesign.ir/r/textarea.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
checkout-guest.tsx
"use client"
import * as React from "react"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Label } from "@/components/ui/label"
import { Link } from "@/components/ui/link"
import { TextField } from "@/components/ui/text-field"
import { Textarea } from "@/components/ui/textarea"
import { formatCurrency, isValidMobile, toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"
const ITEMS: { title: string; image: StockImageName; price: number; quantity: number }[] = [
{ title: "گلدانِ سرامیکی دوقلو", image: "productVase", price: 1_290_000, quantity: 1 },
{ title: "دفترِ یادداشتِ جلدسخت", image: "coverNotebook", price: 180_000, quantity: 2 },
]
/**
* خرید بدونِ ثبتنام: یک فرمِ کوتاه (گیرنده، موبایل، نشانی) و ساختِ حسابِ
* دلخواه با تیک در پایان؛ «ورود» برای مشتری قبلی بالای فرم. خلاصهٔ سفارش با عکس کنارِ فرم.
*/
export default function CheckoutGuestBlock() {
const [account, setAccount] = React.useState(true)
const subtotal = ITEMS.reduce((sum, item) => sum + item.price * item.quantity, 0)
return (
<ControlSizeProvider size="xl" asChild>
<main className="mx-auto grid w-full max-w-5xl grid-cols-1 items-start gap-8 p-4 sm:p-6 lg:grid-cols-[minmax(0,1fr)_20rem]">
<form className="flex flex-col gap-8 rounded-xl border border-border bg-card p-6 sm:p-8" onSubmit={(event) => event.preventDefault()}>
<div className="flex flex-wrap items-end justify-between gap-x-4 gap-y-3">
<h1 className="text-2xl font-bold">تکمیلِ خرید</h1>
<span className="text-sm text-muted-foreground">
قبلاً خرید کردهای؟ <Link href="#">وارد شو</Link>
</span>
</div>
<div className="grid grid-cols-1 gap-5 sm:grid-cols-2">
<TextField label="نامِ گیرنده" autoComplete="name" required />
<TextField label="شماره موبایل" type="tel" dir="ltr" maxLength={11} autoComplete="tel" required validate={(value) => (isValidMobile(value) ? undefined : "شماره موبایل باید با ۰۹ شروع شود و ۱۱ رقم باشد.")} />
<div className="flex flex-col gap-2 sm:col-span-2">
<Label htmlFor="cg-address">نشانی</Label>
<Textarea id="cg-address" rows={3} autoComplete="street-address" placeholder="شهر، خیابان، کوچه، پلاک، واحد" required />
</div>
<TextField label="کد پستی" dir="ltr" maxLength={10} inputMode="numeric" required />
</div>
<div className="flex items-start gap-3 rounded-lg bg-subtle p-4">
<Checkbox id="cg-account" checked={account} onCheckedChange={(checked) => setAccount(checked === true)} className="mt-0.5" />
<Label htmlFor="cg-account" className="flex flex-col items-start gap-1 font-normal">
<span className="font-medium">با همین اطلاعات حساب بساز</span>
<span className="text-sm text-muted-foreground">پیگیری سفارش و خریدِ بعدی سریعتر میشود؛ رمز لازم نیست، با کدِ پیامکی وارد میشوی.</span>
</Label>
</div>
<Button type="submit" className="mt-2">
ادامه و پرداخت
</Button>
</form>
<aside className="flex flex-col gap-4 rounded-xl bg-subtle p-6 lg:sticky lg:top-6">
<h2 className="font-bold">سفارشِ تو</h2>
<ul className="flex flex-col gap-3">
{ITEMS.map((item) => (
<li key={item.title} className="flex items-center gap-3 text-sm">
{/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
<img src={stockImages[item.image].src} alt="" className="size-12 rounded-lg object-cover" />
<span className="flex flex-1 flex-col">
<span className="font-medium">{item.title}</span>
<span className="text-muted-foreground">{toFaDigits(item.quantity)} عدد</span>
</span>
<span className="tabular-nums">{formatCurrency(item.price * item.quantity)}</span>
</li>
))}
</ul>
<div className="flex items-baseline justify-between border-t border-border pt-4">
<span className="font-semibold">جمع</span>
<span className="text-xl font-black tabular-nums">{formatCurrency(subtotal)}</span>
</div>
</aside>
</main>
</ControlSizeProvider>
)
}