Update tracking page to detect Location Services
This commit is contained in:
@@ -59,6 +59,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
|||||||
|
|
||||||
// CRITICAL: Initialize systems in correct order
|
// CRITICAL: Initialize systems in correct order
|
||||||
initializeLanguage();
|
initializeLanguage();
|
||||||
|
initializeLocationServicesCheck();
|
||||||
initializeStaffIdPersistence();
|
initializeStaffIdPersistence();
|
||||||
initializeForm();
|
initializeForm();
|
||||||
initializeLocation();
|
initializeLocation();
|
||||||
@@ -733,3 +734,152 @@ function startClock() {
|
|||||||
updateClock();
|
updateClock();
|
||||||
setInterval(updateClock, 1000);
|
setInterval(updateClock, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkLocationServicesStatus() {
|
||||||
|
console.log("📱 Checking location services status...");
|
||||||
|
|
||||||
|
// Check if geolocation is supported
|
||||||
|
if (!navigator.geolocation) {
|
||||||
|
console.log("❌ Geolocation not supported by this browser");
|
||||||
|
showLocationServicesWarning("not_supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test location access with a quick check
|
||||||
|
const timeoutId = setTimeout(() => {
|
||||||
|
console.log("⏰ Location permission check timed out");
|
||||||
|
showLocationServicesWarning("timeout");
|
||||||
|
}, 3000); // 3 second timeout
|
||||||
|
|
||||||
|
navigator.geolocation.getCurrentPosition(
|
||||||
|
(position) => {
|
||||||
|
// Success - location services are working
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
console.log("✅ Location services are available and enabled");
|
||||||
|
hideLocationServicesWarning();
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// Error - location services may be disabled
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
console.log("❌ Location services error:", error.message);
|
||||||
|
|
||||||
|
switch (error.code) {
|
||||||
|
case error.PERMISSION_DENIED:
|
||||||
|
showLocationServicesWarning("permission_denied");
|
||||||
|
break;
|
||||||
|
case error.POSITION_UNAVAILABLE:
|
||||||
|
showLocationServicesWarning("position_unavailable");
|
||||||
|
break;
|
||||||
|
case error.TIMEOUT:
|
||||||
|
showLocationServicesWarning("timeout");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
showLocationServicesWarning("unknown_error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
enableHighAccuracy: false,
|
||||||
|
timeout: 2500,
|
||||||
|
maximumAge: 60000
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show location services warning banner
|
||||||
|
*/
|
||||||
|
function showLocationServicesWarning(errorType) {
|
||||||
|
// Remove existing warning if present
|
||||||
|
hideLocationServicesWarning();
|
||||||
|
|
||||||
|
const warningMessages = {
|
||||||
|
en: {
|
||||||
|
not_supported: "Location services are not supported by your browser.<br>Los servicios de ubicación no son compatibles con su navegador.",
|
||||||
|
permission_denied: "Location access has been denied. Please enable location services for accurate check-in.<br>Se ha denegado el acceso a la ubicación. Habilite los servicios de ubicación para un registro preciso.",
|
||||||
|
position_unavailable: "Location services appear to be disabled. Please turn on location services for accurate check-in.<br>Los servicios de ubicación parecen estar deshabilitados. Active los servicios de ubicación para un registro preciso.",
|
||||||
|
timeout: "Location services may be disabled. Please check your location settings for accurate check-in.<br>Los servicios de ubicación pueden estar deshabilitados. Verifique su configuración de ubicación para un registro preciso.",
|
||||||
|
unknown_error: "Unable to access location services. Please check your location settings.<br>No se puede acceder a los servicios de ubicación. Verifique su configuración de ubicación."
|
||||||
|
},
|
||||||
|
es: {
|
||||||
|
not_supported: "Los servicios de ubicación no son compatibles con su navegador.",
|
||||||
|
permission_denied: "Se ha denegado el acceso a la ubicación. Habilite los servicios de ubicación para un registro preciso.",
|
||||||
|
position_unavailable: "Los servicios de ubicación parecen estar deshabilitados. Active los servicios de ubicación para un registro preciso.",
|
||||||
|
timeout: "Los servicios de ubicación pueden estar deshabilitados. Verifique su configuración de ubicación para un registro preciso.",
|
||||||
|
unknown_error: "No se puede acceder a los servicios de ubicación. Verifique su configuración de ubicación."
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentLang = currentLanguage || 'en';
|
||||||
|
const message = warningMessages[currentLang][errorType] || warningMessages['en'][errorType];
|
||||||
|
|
||||||
|
// Create warning banner
|
||||||
|
const warningBanner = document.createElement('div');
|
||||||
|
warningBanner.id = 'locationServicesWarning';
|
||||||
|
warningBanner.className = 'location-warning-banner';
|
||||||
|
warningBanner.innerHTML = `
|
||||||
|
<div class="warning-content">
|
||||||
|
<i class="fas fa-exclamation-triangle warning-icon"></i>
|
||||||
|
<div class="warning-text">
|
||||||
|
<span class="warning-message">${message}</span>
|
||||||
|
<div class="warning-actions">
|
||||||
|
<button type="button" class="warning-retry-btn" onclick="checkLocationServicesStatus()">
|
||||||
|
<i class="fas fa-redo"></i>
|
||||||
|
<span class="english-text">Retry</span>
|
||||||
|
<span class="language-separator">/</span>
|
||||||
|
<span class="spanish-text">Reintentar</span>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="warning-dismiss-btn" onclick="hideLocationServicesWarning()">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
<span class="english-text">Dismiss</span>
|
||||||
|
<span class="language-separator">/</span>
|
||||||
|
<span class="spanish-text">Descartar</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Insert warning at the top of the page
|
||||||
|
const container = document.querySelector('.destination-container');
|
||||||
|
if (container) {
|
||||||
|
container.insertBefore(warningBanner, container.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log warning event
|
||||||
|
console.log(`⚠️ Location services warning displayed: ${errorType}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide location services warning banner
|
||||||
|
*/
|
||||||
|
function hideLocationServicesWarning() {
|
||||||
|
const existingWarning = document.getElementById('locationServicesWarning');
|
||||||
|
if (existingWarning) {
|
||||||
|
existingWarning.remove();
|
||||||
|
console.log("✅ Location services warning hidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modified DOMContentLoaded event handler
|
||||||
|
* Add this to your existing initialization
|
||||||
|
*/
|
||||||
|
function initializeLocationServicesCheck() {
|
||||||
|
// Check location services status when page loads
|
||||||
|
setTimeout(() => {
|
||||||
|
checkLocationServicesStatus();
|
||||||
|
}, 1000); // Small delay to ensure page is fully loaded
|
||||||
|
|
||||||
|
// Also check before form submission
|
||||||
|
const originalHandleFormSubmit = handleFormSubmit;
|
||||||
|
window.handleFormSubmit = function(event) {
|
||||||
|
// Quick location check before submission
|
||||||
|
checkLocationServicesStatus();
|
||||||
|
|
||||||
|
// Continue with original form submission after brief delay
|
||||||
|
setTimeout(() => {
|
||||||
|
originalHandleFormSubmit.call(this, event);
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -601,6 +601,127 @@
|
|||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.location-warning-banner {
|
||||||
|
background: linear-gradient(135deg, #fef3c7, #fde68a);
|
||||||
|
border: 2px solid #f59e0b;
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
animation: slideInWarning 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-content {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-icon {
|
||||||
|
color: #d97706;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-top: 0.125rem;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-text {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-message {
|
||||||
|
display: block;
|
||||||
|
color: #92400e;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.5rem;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-retry-btn,
|
||||||
|
.warning-dismiss-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.375rem;
|
||||||
|
padding: 0.5rem 0.75rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: calc(var(--border-radius) * 0.75);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: var(--transition);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-retry-btn {
|
||||||
|
background: #f59e0b;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-retry-btn:hover {
|
||||||
|
background: #d97706;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-dismiss-btn {
|
||||||
|
background: rgba(156, 163, 175, 0.2);
|
||||||
|
color: #6b7280;
|
||||||
|
border: 1px solid rgba(156, 163, 175, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-dismiss-btn:hover {
|
||||||
|
background: rgba(156, 163, 175, 0.3);
|
||||||
|
color: #4b5563;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Warning animation */
|
||||||
|
@keyframes slideInWarning {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Language styling for warning buttons */
|
||||||
|
.warning-retry-btn .language-separator,
|
||||||
|
.warning-dismiss-btn .language-separator {
|
||||||
|
opacity: 0.7;
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-retry-btn .spanish-text,
|
||||||
|
.warning-dismiss-btn .spanish-text {
|
||||||
|
font-style: italic;
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive adjustments for warning */
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.warning-content {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-actions {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning-retry-btn,
|
||||||
|
.warning-dismiss-btn {
|
||||||
|
flex: 1;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 120px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body class="{% if qr_code.location_event == 'Check Out' %}check-out{% else %}check-in{% endif %}">
|
<body class="{% if qr_code.location_event == 'Check Out' %}check-out{% else %}check-in{% endif %}">
|
||||||
|
|||||||
Reference in New Issue
Block a user