From 491a6f537c00dfa6779790b632568b000c4dcaca Mon Sep 17 00:00:00 2001 From: Nguyen Ngo Date: Fri, 15 Aug 2025 09:56:44 -0400 Subject: [PATCH] Update tracking page to detect Location Services --- static/js/qr_destination.js | 150 ++++++++++++++++++++++++++++++++++ templates/qr_destination.html | 121 +++++++++++++++++++++++++++ 2 files changed, 271 insertions(+) diff --git a/static/js/qr_destination.js b/static/js/qr_destination.js index 435fc54..358c772 100644 --- a/static/js/qr_destination.js +++ b/static/js/qr_destination.js @@ -59,6 +59,7 @@ document.addEventListener("DOMContentLoaded", function () { // CRITICAL: Initialize systems in correct order initializeLanguage(); + initializeLocationServicesCheck(); initializeStaffIdPersistence(); initializeForm(); initializeLocation(); @@ -733,3 +734,152 @@ function startClock() { updateClock(); 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.
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.
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.
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.
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.
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 = ` +
+ +
+ ${message} +
+ + +
+
+
+ `; + + // 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); + }; +} diff --git a/templates/qr_destination.html b/templates/qr_destination.html index 1924017..951bd2b 100644 --- a/templates/qr_destination.html +++ b/templates/qr_destination.html @@ -601,6 +601,127 @@ 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; + } + }