"use client"; import { useEffect, useState } from "react"; import { Button } from "@/components/ui/button"; import { CheckCircle2, Clock, Loader2, RotateCw, XCircle } from "lucide-react"; import type { GenerateStatus } from "@/lib/api/generate"; /** * Background-run status chip for the "הפקת מסמכים" generation actions (#227 ג). * * The chip is driven entirely by the server-derived {@link GenerateStatus} — it * holds no run state of its own, so it renders correctly after the chair * navigates away and back. The running timer is anchored to the server * `started_at`, not a click-time counter, so the elapsed value is right on * return too. */ function useElapsedSeconds(startedAt: string | null, active: boolean): number | null { const [now, setNow] = useState(() => Date.now()); useEffect(() => { if (!active) return; const id = setInterval(() => setNow(Date.now()), 1_000); return () => clearInterval(id); }, [active]); if (!startedAt) return null; const start = Date.parse(startedAt); if (Number.isNaN(start)) return null; return Math.max(0, Math.floor((now - start) / 1000)); } function fmtDuration(sec: number): string { const m = Math.floor(sec / 60); const s = sec % 60; if (m >= 60) { const h = Math.floor(m / 60); return `${h}:${String(m % 60).padStart(2, "0")}:${String(s).padStart(2, "0")}`; } return `${m}:${String(s).padStart(2, "0")}`; } function relativeTime(iso: string | null): string { if (!iso) return ""; const t = Date.parse(iso); if (Number.isNaN(t)) return ""; const sec = Math.max(0, Math.floor((Date.now() - t) / 1000)); if (sec < 60) return "הרגע"; const min = Math.floor(sec / 60); if (min < 60) return `לפני ${min} דק׳`; const hr = Math.floor(min / 60); if (hr < 24) return `לפני ${hr} שע׳`; return `לפני ${Math.floor(hr / 24)} ימים`; } const CHIP_BASE = "inline-flex items-center gap-1.5 rounded-full border px-2.5 py-1 text-xs font-semibold whitespace-nowrap"; export function GenerateStatusChip({ status, onRetry, retrying, }: { status: GenerateStatus | undefined; onRetry?: () => void; retrying?: boolean; }) { const state = status?.state ?? "idle"; const elapsed = useElapsedSeconds(status?.started_at ?? null, state === "running"); if (!status || state === "idle") return null; if (state === "queued") { return ( בתור… ); } if (state === "running") { return ( רץ ברקע {elapsed !== null && ( · {fmtDuration(elapsed)} )} ); } if (state === "done") { const rel = relativeTime(status.finished_at); return ( הושלם{rel && ` · ${rel}`} ); } // failed return ( {status.detail || "נכשל"} {onRetry && ( )} ); }