فرصتهای شغلی
پیشنمایش تمامصفحههیرو با عکسهای تیم، مزایا با آیکون، موقعیتهای باز با فیلترِ تیم (تب) و ردیفِ کلیکپذیر با تیم و محل و نوعِ همکاری، حالتِ خالی و ارسالِ رزومهٔ آزاد.
۱. نصب کامپوننتها
این بلاک از ۸ آیتم دیگ استفاده میکند: badgebuttoncontrol-sizeempty-stateiconspersianrevealtoggle-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/empty-state.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.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/empty-state.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.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/empty-state.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.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/empty-state.json https://docs.digdesign.ir/r/icons.json https://docs.digdesign.ir/r/persian.json https://docs.digdesign.ir/r/reveal.json https://docs.digdesign.ir/r/toggle-group.json۲. کد صفحه
کد را در app/<route>/page.tsx بگذارید و متنها، داده و هندلرها را با محصول خودتان عوض کنید.
careers.tsx
"use client"
import * as React from "react"
import { ChevronLeftIcon, ClockIcon, GlobeIcon, HeartIcon, SparklesIcon, UsersIcon, WalletIcon } from "@/components/icons"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { ControlSizeProvider } from "@/components/ui/control-size"
import { EmptyState, EmptyStateDescription, EmptyStateTitle } from "@/components/ui/empty-state"
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"
import { Reveal } from "@/components/ui/reveal"
import { toFaDigits } from "@/lib/persian"
import { stockImages } from "@/lib/stock-images"
const JOBS = [
{ title: "توسعهدهندهٔ ارشدِ فرانتاند", team: "فنی", place: "تهران · هیبرید", type: "تماموقت" },
{ title: "توسعهدهندهٔ بکاند (Go)", team: "فنی", place: "دورکاری", type: "تماموقت" },
{ title: "طراحِ محصول", team: "محصول", place: "تهران", type: "تماموقت" },
{ title: "مدیرِ محصول", team: "محصول", place: "تهران · هیبرید", type: "تماموقت" },
{ title: "کارشناسِ فروشِ سازمانی", team: "فروش", place: "تهران", type: "تماموقت" },
{ title: "کارشناسِ پشتیبانی", team: "فروش", place: "دورکاری", type: "پارهوقت" },
]
const PERKS = [
{ icon: <WalletIcon />, title: "حقوقِ رقابتی", text: "بازبینی دوبار در سال و پاداشِ عملکرد" },
{ icon: <GlobeIcon />, title: "دورکاری و هیبرید", text: "هر جا بهتر کار میکنی" },
{ icon: <HeartIcon />, title: "بیمهٔ تکمیلی", text: "برای خودت و خانواده" },
{ icon: <SparklesIcon />, title: "بودجهٔ یادگیری", text: "دوره، کتاب و کنفرانس" },
]
/**
* فرصتهای شغلی: هیرو با عکسِ تیم، مزایا با آیکون، فهرستِ موقعیتها با فیلترِ تیم
* (تب) و ردیفِ کلیکپذیرِ هر موقعیت، و حالتِ «موقعیتِ مناسب نیست؟».
*/
export default function CareersBlock() {
const [team, setTeam] = React.useState("همه")
const visible = JOBS.filter((job) => team === "همه" || job.team === team)
return (
<ControlSizeProvider size="xl" asChild>
<main className="flex flex-col">
<section className="mx-auto flex w-full max-w-6xl flex-col items-center gap-10 px-4 py-16 text-center sm:px-6 lg:py-24">
<div className="flex max-w-2xl flex-col items-center gap-4">
<Badge variant="soft">فرصتهای شغلی</Badge>
<h1 className="text-4xl leading-snug font-black sm:text-5xl sm:leading-snug">بیا با هم چیزی بسازیم که آدمها هر روز استفاده کنند</h1>
<p className="text-lg leading-8 text-muted-foreground">تیمی کوچک با اثرِ بزرگ؛ {toFaDigits(JOBS.length)} موقعیتِ باز داریم.</p>
</div>
<div className="grid w-full grid-cols-3 gap-3">
{[stockImages.personWoman1, stockImages.studioSunlit, stockImages.personMan1].map((image, index) => (
// eslint-disable-next-line @next/next/no-img-element -- عکس از کتابخانهٔ تصویرِ دیگ
<img key={image.src} src={image.src} alt="" className={`w-full rounded-xl object-cover ${index === 1 ? "aspect-[4/3]" : "mt-8 aspect-[4/5]"}`} />
))}
</div>
</section>
<section aria-labelledby="careers-perks" className="bg-subtle py-20">
<div className="mx-auto flex w-full max-w-6xl flex-col gap-10 px-4 sm:px-6">
<h2 id="careers-perks" className="text-3xl font-black">
چرا اینجا؟
</h2>
<ul className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
{PERKS.map((perk, index) => (
<Reveal asChild key={perk.title} delay={index * 100}>
<li className="flex flex-col gap-3 rounded-xl border border-border bg-card p-6">
<span aria-hidden className="flex size-11 items-center justify-center rounded-xl bg-[color-mix(in_oklab,var(--brand-secondary)_12%,var(--card))] text-brand-secondary [&>svg]:size-5">
{perk.icon}
</span>
<span className="font-bold">{perk.title}</span>
<span className="text-sm text-muted-foreground">{perk.text}</span>
</li>
</Reveal>
))}
</ul>
</div>
</section>
<section aria-labelledby="careers-jobs" className="mx-auto flex w-full max-w-4xl flex-col gap-8 px-4 py-24 sm:px-6">
<div className="flex flex-wrap items-end justify-between gap-4">
<div className="flex flex-col gap-2">
<h2 id="careers-jobs" className="text-3xl font-black">
موقعیتهای باز
</h2>
<p className="text-muted-foreground">رزومه را مستقیم برای همان موقعیت بفرست.</p>
</div>
<ToggleGroup type="single" variant="segmented" value={team} onValueChange={(value) => value && setTeam(value as string)} aria-label="تیم">
{["همه", "فنی", "محصول", "فروش"].map((item) => (
<ToggleGroupItem key={item} value={item}>
{item}
</ToggleGroupItem>
))}
</ToggleGroup>
</div>
{visible.length === 0 ? (
<EmptyState variant="bordered">
<EmptyStateTitle>فعلاً موقعیتی در این تیم نیست</EmptyStateTitle>
<EmptyStateDescription>رزومهات را بفرست؛ موقعیت که باز شد خبرت میکنیم.</EmptyStateDescription>
</EmptyState>
) : (
<ul className="flex flex-col divide-y divide-border border-y border-border">
{visible.map((job) => (
<li key={job.title} className="group relative flex flex-wrap items-center gap-4 py-6">
<div className="flex min-w-0 flex-1 flex-col gap-2">
<a href="#" className="text-lg font-bold outline-none after:absolute after:inset-0 group-hover:text-brand-secondary focus-visible:after:ring-[3px] focus-visible:after:ring-ring/50">
{job.title}
</a>
<span className="flex flex-wrap items-center gap-4 text-sm text-muted-foreground">
<span className="flex items-center gap-1.5">
<UsersIcon aria-hidden className="size-4" />
{job.team}
</span>
<span className="flex items-center gap-1.5">
<GlobeIcon aria-hidden className="size-4" />
{job.place}
</span>
<span className="flex items-center gap-1.5">
<ClockIcon aria-hidden className="size-4" />
{job.type}
</span>
</span>
</div>
<span aria-hidden className="flex size-10 items-center justify-center rounded-full border border-border transition-colors group-hover:border-foreground group-hover:bg-foreground group-hover:text-background [&>svg]:size-4">
<ChevronLeftIcon />
</span>
</li>
))}
</ul>
)}
<div className="flex flex-col items-start gap-4 rounded-xl bg-muted p-6 sm:flex-row sm:items-center sm:justify-between">
<div className="flex flex-col gap-1">
<span className="font-bold">موقعیتِ مناسبت را پیدا نکردی؟</span>
<span className="text-sm text-muted-foreground">رزومهات را بفرست؛ همیشه دنبالِ آدمهای خوبیم.</span>
</div>
<Button variant="outline" className="bg-background">
ارسالِ رزومه
</Button>
</div>
</section>
</main>
</ControlSizeProvider>
)
}