fase(11): dashboard page with charts and realtime

This commit is contained in:
debian
2026-03-05 10:30:16 -05:00
parent 5ef4ce5de0
commit 458302ca86
16 changed files with 964 additions and 52 deletions

View File

@@ -1,8 +1,64 @@
import { useCallback } from 'react'
import { useQueryClient } from '@tanstack/react-query'
import { KPICards } from '@/components/dashboard/KPICards'
import { TrendChart } from '@/components/dashboard/TrendChart'
import { SeverityDistribution } from '@/components/dashboard/SeverityDistribution'
import { RecentFindings } from '@/components/dashboard/RecentFindings'
import { ActiveSessions } from '@/components/dashboard/ActiveSessions'
import { QuickActions } from '@/components/dashboard/QuickActions'
import { useFindings, useFindingStats } from '@/hooks/useFindings'
import { useSessions } from '@/hooks/useSessions'
import { useSocket } from '@/hooks/useSocket'
export function Dashboard() {
const queryClient = useQueryClient()
const { data: findings = [], isLoading: findingsLoading } = useFindings()
const { data: stats, isLoading: statsLoading } = useFindingStats()
const { data: sessions = [] } = useSessions()
const refreshData = useCallback(() => {
void queryClient.invalidateQueries({ queryKey: ['findings'] })
void queryClient.invalidateQueries({ queryKey: ['sessions'] })
}, [queryClient])
useSocket(useCallback((event: string) => {
if (['session:started', 'session:completed', 'session:error', 'anomaly:detected'].includes(event)) {
refreshData()
}
}, [refreshData]))
return (
<div className="flex flex-col items-center justify-center h-full min-h-[60vh] text-center">
<h1 className="text-3xl font-bold mb-2">Dashboard</h1>
<p className="text-muted-foreground">Coming in Phase 11 charts and real-time KPIs</p>
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold">Dashboard</h1>
<p className="text-sm text-muted-foreground">Overview of your security findings</p>
</div>
<QuickActions />
</div>
<KPICards stats={stats} isLoading={statsLoading} />
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">
<TrendChart findings={findings} />
</div>
<SeverityDistribution findings={findings} />
</div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-2">
<RecentFindings findings={findings.slice().sort((a, b) => b.timestamp - a.timestamp)} />
</div>
<ActiveSessions sessions={sessions} />
</div>
{findingsLoading && (
<div className="text-center text-sm text-muted-foreground py-4">
Loading findings...
</div>
)}
</div>
)
}