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:
1 parent
c1de05a7f1
commit
b6c5b2a9ee
14 files changed
+1248
-3
No files matched your search
@@ -0,0 +1,66 @@
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
ResponsiveContainer,
|
||||
} from "recharts";
|
||||
import type { DailyRunData } from "./chart-utils";
|
||||
import { formatShortDate } from "./chart-utils";
|
||||
import { ChartTooltip } from "./ChartTooltip";
|
||||
|
||||
interface SuccessRateChartProps {
|
||||
data: DailyRunData[];
|
||||
reducedMotion: boolean;
|
||||
}
|
||||
|
||||
export function SuccessRateChart({ data, reducedMotion }: SuccessRateChartProps) {
|
||||
const rateData = useMemo(
|
||||
() =>
|
||||
data.map((d) => ({
|
||||
date: d.date,
|
||||
rate: d.total > 0 ? Math.round((d.succeeded / d.total) * 100) : 0,
|
||||
})),
|
||||
[data],
|
||||
);
|
||||
|
||||
return (
|
||||
<ResponsiveContainer width="100%" height={220}>
|
||||
<LineChart data={rateData}>
|
||||
<CartesianGrid
|
||||
strokeDasharray="3 3"
|
||||
stroke="var(--line)"
|
||||
horizontal={true}
|
||||
vertical={false}
|
||||
/>
|
||||
<XAxis
|
||||
dataKey="date"
|
||||
tickFormatter={formatShortDate}
|
||||
tick={{ fontSize: 11, fill: "var(--muted)" }}
|
||||
axisLine={{ stroke: "var(--line)" }}
|
||||
tickLine={false}
|
||||
/>
|
||||
<YAxis
|
||||
domain={[0, 100]}
|
||||
tickFormatter={(val: number) => `${val}%`}
|
||||
tick={{ fontSize: 11, fill: "var(--muted)" }}
|
||||
axisLine={false}
|
||||
tickLine={false}
|
||||
/>
|
||||
<Tooltip content={<ChartTooltip valueSuffix="%" />} />
|
||||
<Line
|
||||
type="monotone"
|
||||
dataKey="rate"
|
||||
stroke="var(--success)"
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
activeDot={{ r: 4, fill: "var(--success)" }}
|
||||
isAnimationActive={!reducedMotion}
|
||||
/>
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user