Files
boc/iom/quixzoom-app.backup.20260706-092414/src/hooks/useLocation.js
T
Bernt 6989a98d75 feat: Passwordless cross-device authentication
- Arkitektur: docs/auth/passwordless-architecture.md
- Backend: iom/quixzoom-auth-service/ (FastAPI + Redis)
- Webb: quixzoom-market-pages/se/login/ (QR-kod + polling)
- App: iom/quixzoom-app/src/features/auth/ (push + deep links)

Flöde: QR-kod → app-godkännande → webb-inloggad
2026-07-07 07:11:50 +00:00

148 lines
3.5 KiB
JavaScript

/**
* useLocation Hook
* React hook for GPS location tracking
*/
import { useState, useEffect, useCallback, useRef } from 'react';
import Geolocation from '@react-native-community/geolocation';
export function useLocation(options = {}) {
const [location, setLocation] = useState(null);
const [hasPermission, setHasPermission] = useState(false);
const [isTracking, setIsTracking] = useState(false);
const [error, setError] = useState(null);
const watchIdRef = useRef(null);
const defaultOptions = {
enableHighAccuracy: true,
timeout: 15000,
maximumAge: 10000,
distanceFilter: 10, // meters
...options,
};
/**
* Request location permission
*/
const requestPermission = useCallback(async () => {
try {
const result = await Geolocation.requestAuthorization();
setHasPermission(result === 'granted');
return result === 'granted';
} catch (err) {
setError(err.message);
return false;
}
}, []);
/**
* Get current location (one-time)
*/
const getCurrentLocation = useCallback(() => {
return new Promise((resolve, reject) => {
Geolocation.getCurrentPosition(
(position) => {
const loc = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
altitude: position.coords.altitude,
accuracy: position.coords.accuracy,
heading: position.coords.heading,
speed: position.coords.speed,
timestamp: new Date(position.timestamp).toISOString(),
};
setLocation(loc);
setError(null);
resolve(loc);
},
(err) => {
setError(err.message);
reject(err);
},
defaultOptions
);
});
}, [defaultOptions]);
/**
* Start continuous location tracking
*/
const startTracking = useCallback(() => {
if (watchIdRef.current) {
return; // Already tracking
}
setIsTracking(true);
watchIdRef.current = Geolocation.watchPosition(
(position) => {
const loc = {
latitude: position.coords.latitude,
longitude: position.coords.longitude,
altitude: position.coords.altitude,
accuracy: position.coords.accuracy,
heading: position.coords.heading,
speed: position.coords.speed,
timestamp: new Date(position.timestamp).toISOString(),
};
setLocation(loc);
setError(null);
},
(err) => {
setError(err.message);
},
{
...defaultOptions,
distanceFilter: defaultOptions.distanceFilter,
}
);
}, [defaultOptions]);
/**
* Stop location tracking
*/
const stopTracking = useCallback(() => {
if (watchIdRef.current) {
Geolocation.clearWatch(watchIdRef.current);
watchIdRef.current = null;
}
setIsTracking(false);
}, []);
/**
* Toggle tracking
*/
const toggleTracking = useCallback(() => {
if (isTracking) {
stopTracking();
} else {
startTracking();
}
}, [isTracking, startTracking, stopTracking]);
// Cleanup on unmount
useEffect(() => {
return () => {
if (watchIdRef.current) {
Geolocation.clearWatch(watchIdRef.current);
}
};
}, []);
return {
// State
location,
hasPermission,
isTracking,
error,
// Actions
requestPermission,
getCurrentLocation,
startTracking,
stopTracking,
toggleTracking,
};
}