import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "../../components/ui/card"; import { Skeleton } from "../../components/ui/skeleton"; import { api } from "../../lib/api"; interface TasksByStatus { todo: number; in_progress: number; in_review: number; done: number; cancelled: number; } interface AdminStats { users: { total: number; recent: number }; agents: { total: number; online: number }; machines: { total: number; online: number }; tasks: TasksByStatus; boards: { total: number }; runtime_sessions: { total: number; active: number }; } const STATUS_BAR_CLASS: Record = { todo: "bg-zinc-500", in_progress: "bg-accent", in_review: "bg-warning", done: "bg-success", cancelled: "bg-zinc-700", }; const STATUS_LABELS: Record = { todo: "Todo", in_progress: "In Progress", in_review: "In Review", done: "Done", cancelled: "Cancelled", }; function StatCard({ label, value, subtitle }: { label: string; value: number; subtitle: string }) { return ( {label}

{value}

{subtitle &&

{subtitle}

}
); } function StatCardSkeleton() { return ( ); } type StatusKey = keyof TasksByStatus; function TaskStatusBar({ byStatus }: { byStatus: TasksByStatus }) { const statuses: StatusKey[] = ["todo", "in_progress", "in_review", "done", "cancelled"]; const total = statuses.reduce((sum, s) => sum + (byStatus[s] || 0), 0); if (total === 0) return null; return (

Task Status Breakdown

{statuses.map((status) => { const count = byStatus[status] || 0; if (count === 0) return null; const pct = (count / total) * 100; return
; })}
{statuses.map((status) => { const count = byStatus[status] || 0; return (
{STATUS_LABELS[status]} {count}
); })}
); } export function AdminDashboardPage() { const [stats, setStats] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { api.admin .getStats() .then(setStats) .finally(() => setLoading(false)); }, []); const tasksByStatus: TasksByStatus = stats?.tasks ?? { todo: 0, in_progress: 0, in_review: 0, done: 0, cancelled: 0 }; const taskTotal = Object.values(tasksByStatus).reduce((sum, n) => sum + n, 0); const activeTaskCount = (tasksByStatus.in_progress || 0) + (tasksByStatus.in_review || 0); return (

Dashboard

{loading ? (
{[0, 1, 2, 3, 4, 5].map((i) => ( ))}
) : stats ? ( <>
) : (

Failed to load stats.

)}
); }