Commit completed Torbat Pages admin frontend module, BFF proxy, routes, and validation artifacts for official platform deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
216 lines
7.6 KiB
TypeScript
216 lines
7.6 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { PageHeader, Card, CardContent, Button, Badge } from "@/components/ds";
|
||
import { ExperienceBreadcrumbs } from "@/modules/experience/components/ExperienceBreadcrumbs";
|
||
import {
|
||
ExperienceChart,
|
||
ExperienceEmptyState,
|
||
ExperienceKanban,
|
||
ExperienceMap,
|
||
ExperienceSkeleton,
|
||
ExperienceStatusChip,
|
||
ExperienceStatGrid,
|
||
ExperienceTablePage,
|
||
ExperienceThemeProvider,
|
||
ExperienceTimeline,
|
||
ExperienceFadeUp,
|
||
ExperienceFadeIn,
|
||
experienceTokens,
|
||
} from "@/modules/experience/design-system";
|
||
|
||
const demoChart = [
|
||
{ name: "فضاها", value: 3 },
|
||
{ name: "سایت", value: 5 },
|
||
{ name: "صفحات", value: 12 },
|
||
{ name: "فرم", value: 4 },
|
||
];
|
||
|
||
export function DesignSystemPlaygroundPage() {
|
||
const [dir, setDir] = useState<"rtl" | "ltr">("rtl");
|
||
const [brandAccent, setBrandAccent] = useState("#0891b2");
|
||
const [kanban, setKanban] = useState([
|
||
{
|
||
id: "draft",
|
||
title: "پیشنویس",
|
||
cards: [
|
||
{ id: "c1", title: "صفحه خانه", subtitle: "workspace-a" },
|
||
{ id: "c2", title: "فرم تماس", subtitle: "forms" },
|
||
],
|
||
},
|
||
{
|
||
id: "review",
|
||
title: "بازبینی",
|
||
cards: [{ id: "c3", title: "قالب رویداد", subtitle: "templates" }],
|
||
},
|
||
{
|
||
id: "live",
|
||
title: "منتشر",
|
||
cards: [{ id: "c4", title: "سایت اصلی", subtitle: "sites" }],
|
||
},
|
||
]);
|
||
|
||
return (
|
||
<ExperienceThemeProvider
|
||
direction={dir}
|
||
brand={{ accent: brandAccent, accentSoft: `${brandAccent}22` }}
|
||
tenantThemeId="playground"
|
||
>
|
||
<ExperienceFadeUp className="space-y-6">
|
||
<ExperienceBreadcrumbs current="سیستم طراحی" />
|
||
<PageHeader
|
||
title="زمین بازی سیستم طراحی"
|
||
description="کامپوننتهای مستقل Experience — تم روشن/تیره از هدر، برند و جهت از این صفحه."
|
||
actions={
|
||
<div className="flex flex-wrap gap-2">
|
||
<Button
|
||
variant="outline"
|
||
size="sm"
|
||
onClick={() => setDir((d) => (d === "rtl" ? "ltr" : "rtl"))}
|
||
>
|
||
جهت: {dir.toUpperCase()}
|
||
</Button>
|
||
<label className="flex items-center gap-2 text-sm">
|
||
برند
|
||
<input
|
||
type="color"
|
||
value={brandAccent}
|
||
onChange={(e) => setBrandAccent(e.target.value)}
|
||
aria-label="رنگ برند"
|
||
className="h-8 w-10 cursor-pointer rounded border border-[var(--border)]"
|
||
/>
|
||
</label>
|
||
</div>
|
||
}
|
||
/>
|
||
|
||
<Card>
|
||
<CardContent className="space-y-3 p-4">
|
||
<h2 className="text-sm font-semibold">توکنها</h2>
|
||
<div className="flex flex-wrap gap-2">
|
||
{Object.entries(experienceTokens).map(([k, v]) => (
|
||
<Badge key={k} tone="default">
|
||
{k}: {v}
|
||
</Badge>
|
||
))}
|
||
<ExperienceStatusChip status="published" />
|
||
<ExperienceStatusChip status="draft" />
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<ExperienceStatGrid
|
||
stats={[
|
||
{ label: "فضاهای کاری", value: "3" },
|
||
{ label: "سایتها", value: "5" },
|
||
{ label: "صفحات", value: "12" },
|
||
{ label: "انتشار", value: "2" },
|
||
]}
|
||
/>
|
||
|
||
<div className="grid gap-4 lg:grid-cols-2">
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h2 className="mb-3 text-sm font-semibold">نمودار</h2>
|
||
<ExperienceChart data={demoChart} ariaLabel="نمودار نمونه منابع" />
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h2 className="mb-3 text-sm font-semibold">نقشه</h2>
|
||
<ExperienceMap
|
||
title="نقشه نمونه تربت"
|
||
markers={[
|
||
{ id: "1", label: "مرکز", lat: 35.25, lng: 59.22 },
|
||
{ id: "2", label: "شعبه", lat: 35.27, lng: 59.25 },
|
||
]}
|
||
/>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h2 className="mb-3 text-sm font-semibold">خط زمانی</h2>
|
||
<ExperienceTimeline
|
||
items={[
|
||
{
|
||
id: "t1",
|
||
title: "ایجاد فضای کاری",
|
||
description: "از API workspaces",
|
||
at: new Date().toISOString(),
|
||
tone: "success",
|
||
},
|
||
{
|
||
id: "t2",
|
||
title: "انتشار پیشنویس",
|
||
description: "publish-releases",
|
||
at: new Date(Date.now() - 3600_000).toISOString(),
|
||
tone: "warning",
|
||
},
|
||
]}
|
||
/>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h2 className="mb-3 text-sm font-semibold">کانبان</h2>
|
||
<ExperienceKanban
|
||
columns={kanban}
|
||
onMove={(cardId, fromId, toId) => {
|
||
setKanban((cols) => {
|
||
const next = cols.map((c) => ({ ...c, cards: [...c.cards] }));
|
||
const from = next.find((c) => c.id === fromId);
|
||
const to = next.find((c) => c.id === toId);
|
||
if (!from || !to) return cols;
|
||
const idx = from.cards.findIndex((c) => c.id === cardId);
|
||
if (idx < 0) return cols;
|
||
const [card] = from.cards.splice(idx, 1);
|
||
to.cards.push(card);
|
||
return next;
|
||
});
|
||
}}
|
||
/>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
<div className="grid gap-4 lg:grid-cols-2">
|
||
<Card>
|
||
<CardContent className="p-4">
|
||
<h2 className="mb-3 text-sm font-semibold">جدول</h2>
|
||
<ExperienceTablePage
|
||
title="نمونه جدول"
|
||
rows={[
|
||
{ id: "1", name: "سایت اصلی", status: "published" },
|
||
{ id: "2", name: "لندینگ", status: "draft" },
|
||
]}
|
||
columns={[
|
||
{ key: "name", header: "نام" },
|
||
{
|
||
key: "status",
|
||
header: "وضعیت",
|
||
render: (row) => <ExperienceStatusChip status={String(row.status)} />,
|
||
},
|
||
]}
|
||
/>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="space-y-4 p-4">
|
||
<h2 className="text-sm font-semibold">Empty / Skeleton / Motion</h2>
|
||
<ExperienceEmptyState title="نمونه Empty" description="برای لیستهای خالی API." />
|
||
<ExperienceSkeleton rows={3} />
|
||
<ExperienceFadeIn>
|
||
<p className="text-sm text-[var(--muted)]">انیمیشن FadeIn فعال است.</p>
|
||
</ExperienceFadeIn>
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
</ExperienceFadeUp>
|
||
</ExperienceThemeProvider>
|
||
);
|
||
}
|
||
|
||
export default DesignSystemPlaygroundPage;
|