WFDASHDRIVER-APP/components/LocationTracker.tsx
SJCoetz b738bc7495 feat: initialize project with Next.js, TypeScript, and Tailwind CSS
- Added package.json with dependencies for Next.js, React, and Tailwind CSS.
- Created postcss.config.js for Tailwind CSS and autoprefixer integration.
- Added SVG icon for the application in public/icons/icon.svg.
- Created manifest.json for PWA support with app details and icon.
- Configured Tailwind CSS in tailwind.config.js with custom colors and animations.
- Set up TypeScript configuration in tsconfig.json for strict type checking and module resolution.
2026-05-24 21:51:29 +02:00

111 lines
3.1 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 watchRef = useRef<number | null>(null);
const sendLocation = useCallback(async (position: GeolocationPosition) => {
if (!isAuthenticated()) return;
const user = JSON.parse(localStorage.getItem('pocketbase_auth') || '{}')?.model;
if (!user) return;
const locationData = {
driver: user.id,
latitude: position.coords.latitude,
longitude: position.coords.longitude,
accuracy: position.coords.accuracy,
altitude: position.coords.altitude || undefined,
speed: position.coords.speed || undefined,
heading: position.coords.heading || undefined,
timestamp: new Date().toISOString(),
};
try {
await saveDriverLocation(locationData);
} catch (error) {
console.error('Failed to save location:', error);
// Queue for sync when back online
addToQueue({
type: 'status_update',
data: locationData,
});
}
}, []);
useEffect(() => {
if (!('geolocation' in navigator)) {
console.warn('Geolocation not supported');
return;
}
const settings = getSettings();
const intervalMs = Math.max(10000, settings.locationInterval * 1000);
const startTracking = () => {
// Use watchPosition for more frequent updates
watchRef.current = navigator.geolocation.watchPosition(
sendLocation,
(error) => {
console.error('Geolocation error:', error);
},
{
enableHighAccuracy: settings.enableHighAccuracy,
maximumAge: intervalMs,
timeout: 10000,
}
);
// Also send on interval as backup
intervalRef.current = setInterval(() => {
navigator.geolocation.getCurrentPosition(
sendLocation,
(error) => console.error('Interval geolocation error:', error),
{
enableHighAccuracy: settings.enableHighAccuracy,
timeout: 10000,
}
);
}, intervalMs);
};
// Start tracking if authenticated
if (isAuthenticated()) {
startTracking();
}
// Listen for auth changes
const handleAuthChange = () => {
if (isAuthenticated()) {
startTracking();
} else {
stopTracking();
}
};
// Check periodically for auth state
const authCheckInterval = setInterval(handleAuthChange, 5000);
const stopTracking = () => {
if (watchRef.current !== null) {
navigator.geolocation.clearWatch(watchRef.current);
watchRef.current = null;
}
if (intervalRef.current !== null) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
};
return () => {
stopTracking();
clearInterval(authCheckInterval);
};
}, [sendLocation]);
// This component doesn't render anything
return null;
}