بلاک‌ها · پنل مدیریت

دپارتمان‌ها: کارتِ هر دپارتمان با نوارِ رنگی، مدیر با عکس، اعضای عکس‌دار با شمار و جایگاه‌های خالی.

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

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

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

۲. کد صفحه

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

team-departments.tsx
"use client"

import { PlusIcon } from "@/components/icons"
import { Avatar, AvatarGroup } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"

const DEPARTMENTS: { name: string; head: string; headPhoto: StockImageName; members: StockImageName[]; count: number; open: number; tone: string }[] = [
  { name: "محصول", head: "مهسا کریمی", headPhoto: "personWoman1", members: ["personWoman2", "personMan1", "personWoman3"], count: 8, open: 1, tone: "violet" },
  { name: "فنی", head: "امیر رضایی", headPhoto: "personMan1", members: ["personMan2", "personWoman1", "personWoman2"], count: 14, open: 3, tone: "blue" },
  { name: "فروش", head: "علی کاظمی", headPhoto: "personMan2", members: ["personWoman3", "personMan1"], count: 6, open: 0, tone: "green" },
  { name: "مالی", head: "نگار احمدی", headPhoto: "personWoman3", members: ["personWoman2"], count: 3, open: 1, tone: "orange" },
]

/**
 * ساختارِ تیم بر اساسِ دپارتمان: کارتِ هر دپارتمان با نوارِ رنگی هویت، مدیر با عکس و نقش،
 * عکسِ چند عضو و شمار، و جایگاه‌های خالی که به صفحهٔ استخدام می‌رسند.
 */
export default function TeamDepartmentsBlock() {
  const total = DEPARTMENTS.reduce((sum, item) => sum + item.count, 0)

  return (
    <ControlSizeProvider size="xl" asChild>
      <main className="mx-auto flex w-full max-w-5xl flex-col gap-8 p-4 sm:p-6">
        <header className="flex flex-wrap items-end justify-between gap-x-4 gap-y-8">
          <div className="flex flex-col gap-1">
            <h1 className="text-2xl font-bold">ساختارِ تیم</h1>
            <p className="text-muted-foreground">
              {toFaDigits(total)} نفر در {toFaDigits(DEPARTMENTS.length)} دپارتمان
            </p>
          </div>
          <Button>
            <PlusIcon />
            دپارتمانِ تازه
          </Button>
        </header>
        <ul className="grid grid-cols-1 gap-4 md:grid-cols-2">
          {DEPARTMENTS.map((department) => (
            <li key={department.name} className="flex flex-col overflow-hidden rounded-xl border border-border bg-card">
              <span aria-hidden className="h-1.5" style={{ background: `var(--dig-${department.tone}-500)` }} />
              <div className="flex flex-col gap-5 p-5">
                <div className="flex items-center justify-between gap-3">
                  <h2 className="text-lg font-bold">{department.name}</h2>
                  <span className="text-sm text-muted-foreground">{toFaDigits(department.count)} نفر</span>
                </div>
                <div className="flex items-center gap-3 rounded-lg bg-subtle p-3">
                  <Avatar alt="" src={stockImages[department.headPhoto].src} />
                  <span className="flex flex-col">
                    <span className="text-sm font-semibold">{department.head}</span>
                    <span className="text-xs text-muted-foreground">مدیرِ دپارتمان</span>
                  </span>
                </div>
                <div className="flex items-center justify-between gap-3">
                  <AvatarGroup max={3} total={department.count - 1 > 3 ? department.count - 4 : undefined}>
                    {department.members.map((photo) => (
                      <Avatar key={photo} size="sm" alt="" src={stockImages[photo].src} />
                    ))}
                  </AvatarGroup>
                  {department.open > 0 ? (
                    <a href="#" className="text-sm font-medium text-brand-secondary hover:underline">
                      {toFaDigits(department.open)} جایگاهِ خالی
                    </a>
                  ) : (
                    <span className="text-sm text-muted-foreground">تکمیل</span>
                  )}
                </div>
              </div>
            </li>
          ))}
        </ul>
      </main>
    </ControlSizeProvider>
  )
}