feat: add GPS tracking with Traccar integration

- Add GPS module with Traccar client service for device management
- Add driver enrollment flow with QR code generation
- Add real-time location tracking on driver profiles
- Add GPS settings configuration in admin tools
- Add Auth0 OpenID Connect setup script for Traccar
- Add deployment configs for production server
- Update nginx configs for SSL on GPS port 5055
- Add timezone setting support
- Various UI improvements and bug fixes

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-03 18:13:17 +01:00
parent 3814d175ff
commit 5ded039793
91 changed files with 4403 additions and 68 deletions

View File

@@ -153,6 +153,18 @@ export function CommandCenter() {
},
});
// Compute awaiting confirmation BEFORE any conditional returns (for hooks)
const now = currentTime;
const awaitingConfirmation = (events || []).filter((event) => {
if (event.status !== 'SCHEDULED' || event.type !== 'TRANSPORT') return false;
const start = new Date(event.startTime);
return start <= now;
});
// Check which awaiting events have driver responses since the event started
// MUST be called before any conditional returns to satisfy React's rules of hooks
const { data: respondedEventIds } = useDriverResponseCheck(awaitingConfirmation);
// Update clock every second
useEffect(() => {
const clockInterval = setInterval(() => {
@@ -242,7 +254,6 @@ export function CommandCenter() {
return <Loading message="Loading Command Center..." />;
}
const now = currentTime;
const fifteenMinutes = new Date(now.getTime() + 15 * 60 * 1000);
const thirtyMinutes = new Date(now.getTime() + 30 * 60 * 1000);
const twoHoursLater = new Date(now.getTime() + 2 * 60 * 60 * 1000);
@@ -253,17 +264,6 @@ export function CommandCenter() {
(event) => event.status === 'IN_PROGRESS' && event.type === 'TRANSPORT'
);
// Trips that SHOULD be active (past start time but still SCHEDULED)
// These are awaiting driver confirmation
const awaitingConfirmation = events.filter((event) => {
if (event.status !== 'SCHEDULED' || event.type !== 'TRANSPORT') return false;
const start = new Date(event.startTime);
return start <= now;
});
// Check which awaiting events have driver responses since the event started
const { data: respondedEventIds } = useDriverResponseCheck(awaitingConfirmation);
// Upcoming trips in next 2 hours
const upcomingTrips = events
.filter((event) => {