import * as React from 'react'; import { Link } from 'react-router-dom'; import { Sparkles, Inbox, FolderKanban, Bot, ScrollText } from 'lucide-react'; import { api, type Skill, type Proposal, type Project, type Agent } from '../api'; import { Card, CardContent, CardHeader, CardTitle } from '../components/ui/card'; import { Badge } from '../components/ui/badge'; /** * At-a-glance home page. Counts come from the `/api/v1/` * lists; pending proposals are highlighted with an amber badge to draw * the reviewer in. */ export function DashboardPage(): React.JSX.Element { const [counts, setCounts] = React.useState<{ skills: number; proposals: { pending: number; approved: number; rejected: number }; projects: number; agents: number; prompts: number; } | null>(null); const [error, setError] = React.useState(null); React.useEffect(() => { let cancelled = false; async function load(): Promise { try { const [skills, proposals, projects, agents, prompts] = await Promise.all([ api.get('/api/v1/skills'), api.get('/api/v1/proposals'), api.get('/api/v1/projects'), api.get('/api/v1/agents'), api.get('/api/v1/prompts'), ]); if (cancelled) return; setCounts({ skills: skills.length, proposals: { pending: proposals.filter((p) => p.status === 'pending').length, approved: proposals.filter((p) => p.status === 'approved').length, rejected: proposals.filter((p) => p.status === 'rejected').length, }, projects: projects.length, agents: agents.length, prompts: prompts.length, }); } catch (err) { if (!cancelled) setError((err as Error).message); } } void load(); return () => { cancelled = true; }; }, []); if (error !== null) return
Error: {error}
; if (counts === null) return
Loading…
; return (

Dashboard

A glance at what's in mcpd. Numbers update on page load.

{counts.proposals.pending > 0 && (
{counts.proposals.pending}{' '} pending {counts.proposals.pending === 1 ? 'proposal' : 'proposals'}
Review the queue to approve or reject incoming changes.
Review
)}
); } function CountCard({ to, icon: Icon, label, value, subtitle, }: { to: string; icon: React.ComponentType<{ className?: string }>; label: string; value: number; subtitle?: string; }): React.JSX.Element { return ( {label}
{value}
{subtitle !== undefined && (

{subtitle}

)}
); }