"use client"; import { useMemo, useState } from "react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faBan, faCheck, faCircleInfo, faListCheck, faTriangleExclamation, faXmark, } from "@fortawesome/free-solid-svg-icons"; import type { AnalysisReport, TestResult, TestSeverity } from "../../types/analysis"; import HopChainVisualisation from "./HopChainVisualisation"; import ReportExport from "./ReportExport"; import ReportSearchBar from "./ReportSearchBar"; import SecurityAppliancesSummary from "./SecurityAppliancesSummary"; import TestResultCard from "./TestResultCard"; type SummaryItem = { label: string; value: number; testId: string; icon: typeof faCheck; iconClassName: string; }; const countBySeverity = (results: TestResult[]): Record => results.reduce( (accumulator, result) => { accumulator[result.severity] += 1; return accumulator; }, { spam: 0, suspicious: 0, clean: 0, info: 0 }, ); const filterResults = (query: string, results: TestResult[]): TestResult[] => { const normalizedQuery = query.trim().toLowerCase(); if (!normalizedQuery) { return results; } return results.filter((result) => { return ( result.testName.toLowerCase().includes(normalizedQuery) || result.headerName.toLowerCase().includes(normalizedQuery) || result.analysis.toLowerCase().includes(normalizedQuery) ); }); }; export default function ReportContainer({ report }: { report: AnalysisReport }) { const [query, setQuery] = useState(""); const severityCounts = useMemo(() => countBySeverity(report.results), [report.results]); const filteredResults = useMemo( () => filterResults(query, report.results), [query, report.results], ); const summaryItems: SummaryItem[] = [ { label: "Total Tests", value: report.metadata.totalTests, testId: "report-summary-total", icon: faListCheck, iconClassName: "text-info", }, { label: "Passed", value: report.metadata.passedTests, testId: "report-summary-passed", icon: faCheck, iconClassName: "text-clean", }, { label: "Failed", value: report.metadata.failedTests, testId: "report-summary-failed", icon: faXmark, iconClassName: "text-spam", }, { label: "Spam", value: severityCounts.spam, testId: "report-summary-severity-spam", icon: faBan, iconClassName: "text-spam", }, { label: "Suspicious", value: severityCounts.suspicious, testId: "report-summary-severity-suspicious", icon: faTriangleExclamation, iconClassName: "text-suspicious", }, { label: "Clean", value: severityCounts.clean, testId: "report-summary-severity-clean", icon: faCheck, iconClassName: "text-clean", }, { label: "Info", value: severityCounts.info, testId: "report-summary-severity-info", icon: faCircleInfo, iconClassName: "text-accent", }, ]; return (

Interactive Report

Header Analysis Summary

{report.metadata.passedTests} passed ยท {report.metadata.failedTests} failed

Summary Stats

Totals
{summaryItems.map((item) => (
{item.label}
{item.value}
))}

Test Results

Detailed analysis per header test with severity context.

{filteredResults.length} / {report.results.length}
{filteredResults.map((result) => (
))} {filteredResults.length === 0 ? (

No results match the current search.

) : null}
); }