import { useQuery } from "@tanstack/react-query"; import { useNavigate } from "react-router-dom"; import { Loader2, AlertCircle, TrendingUp, TrendingDown, Minus, ArrowRight, } from "lucide-react"; import { LineChart, Line, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Cell, } from "recharts"; import { getOrganizationScore, getScoreHistory } from "../api/scores"; import { getOperationalMetrics, getMetricsByTeam, } from "../api/operational-metrics"; import { getCoverageByTactic } from "../api/metrics"; import { getThreatActors } from "../api/threat-actors"; import { getTechniques, type TechniqueSummary } from "../api/techniques"; // ── Score Gauge Component ──────────────────────────────────────────── function ScoreGauge({ score, label }: { score: number; label: string }) { const getColor = (s: number) => { if (s < 30) return "#ef4444"; if (s < 50) return "#f97316"; if (s < 70) return "#eab308"; return "#22c55e"; }; const color = getColor(score); const circumference = 2 * Math.PI * 54; const strokeDasharray = `${(score / 100) * circumference} ${circumference}`; return (
{Math.round(score)} / 100
{label}
); } // ── KPI Card Component ────────────────────────────────────────────── function KPICard({ label, value, unit, trend, }: { label: string; value: string | number; unit?: string; trend?: "improving" | "declining" | "stable" | null; }) { const TrendIcon = trend === "improving" ? TrendingUp : trend === "declining" ? TrendingDown : Minus; const trendColor = trend === "improving" ? "text-green-400" : trend === "declining" ? "text-red-400" : "text-gray-500"; return (

{label}

{value === null || value === undefined ? "N/A" : value} {unit && {unit}}
{trend && ( )}
); } // ── Main Component ────────────────────────────────────────────────── export default function ExecutiveDashboardPage() { const navigate = useNavigate(); const { data: orgScore, isLoading: loadingScore } = useQuery({ queryKey: ["org-score"], queryFn: getOrganizationScore, }); const { data: scoreHistory } = useQuery({ queryKey: ["score-history", "90d"], queryFn: () => getScoreHistory("90d"), }); const { data: opMetrics, isLoading: loadingMetrics } = useQuery({ queryKey: ["operational-metrics"], queryFn: getOperationalMetrics, }); const { data: teamMetrics } = useQuery({ queryKey: ["team-metrics"], queryFn: getMetricsByTeam, }); const { data: tacticCoverage } = useQuery({ queryKey: ["tactic-coverage"], queryFn: getCoverageByTactic, }); const { data: threatActors } = useQuery({ queryKey: ["threat-actors-top"], queryFn: () => getThreatActors({ limit: 5 }), }); const { data: allTechniques } = useQuery({ queryKey: ["techniques-exec"], queryFn: () => getTechniques(), }); const isLoading = loadingScore || loadingMetrics; if (isLoading) { return (
); } // Critical gaps: not_covered or not_evaluated techniques const criticalGaps: TechniqueSummary[] = (allTechniques || []) .filter((t) => t.status_global === "not_covered" || t.status_global === "not_evaluated") .slice(0, 10); // Coverage by tactic for bar chart const tacticData = (tacticCoverage || []).map((tc) => ({ name: tc.tactic .split("-") .map((w: string) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" "), coverage: tc.total > 0 ? Math.round(((tc.validated + tc.partial) / tc.total) * 100) : 0, })); const getBarColor = (coverage: number) => { if (coverage < 30) return "#ef4444"; if (coverage < 50) return "#f97316"; if (coverage < 70) return "#eab308"; return "#22c55e"; }; return (
{/* Header */}

Executive Dashboard

Organization security posture overview

{/* Section 1: Score Card + Sub-scores */}

{orgScore?.total_coverage ?? 0}

Coverage

{orgScore?.detection_maturity ?? 0}

Detection

{orgScore?.critical_coverage ?? 0}

Critical

{orgScore?.response_readiness ?? 0}

Response

{/* Section 2: Trend Chart */}

Score Trend (90 days)

{ const d = new Date(val); return `${d.getMonth() + 1}/${d.getDate()}`; }} />
{/* Section 3: Top Threat Actors */}

Top Threat Actors

{(threatActors?.items || []).map((actor) => (
navigate(`/threat-actors/${actor.id}`)} >
{actor.country?.slice(0, 2).toUpperCase() || "??"}

{actor.name}

{actor.target_sectors?.slice(0, 3).join(", ")}

70 ? "#22c55e" : actor.coverage_pct > 40 ? "#eab308" : "#ef4444", }} />
{actor.coverage_pct}%
))}
{/* Section 4: Operational KPIs */}
{/* Section 5: Coverage by Tactic */}

Coverage by Tactic

`${v}%`} /> [`${value}%`, "Coverage"]} /> {tacticData.map((entry, index) => ( ))}
{/* Section 6: Critical Gaps */}

Critical Gaps (Top 10 Uncovered Techniques)

{criticalGaps.map((tech) => ( navigate(`/techniques/${tech.mitre_id}`)} > ))} {criticalGaps.length === 0 && ( )}
MITRE ID Name Tactic Status
{tech.mitre_id} {tech.name} {tech.tactic ?.split(",")[0] .trim() .split("-") .map((w: string) => w.charAt(0).toUpperCase() + w.slice(1)) .join(" ")} {tech.status_global?.replace(/_/g, " ")}
No critical gaps found
{/* Section 7: Team Performance */} {teamMetrics && (
{/* Red Team */}

Red Team

{teamMetrics.red_team.tests_completed}

Tests Done

{teamMetrics.red_team.avg_completion_hours ? `${teamMetrics.red_team.avg_completion_hours}h` : "N/A"}

Avg Time

{teamMetrics.red_team.rejection_rate}%

Rejection

{/* Blue Team */}

Blue Team

{teamMetrics.blue_team.tests_completed}

Tests Done

{teamMetrics.blue_team.avg_completion_hours ? `${teamMetrics.blue_team.avg_completion_hours}h` : "N/A"}

Avg Time

{teamMetrics.blue_team.rejection_rate}%

Rejection

)}
); }