import { useState, useMemo } from 'react'; import { useQuery } from '@tanstack/react-query'; import { Container, Grid, Card, Stack, Group, Select, Text, Badge, Button, Box, Table, ThemeIcon, SimpleGrid } from '@mantine/core'; import { MapPin, Navigation, Radio, Activity } from 'lucide-react'; import Breadcrumbs from '@/components/ui/Breadcrumbs'; import { QUERY_KEYS } from '@/constants/QUERY_KEYS'; import { vehiclesService } from '@/services/vehicles.service'; import { freightBrand } from '@/theme/freight-brand'; interface Vehicle { id: string; registrationNumber: string; plateNumber: string; manufacturer: string; model: string; status?: string; } interface GPSLocation { lat: number; lng: number; speed?: number; heading?: number; lastUpdate?: string; } // Mock GPS data for demo const generateMockGPS = (index: number): GPSLocation => ({ lat: 9.0 + Math.random() * 0.5, lng: 38.7 + Math.random() * 0.5, speed: Math.floor(Math.random() * 120), heading: Math.floor(Math.random() * 360), lastUpdate: new Date(Date.now() - Math.random() * 300000).toLocaleTimeString(), }); export function TrackingPage() { const [selectedVehicleId, setSelectedVehicleId] = useState(null); const [mapCenter] = useState({ lat: 9.0, lng: 38.8 }); const mapZoom = 10; const { data: vehicles = [] } = useQuery({ queryKey: QUERY_KEYS.VEHICLES.list(), queryFn: async () => { const res = await vehiclesService.getAll({ limit: 1000 }); return res.data || []; }, }); // Generate mock GPS data for each vehicle const vehiclesWithGPS = useMemo(() => { return (vehicles as Vehicle[]).map((v, idx) => ({ ...v, gps: generateMockGPS(idx), })); }, [vehicles]); // For demo: show all vehicles as trackable (or filter by ACTIVE if status data available) const trackableVehicles = useMemo( () => vehiclesWithGPS.slice(0, 10), // Limit to first 10 for demo [vehiclesWithGPS] ); const selectedVehicle = trackableVehicles.find(v => v.id === selectedVehicleId); const vehicleOptions = useMemo( () => trackableVehicles.map(v => ({ label: v.registrationNumber, value: v.id })), [trackableVehicles] ); // Map dimensions const mapWidth = 800; const mapHeight = 500; const pixelsPerLat = mapHeight / 0.6; const pixelsPerLng = mapWidth / 0.6; const getMapCoords = (lat: number, lng: number) => ({ x: ((lng - (mapCenter.lng - 0.3)) * pixelsPerLng), y: ((mapCenter.lat + 0.3 - lat) * pixelsPerLat), }); return (
Real-Time Vehicle Tracking Monitor vehicle locations, speed, and status
{/* Map Section */} Map View }> {trackableVehicles.length} Tracked {/* Grid background */} {/* Latitude lines */} {[0, 1, 2, 3, 4, 5, 6].map(i => ( ))} {/* Longitude lines */} {[0, 1, 2, 3, 4, 5, 6].map(i => ( ))} {/* Vehicle markers */} {trackableVehicles.map((vehicle) => { const coords = getMapCoords(vehicle.gps.lat, vehicle.gps.lng); const isSelected = vehicle.id === selectedVehicleId; return ( setSelectedVehicleId(vehicle.id)} title={vehicle.registrationNumber} > ); })} {/* Map labels */} 📍 Addis Ababa, Ethiopia {/* Sidebar */} {/* Vehicle Selector */}