بلاک‌ها · حساب کاربری

پروفایلِ عمومی

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

پروفایلی که دیگران می‌بینند: کاور، عکس روی لبه، نام و نقش، شهر و لینک، آمار، دنبال‌کردن و پیام، و کارها یا مهارت‌ها در سگمنت.

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

این بلاک از ۷ آیتم دیگ استفاده می‌کند: avatarbadgebuttoncontrol-sizeiconspersiantoggle-group

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

۲. کد صفحه

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

profile-public.tsx
"use client"

import * as React from "react"

import { GlobeIcon, LinkIcon } from "@/components/icons"
import { Avatar } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { toFaDigits } from "@/lib/persian"
import { stockImages, type StockImageName } from "@/lib/stock-images"

const WORKS: { title: string; image: StockImageName }[] = [
  { title: "اپِ بانکی نو", image: "projectMobileApp" },
  { title: "داشبوردِ فروش", image: "projectDashboard" },
  { title: "هویتِ بصری کافه", image: "projectCafeBrand" },
]
const SKILLS = ["طراحی محصول", "تحقیقِ کاربر", "سیستمِ طراحی", "پروتوتایپ"]

/**
 * پروفایلِ عمومی (آنچه دیگران می‌بینند): کاور، عکسِ روی لبه، نام و نقش، شهر و لینک، آمار،
 * دنبال‌کردن و پیام؛ مهارت‌ها و کارها در زبانه‌های سگمنت.
 */
export default function ProfilePublicBlock() {
  const [following, setFollowing] = React.useState(false)
  const [tab, setTab] = React.useState("works")

  return (
    <ControlSizeProvider size="xl" asChild>
      <main className="mx-auto flex w-full max-w-4xl flex-col gap-8 p-4 sm:p-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-40 w-full object-cover sm:h-52" />
          <div className="flex flex-col gap-6 px-6 pb-6">
            <div className="flex flex-wrap items-start justify-between gap-4">
              <div className="flex items-start gap-4">
                <Avatar alt="" src={stockImages.personWoman2.src} className="-mt-12 size-24 shrink-0 ring-4 ring-card" />
                <div className="flex flex-col gap-0.5 pt-3">
                  <h1 className="text-2xl font-bold">سارا محمدی</h1>
                  <span className="text-muted-foreground">طراحِ محصول در آوند</span>
                </div>
              </div>
              <div className="flex gap-2 pt-3">
                <Button variant="outline">پیام</Button>
                <Button variant={following ? "outline" : "default"} aria-pressed={following} onClick={() => setFollowing((value) => !value)}>
                  {following ? "دنبال می‌کنی" : "دنبال کردن"}
                </Button>
              </div>
            </div>
            <p className="max-w-2xl leading-8 text-muted-foreground">هشت سال طراحی محصولاتِ مالی؛ عاشقِ ساده‌کردنِ چیزهایی که پیچیده به نظر می‌رسند.</p>
            <div className="flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-muted-foreground">
              <span className="flex items-center gap-1.5">
                <GlobeIcon aria-hidden className="size-4" />
                تهران
              </span>
              <a href="#" className="flex items-center gap-1.5 hover:text-foreground">
                <LinkIcon aria-hidden className="size-4" />
                <bdi dir="ltr">sara.design</bdi>
              </a>
              <span>
                <span className="font-semibold text-foreground">{toFaDigits(following ? 1241 : 1240)}</span> دنبال‌کننده
              </span>
              <span>
                <span className="font-semibold text-foreground">{toFaDigits(186)}</span> دنبال‌شده
              </span>
            </div>
          </div>
        </section>

        <ToggleGroup type="single" variant="segmented" value={tab} onValueChange={(value) => value && setTab(value as string)} aria-label="بخش" className="self-start">
          <ToggleGroupItem value="works">کارها</ToggleGroupItem>
          <ToggleGroupItem value="skills">مهارت‌ها</ToggleGroupItem>
        </ToggleGroup>

        {tab === "works" ? (
          <ul className="grid grid-cols-2 gap-3 sm:grid-cols-3 sm:gap-4">
            {WORKS.map((work) => (
              <li key={work.title} className="flex flex-col gap-3">
                {/* eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ */}
                <img src={stockImages[work.image].src} alt="" loading="lazy" className="aspect-[4/3] w-full rounded-xl object-cover" />
                <span className="font-semibold">{work.title}</span>
              </li>
            ))}
          </ul>
        ) : (
          <ul className="flex flex-wrap gap-2">
            {SKILLS.map((skill) => (
              <li key={skill}>
                <Badge variant="soft" className="px-3 py-1 text-sm">
                  {skill}
                </Badge>
              </li>
            ))}
          </ul>
        )}
      </main>
    </ControlSizeProvider>
  )
}