قیمت به ازای کاربر
پیشنمایش تمامصفحهقیمتگذاریِ وابسته به تعداد: اسلایدرِ تعدادِ کاربر، سگمنتِ ماهانه/سالانه و کارتِ تیرهٔ قیمتِ زنده با صرفهجوییِ سالانه.
۱. نصب کامپوننتها
این بلاک از ۷ آیتم دیگ استفاده میکند: badgebuttoncontrol-sizeiconspersianslidertoggle-group
پکیجمنیجر پیشفرض 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/slider.json https://docs.digdesign.ir/r/toggle-group.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/slider.json https://docs.digdesign.ir/r/toggle-group.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/slider.json https://docs.digdesign.ir/r/toggle-group.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/slider.json https://docs.digdesign.ir/r/toggle-group.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
pricing-calculator.tsx
"use client"
import * as React from "react"
import { CheckIcon } from "@/components/icons"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Slider } from "@/components/ui/slider"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { formatCurrency, toFaDigits } from "@/lib/persian"
const PER_SEAT = 95_000
const INCLUDED = ["فاکتور و گزارشِ نامحدود", "اتصال به همهٔ بانکها", "پشتیبانی آنلاین", "نسخهٔ پشتیبانِ روزانه"]
/**
* قیمتگذاری وابسته به تعداد: اسلایدرِ تعدادِ کاربر و سگمنتِ ماهانه/سالانه، و کارتِ
* تیره که قیمتِ هر ماه، تخفیفِ سالانه و جمعِ پرداخت را زنده نشان میدهد.
*/
export default function PricingCalculatorBlock() {
const [seats, setSeats] = React.useState([8])
const [period, setPeriod] = React.useState("yearly")
const yearly = period === "yearly"
const monthly = seats[0] * PER_SEAT * (yearly ? 0.8 : 1)
return (
<ControlSizeProvider size="xl" asChild>
<main className="mx-auto flex w-full max-w-5xl flex-col gap-12 px-4 py-20 sm:px-6">
<header className="mx-auto flex max-w-2xl flex-col items-center gap-3 text-center">
<h1 className="text-4xl font-black text-balance">فقط به اندازهٔ تیمت پول بده</h1>
<p className="text-lg leading-8 text-muted-foreground">هر کاربر {formatCurrency(PER_SEAT)} در ماه؛ همهٔ امکانات برای همه.</p>
</header>
<div className="grid grid-cols-1 items-stretch gap-6 md:grid-cols-[minmax(0,1.2fr)_minmax(0,1fr)]">
<section className="flex flex-col gap-10 rounded-xl border border-border bg-card p-6 sm:p-8">
<div className="flex flex-col gap-5">
<div className="flex items-baseline justify-between gap-2">
<span id="pc-seats" className="font-medium">
تعدادِ کاربر
</span>
<span className="text-3xl font-black tabular-nums">{toFaDigits(seats[0])}</span>
</div>
<Slider aria-labelledby="pc-seats" value={seats} onValueChange={setSeats} min={1} max={50} />
<div className="flex justify-between text-xs text-muted-foreground">
<span>{toFaDigits(1)}</span>
<span>{toFaDigits(50)}</span>
</div>
</div>
<div className="flex flex-col gap-3">
<span id="pc-period" className="font-medium">
دورهٔ پرداخت
</span>
<ToggleGroup type="single" variant="segmented" value={period} onValueChange={(value) => value && setPeriod(value as string)} aria-labelledby="pc-period" className="w-full">
<ToggleGroupItem value="monthly" className="flex-1">
ماهانه
</ToggleGroupItem>
<ToggleGroupItem value="yearly" className="flex-1 gap-2">
سالانه
<Badge variant="soft" color="success">
٪۲۰ کمتر
</Badge>
</ToggleGroupItem>
</ToggleGroup>
</div>
<ul className="mt-auto flex flex-col gap-3 border-t border-border pt-6 text-sm">
{INCLUDED.map((item) => (
<li key={item} className="flex items-center gap-2">
<CheckIcon aria-hidden className="size-4 text-success" />
{item}
</li>
))}
</ul>
</section>
<section aria-live="polite" className="flex flex-col gap-6 rounded-xl bg-inverse p-6 text-[var(--dig-white)] [--border:var(--inverse-border)] [--muted-foreground:var(--dig-neutral-400)] [--primary-foreground:var(--dig-graphite-950)] [--primary:var(--dig-white)] sm:p-8">
<span className="text-sm text-muted-foreground">هزینهٔ تو</span>
<div className="flex items-baseline gap-2">
<span className="text-4xl font-black tabular-nums">{formatCurrency(Math.round(monthly))}</span>
<span className="text-muted-foreground">در ماه</span>
</div>
<dl className="flex flex-col gap-3 border-t border-border pt-6 text-sm">
<div className="flex justify-between gap-2">
<dt className="text-muted-foreground">پرداختِ {yearly ? "سالانه" : "ماهانه"}</dt>
<dd className="tabular-nums">{formatCurrency(Math.round(yearly ? monthly * 12 : monthly))}</dd>
</div>
{yearly && (
<div className="flex justify-between gap-2">
<dt className="text-muted-foreground">صرفهجویی</dt>
<dd className="text-[var(--dig-green-400)] tabular-nums">{formatCurrency(Math.round(seats[0] * PER_SEAT * 12 * 0.2))}</dd>
</div>
)}
</dl>
<Button fullWidth className="mt-auto">
شروعِ ۱۴ روز رایگان
</Button>
</section>
</div>
</main>
</ControlSizeProvider>
)
}