diff --git a/apps/fabro-web/app/lib/run-events.ts b/apps/fabro-web/app/lib/run-events.ts index caea81225..c06c251a0 100644 --- a/apps/fabro-web/app/lib/run-events.ts +++ b/apps/fabro-web/app/lib/run-events.ts @@ -184,4 +184,4 @@ export function useRunEvents(runId: string | undefined) { if (!runId) return; return subscribeToRunEvents(runId, mutate as MutateFn); }, [mutate, runId]); -} \ No newline at end of file +} diff --git a/apps/fabro-web/app/lib/stage-sidebar.ts b/apps/fabro-web/app/lib/stage-sidebar.ts index 1423ec2c2..8ddccb267 100644 --- a/apps/fabro-web/app/lib/stage-sidebar.ts +++ b/apps/fabro-web/app/lib/stage-sidebar.ts @@ -33,4 +33,4 @@ export function mapRunStagesToSidebarStages( ? formatDurationSecs(stage.duration_secs) : "--", })); -} \ No newline at end of file +} diff --git a/apps/fabro-web/app/lib/time.ts b/apps/fabro-web/app/lib/time.ts index 1810ce947..fb6f9b87f 100644 --- a/apps/fabro-web/app/lib/time.ts +++ b/apps/fabro-web/app/lib/time.ts @@ -9,6 +9,7 @@ export function useTickingNow(active: boolean, intervalMs = 1000): number { const [now, setNow] = useState(() => Date.now()); useEffect(() => { if (!active) return; + setNow(Date.now()); const interval = setInterval(() => setNow(Date.now()), intervalMs); return () => clearInterval(interval); }, [active, intervalMs]); diff --git a/apps/fabro-web/app/routes/run-billing.test.tsx b/apps/fabro-web/app/routes/run-billing.test.tsx index 4953b7499..c35ab52cb 100644 --- a/apps/fabro-web/app/routes/run-billing.test.tsx +++ b/apps/fabro-web/app/routes/run-billing.test.tsx @@ -98,7 +98,7 @@ describe("RunBilling", () => { expect(text).toMatch(/—\s*\/\s*—/); expect(text).toContain("1m 1s"); expect(text).not.toContain("By model"); - expect(text).not.toContain("No completed stages yet"); + expect(text).not.toContain("No stages yet"); }); test("renders mixed LLM and non-LLM rows while counting only LLM rows by model", () => { @@ -159,12 +159,12 @@ describe("RunBilling", () => { expect(textFromInstance(byModelFooterCells[1])).toBe("1"); }); - test("keeps the empty state for runs with no completed stages", () => { + test("keeps the empty state for runs with no stages", () => { const renderer = renderBilling(billing()); const text = textFromNode(renderer.toJSON()); - expect(text).toContain("No completed stages yet"); - expect(text).toContain("Stages will appear once the run produces completed nodes."); + expect(text).toContain("No stages yet"); + expect(text).toContain("Stages will appear as soon as the run starts executing."); }); test("renders an in-flight row with live runtime and includes its elapsed time in the footer", () => { @@ -199,7 +199,7 @@ describe("RunBilling", () => { const text = textFromNode(renderer.toJSON()); // Empty-state must NOT show — the table should appear as soon as the // first stage starts. - expect(text).not.toContain("No completed stages yet"); + expect(text).not.toContain("No stages yet"); expect(text).toContain("in-flight"); // Both the row's runtime cell and the footer total should reflect @@ -216,4 +216,4 @@ describe("RunBilling", () => { Date.now = originalNow; } }); -}); \ No newline at end of file +}); diff --git a/apps/fabro-web/app/routes/run-billing.tsx b/apps/fabro-web/app/routes/run-billing.tsx index 959e9ef9a..be0d52386 100644 --- a/apps/fabro-web/app/routes/run-billing.tsx +++ b/apps/fabro-web/app/routes/run-billing.tsx @@ -5,7 +5,7 @@ import { formatDurationSecs } from "../lib/format"; import { useRunBilling } from "../lib/queries"; import { IN_FLIGHT_STAGE_STATES } from "../lib/stage-sidebar"; import { useTickingNow } from "../lib/time"; -import type { RunBilling, RunBillingStage, StageState } from "@qltysh/fabro-api-client"; +import type { RunBilling, RunBillingStage } from "@qltysh/fabro-api-client"; const EMPTY_VALUE = "—"; @@ -19,7 +19,7 @@ function formatUsdMicros(usdMicros?: number | null) { } function isInFlight(stage: RunBillingStage): boolean { - return stage.state != null && IN_FLIGHT_STAGE_STATES.has(stage.state as StageState); + return stage.state != null && IN_FLIGHT_STAGE_STATES.has(stage.state); } interface MappedStageRow { @@ -113,8 +113,8 @@ export default function RunBilling({ params }: { params: { id: string } }) { return (