diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index f4f6b39f..72b7f982 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -27,8 +27,7 @@ export function AppRoutes() { } /> } /> } /> - } /> - + } /> -0 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 9 } /> ) diff --git a/frontend/src/components/AppShell.tsx b/frontend/src/components/AppShell.tsx index 1c73e91b..d998d147 100644 --- a/frontend/src/components/AppShell.tsx +++ b/frontend/src/components/AppShell.tsx @@ -46,8 +46,7 @@ export default function AppShell({ children }: AppShellProps) { { to: routes.reports, icon: 'summarize', label: 'Reports' }, { to: routes.workflows, icon: 'account_tree', label: 'Workflows' }, { to: routes.toolkit, icon: 'add_circle', label: 'Toolkit' }, - ] - const mobileDrawerNav = [ + ]; const mobileDrawerNav = [ { to: routes.dashboard, label: 'Dashboard' }, { to: routes.scans, label: 'Scans' }, { to: routes.findings, label: 'Findings' }, @@ -111,22 +110,22 @@ export default function AppShell({ children }: AppShellProps) { {children} - + ) diff --git a/frontend/src/pages/Analytics.tsx b/frontend/src/pages/Analytics.tsx new file mode 100644 index 00000000..67799660 --- /dev/null +++ b/frontend/src/pages/Analytics.tsx @@ -0,0 +1,187 @@ +import { + Bar, + BarChart, + CartesianGrid, + Cell, + Line, + LineChart, + Pie, + PieChart, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis, +} from 'recharts' +import { useEffect, useMemo, useState } from 'react' + +const vulnerabilityTrend = [ + { day: 'Mon', critical: 4, high: 9, medium: 18 }, + { day: 'Tue', critical: 6, high: 12, medium: 21 }, + { day: 'Wed', critical: 3, high: 10, medium: 16 }, + { day: 'Thu', critical: 8, high: 14, medium: 24 }, + { day: 'Fri', critical: 5, high: 11, medium: 19 }, + { day: 'Sat', critical: 7, high: 13, medium: 22 }, + { day: 'Sun', critical: 4, high: 8, medium: 15 }, +] + +const severityData = [ + { name: 'Critical', value: 18 }, + { name: 'High', value: 42 }, + { name: 'Medium', value: 76 }, + { name: 'Low', value: 55 }, +] + +const targetRisk = [ + { target: 'api.secuscan.local', risk: 94 }, + { target: 'admin.panel', risk: 87 }, + { target: 'auth.gateway', risk: 72 }, + { target: 'cdn.edge', risk: 51 }, +] + +const scanStats = [ + { name: 'Success', value: 72 }, + { name: 'Failed', value: 18 }, + { name: 'Aborted', value: 10 }, +] + +const COLORS = ['#ef4444', '#f97316', '#eab308', '#22c55e'] + +function MetricCard({ label, value, detail }: { label: string; value: string; detail: string }) { + return ( +
+

{label}

+

{value}

+

{detail}

+
+ ) +} + +function ChartCard({ title, children }: { title: string; children: React.ReactNode }) { + return ( +
+

+ {title} +

+
{children}
+
+ ) +} +export default function Analytics() { + + const [timeRange, setTimeRange] = useState<'7d' | '30d' | '90d'>('7d') + const [lastUpdated, setLastUpdated] = useState(new Date()) + + useEffect(() => { + const interval = window.setInterval(() => { + setLastUpdated(new Date()) + }, 30000) + + return () => window.clearInterval(interval) + }, []) + + const filteredTrend = useMemo(() => { + if (timeRange === '7d') return vulnerabilityTrend.slice(-7) + if (timeRange === '30d') return vulnerabilityTrend + return vulnerabilityTrend + }, [timeRange]) + + return ( +
+
+
+ Analytics_Core v1.0 +
+ +

+ Security Analytics +

+ +

+ Vulnerability trends // scan statistics // target risk analysis +

+ +
+ {(['7d', '30d', '90d'] as const).map((range) => ( + + ))} +
+ +

+ Auto refresh enabled // Last updated: {lastUpdated.toLocaleTimeString()} +

+ +
+ +
+ + + + +
+ +
+ + + + + + + + + + + + + + + + + + + {severityData.map((_, index) => ( + + ))} + + + + + + + + + + + + + + + + + + + + + + + {scanStats.map((_, index) => ( + + ))} + + + + + +
+
+ ) +} \ No newline at end of file diff --git a/frontend/src/routes.ts b/frontend/src/routes.ts index 38caa98f..c929e937 100644 --- a/frontend/src/routes.ts +++ b/frontend/src/routes.ts @@ -4,6 +4,7 @@ export const routes = { scanTool: '/toolkit/:toolId', findings: '/findings', scans: '/scans', + analytics: '/analytics', reports: '/reports', workflows: '/workflows', settings: '/settings',