Commit completed Torbat Pages admin frontend module, BFF proxy, routes, and validation artifacts for official platform deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
2.9 KiB
TypeScript
85 lines
2.9 KiB
TypeScript
"use client";
|
||
|
||
import { cn } from "@/lib/utils";
|
||
|
||
export type ExperienceKanbanCard = {
|
||
id: string;
|
||
title: string;
|
||
subtitle?: string;
|
||
};
|
||
|
||
export type ExperienceKanbanColumn = {
|
||
id: string;
|
||
title: string;
|
||
cards: ExperienceKanbanCard[];
|
||
};
|
||
|
||
export function ExperienceKanban({
|
||
columns,
|
||
onMove,
|
||
}: {
|
||
columns: ExperienceKanbanColumn[];
|
||
onMove?: (cardId: string, fromColumnId: string, toColumnId: string) => void;
|
||
}) {
|
||
return (
|
||
<div
|
||
className="flex gap-3 overflow-x-auto pb-2"
|
||
role="list"
|
||
aria-label="بورد کانبان"
|
||
>
|
||
{columns.map((col) => (
|
||
<section
|
||
key={col.id}
|
||
role="listitem"
|
||
aria-label={col.title}
|
||
className="min-w-[220px] flex-1 rounded-xl border border-[var(--border)] bg-[var(--surface-muted)] p-3"
|
||
>
|
||
<header className="mb-3 flex items-center justify-between">
|
||
<h3 className="text-sm font-semibold">{col.title}</h3>
|
||
<span className="rounded-full bg-[var(--experience-accent-soft)] px-2 py-0.5 text-xs text-[var(--experience-accent)]">
|
||
{col.cards.length}
|
||
</span>
|
||
</header>
|
||
<ul className="space-y-2">
|
||
{col.cards.map((card) => (
|
||
<li
|
||
key={card.id}
|
||
className={cn(
|
||
"rounded-lg border border-[var(--border)] bg-[var(--surface)] p-3 shadow-[var(--shadow-sm)]",
|
||
"transition-transform duration-150 hover:-translate-y-0.5"
|
||
)}
|
||
>
|
||
<p className="text-sm font-medium">{card.title}</p>
|
||
{card.subtitle ? (
|
||
<p className="mt-1 text-xs text-[var(--muted)]">{card.subtitle}</p>
|
||
) : null}
|
||
{onMove && columns.length > 1 ? (
|
||
<div className="mt-2 flex flex-wrap gap-1">
|
||
{columns
|
||
.filter((c) => c.id !== col.id)
|
||
.map((target) => (
|
||
<button
|
||
key={target.id}
|
||
type="button"
|
||
className="rounded-md border border-[var(--border)] px-2 py-0.5 text-[10px] hover:bg-[var(--experience-accent-soft)]"
|
||
onClick={() => onMove(card.id, col.id, target.id)}
|
||
>
|
||
→ {target.title}
|
||
</button>
|
||
))}
|
||
</div>
|
||
) : null}
|
||
</li>
|
||
))}
|
||
{col.cards.length === 0 ? (
|
||
<li className="rounded-lg border border-dashed border-[var(--border)] p-4 text-center text-xs text-[var(--muted)]">
|
||
خالی
|
||
</li>
|
||
) : null}
|
||
</ul>
|
||
</section>
|
||
))}
|
||
</div>
|
||
);
|
||
}
|