import React, { useState } from 'react'; import './index.css'; import MapComponent from './MapComponent'; import UserManagement from './UserManagement'; import ESGDashboard from './ESGDashboard'; import VerificationQueue from './VerificationQueue'; import Registration from './Registration'; import IncidentQueue from './IncidentQueue'; import TripsDashboard from './TripsDashboard'; import Settings from './Settings'; import UserPortal from './UserPortal'; import PassengerDashboard from './PassengerDashboard'; import PoolHostDashboard from './PoolHostDashboard'; import AppLayout from './AppLayout'; import { io } from 'socket.io-client'; // Live data will be fetched inside the App component. function App() { const [session, setSession] = useState(() => { const saved = localStorage.getItem('carpool_session'); return saved ? JSON.parse(saved) : null; }); const [activeTab, setActiveTab] = useState('Overview'); const [toasts, setToasts] = useState([]); const [autoSelectPending, setAutoSelectPending] = useState(false); const [selectedCity, setSelectedCity] = useState('all'); const [showAdminProfile, setShowAdminProfile] = useState(false); const [showRegistration, setShowRegistration] = useState(false); // Register without logging in const [dashboardData, setDashboardData] = useState({ users: [], trips: [], incidents: [] }); React.useEffect(() => { if (!session) return; const socket = io(``); if (session.role === 'Admin') { socket.emit('join_admin'); socket.on('sos_alert', (data) => { showToast(data.message, 'danger'); }); } else { socket.emit('join', session.id); socket.on('ride_requested', (data) => showToast(data.message, 'info')); socket.on('ride_accepted', (data) => showToast(data.message, 'success')); socket.on('ride_rejected', (data) => showToast(data.message, 'warning')); socket.on('location_update', (data) => { window.dispatchEvent(new CustomEvent('live_location', { detail: data })); }); socket.on('ride_completed', () => { window.dispatchEvent(new CustomEvent('ride_completed')); }); } return () => socket.disconnect(); }, [session]); React.useEffect(() => { if (session && session.role === 'Admin' && activeTab === 'Overview') { const fetchAdminData = async () => { try { const token = session.token || localStorage.getItem('token'); const headers = { 'Authorization': `Bearer ${token}` }; const [usersRes, tripsRes, incidentsRes] = await Promise.all([ fetch(`/api/users`, { headers }), fetch(`/api/trips`, { headers }), fetch(`/api/incidents`, { headers }) ]); if (usersRes.ok && tripsRes.ok && incidentsRes.ok) { setDashboardData({ users: await usersRes.json(), trips: await tripsRes.json(), incidents: await incidentsRes.json() }); } } catch (err) { console.error("Failed to fetch admin data", err); } }; fetchAdminData(); } }, [session, activeTab]); const activeTripsCount = dashboardData.trips.filter(t => t.status === 'Scheduled').length; const totalUsersCount = dashboardData.users.length; const openSosCount = dashboardData.incidents.filter(i => i.status === 'Open').length; const verificationCount = dashboardData.users.filter(u => u.has_vehicle_pass === 0 && u.role === 'Pool Host').length; const kpiData = [ { id: 1, title: 'Active Trips Now', value: activeTripsCount.toString(), trend: 'Live', isUp: true }, { id: 2, title: 'Total Registered Users', value: totalUsersCount.toString(), trend: 'Live', isUp: true }, { id: 3, title: 'Total Rides Listed', value: dashboardData.trips.length.toString(), trend: 'Live', isUp: true }, { id: 4, title: 'Open SOS', value: openSosCount.toString(), trend: openSosCount === 0 ? 'Safe' : 'Action Req', isUp: openSosCount === 0 }, { id: 5, title: 'Verification Backlog', value: verificationCount.toString(), trend: 'Pending', isUp: false }, ]; const incidentQueue = dashboardData.incidents.filter(i => i.status === 'Open').map(inc => ({ id: `INC-${inc.id}`, user: inc.reporter_name || `User ${inc.reported_by}`, category: inc.type, status: 'Critical', time: new Date(inc.created_at).toLocaleTimeString() })); const verificationQueue = dashboardData.users.filter(u => u.has_vehicle_pass === 0 && u.role === 'Pool Host').map(u => ({ id: `V-${u.id}`, name: u.name, type: 'Vehicle Pass', status: 'Pending', time: new Date(u.created_at).toLocaleDateString() })); const showToast = (message, type = 'info') => { const id = Math.random().toString(36).substring(2, 9); setToasts((prev) => [...prev, { id, message, type }]); setTimeout(() => { setToasts((prev) => prev.filter((t) => t.id !== id)); }, 4000); }; const handleLoginSuccess = (userObject) => { setSession(userObject); localStorage.setItem('carpool_session', JSON.stringify(userObject)); setActiveTab('Overview'); setShowRegistration(false); }; const handleUpdateUser = (updatedUser) => { setSession(updatedUser); localStorage.setItem('carpool_session', JSON.stringify(updatedUser)); }; const handleLogout = () => { setSession(null); localStorage.removeItem('carpool_session'); showToast('Logged out successfully.', 'info'); }; const navItems = [ { id: 'Overview', label: 'Overview', icon: '📊' }, { id: 'Registration', label: 'Corporate Registration', icon: '📝' }, { id: 'Verifications', label: 'Verification Backlog', icon: '🔍' }, { id: 'Incidents', label: 'Live Incidents', icon: '🚨' }, { id: 'Trips', label: 'Trips & Disputes', icon: '🚗' }, { id: 'Users', label: 'User Directory', icon: '👥' }, { id: 'ESG', label: 'ESG Impact Dashboard', icon: '🌱' }, { id: 'Settings', label: 'Platform Settings', icon: '⚙️' } ]; const handleCityChange = (e) => { const city = e.target.value; setSelectedCity(city); const cityName = city === 'all' ? 'All Cities' : city.charAt(0).toUpperCase() + city.slice(1); showToast(`Dashboard filtered to ${cityName}`, 'success'); }; const handleTodayClick = () => { const todayStr = new Date().toLocaleDateString('en-IN', { day: 'numeric', month: 'short', year: 'numeric' }); showToast(`Showing carpool data for ${todayStr}`, 'info'); }; const handleApproveVerification = async (userId) => { try { const res = await fetch(`/api/users/${userId}/verify`, { method: 'POST', headers: { 'Authorization': `Bearer ${session.token}` } }); if (res.ok) { showToast('Host verified successfully!', 'success'); // Refresh admin data const headers = { 'Authorization': `Bearer ${session.token}` }; const [usersRes, tripsRes, incidentsRes] = await Promise.all([ fetch(`/api/users`, { headers }), fetch(`/api/trips`, { headers }), fetch(`/api/incidents`, { headers }) ]); if (usersRes.ok && tripsRes.ok && incidentsRes.ok) { setDashboardData({ users: await usersRes.json(), trips: await tripsRes.json(), incidents: await incidentsRes.json() }); } } else { showToast('Failed to verify host.', 'danger'); } } catch (err) { showToast('Network error during verification.', 'danger'); } }; const handleResolveIncident = async (incidentId) => { try { const res = await fetch(`/api/incidents/resolve`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${session.token}` }, body: JSON.stringify({ incident_id: incidentId }) }); if (res.ok) { showToast('Incident resolved successfully.', 'success'); // Refresh admin data const headers = { 'Authorization': `Bearer ${session.token}` }; const [usersRes, tripsRes, incidentsRes] = await Promise.all([ fetch(`/api/users`, { headers }), fetch(`/api/trips`, { headers }), fetch(`/api/incidents`, { headers }) ]); if (usersRes.ok && tripsRes.ok && incidentsRes.ok) { setDashboardData({ users: await usersRes.json(), trips: await tripsRes.json(), incidents: await incidentsRes.json() }); } } else { showToast('Failed to resolve incident.', 'danger'); } } catch (err) { showToast('Network error resolving incident.', 'danger'); } }; const toastElement = (
Real-time system metrics and administrative queue management.
Daily Active Users
CO₂ Saved (kg)
Active Rides Now
Pending Verifications
Host • {u.vehicle_make || 'N/A'} {u.vehicle_model || ''} ({u.vehicle_no || 'N/A'})
Type: {inc.type}