بلاک‌ها · بخش‌های صفحه

خدمات با قیمتِ شروع

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

بخشِ خدمات در کارت‌های عکس‌دار با قیمتِ «از»، مدتِ تحویل، اقلامِ بسته و دکمهٔ پیش‌فاکتور؛ برای استودیو و فریلنسر.

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

این بلاک از ۵ آیتم دیگ استفاده می‌کند: buttoncontrol-sizeiconspersianreveal

پکیج‌منیجر پیش‌فرض Node.jsنصب سریع با لینک سخت و دیسک مشترکYarn نسخهٔ ۲ به بالا (Berry)رانتایم و پکیج‌منیجر Bun
npx digdesign@latest add 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/reveal.json
pnpm dlx digdesign@latest add 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/reveal.json
yarn dlx digdesign@latest add 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/reveal.json
bunx --bun digdesign@latest add 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/reveal.json

۲. کد صفحه

کد را در app/<route>/page.tsx بگذارید و متن‌ها، داده و هندلرها را با محصول خودتان عوض کنید.

services-cards.tsx
"use client"

import { CheckIcon } from "@/components/icons"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { Reveal } from "@/components/ui/reveal"
import { formatCurrency, toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"

const SERVICES: { title: string; text: string; from: number; days: number; points: string[]; photo: StockImageName }[] = [
  {
    title: "عکاسیِ محصول",
    text: "عکسِ سفید و صحنه‌پردازی‌شده برای فروشگاهِ آنلاین.",
    from: 4_500_000,
    days: 3,
    points: ["۲۰ عکسِ ویرایش‌شده", "پس‌زمینهٔ سفید و صحنه", "فایلِ مخصوصِ موبایل"],
    photo: "productVase",
  },
  {
    title: "هویتِ بصری",
    text: "نشانه، رنگ و حروف، با راهنمای استفاده.",
    from: 18_000_000,
    days: 14,
    points: ["سه پیشنهادِ اولیه", "دو دورِ بازبینی", "کتابچهٔ برند"],
    photo: "projectCafeBrand",
  },
  {
    title: "طراحیِ اپ",
    text: "از نقشهٔ صفحه تا نمونهٔ قابلِ کلیک.",
    from: 42_000_000,
    days: 30,
    points: ["پژوهشِ کاربر", "طراحیِ ۲۵ صفحه", "تحویل به تیمِ فنی"],
    photo: "projectMobileApp",
  },
]

/**
 * خدمات در کارت‌های عکس‌دار با قیمتِ شروع: عکس بالای کارت، تیتر و توضیح، قیمتِ «از» و مدتِ
 * تحویل، سه مورد از آنچه در بسته هست و دکمهٔ درخواست؛ برای استودیو و فریلنسر.
 */
export default function ServicesCardsBlock() {
  return (
    <ControlSizeProvider size="xl" asChild>
      <section aria-labelledby="sc-title" className="w-full bg-subtle py-24">
        <div className="mx-auto flex w-full max-w-6xl flex-col gap-12 px-4 sm:px-6">
          <div className="mx-auto flex max-w-2xl flex-col items-center gap-3 text-center">
            <span className="text-sm font-semibold text-brand-secondary">خدماتِ استودیو</span>
            <h2 id="sc-title" className="text-3xl leading-snug font-black text-balance sm:text-4xl">
              قیمتِ روشن، تحویلِ سرِ وقت
            </h2>
          </div>
          <ul className="grid grid-cols-1 gap-6 md:grid-cols-3">
            {SERVICES.map((service, index) => (
              <Reveal asChild key={service.title} delay={index * 100}>
                <li className="flex flex-col overflow-hidden rounded-xl bg-card shadow-sm">
                  {/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
                  <img src={stockImages[service.photo].src} alt="" className="aspect-[16/10] w-full object-cover" />
                  <div className="flex flex-1 flex-col gap-5 p-6">
                    <div className="flex flex-col gap-1.5">
                      <h3 className="text-xl font-bold">{service.title}</h3>
                      <p className="leading-7 text-muted-foreground">{service.text}</p>
                    </div>
                    <div className="flex items-baseline justify-between gap-2 border-y border-border py-4">
                      <span className="flex items-baseline gap-1.5">
                        <span className="text-sm text-muted-foreground">از</span>
                        <span className="text-xl font-black tabular-nums">{formatCurrency(service.from)}</span>
                      </span>
                      <span className="text-sm text-muted-foreground">{toFaDigits(service.days)} روزِ کاری</span>
                    </div>
                    <ul className="flex flex-col gap-2.5">
                      {service.points.map((point) => (
                        <li key={point} className="flex items-center gap-2.5 text-sm">
                          <span aria-hidden className="flex size-5 items-center justify-center rounded-full bg-success-subtle text-success">
                            <CheckIcon className="size-3.5" />
                          </span>
                          {point}
                        </li>
                      ))}
                    </ul>
                    <Button variant={index === 1 ? "default" : "outline"} className="mt-auto" fullWidth>
                      درخواستِ پیش‌فاکتور
                    </Button>
                  </div>
                </li>
              </Reveal>
            ))}
          </ul>
        </div>
      </section>
    </ControlSizeProvider>
  )
}