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:
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user