fix: attendance clock-in hanging after geolocation confirmation

On desktop browsers without GPS hardware, getCurrentPosition with
enableHighAccuracy:true can silently hang after the user grants
permission — neither success nor error callback fires.

Previous safety timeout (12s) only reset the button without sending
the punch request, leaving users stuck. Now:
- enableHighAccuracy: false (faster fallback to IP-based location)
- Browser timeout reduced to 5s
- Safety timeout reduced to 6s and automatically calls submitPunch
  without GPS data instead of just showing an error
- Wrapped success callback in try/catch as additional safeguard

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-04-27 08:23:12 +02:00
parent c4f6723042
commit d873c96ae3

View File

@@ -186,15 +186,14 @@ export default function Attendance() {
setSubmitting(true);
latestActionRef.current = action;
// Safety timeout: if geolocation hangs silently (some browsers ignore
// the timeout option), reset the button so the user isn't stuck.
// Some browsers silently hang on getCurrentPosition (especially with
// enableHighAccuracy:true on desktops without GPS). Use a short safety
// timeout and proceed without GPS rather than leaving the user stuck.
const safetyTimeout = setTimeout(() => {
if (mountedRef.current) {
setSubmitting(false);
alert.error("Vypršel časový limit pro získání polohy");
setGpsConfirm({ isOpen: true, action });
submitPunch(action, {});
}
}, 12000);
}, 6000);
if (!navigator.geolocation) {
clearTimeout(safetyTimeout);
@@ -207,14 +206,19 @@ export default function Attendance() {
(position) => {
clearTimeout(safetyTimeout);
if (!mountedRef.current) return;
const { latitude, longitude, accuracy } = position.coords;
submitPunch(action, { latitude, longitude, accuracy, address: "" });
try {
const { latitude, longitude, accuracy } = position.coords;
submitPunch(action, { latitude, longitude, accuracy, address: "" });
} catch {
submitPunch(action, {});
}
// Fire-and-forget reverse geocoding to update the address later
if (geoAbortRef.current) geoAbortRef.current.abort();
const controller = new AbortController();
geoAbortRef.current = controller;
fetch(
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&zoom=18&addressdetails=1`,
`https://nominatim.openstreetmap.org/reverse?format=json&lat=${position.coords.latitude}&lon=${position.coords.longitude}&zoom=18&addressdetails=1`,
{
headers: { "Accept-Language": "cs" },
signal: controller.signal,
@@ -229,8 +233,8 @@ export default function Attendance() {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
latitude,
longitude,
latitude: position.coords.latitude,
longitude: position.coords.longitude,
address: geoData.display_name,
punch_action: action,
}),
@@ -252,7 +256,7 @@ export default function Attendance() {
setSubmitting(false);
setGpsConfirm({ isOpen: true, action });
},
{ enableHighAccuracy: true, timeout: 10000, maximumAge: 60000 },
{ enableHighAccuracy: false, timeout: 5000, maximumAge: 60000 },
);
};