import React, { useState, useEffect } from 'react'; import { useSocket } from '../contexts/SocketContext'; import MovementAlertsPanel from '../components/MovementAlertsPanel'; import api from '../services/api'; import { ServerIcon, ExclamationTriangleIcon, BellIcon, SignalIcon, EyeIcon } from '@heroicons/react/24/outline'; import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, BarChart, Bar, PieChart, Pie, Cell } from 'recharts'; import { format } from 'date-fns'; const Dashboard = () => { const [overview, setOverview] = useState(null); const [chartData, setChartData] = useState([]); const [deviceActivity, setDeviceActivity] = useState([]); const [recentActivity, setRecentActivity] = useState([]); const [loading, setLoading] = useState(true); const [showMovementAlerts, setShowMovementAlerts] = useState(true); const { recentDetections, deviceStatus, connected, movementAlerts, notificationsEnabled, toggleNotifications } = useSocket(); useEffect(() => { fetchDashboardData(); const interval = setInterval(fetchDashboardData, 30000); // Refresh every 30 seconds return () => clearInterval(interval); }, []); const fetchDashboardData = async () => { try { const [overviewRes, chartRes, deviceRes, activityRes] = await Promise.all([ api.get('/dashboard/overview?hours=24'), api.get('/dashboard/charts/detections?hours=24&interval=hour'), api.get('/dashboard/charts/devices?hours=24'), api.get('/dashboard/activity?hours=24&limit=10') ]); setOverview(overviewRes.data.data); setChartData(chartRes.data.data); setDeviceActivity(deviceRes.data.data); setRecentActivity(activityRes.data.data); } catch (error) { console.error('Error fetching dashboard data:', error); } finally { setLoading(false); } }; if (loading) { return (
); } const stats = [ { id: 1, name: 'Total Devices', stat: overview?.summary?.total_devices || 0, icon: ServerIcon, change: null, changeType: 'neutral', color: 'bg-blue-500' }, { id: 2, name: 'Online Devices', stat: overview?.summary?.online_devices || 0, icon: SignalIcon, change: null, changeType: 'positive', color: 'bg-green-500' }, { id: 3, name: 'Recent Detections', stat: overview?.summary?.recent_detections || 0, icon: ExclamationTriangleIcon, change: null, changeType: 'negative', color: 'bg-red-500' }, { id: 4, name: 'Unique Drones', stat: overview?.summary?.unique_drones_detected || 0, icon: EyeIcon, change: null, changeType: 'neutral', color: 'bg-purple-500' } ]; const deviceStatusData = [ { name: 'Online', value: overview?.device_status?.online || 0, color: '#22c55e' }, { name: 'Offline', value: overview?.device_status?.offline || 0, color: '#ef4444' }, { name: 'Inactive', value: overview?.device_status?.inactive || 0, color: '#6b7280' } ]; return (
{/* Stats */}

System Overview

{stats.map((item) => (

{item.name}

{item.stat}

))}
{/* Charts */}
{/* Detection Timeline */}

Detections Timeline (24h)

format(new Date(value), 'HH:mm')} /> format(new Date(value), 'MMM dd, HH:mm')} />
{/* Device Status */}

Device Status

{deviceStatusData.map((entry, index) => ( ))}
{deviceStatusData.map((item, index) => (
{item.name}: {item.value}
))}
{/* Device Activity */} {deviceActivity.length > 0 && (

Device Activity (24h)

)} {/* Recent Activity & Real-time Detections */}
{/* Recent Activity */}

Recent Activity

{recentActivity.map((activity, index) => (

{activity.type === 'detection' ? ( <>Drone {activity.data.drone_id} detected by {activity.data.device_name} ) : ( <>Heartbeat from {activity.data.device_name} )}

{format(new Date(activity.timestamp), 'MMM dd, HH:mm:ss')}

))} {recentActivity.length === 0 && (
No recent activity
)}
{/* Real-time Detections */}

Live Detections

{connected ? 'Live' : 'Disconnected'}
{recentDetections.map((detection, index) => (

Drone {detection.drone_id} detected

{detection.device.name || `Device ${detection.device_id}`} • RSSI: {detection.rssi}dBm • Freq: {detection.freq}MHz

{format(new Date(detection.server_timestamp), 'HH:mm:ss')}

))} {recentDetections.length === 0 && (
No recent detections
)}
{/* Movement Alerts Panel */}
{/* Movement Summary Stats */}

Movement Tracking

Critical Alerts
Very close approaches
{movementAlerts.filter(a => a.analysis.alertLevel >= 3).length}
High Priority
Approaching drones
{movementAlerts.filter(a => a.analysis.alertLevel === 2).length}
Medium Priority
Movement changes
{movementAlerts.filter(a => a.analysis.alertLevel === 1).length}
Total Tracked: {movementAlerts.length} events
Last Alert: {movementAlerts.length > 0 ? format(new Date(movementAlerts[0].timestamp), 'HH:mm:ss') : 'None' }
); }; export default Dashboard;