diff --git a/apps/web/src/components/pipeline/PipelineTab.tsx b/apps/web/src/components/pipeline/PipelineTab.tsx index 25fd4ff..3f873d7 100644 --- a/apps/web/src/components/pipeline/PipelineTab.tsx +++ b/apps/web/src/components/pipeline/PipelineTab.tsx @@ -1,6 +1,7 @@ import { useEffect, useMemo } from "react"; -import { Loader2, Play } from "lucide-react"; +import { CheckCircle2, CircleDashed, Loader2, Play } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; import { trpc } from "@/lib/trpc"; import { groupPhasesByDependencyLevel, @@ -196,10 +197,49 @@ function PipelineTabInner({ initiativeId, phases, phasesLoading }: PipelineTabPr ); } + const totalTasks = displayTasks.length; + const completedTasks = displayTasks.filter((t) => t.status === "completed").length; + const runningPhases = phases.filter((p) => p.status === "in_progress").length; + const completedPhases = phases.filter((p) => p.status === "completed").length; + const isMutating = approvePhase.isPending || queueAll.isPending; + return ( -
- {actionableCount > 0 && ( -
+
+ {/* Pipeline summary bar */} +
+ {/* Stats */} +
+ + {phases.length} phase{phases.length === 1 ? "" : "s"} + + + {totalTasks} task{totalTasks === 1 ? "" : "s"} + + {runningPhases > 0 && ( + + + {runningPhases} running + + )} + {completedPhases > 0 && ( + + + {completedPhases}/{phases.length} done + + )} + {completedPhases === 0 && runningPhases === 0 && actionableCount > 0 && ( + + + Ready + + )} +
+ + {/* Execute action */} + {actionableCount > 0 && ( -
- )} + )} +
+