import { useState, useMemo } from "react"; import { useQuery } from "@tanstack/react-query"; import { useNavigate } from "react-router-dom"; import { Loader2, AlertCircle, CheckCircle, Search, ChevronUp, ChevronDown, ChevronsUpDown, ShieldCheck, Swords, } from "lucide-react"; import { getTests } from "../api/tests"; import type { Test, TestResult } from "../types/models"; /* ── Result helpers ─────────────────────────────────────────────────── */ const detectionColors: Record = { detected: "bg-green-500/10 text-green-400 border-green-500/20", partially_detected: "bg-yellow-500/10 text-yellow-400 border-yellow-500/20", not_detected: "bg-red-500/10 text-red-400 border-red-500/20", }; const detectionLabels: Record = { detected: "Detected", partially_detected: "Partial", not_detected: "Not Detected", }; function DetectionBadge({ result }: { result: TestResult | null | undefined }) { if (!result) return ; return ( {detectionLabels[result]} ); } function AttackBadge({ success }: { success: boolean | null | undefined }) { if (success === null || success === undefined) return ; return ( {success ? "Success" : "Blocked"} ); } /* ── Component ──────────────────────────────────────────────────────── */ export default function ValidatedTestsPage() { const navigate = useNavigate(); const [searchText, setSearchText] = useState(""); type SortKey = | "name" | "technique" | "platform" | "attack_success" | "detection_result" | "created_at" | "updated_at"; const [sortKey, setSortKey] = useState("updated_at"); const [sortDir, setSortDir] = useState<"asc" | "desc">("desc"); const handleSort = (key: SortKey) => { if (sortKey === key) { setSortDir((d) => (d === "asc" ? "desc" : "asc")); } else { setSortKey(key); setSortDir("desc"); } }; const { data: validatedTests, isLoading, error } = useQuery({ queryKey: ["tests", "validated"], queryFn: () => getTests({ state: "validated", limit: 200 }), }); const formatDate = (dateStr: string | null | undefined) => { if (!dateStr) return "—"; const utc = dateStr.endsWith("Z") || dateStr.includes("+") ? dateStr : dateStr + "Z"; return new Date(utc).toLocaleDateString("es-ES", { year: "numeric", month: "short", day: "numeric", }); }; const tests = useMemo(() => { if (!validatedTests) return []; let list = validatedTests; if (searchText.trim()) { const q = searchText.toLowerCase(); list = list.filter( (t) => t.name.toLowerCase().includes(q) || (t.technique_mitre_id && t.technique_mitre_id.toLowerCase().includes(q)) || (t.technique_name && t.technique_name.toLowerCase().includes(q)) ); } return [...list].sort((a, b) => { let av = ""; let bv = ""; switch (sortKey) { case "name": av = a.name.toLowerCase(); bv = b.name.toLowerCase(); break; case "technique": av = (a.technique_mitre_id || "").toLowerCase(); bv = (b.technique_mitre_id || "").toLowerCase(); break; case "platform": av = (a.platform || "").toLowerCase(); bv = (b.platform || "").toLowerCase(); break; case "attack_success": av = String(a.attack_success ?? ""); bv = String(b.attack_success ?? ""); break; case "detection_result": av = a.detection_result ?? ""; bv = b.detection_result ?? ""; break; case "created_at": av = a.created_at || ""; bv = b.created_at || ""; break; case "updated_at": av = a.updated_at || ""; bv = b.updated_at || ""; break; } const cmp = av < bv ? -1 : av > bv ? 1 : 0; return sortDir === "asc" ? cmp : -cmp; }); }, [validatedTests, searchText, sortKey, sortDir]); const SortIcon = ({ col }: { col: SortKey }) => sortKey === col ? ( sortDir === "asc" ? ( ) : ( ) ) : ( ); if (isLoading) { return (
); } if (error) { return (

Failed to load validated tests

); } const columns: { key: SortKey; label: string }[] = [ { key: "name", label: "Name" }, { key: "technique", label: "Technique" }, { key: "platform", label: "Platform" }, { key: "attack_success", label: "Attack" }, { key: "detection_result", label: "Detection" }, { key: "created_at", label: "Created" }, { key: "updated_at", label: "Validated" }, ]; return (
{/* Header */}

Validated Tests

Tests that have completed the full Red/Blue validation workflow

{validatedTests?.length ?? 0} validated
{/* Search */}
setSearchText(e.target.value)} placeholder="Search by name or technique…" className="w-full rounded-lg border border-gray-700 bg-gray-900 pl-9 pr-3 py-2 text-sm text-gray-300 placeholder-gray-500 focus:border-green-500 focus:outline-none" />
{/* Table */}
{columns.map(({ key, label }) => ( ))} {tests.map((test: Test) => ( navigate(`/tests/${test.id}`)} > ))}
handleSort(key)} > {label} Action
{test.name} {test.technique_mitre_id ? (
{test.technique_mitre_id} {test.technique_name}
) : ( )}
{test.platform || "—"} {formatDate(test.created_at)} {formatDate(test.updated_at)}
{tests.length === 0 && (
{searchText ? "No validated tests match your search." : "No validated tests yet."}
)}
); }