import { useCallback, useEffect, useState } from "react"; import { Link } from "react-router-dom"; import { requests as requestsApi, agents as agentsApi } from "../api/client"; import type { Agent, ChangeRequest, RequestState } from "../api/types"; import { useNotifications } from "../context/NotificationsContext"; import { Card, EmptyState, PageHeader, Spinner, textLinkClass } from "../components/ui"; import { StateBadge } from "../components/StateBadge"; import { AgentAvatar } from "../components/AgentAvatar"; import { ChevronRightIcon } from "../components/icons"; import { expiresIn, relativeTime } from "../utils"; const summaryTiles: { state: RequestState; label: string }[] = [ { state: "PENDING", label: "Pending" }, { state: "CHANGES_REQUESTED", label: "Changes requested" }, { state: "APPROVED", label: "Approved" }, { state: "CONSUMED", label: "Consumed" }, ]; export function DashboardPage() { const { requestEventTick } = useNotifications(); const [pending, setPending] = useState([]); const [counts, setCounts] = useState>({}); const [agents, setAgents] = useState([]); const [loading, setLoading] = useState(true); const load = useCallback(async () => { try { const [list, summary, agentList] = await Promise.all([ requestsApi.list({ state: "PENDING", page_size: 20 }), requestsApi.summary(), agentsApi.list(), ]); setPending(list.requests); setCounts(summary.counts); setAgents(agentList); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load, requestEventTick]); if (loading) { return (
); } return (
{summaryTiles.map((t) => (

{counts[t.state] ?? 0}

{t.label}

))}
{/* min-w-0 on both tracks: grid items default to min-width:auto, so the truncated meta lines below would otherwise widen the column past the viewport on narrow phones. */}

Awaiting review

View all →
{pending.length === 0 ? ( ) : (
{pending.map((r) => ( ))}
)}

Agents

Manage →
{agents.length === 0 ? ( ) : (
{agents.map((a) => (

{a.name}

{a.pending_count ?? 0}/{a.max_pending_requests} pending {a.disabled && · disabled}

))}
)}
); } function PendingRow({ request }: { request: ChangeRequest }) { const exp = expiresIn(request.expires_at); return (

{request.title}

{request.resubmitted && ( UPDATED )}

{request.agent?.name} · {request.changes.length} change {request.changes.length === 1 ? "" : "s"} · {relativeTime(request.created_at)}

{/* Stacked under the title on phones, where a side column would squeeze the text to a couple of words per line. */}
{exp.text}
{exp.text}
); }