UI: approval detail page, agent hiring UX, costs breakdown, sidebar badges, and dashboard improvements

Add ApprovalDetail page with comment thread, revision request/resubmit flow,
and ApprovalPayload component for structured payload display. Extend AgentDetail
with permissions management, config revision history, and duplicate action.
Add agent hire dialog with permission-gated access. Rework Costs page with
per-agent breakdown table and period filtering. Add sidebar badge counts for
pending approvals and inbox items. Enhance Dashboard with live metrics and
sparkline trends. Extend Agents list with pending_approval status and bulk
actions. Update IssueDetail with approval linking. Various component improvements
to MetricCard, InlineEditor, CommentThread, and StatusBadge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Forgotten
2026-02-19 13:03:08 -06:00
parent 0d73e1b407
commit 176d279403
31 changed files with 1271 additions and 214 deletions

View File

@@ -1,29 +1,41 @@
import type { LucideIcon } from "lucide-react";
import type { ReactNode } from "react";
import { Card, CardContent } from "@/components/ui/card";
interface MetricCardProps {
icon: LucideIcon;
value: string | number;
label: string;
description?: string;
description?: ReactNode;
onClick?: () => void;
}
export function MetricCard({ icon: Icon, value, label, description }: MetricCardProps) {
export function MetricCard({ icon: Icon, value, label, description, onClick }: MetricCardProps) {
return (
<Card>
<CardContent className="p-4">
<div className="flex items-center gap-3">
<div className="bg-muted p-2">
<div className="flex gap-3">
<div className="flex-1 min-w-0">
<p
className={`text-2xl font-bold${onClick ? " cursor-pointer" : ""}`}
onClick={onClick}
>
{value}
</p>
<p
className={`text-sm text-muted-foreground${onClick ? " cursor-pointer" : ""}`}
onClick={onClick}
>
{label}
</p>
{description && (
<div className="text-xs text-muted-foreground mt-1">{description}</div>
)}
</div>
<div className="bg-muted p-2 rounded-md h-fit shrink-0">
<Icon className="h-4 w-4 text-muted-foreground" />
</div>
<div className="flex-1 min-w-0">
<p className="text-2xl font-bold">{value}</p>
<p className="text-sm text-muted-foreground">{label}</p>
</div>
</div>
{description && (
<p className="text-xs text-muted-foreground mt-2">{description}</p>
)}
</CardContent>
</Card>
);