sw-fe/src/components/Map/useUserPosition.js

85 lines
1.9 KiB
JavaScript

import { useEffect, useState } from "react";
import { LAST_POS_KEY } from "./mapConfig";
import { fetchIpLocation } from "../../api/client";
export function useUserPosition(mapRef, hasLastView) {
const [userPosition, setUserPosition] = useState(null); // [lng, lat]
useEffect(() => {
const map = mapRef.current;
if (!map) return;
let cancelled = false;
function saveUserPos(lat, lon) {
if (cancelled) return;
const coords = [lon, lat];
setUserPosition(coords);
try {
localStorage.setItem(LAST_POS_KEY, JSON.stringify({ lat, lon }));
} catch {
// ignore
}
if (!hasLastView) {
map.flyTo({
center: coords,
zoom: 9,
speed: 1.2,
curve: 1.5,
essential: true,
});
}
}
// 1) dernière position user
try {
const raw = localStorage.getItem(LAST_POS_KEY);
if (raw) {
const p = JSON.parse(raw);
if (typeof p.lat === "number" && typeof p.lon === "number") {
setUserPosition([p.lon, p.lat]);
}
}
} catch {
// ignore
}
// 2) GPS → 3) IP backend
function viaIpFallback() {
(async () => {
const ipCoords = await fetchIpLocation();
if (!ipCoords || cancelled) return;
const [lon, lat] = ipCoords;
saveUserPos(lat, lon);
})();
}
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
(pos) => {
if (cancelled) return;
saveUserPos(pos.coords.latitude, pos.coords.longitude);
},
() => {
if (cancelled) return;
viaIpFallback();
},
{
enableHighAccuracy: true,
timeout: 8000,
maximumAge: 30000,
}
);
} else {
viaIpFallback();
}
return () => {
cancelled = true;
};
}, [mapRef, hasLastView]);
return userPosition;
}