fase(11): dashboard page with charts and realtime
This commit is contained in:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user