feat(snapshots): evolution API, tactic breakdown and dashboard trend chart [FASE-5.2]
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled

This commit is contained in:
2026-05-18 15:07:12 +02:00
parent 05b221a22d
commit 1249391ef0
2 changed files with 106 additions and 0 deletions

View File

@@ -16,6 +16,16 @@ import {
TrendingUp,
ArrowRight,
} from "lucide-react";
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
Legend,
} from "recharts";
import {
getCoverageSummary,
getCoverageByTactic,
@@ -28,6 +38,7 @@ import {
type ValidationRateItem,
type RecentTestItem,
} from "../api/metrics";
import { getCoverageEvolution } from "../api/snapshots";
import CoverageSummaryCard from "../components/CoverageSummaryCard";
import TacticCoverageChart from "../components/TacticCoverageChart";
import type { TestState } from "../types/models";
@@ -97,6 +108,11 @@ export default function DashboardPage() {
queryFn: getRecentTests,
});
const { data: coverageEvolution, isLoading: evolutionLoading } = useQuery({
queryKey: ["snapshots", "evolution", 6],
queryFn: () => getCoverageEvolution(6),
});
if (summaryLoading || tacticsLoading) {
return (
<div className="flex h-64 items-center justify-center">
@@ -191,6 +207,67 @@ export default function DashboardPage() {
</div>
)}
{/* Coverage evolution (snapshots) */}
<div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
<h2 className="mb-4 text-lg font-semibold text-white flex items-center gap-2">
<TrendingUp className="h-5 w-5 text-cyan-400" />
Coverage Evolution (6 months)
</h2>
{evolutionLoading ? (
<div className="flex h-48 items-center justify-center">
<Loader2 className="h-6 w-6 animate-spin text-cyan-400" />
</div>
) : coverageEvolution && coverageEvolution.length > 0 ? (
<ResponsiveContainer width="100%" height={240}>
<LineChart data={coverageEvolution}>
<CartesianGrid strokeDasharray="3 3" stroke="#1f2937" />
<XAxis
dataKey="date"
tick={{ fill: "#6b7280", fontSize: 10 }}
tickFormatter={(val) => {
const d = new Date(val);
return `${d.getMonth() + 1}/${d.getDate()}`;
}}
/>
<YAxis
domain={[0, 100]}
tick={{ fill: "#6b7280", fontSize: 10 }}
/>
<Tooltip
contentStyle={{
backgroundColor: "#111827",
border: "1px solid #374151",
borderRadius: "8px",
fontSize: "12px",
}}
labelStyle={{ color: "#9ca3af" }}
/>
<Legend />
<Line
type="monotone"
dataKey="org_score"
stroke="#06b6d4"
strokeWidth={2}
dot={{ r: 3 }}
name="Org score"
/>
<Line
type="monotone"
dataKey="coverage_pct"
stroke="#22c55e"
strokeWidth={2}
dot={{ r: 3 }}
name="Coverage %"
/>
</LineChart>
</ResponsiveContainer>
) : (
<p className="text-sm text-gray-500 py-8 text-center">
No snapshots yet. Weekly snapshots populate this chart automatically.
</p>
)}
</div>
{/* ── V2 Section: Test Pipeline ────────────────────────────────── */}
<div className="rounded-xl border border-gray-800 bg-gray-900 p-6">
<div className="mb-4 flex items-center justify-between">