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

صفحهٔ برند یا فروشنده: کاورِ عکس، نشانِ برند روی لبه با تیکِ تأیید، آمار (امتیاز، کالا، دنبال‌کننده)، دنبال‌کردن، معرفیِ کوتاه و کالاهای برند با مرتب‌سازیِ سگمنت.

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

این بلاک از ۷ آیتم دیگ استفاده می‌کند: add-to-cartbuttoncontrol-sizeiconspersianproduct-cardtoggle-group

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

۲. کد صفحه

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

brand-page.tsx
"use client"

import * as React from "react"

import { CheckIcon, StarIcon } from "@/components/icons"
import { AddToCart } from "@/components/ui/add-to-cart"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { ProductCard, ProductCardBody, ProductCardFooter, ProductCardMedia, ProductCardPrice, ProductCardTitle } from "@/components/ui/product-card"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { formatCurrency, toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"

const PRODUCTS: { id: string; title: string; image: StockImageName; price: number; sold: number; isNew?: boolean }[] = [
  { id: "1", title: "گلدانِ سرامیکی دوقلو", image: "productVase", price: 1_290_000, sold: 412 },
  { id: "2", title: "ظرفِ سفالی لعاب‌مات", image: "coverMinimalRoom", price: 890_000, sold: 238, isNew: true },
  { id: "3", title: "ست فنجانِ دست‌ساز", image: "studioSunlit", price: 1_640_000, sold: 156 },
  { id: "4", title: "جاشمعی سنگی", image: "coverNotebook", price: 420_000, sold: 98, isNew: true },
]
const SORTS = [
  { value: "popular", label: "پرفروش" },
  { value: "new", label: "تازه‌ها" },
  { value: "cheap", label: "ارزان‌ترین" },
]

/**
 * صفحهٔ برند در فروشگاه: کاورِ عکس، نشانِ برند روی لبه با تیکِ تأیید، آمار (امتیاز،
 * کالا، دنبال‌کننده) و دنبال‌کردن؛ معرفی کوتاه و کالاهای برند با مرتب‌سازی سگمنت.
 */
export default function BrandPageBlock() {
  const [following, setFollowing] = React.useState(false)
  const [sort, setSort] = React.useState("popular")
  const products = [...PRODUCTS].sort((a, b) => (sort === "cheap" ? a.price - b.price : sort === "new" ? Number(Boolean(b.isNew)) - Number(Boolean(a.isNew)) : b.sold - a.sold))

  return (
    <ControlSizeProvider size="xl" asChild>
      <main className="mx-auto flex w-full max-w-6xl flex-col gap-12 px-4 py-8 sm:px-6">
        <section className="overflow-hidden rounded-xl border border-border bg-card">
          {/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
          <img src={stockImages.studioSunlit.src} alt="" className="h-48 w-full object-cover sm:h-64" />
          <div className="flex flex-col gap-6 px-6 pb-6 sm:px-8 sm:pb-8">
            <div className="flex flex-wrap items-end justify-between gap-4">
              <div className="flex items-start gap-4">
                <span className="-mt-10 flex size-20 shrink-0 items-center justify-center rounded-xl bg-[var(--dig-orange-500)] text-3xl font-black text-[var(--dig-white)] ring-4 ring-card">س</span>
                <div className="flex flex-col gap-0.5 pt-3">
                  <h1 className="flex items-center gap-2 text-2xl font-bold">
                    خانهٔ سفال
                    <span className="flex size-5 items-center justify-center rounded-full bg-[var(--dig-blue-500)] text-[var(--dig-white)] [&>svg]:size-3" aria-label="فروشندهٔ تأییدشده">
                      <CheckIcon />
                    </span>
                  </h1>
                  <span className="text-sm text-muted-foreground">سفالِ دست‌سازِ لالجین، از ۱۳۹۸</span>
                </div>
              </div>
              <Button variant={following ? "outline" : "default"} aria-pressed={following} onClick={() => setFollowing((value) => !value)}>
                {following ? "دنبال می‌کنی" : "دنبال کردن"}
              </Button>
            </div>
            <dl className="grid grid-cols-3 gap-4 rounded-lg bg-subtle p-4 text-center">
              <div className="flex flex-col gap-0.5">
                <dd className="flex items-center justify-center gap-1 text-xl font-black tabular-nums">
                  ۴٫۸
                  <StarIcon aria-hidden className="size-4 fill-[var(--dig-orange-400)] text-[var(--dig-orange-400)]" />
                </dd>
                <dt className="text-xs text-muted-foreground">از ۲٬۳۱۰ نظر</dt>
              </div>
              <div className="flex flex-col gap-0.5">
                <dd className="text-xl font-black tabular-nums">{toFaDigits(128)}</dd>
                <dt className="text-xs text-muted-foreground">کالا</dt>
              </div>
              <div className="flex flex-col gap-0.5">
                <dd className="text-xl font-black tabular-nums">{toFaDigits(following ? "18.5K" : "18.4K").replace(".", "٫")}</dd>
                <dt className="text-xs text-muted-foreground">دنبال‌کننده</dt>
              </div>
            </dl>
            <p className="max-w-3xl leading-8 text-muted-foreground">کارگاهی خانوادگی در لالجینِ همدان؛ هر تکه با دست چرخ و لعاب می‌خورد و برای همین هیچ دو گلدانی دقیقاً یکی نیستند.</p>
          </div>
        </section>

        <section aria-labelledby="brand-products" className="flex flex-col gap-8">
          <div className="flex flex-wrap items-center justify-between gap-4">
            <h2 id="brand-products" className="text-2xl font-black">
              کالاهای خانهٔ سفال
            </h2>
            <ToggleGroup type="single" variant="segmented" value={sort} onValueChange={(value) => value && setSort(value as string)} aria-label="مرتب‌سازی">
              {SORTS.map((item) => (
                <ToggleGroupItem key={item.value} value={item.value}>
                  {item.label}
                </ToggleGroupItem>
              ))}
            </ToggleGroup>
          </div>
          <div className="grid grid-cols-2 gap-4 lg:grid-cols-4">
            {products.map((product) => (
              <ProductCard key={product.id} className="w-full">
                <ProductCardMedia>
                  {/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
                  <img src={stockImages[product.image].src} alt={stockImages[product.image].alt} loading="lazy" />
                </ProductCardMedia>
                <ProductCardBody>
                  <ProductCardTitle>{product.title}</ProductCardTitle>
                  <span className="text-xs text-muted-foreground">{product.isNew ? "تازه رسیده" : `${toFaDigits(product.sold)} فروش`}</span>
                  <ProductCardPrice amount={formatCurrency(product.price)} />
                </ProductCardBody>
                <ProductCardFooter>
                  <AddToCart fullWidth label="افزودن" itemName={product.title} />
                </ProductCardFooter>
              </ProductCard>
            ))}
          </div>
        </section>
      </main>
    </ControlSizeProvider>
  )
}