// frontend/src/shell/WorkflowBar.tsx import { useSessionStore } from "../store/sessionStore"; import { ElapsedTimer } from "./ElapsedTimer"; // Mirror of harness/workflow.yaml phase ids/names (F1 chiarimento … F8 datamart). // Keep the two lists in lockstep: the harness is the single source of phase truth, // and a drifted label here mislabels every live session from that phase on. const PHASES = [ { id: "F1", name: "Clarification" }, { id: "F2", name: "Memory" }, { id: "F3", name: "Rewrite" }, { id: "F4", name: "Schema linking" }, { id: "F5", name: "Plan" }, { id: "F6", name: "CTE build" }, { id: "F7", name: "Final SQL" }, { id: "F8", name: "Datamart" }, ]; // Synthetic, human-readable title for the current phase, shown under the dots. // Static bilingual strings (no LLM): PHASE_LANG picks which set is displayed. // The rest of the app chrome is English, so the label follows suit. const PHASE_LANG: "en" | "it" = "en"; const PHASE_TITLES: Record = { F1: { en: "Clarifying the question", it: "Chiarimento della domanda" }, F2: { en: "Recalling relevant memory", it: "Recupero delle memorie utili" }, F3: { en: "Rewriting the question", it: "Riscrittura della domanda" }, F4: { en: "Linking the schema", it: "Collegamento dello schema" }, F5: { en: "Planning the SQL", it: "Pianificazione della query" }, F6: { en: "Building the CTEs", it: "Costruzione delle CTE" }, F7: { en: "Finalizing the SQL", it: "Finalizzazione della query" }, F8: { en: "Building the datamart", it: "Costruzione del datamart" }, }; type DotState = "done" | "running" | "error" | "pending"; // Each state is a tinted chip; red is reserved strictly for error (the GSD theme's // primary is already red), green = done, amber = the live phase, neutral = pending. const DOT: Record = { done: "bg-[oklch(var(--success)/0.16)] text-[oklch(0.5_0.13_165)] ring-[oklch(var(--success)/0.32)]", running: "bg-[oklch(var(--warning)/0.24)] text-[oklch(0.46_0.11_79)] ring-[oklch(var(--warning)/0.6)]", error: "bg-destructive/15 text-destructive ring-destructive/45", pending: "bg-transparent text-muted-foreground/70 ring-border", }; export function WorkflowBar({ finalized = false, running = false, resetKey = null, }: { finalized?: boolean; /** The harness/model is actively working (drives the processing timer). */ running?: boolean; /** Active session id — remounts the timer (resets it) when the session changes. */ resetKey?: string | null; }) { const currentPhase = useSessionStore((s) => s.currentPhase); const phaseError = useSessionStore((s) => s.phaseError); const activeIdx = PHASES.findIndex((p) => p.id === currentPhase); // On a finalized session all phases are done — surface the closing phase's title. const titleId = finalized ? "F8" : currentPhase; const phaseTitle = titleId ? PHASE_TITLES[titleId]?.[PHASE_LANG] : null; return (
{phaseTitle && ( {phaseTitle} )}
); }