135 lines
3.8 KiB
TypeScript
135 lines
3.8 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
||
import {
|
||
IonPage,
|
||
IonContent,
|
||
IonSpinner,
|
||
IonText,
|
||
IonButton,
|
||
} from "@ionic/react";
|
||
import { GEO_ACCESS_API } from "../api_endpoints";
|
||
|
||
const MAX_ACCEPTABLE_ACCURACY = 100; // metri
|
||
|
||
const LocationAccessChecker: React.FC<{
|
||
onAccessChecked?: (granted: boolean) => void;
|
||
}> = ({ onAccessChecked }) => {
|
||
const [loading, setLoading] = useState(true);
|
||
const [accessGranted, setAccessGranted] = useState<boolean | null>(null);
|
||
const [error, setError] = useState<string | null>(null);
|
||
const [accuracy, setAccuracy] = useState<number | null>(null);
|
||
|
||
useEffect(() => {
|
||
const checkLocationAccess = async () => {
|
||
if (!navigator.geolocation) {
|
||
setError("Geolocation non supportata dal browser");
|
||
setAccessGranted(false);
|
||
setLoading(false);
|
||
onAccessChecked?.(false);
|
||
return;
|
||
}
|
||
|
||
navigator.geolocation.getCurrentPosition(
|
||
async (position) => {
|
||
const latitude = position.coords.latitude;
|
||
const longitude = position.coords.longitude;
|
||
const positionAccuracy = position.coords.accuracy;
|
||
|
||
console.log("Lat:", latitude);
|
||
console.log("Lng:", longitude);
|
||
console.log("Accuracy (m):", positionAccuracy);
|
||
setAccuracy(positionAccuracy);
|
||
|
||
if (positionAccuracy > MAX_ACCEPTABLE_ACCURACY) {
|
||
setError(
|
||
`Precisione troppo bassa: ${positionAccuracy.toFixed(1)} metri`
|
||
);
|
||
setAccessGranted(false);
|
||
setLoading(false);
|
||
onAccessChecked?.(false);
|
||
return;
|
||
}
|
||
|
||
const coordinates = {
|
||
coords: [latitude, longitude],
|
||
};
|
||
|
||
try {
|
||
const response = await fetch(GEO_ACCESS_API, {
|
||
method: "POST",
|
||
headers: { "Content-Type": "application/json" },
|
||
body: JSON.stringify(coordinates),
|
||
});
|
||
|
||
if (!response.ok) {
|
||
throw new Error("Errore nella risposta dal server");
|
||
}
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.success === true) {
|
||
setAccessGranted(true);
|
||
onAccessChecked?.(true);
|
||
} else {
|
||
setAccessGranted(false);
|
||
onAccessChecked?.(false);
|
||
}
|
||
} catch (e) {
|
||
setError("Errore di rete o server");
|
||
setAccessGranted(false);
|
||
onAccessChecked?.(false);
|
||
} finally {
|
||
setLoading(false);
|
||
}
|
||
},
|
||
(err) => {
|
||
setError(`Errore geolocalizzazione: ${err.message}`);
|
||
setAccessGranted(false);
|
||
setLoading(false);
|
||
onAccessChecked?.(false);
|
||
},
|
||
{
|
||
enableHighAccuracy: true,
|
||
timeout: 10000,
|
||
maximumAge: 60000,
|
||
}
|
||
);
|
||
};
|
||
|
||
checkLocationAccess();
|
||
}, [onAccessChecked]);
|
||
|
||
if (loading) {
|
||
return (
|
||
<IonPage>
|
||
<IonContent className="ion-padding" fullscreen>
|
||
<IonSpinner name="crescent" />
|
||
<IonText>Verifica posizione in corso...</IonText>
|
||
</IonContent>
|
||
</IonPage>
|
||
);
|
||
}
|
||
|
||
if (accessGranted === false) {
|
||
return (
|
||
<IonPage>
|
||
<IonContent className="ion-padding" fullscreen>
|
||
<IonText color="danger">
|
||
<h2>Accesso non consentito</h2>
|
||
<p>La tua posizione non permette l’uso dell’app.</p>
|
||
{error && <p>Errore: {error}</p>}
|
||
{accuracy !== null && (
|
||
<p>Precisione posizione: {accuracy.toFixed(1)} metri</p>
|
||
)}
|
||
</IonText>
|
||
<IonButton onClick={() => window.location.reload()}>
|
||
Riprova
|
||
</IonButton>
|
||
</IonContent>
|
||
</IonPage>
|
||
);
|
||
}
|
||
|
||
return null; // accesso consentito, niente da mostrare
|
||
};
|
||
|
||
export default LocationAccessChecker;
|