feat(08-02): create 5 dashboard chart components with ChartSection container

- Add RunActivityChart (area chart), SuccessRateChart (line chart), CostTrendChart (area chart), AgentWorkloadChart (bar chart) using Recharts
- Add BudgetUtilization with CSS progress bars, color thresholds (success/warn/danger), and empty state
- Create ChartSection container orchestrating all charts with Framer Motion entrance animation
- Integrate ChartSection into Dashboard.tsx between MetricsGrid and NeedsAttention
- Add companyId prop to DashboardProps and pass from App.tsx
- Include Plan 01 infrastructure: chart-utils.ts, ChartCard.tsx, ChartTooltip.tsx, recharts dependency
- All charts respect reduced motion via useReducedMotion hook
- 16 unit tests pass for aggregation functions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 4.6 committed 2026-03-27 08:59:59 -04:00
1 parent c1de05a7f1
commit b6c5b2a9ee
14 files changed
+1248 -3

No files matched your search

@@ -27,9 +27,11 @@ import { MetricCard } from "./MetricsGrid";
import { ActivityFeed } from "./ActivityFeed";
import { RecoveryBanner } from "./RecoveryBanner";
import { BudgetAlertBanner } from "./BudgetAlertBanner";
import { ChartSection } from "./ChartSection";
export interface DashboardProps {
companyName?: string;
companyId?: string;
agents: AgentRecord[];
tasks: TaskRecord[];
runs: RunRecord[];
@@ -44,7 +46,7 @@ export interface DashboardProps {
export function Dashboard(props: DashboardProps) {
const t = useT();
const { companyName, agents, tasks, runs, approvals, activity, costs, messages = [], onNavigate } = props;
const { companyName, companyId, agents, tasks, runs, approvals, activity, costs, messages = [], onNavigate } = props;
const agentMap = useMemo(() => new Map(agents.map((a) => [a.id, a])), [agents]);
const taskMap = useMemo(() => new Map(tasks.map((t) => [t.id, t])), [tasks]);
@@ -131,6 +133,9 @@ export function Dashboard(props: DashboardProps) {
/>
</div>
{/* Performance Charts */}
{companyId ? <ChartSection runs={runs} costs={costs} agents={agents} companyId={companyId} /> : null}
{/* Needs Attention — moved to top, only shows when items exist */}
{hasAttentionItems ? (
<section>