Commit completed Torbat Pages admin frontend module, BFF proxy, routes, and validation artifacts for official platform deploy. Co-authored-by: Cursor <cursoragent@cursor.com>
55 lines
1.8 KiB
TypeScript
55 lines
1.8 KiB
TypeScript
"use client";
|
|
|
|
export type ExperienceTimelineItem = {
|
|
id: string;
|
|
title: string;
|
|
description?: string;
|
|
at?: string;
|
|
tone?: "default" | "success" | "warning" | "danger";
|
|
};
|
|
|
|
const toneDot: Record<NonNullable<ExperienceTimelineItem["tone"]>, string> = {
|
|
default: "bg-[var(--experience-accent)]",
|
|
success: "bg-[var(--experience-success)]",
|
|
warning: "bg-[var(--experience-warning)]",
|
|
danger: "bg-[var(--experience-danger)]",
|
|
};
|
|
|
|
export function ExperienceTimeline({
|
|
items,
|
|
emptyLabel = "رویدادی ثبت نشده",
|
|
}: {
|
|
items: ExperienceTimelineItem[];
|
|
emptyLabel?: string;
|
|
}) {
|
|
if (!items.length) {
|
|
return <p className="text-sm text-[var(--muted)]">{emptyLabel}</p>;
|
|
}
|
|
|
|
return (
|
|
<ol className="relative space-y-4 border-s border-[var(--border)] ps-6" aria-label="خط زمانی">
|
|
{items.map((item) => (
|
|
<li key={item.id} className="relative">
|
|
<span
|
|
className={`absolute -start-[1.6rem] top-1.5 h-3 w-3 rounded-full ring-4 ring-[var(--surface)] ${toneDot[item.tone ?? "default"]}`}
|
|
aria-hidden
|
|
/>
|
|
<div className="rounded-lg border border-[var(--border)] bg-[var(--surface)] p-3 transition-colors">
|
|
<div className="flex flex-wrap items-baseline justify-between gap-2">
|
|
<p className="text-sm font-semibold">{item.title}</p>
|
|
{item.at ? (
|
|
<time className="text-xs text-[var(--muted)]" dateTime={item.at}>
|
|
{new Date(item.at).toLocaleString("fa-IR")}
|
|
</time>
|
|
) : null}
|
|
</div>
|
|
{item.description ? (
|
|
<p className="mt-1 text-sm text-[var(--muted)]">{item.description}</p>
|
|
) : null}
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ol>
|
|
);
|
|
}
|