import { useState } from "react"; import type { Experiment, LiveJobState } from "../types"; import { deriveDisplayStatus, statusBadgeColor } from "../types"; function jobSummaryText(jobs: Record): string { const all = Object.values(jobs); if (all.length === 0) return ""; const running = all.filter((j) => j.status === "running").length; const blocked = all.filter((j) => j.status === "blocked").length; const completed = all.filter((j) => j.status === "completed").length; const parts: string[] = []; if (running > 0) parts.push(`${running}/${all.length} running`); if (blocked > 0) parts.push(`${blocked} blocked`); if (completed > 0 && running === 0 && blocked === 0) parts.push(`${completed} completed`); return parts.join(", "); } type SortKey = "updated" | "name" | "completeness"; interface Props { experiments: Experiment[]; onSelect: (id: string) => void; onRefresh: () => void; } export default function ExperimentList({ experiments, onSelect, onRefresh }: Props) { const [sortBy, setSortBy] = useState("updated"); const [filterFinished, setFilterFinished] = useState<"all" | "finished" | "active">("all"); const filtered = experiments.filter((e) => { if (filterFinished === "all") return true; const isFinished = !!e.zayne_findings; return filterFinished === "finished" ? isFinished : !isFinished; }); const sorted = [...filtered].sort((a, b) => { switch (sortBy) { case "updated": return (b.updated || "").localeCompare(a.updated || ""); case "name": return a.name.localeCompare(b.name); case "completeness": return (b.completeness || 0) - (a.completeness || 0); default: return 0; } }); return (
{/* Header */}

Experiments

{/* Filter */} {/* Sort */}
{/* Experiment cards */}
{sorted.length === 0 ? (

No experiments found

Try a different filter

) : (
{sorted.map((exp) => { const isFinished = !!exp.zayne_findings; return ( ); })}
)}
); }