Initial commit - frontend

This commit is contained in:
Bailey Taylor
2025-09-19 03:26:52 +00:00
commit 27e9a08ee0
234 changed files with 32097 additions and 0 deletions

View File

@@ -0,0 +1,142 @@
'use client';
import React, { useEffect, useState } from 'react';
import { Card, CardContent, Typography, Grid, CircularProgress, Box } from '@mui/material';
import api from '@/lib/axios';
interface Stats {
total: number;
missing_title: number;
missing_severity: number;
missing_cvss_score: number;
missing_cvss_vector: number;
missing_references: number;
missing_published_date: number;
missing_description: number;
missing_cwe: number;
missing_cisa_kev: number;
missing_cert_notes: number;
missing_cert_alerts: number;
}
export default function CVEStatisticsPage() {
const [stats, setStats] = useState<Stats | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchStats = async () => {
try {
const response = await api.get('/admin/statistics');
setStats(response.data);
} catch (error) {
console.error('Failed to fetch CVE stats:', error);
} finally {
setLoading(false);
}
};
fetchStats();
}, []);
if (loading) {
return (
<Box display="flex" flexDirection="column" alignItems="center" justifyContent="center" mt={4}>
<CircularProgress sx={{ mb: 2 }} />
<Typography variant="body1">Fetching CVE statistics...</Typography>
</Box>
);
}
if (!stats) {
return <Typography variant="h6">No data available</Typography>;
}
const {
total,
missing_title,
missing_severity,
missing_cvss_score,
missing_cvss_vector,
missing_references,
missing_published_date,
missing_description,
missing_cwe,
missing_cisa_kev,
missing_cert_notes,
missing_cert_alerts,
} = stats;
const complete = (value: number) => (total > 0 ? (((total - value) / total) * 100).toFixed(2) : '0');
return (
<div className="p-6">
<Typography variant="h4" gutterBottom>
CVE Enrichment Statistics
</Typography>
<Grid container spacing={3}>
<StatCard label="Total CVEs" value={total} />
<StatCard label="Missing Title" value={missing_title} />
<StatCard label="Missing Severity" value={missing_severity} />
<StatCard label="Missing CVSS Score" value={missing_cvss_score} />
<StatCard label="Missing CVSS Vector" value={missing_cvss_vector} />
<StatCard label="Missing References" value={missing_references} />
<StatCard label="Missing Published Date" value={missing_published_date} />
<StatCard label="Missing Description" value={missing_description} />
<StatCard label="Missing CWE" value={missing_cwe} />
<StatCard label="Missing CISA KEV" value={missing_cisa_kev} />
<StatCard label="Missing CERT Notes" value={missing_cert_notes} />
<StatCard label="Missing CERT Alerts" value={missing_cert_alerts} />
</Grid>
<Typography variant="h5" gutterBottom sx={{ mt: 5 }}>
Completion Rates
</Typography>
<Grid container spacing={3}>
<StatCard label="Title Completion" value={Number(complete(missing_title))} isPercentage />
<StatCard label="Severity Completion" value={Number(complete(missing_severity))} isPercentage />
<StatCard label="CVSS Score Completion" value={Number(complete(missing_cvss_score))} isPercentage />
<StatCard label="CVSS Vector Completion" value={Number(complete(missing_cvss_vector))} isPercentage />
<StatCard label="References Completion" value={Number(complete(missing_references))} isPercentage />
<StatCard label="Published Date Completion" value={Number(complete(missing_published_date))} isPercentage />
<StatCard label="Description Completion" value={Number(complete(missing_description))} isPercentage />
<StatCard label="CWE Completion" value={Number(complete(missing_cwe))} isPercentage />
<StatCard label="CISA KEV Completion" value={Number(complete(missing_cisa_kev))} isPercentage />
<StatCard label="CERT Notes Completion" value={Number(complete(missing_cert_notes))} isPercentage />
<StatCard label="CERT Alerts Completion" value={Number(complete(missing_cert_alerts))} isPercentage />
</Grid>
</div>
);
}
interface StatCardProps {
label: string;
value: number;
isPercentage?: boolean;
}
function StatCard({ label, value, isPercentage = false }: StatCardProps) {
let color: 'error' | 'warning' | 'success' | 'textPrimary' = 'textPrimary';
if (isPercentage) {
if (value >= 90) color = 'success';
else if (value >= 70) color = 'warning';
else color = 'error';
}
return (
<Grid>
<Card sx={{ borderRadius: 2, boxShadow: 3 }}>
<CardContent>
<Typography variant="h6" gutterBottom>
{label}
</Typography>
<Typography variant="h4" color={color}>
{isPercentage ? `${value.toFixed(2)}%` : value.toLocaleString()}
</Typography>
</CardContent>
</Card>
</Grid>
);
}