Spaces:
Paused
Paused
| import { | |
| Rss, Activity, TrendingUp, AlertTriangle, Globe, | |
| Database, Zap, BarChart3, LineChart, Map, Target, Radar, Grid3X3 | |
| } from 'lucide-react'; | |
| interface WidgetContentProps { | |
| type: string; | |
| } | |
| // Mini widget components for dashboard | |
| const NewsWidget = () => { | |
| const news = [ | |
| { title: "Critical Zero-Day Exploit", severity: "critical", time: "2m" }, | |
| { title: "APT Group Activity Detected", severity: "high", time: "15m" }, | |
| { title: "New Ransomware Variant", severity: "high", time: "32m" }, | |
| ]; | |
| return ( | |
| <div className="space-y-2"> | |
| {news.map((item, i) => ( | |
| <div key={i} className="p-2 bg-secondary/30 border-l-2 border-primary/50 text-xs"> | |
| <span className="text-foreground">{item.title}</span> | |
| <div className="flex gap-2 mt-1 text-muted-foreground"> | |
| <span className={item.severity === 'critical' ? 'text-destructive' : 'text-orange-400'}> | |
| {item.severity} | |
| </span> | |
| <span>• {item.time}</span> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| }; | |
| const DataStreamsWidget = () => { | |
| const streams = [ | |
| { name: "Network Traffic", rate: "2.4 GB/s", ok: true }, | |
| { name: "Log Ingestion", rate: "12K/s", ok: true }, | |
| { name: "Alert Pipeline", rate: "847/min", ok: false }, | |
| ]; | |
| return ( | |
| <div className="space-y-2"> | |
| {streams.map((s, i) => ( | |
| <div key={i} className="flex justify-between items-center p-2 bg-secondary/30 text-xs"> | |
| <span className="text-foreground">{s.name}</span> | |
| <div className="flex items-center gap-2"> | |
| <span className="font-mono text-primary">{s.rate}</span> | |
| <div className={`w-2 h-2 rounded-full ${s.ok ? 'bg-green-400' : 'bg-orange-400 animate-pulse'}`} /> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| }; | |
| const MetricsWidget = () => ( | |
| <div className="grid grid-cols-2 gap-2"> | |
| {[ | |
| { label: "Threats", value: "127", change: "+12%" }, | |
| { label: "Blocked", value: "8,432", change: "+23%" }, | |
| { label: "Vulns", value: "45", change: "-8%" }, | |
| { label: "Risk", value: "72", change: "+5" }, | |
| ].map((m, i) => ( | |
| <div key={i} className="p-2 bg-secondary/30 text-center"> | |
| <div className="text-lg font-mono text-primary">{m.value}</div> | |
| <div className="text-xs text-muted-foreground">{m.label}</div> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| const AlertsWidget = () => { | |
| const alerts = [ | |
| { type: "CRITICAL", msg: "Unauthorized access attempt", time: "Now" }, | |
| { type: "WARNING", msg: "Unusual outbound traffic", time: "5m" }, | |
| ]; | |
| return ( | |
| <div className="space-y-2"> | |
| {alerts.map((a, i) => ( | |
| <div key={i} className={`p-2 border-l-2 text-xs ${ | |
| a.type === 'CRITICAL' ? 'border-destructive bg-destructive/10' : 'border-orange-400 bg-orange-400/10' | |
| }`}> | |
| <span className={a.type === 'CRITICAL' ? 'text-destructive' : 'text-orange-400'}>{a.type}</span> | |
| <span className="text-muted-foreground ml-2">{a.time}</span> | |
| <p className="text-foreground mt-1">{a.msg}</p> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| }; | |
| const GlobalWidget = () => ( | |
| <div className="space-y-2"> | |
| {[ | |
| { region: "North America", threats: 234, up: true }, | |
| { region: "Europe", threats: 189, up: false }, | |
| { region: "Asia Pacific", threats: 412, up: true }, | |
| ].map((r, i) => ( | |
| <div key={i} className="flex justify-between p-2 bg-secondary/30 text-xs"> | |
| <span className="text-foreground">{r.region}</span> | |
| <span className="text-primary"> | |
| {r.threats} {r.up ? '↑' : '↓'} | |
| </span> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| const DatabaseWidget = () => ( | |
| <div className="space-y-2"> | |
| {[ | |
| { name: "Threat Intel DB", status: "online" }, | |
| { name: "Log Archive", status: "online" }, | |
| { name: "IOC Database", status: "syncing" }, | |
| ].map((db, i) => ( | |
| <div key={i} className="flex justify-between p-2 bg-secondary/30 text-xs"> | |
| <span className="text-foreground">{db.name}</span> | |
| <span className={db.status === 'online' ? 'text-green-400' : 'text-primary'}>{db.status}</span> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| const EventsWidget = () => ( | |
| <div className="space-y-1 font-mono text-xs"> | |
| {[ | |
| { type: "AUTH", msg: "Failed login from 192.168.1.45" }, | |
| { type: "NET", msg: "Unknown IP connection" }, | |
| { type: "FILE", msg: "Suspicious file quarantined" }, | |
| ].map((e, i) => ( | |
| <div key={i} className="flex gap-2 p-1 bg-secondary/20"> | |
| <span className="text-primary">[{e.type}]</span> | |
| <span className="text-foreground truncate">{e.msg}</span> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| const StatisticsWidget = () => ( | |
| <div className="space-y-2"> | |
| {[ | |
| { label: "Malware", value: 89 }, | |
| { label: "Phishing", value: 67 }, | |
| { label: "Brute Force", value: 45 }, | |
| ].map((s, i) => ( | |
| <div key={i} className="space-y-1"> | |
| <div className="flex justify-between text-xs"> | |
| <span className="text-muted-foreground">{s.label}</span> | |
| <span className="text-foreground">{s.value}%</span> | |
| </div> | |
| <div className="h-1.5 bg-secondary rounded-full overflow-hidden"> | |
| <div className="h-full bg-primary rounded-full" style={{ width: `${s.value}%` }} /> | |
| </div> | |
| </div> | |
| ))} | |
| </div> | |
| ); | |
| const TrendsWidget = () => { | |
| const data = [20, 35, 45, 80, 65, 90, 70]; | |
| return ( | |
| <div className="h-20 flex items-end justify-between gap-1"> | |
| {data.map((v, i) => ( | |
| <div key={i} className="flex-1 bg-primary/60 hover:bg-primary rounded-t transition-colors" style={{ height: `${v}%` }} /> | |
| ))} | |
| </div> | |
| ); | |
| }; | |
| const ThreatMapWidget = () => ( | |
| <div className="aspect-video bg-secondary/30 border border-border/50 relative"> | |
| {[ | |
| { x: 20, y: 30, pulse: true }, | |
| { x: 45, y: 25, pulse: false }, | |
| { x: 70, y: 40, pulse: true }, | |
| ].map((p, i) => ( | |
| <div | |
| key={i} | |
| className={`absolute w-2 h-2 rounded-full bg-destructive ${p.pulse ? 'animate-ping' : ''}`} | |
| style={{ left: `${p.x}%`, top: `${p.y}%` }} | |
| /> | |
| ))} | |
| <div className="absolute bottom-1 right-2 text-xs text-muted-foreground">3 hotspots</div> | |
| </div> | |
| ); | |
| const TargetWidget = () => ( | |
| <div className="aspect-square max-w-24 mx-auto relative"> | |
| {[100, 75, 50, 25].map((size, i) => ( | |
| <div | |
| key={i} | |
| className="absolute rounded-full border border-destructive/30" | |
| style={{ | |
| width: `${size}%`, | |
| height: `${size}%`, | |
| left: `${(100 - size) / 2}%`, | |
| top: `${(100 - size) / 2}%`, | |
| }} | |
| /> | |
| ))} | |
| <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-2 h-2 bg-destructive rounded-full animate-pulse" /> | |
| </div> | |
| ); | |
| const RadarWidget = () => ( | |
| <div className="aspect-square max-w-24 mx-auto relative bg-secondary/30 rounded-full overflow-hidden"> | |
| {[100, 66, 33].map((size, i) => ( | |
| <div | |
| key={i} | |
| className="absolute rounded-full border border-primary/20" | |
| style={{ | |
| width: `${size}%`, | |
| height: `${size}%`, | |
| left: `${(100 - size) / 2}%`, | |
| top: `${(100 - size) / 2}%`, | |
| }} | |
| /> | |
| ))} | |
| <div | |
| className="absolute top-1/2 left-1/2 w-1/2 h-0.5 bg-gradient-to-r from-primary to-transparent origin-left animate-spin" | |
| style={{ animationDuration: '3s' }} | |
| /> | |
| <div className="absolute top-1/4 left-1/3 w-1.5 h-1.5 bg-destructive rounded-full animate-pulse" /> | |
| </div> | |
| ); | |
| const GridWidget = () => { | |
| const grid = Array.from({ length: 16 }).map(() => Math.random() > 0.75); | |
| return ( | |
| <div className="grid grid-cols-4 gap-0.5"> | |
| {grid.map((active, i) => ( | |
| <div | |
| key={i} | |
| className={`aspect-square ${active ? 'bg-destructive/60 animate-pulse' : 'bg-secondary/30'}`} | |
| /> | |
| ))} | |
| </div> | |
| ); | |
| }; | |
| const WidgetContent = ({ type }: WidgetContentProps) => { | |
| const widgets: Record<string, JSX.Element> = { | |
| news: <NewsWidget />, | |
| datastreams: <DataStreamsWidget />, | |
| metrics: <MetricsWidget />, | |
| alerts: <AlertsWidget />, | |
| global: <GlobalWidget />, | |
| database: <DatabaseWidget />, | |
| events: <EventsWidget />, | |
| statistics: <StatisticsWidget />, | |
| trends: <TrendsWidget />, | |
| threatmap: <ThreatMapWidget />, | |
| target: <TargetWidget />, | |
| radar: <RadarWidget />, | |
| grid: <GridWidget />, | |
| }; | |
| return widgets[type] || <div className="text-muted-foreground text-sm">Widget not found</div>; | |
| }; | |
| export default WidgetContent; | |