"use client"; import { useCallback, useState } from "react"; import { toast } from "sonner"; import type { ProjectManifest, RunRecord, StepStatus } from "@/lib/types"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { InputsPanel } from "./inputs/inputs-panel"; import { PipelinePanel } from "./pipeline/pipeline-panel"; import { ResultsPanel } from "./qc/results-panel"; import { SpecPanel } from "./spec/spec-panel"; import { ConclusionsPanel } from "./conclusions/conclusions-panel"; import { ChatDock } from "./chat/chat-dock"; export function Workspace({ project, initialRuns, }: { project: ProjectManifest; initialRuns: RunRecord[]; }) { const [runs, setRuns] = useState(initialRuns); const [selectedRunId, setSelectedRunId] = useState( initialRuns[0]?.id ?? null, ); const [tab, setTab] = useState(initialRuns[0]?.overall ? "results" : "pipeline"); const [reloadToken, setReloadToken] = useState(0); const [specHighlight, setSpecHighlight] = useState(null); const [specToken, setSpecToken] = useState(0); const [conclusionsToken, setConclusionsToken] = useState(0); const navigateToSpec = useCallback((anchorId: string) => { setSpecHighlight(anchorId); setSpecToken((t) => t + 1); setTab("spec"); }, []); const selectedRun = runs.find((r) => r.id === selectedRunId) ?? null; const busy = runs.some( (r) => r.overallStatus === "running" || r.overallStatus === "queued", ); const refreshRuns = useCallback(async () => { const res = await fetch(`/api/projects/${project.id}/runs`, { cache: "no-store" }); if (res.ok) setRuns((await res.json()) as RunRecord[]); }, [project.id]); const startRun = useCallback( async (opts: { useLlm: boolean; fastqSource: "sim" | "control" }) => { const res = await fetch(`/api/projects/${project.id}/runs`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(opts), }); if (!res.ok) { const { error } = await res.json().catch(() => ({ error: "unknown error" })); toast.error(`Could not start run: ${error}`); return; } const { runId } = (await res.json()) as { runId: string }; setSelectedRunId(runId); setTab("pipeline"); await refreshRuns(); }, [project.id, refreshRuns], ); const onRunDone = useCallback( async (status: StepStatus) => { await refreshRuns(); setReloadToken((t) => t + 1); if (status === "succeeded") { setTab("results"); toast.success("QC run complete"); } else if (status === "failed") { toast.error("QC run failed — check the log"); } }, [refreshRuns], ); return (
Inputs Pipeline Results Spec Conclusions setConclusionsToken((t) => t + 1)} />
); }