// frontend/src/shell/WorkflowBar.tsx import { useSessionStore } from "../store/sessionStore"; import { ElapsedTimer } from "./ElapsedTimer"; const PHASES = [ { id: "F1", name: "Disambiguation" }, { id: "F2", name: "Schema linking" }, { id: "F3", name: "Exploration" }, { id: "F4", name: "SQL plan" }, { id: "F5", name: "SQL generation" }, { id: "F6", name: "Validation" }, { id: "F7", name: "Review" }, { id: "F8", name: "Results" }, ]; // 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: "Linking the schema", it: "Collegamento dello schema" }, F3: { en: "Exploring the data", it: "Esplorazione dei dati" }, F4: { en: "Planning the SQL", it: "Pianificazione della query" }, F5: { en: "Generating the SQL", it: "Generazione della query" }, F6: { en: "Validating the results", it: "Validazione dei risultati" }, F7: { en: "Reviewing with you", it: "Revisione con te" }, F8: { en: "Presenting results", it: "Presentazione dei risultati" }, }; 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} )}
); }