WFDASHDRIVER-APP/components/LocationTracker.tsx

100 lines
2.7 KiB
TypeScript

'use client';
import { useEffect, useRef, useCallback } from 'react';
import { getSettings, saveDriverLocation, addToQueue, isAuthenticated } from '@/lib/pocketbase';
export default function LocationTracker() {
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
const lastSentRef = useRef<number>(0);
const hasPermissionRef = useRef<boolean | null>(null);
const sendLocation = useCallback(async (position: GeolocationPosition) => {
if (!isAuthenticated()) return;
const user = getCurrentUser();
if (!user) return;
// Skip if accuracy is too poor (based on settings)
const settings = getSettings();
if (position.coords.accuracy && position.coords.accuracy > settings.minimumAccuracy) {
return;
}
const locationData = {
driver: user.id,
latitude: position.coords.latitude,
longitude: position.coords.longitude,
accuracy: position.coords.accuracy || undefined,
altitude: position.coords.altitude || undefined,
speed: position.coords.speed || undefined,
heading: position.coords.heading || undefined,
timestamp: new Date().toISOString(),
};
try {
await saveDriverLocation(locationData);
lastSentRef.current = Date.now();
} catch (error) {
// Queue for sync when back online
addToQueue({
type: 'status_update',
data: locationData,
});
}
}, []);
useEffect(() => {
if (!('geolocation' in navigator)) {
return;
}
const settings = getSettings();
const intervalMs = Math.max(30000, settings.locationInterval * 1000);
const trackLocation = () => {
navigator.geolocation.getCurrentPosition(
(position) => {
hasPermissionRef.current = true;
sendLocation(position);
},
(error) => {
// Silently handle errors - don't spam console
if (error.code === error.PERMISSION_DENIED) {
hasPermissionRef.current = false;
}
// TIMEOUT and POSITION_UNAVAILABLE are expected on desktop
},
{
enableHighAccuracy: settings.enableHighAccuracy,
maximumAge: intervalMs,
timeout: 30000,
}
);
};
// Send immediately on mount
trackLocation();
// Then on interval
intervalRef.current = setInterval(trackLocation, intervalMs);
return () => {
if (intervalRef.current !== null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
}, [sendLocation]);
// This component doesn't render anything
return null;
}
function getCurrentUser() {
try {
const auth = JSON.parse(localStorage.getItem('pocketbase_auth') || '{}');
return auth?.model;
} catch {
return null;
}
}