refactor: simplify GPS page, lean into Traccar for live map and trips

Remove ~2,300 lines of code that duplicated Traccar's native capabilities:
- Remove Leaflet live map, trip stats/playback, and OSRM route matching from frontend
- Delete osrm.service.ts entirely (415 lines)
- Remove 6 dead backend endpoints and unused service methods
- Clean up unused hooks and TypeScript types
- Keep device enrollment, QR codes, settings, and CommandCenter integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-09 19:53:57 +01:00
parent 14c6c9506f
commit 139cb4aebe
7 changed files with 52 additions and 2286 deletions

View File

@@ -9,9 +9,6 @@ import type {
EnrollmentResponse,
MyGpsStatus,
DeviceQrInfo,
LocationHistoryResponse,
GpsTrip,
GpsTripDetail,
} from '@/types/gps';
import toast from 'react-hot-toast';
import { queryKeys } from '@/lib/query-keys';
@@ -98,7 +95,7 @@ export function useDeviceQr(driverId: string | null) {
}
/**
* Get all active driver locations (for map)
* Get all active driver locations (used by CommandCenter)
*/
export function useDriverLocations() {
return useQuery<DriverLocation[]>({
@@ -111,109 +108,6 @@ export function useDriverLocations() {
});
}
/**
* Get a specific driver's location
*/
export function useDriverLocation(driverId: string) {
return useQuery<DriverLocation>({
queryKey: queryKeys.gps.locations.detail(driverId),
queryFn: async () => {
const { data } = await api.get(`/gps/locations/${driverId}`);
return data;
},
enabled: !!driverId,
refetchInterval: 15000,
});
}
/**
* Get driver location history (for route trail display)
* By default, requests road-snapped routes from OSRM map matching
*/
export function useDriverLocationHistory(driverId: string | null, from?: string, to?: string) {
return useQuery({
queryKey: ['gps', 'locations', driverId, 'history', from, to],
queryFn: async () => {
const params = new URLSearchParams();
if (from) params.append('from', from);
if (to) params.append('to', to);
params.append('matched', 'true'); // Request road-snapped route
const { data } = await api.get(`/gps/locations/${driverId}/history?${params}`);
return data;
},
enabled: !!driverId,
refetchInterval: 60000, // Match routes less frequently (60s) since OSRM has rate limits
staleTime: 30000, // Consider data fresh for 30s
});
}
/**
* Get driver stats
*/
export function useDriverStats(driverId: string, from?: string, to?: string) {
return useQuery<DriverStats>({
queryKey: queryKeys.gps.stats(driverId, from, to),
queryFn: async () => {
const params = new URLSearchParams();
if (from) params.append('from', from);
if (to) params.append('to', to);
const { data } = await api.get(`/gps/stats/${driverId}?${params.toString()}`);
return data;
},
enabled: !!driverId,
});
}
// ============================================
// Trip Hooks
// ============================================
/**
* Get trips for a driver (powered by Traccar)
*/
export function useDriverTrips(driverId: string | null, from?: string, to?: string) {
return useQuery<GpsTrip[]>({
queryKey: ['gps', 'trips', driverId, from, to],
queryFn: async () => {
const params = new URLSearchParams();
if (from) params.append('from', from);
if (to) params.append('to', to);
const { data } = await api.get(`/gps/trips/${driverId}?${params}`);
return data;
},
enabled: !!driverId,
});
}
/**
* Get a single trip with full detail (matchedRoute + rawPoints)
*/
export function useDriverTripDetail(driverId: string | null, tripId: string | null) {
return useQuery<GpsTripDetail>({
queryKey: ['gps', 'trips', driverId, tripId],
queryFn: async () => {
const { data } = await api.get(`/gps/trips/${driverId}/${tripId}`);
return data;
},
enabled: !!driverId && !!tripId,
});
}
/**
* Get active trip for a driver
*/
export function useActiveTrip(driverId: string | null) {
return useQuery<GpsTrip | null>({
queryKey: ['gps', 'trips', driverId, 'active'],
queryFn: async () => {
const { data } = await api.get(`/gps/trips/${driverId}/active`);
return data;
},
enabled: !!driverId,
refetchInterval: 15000,
});
}
/**
* Enroll a driver for GPS tracking
*/

File diff suppressed because it is too large Load Diff

View File

@@ -106,60 +106,3 @@ export interface MyGpsStatus {
lastActive?: string;
message?: string;
}
export type TripStatus = 'ACTIVE' | 'COMPLETED' | 'PROCESSING' | 'FAILED';
export interface GpsTrip {
id: string;
deviceId: string;
status: TripStatus;
startTime: string;
endTime: string | null;
startLatitude: number;
startLongitude: number;
endLatitude: number | null;
endLongitude: number | null;
distanceMiles: number | null;
durationSeconds: number | null;
topSpeedMph: number | null;
averageSpeedMph: number | null;
pointCount: number;
startAddress?: string | null;
endAddress?: string | null;
}
export interface GpsTripDetail extends GpsTrip {
matchedRoute: {
coordinates: [number, number][];
distance: number;
duration: number;
confidence: number;
} | null;
rawPoints: Array<{
latitude: number;
longitude: number;
speed: number | null;
course?: number | null;
battery?: number | null;
timestamp: string;
}>;
}
export interface LocationHistoryResponse {
rawPoints: Array<{
latitude: number;
longitude: number;
altitude?: number | null;
speed?: number | null;
course?: number | null;
accuracy?: number | null;
battery?: number | null;
timestamp: string;
}>;
matchedRoute: {
coordinates: [number, number][]; // road-snapped [lat, lng] pairs
distance: number; // road distance in miles
duration: number; // duration in seconds
confidence: number; // 0-1 confidence score
} | null;
}