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,57 @@
|
||||
import type { TooltipContentProps } from "recharts";
|
||||
|
||||
interface ChartTooltipExtraProps {
|
||||
valuePrefix?: string;
|
||||
valueSuffix?: string;
|
||||
}
|
||||
|
||||
type Props = Partial<TooltipContentProps<number, string>> & ChartTooltipExtraProps;
|
||||
|
||||
export function ChartTooltip({
|
||||
active,
|
||||
payload,
|
||||
label,
|
||||
valuePrefix = "",
|
||||
valueSuffix = "",
|
||||
}: Props) {
|
||||
if (!active || !payload?.length) return null;
|
||||
|
||||
const dateStr =
|
||||
typeof label === "string"
|
||||
? new Date(label + "T00:00:00").toLocaleDateString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})
|
||||
: String(label);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="rounded-[6px] border border-[color:var(--line-strong)] bg-[color:var(--panel)] px-3 py-2 shadow-md"
|
||||
style={{ maxWidth: 200, zIndex: 50 }}
|
||||
>
|
||||
<div className="text-[11px] text-[color:var(--muted)]">{dateStr}</div>
|
||||
{payload.map((entry, i) => (
|
||||
<div key={i} className="mt-1 flex items-center gap-2">
|
||||
<span
|
||||
className="inline-block h-2 w-2 shrink-0 rounded-full"
|
||||
style={{ backgroundColor: entry.color }}
|
||||
/>
|
||||
<span
|
||||
className="text-[13px] font-semibold text-[color:var(--text)]"
|
||||
style={{
|
||||
fontFamily: "var(--font-mono)",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
{valuePrefix}
|
||||
{typeof entry.value === "number"
|
||||
? entry.value.toLocaleString()
|
||||
: entry.value}
|
||||
{valueSuffix}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user