Implement Smart Location: auto-detect user location if preference is enabled, hide location button, and handle permission denial by resetting preference

This commit is contained in:
2026-03-01 12:15:08 -05:00
parent d0d75b8c98
commit 4d7b472c6c
20 changed files with 852 additions and 344 deletions

View File

@ -5,7 +5,11 @@
"noData": "No data available",
"select": "Select",
"clear": "Clear",
"clearSelection": "Clear selection"
"clearSelection": "Clear selection",
"notAvailable": "Not available",
"back": "Back",
"all": "All",
"retry": "Retry"
},
"navigation": {
"map": "Map",
@ -17,6 +21,24 @@
"discover": "Discover",
"profile": "Profile"
},
"menu": {
"management": "MANAGEMENT",
"adminPanel": "Admin Panel",
"driverPanel": "Driver Panel",
"operations": "OPERATIONS",
"favorites": "Favorites",
"support": "SUPPORT",
"sendReport": "Send Report",
"login": "LOGIN",
"logout": "LOGOUT",
"welcome": "HELLO,",
"guest": "GUEST",
"lightMode": "Light Mode",
"darkMode": "Dark Mode",
"translate": "Español (ES)",
"admin": "ADMIN",
"driver": "DRIVER"
},
"favorites": {
"title": "My Favorites",
"subtitle": "Save your favorite routes, taxis, and businesses for quick access.",
@ -27,22 +49,31 @@
"viewSchedules": "Tap to view schedules",
"tabs": {
"routes": "Routes",
"taxis": "Taxis",
"taxis": "Transport",
"businesses": "Businesses",
"coupons": "Offers"
"coupons": "Events"
},
"empty": {
"title": "Nothing saved yet",
"subtitle": "You don't have any favorites yet",
"description": "Explore routes, taxis, and businesses to save your favorites here",
"routes": "You don't have any saved favorite routes.",
"taxis": "You don't have any saved favorite taxis.",
"businesses": "You don't have any saved favorite businesses.",
"coupons": "You don't have any saved favorite offers."
"coupons": "You don't have any saved favorite events.",
"noResultsCategory": "You don't have favorites in this category"
},
"cta": {
"exploreNow": "Explore now",
"routes": "Explore Routes",
"taxis": "View Directory",
"businesses": "Discover Businesses",
"coupons": "View Offers"
}
"coupons": "View Events"
},
"count": "{count} saved | {count} saved",
"removeTitle": "Remove from favorites",
"availability": "Check availability",
"details": "View details →"
},
"header": {
"title": "SIBU",
@ -63,7 +94,15 @@
"selectRoute": "Select a route",
"route": "Route",
"stops": "stops",
"stop": "stop"
"stop": "stop",
"calculatingRoute": "Calculating real route...",
"viewRoutes": "view routes",
"arrivalTime": "Arrival time",
"availableRoutes": "Available Routes",
"busRoute": "Bus Route",
"showMyLocation": "Show my location",
"promo": "PROMO",
"search": "Search"
},
"schedules": {
"title": "Schedules",
@ -77,6 +116,12 @@
"schedules": "schedules",
"schedule": "schedule",
"departureTime": "Departure time",
"today": "Today",
"tomorrow": "Tomorrow",
"loading": "Loading schedules...",
"viewAll": "View all schedules",
"departing": "DEPARTING",
"daily": "Daily",
"types": {
"weekday": "Weekday",
"weekend": "Weekend",
@ -87,19 +132,23 @@
"title": "Offers",
"loadingCoupons": "Loading offers...",
"noCouponsAvailable": "No offers available",
"noResults": "No results found for your search.",
"off": "OFF",
"searchPlaceholder": "Search offers...",
"filterByCategory": "Filter by category",
"apply": "Apply",
"offerDetails": "Offer Details",
"description": "Description",
"noDescription": "No additional description.",
"validity": "Validity",
"category": "Category",
"viewLocation": "View location",
"validUntil": "Valid until",
"tomorrow": "Tomorrow",
"active": "Active",
"offersCount": "{count} offer | {count} offers"
"offersCount": "{count} offer | {count} offers",
"viewDetails": "View details",
"restaurant": "Restaurant"
},
"taxi": {
"title": "Transport Hub",
@ -115,7 +164,8 @@
"allZones": "All zones",
"dayShift": "Day",
"afternoonShift": "Afternoon",
"nightShift": "Night"
"nightShift": "Night",
"errorLoading": "Error loading transport section"
},
"shuttle": {
"title": "Tourist Trips & Shuttles",
@ -128,9 +178,21 @@
"filterRoute": "Filter by route",
"allRoutes": "All routes",
"tripType": "Trip type",
"oneWay": "Outbound",
"roundTrip": "Return",
"both": "Both"
"oneWay": "One way",
"roundTrip": "Round trip",
"both": "Both",
"detailTitle": "Trip Detail",
"origin": "Origin",
"destination": "Destination",
"departureTimes": "Departure Times",
"languages": "Languages",
"pricePerPerson": "Price per passenger",
"private": "Private",
"bookingInfo": "Booking & Information",
"contactOperator": "Contact the operator directly to confirm availability.",
"bookWhatsapp": "Book via WhatsApp",
"callOperator": "Call Operator",
"errorLoading": "Could not load trip information"
},
"busStop": {
"loadingDetails": "Loading bus stop details...",
@ -140,14 +202,149 @@
"accessible": "Accessible"
},
"discover": {
"title": "Discover",
"subtitle": "Explore the best places in Chiriqui",
"searchPlaceholder": "Explore the best places in Chiriqui",
"title": "Explore Chiriquí! 🌿",
"subtitle": "Discover the best places near you",
"searchPlaceholder": "Search restaurants, hotels...",
"filterLabel": "Filter by area:",
"allAreas": "All",
"loading": "Searching for treasures...",
"empty": "No places found in this area yet.",
"loading": "Loading places...",
"error": "Could not load places. Check your connection.",
"empty": "No places yet",
"emptyDesc": "Business and tourist places will be available here soon.",
"noResults": "No results",
"noResultsDesc": "We couldn't find any places matching that filter.",
"viewAll": "View all places",
"exploreMore": "Explore Place",
"tourism": "Tourism"
"tourism": "Tourism",
"results": "{count} place | {count} places",
"in": "in",
"lookingMore": "Looking for something else?",
"exploreWithoutFilters": "Explore without filters to discover everything",
"sections": {
"byArea": "🗺️ By Area",
"featured": "✨ Featured",
"allPlaces": "🏙️ All places"
},
"categories": {
"all": "All",
"restaurant": "Restaurant",
"hotel": "Hotel",
"cafe": "Cafe",
"commerce": "Commerce",
"tourism": "Tourism",
"drinks": "Drinks"
}
},
"business": {
"detailsTitle": "Explore Our History For Refined Cuisine And A Timeless Atmosphere",
"detailsDescription": "Our story is one of growth, exploration, and unforgettable culinary memories, where each chapter is served with elegance.",
"timelessHeritage": "Timeless Heritage",
"timelessHeritageDesc": "Signature dishes that evolve with local inspiration and culture.",
"worldClassDishes": "World Class Dishes",
"worldClassDishesDesc": "Gastronomic experience designed to delight the most demanding senses.",
"emotionElegance": "Emotion and Elegance",
"emotionEleganceDesc": "Evenings enhanced by the timeless charm of an exclusive atmosphere.",
"unmatchedExperience": "Unmatched Experience",
"unmatchedExperienceDesc": "Personalized service from a dedicated host for your comfort.",
"address": "Address",
"contact": "Contact",
"socialMedia": "Social Media",
"availableOffers": "Available Offers",
"viewBusiness": "View Business",
"loadingPremium": "Loading premium experience..."
},
"profile": {
"title": "Profile",
"myCoupons": "My Coupons",
"emptyCoupons": "You don't have any coupons",
"exploreOffers": "Explore the benefits we have for you for using SIBU.",
"viewOffers": "View Offers",
"viewCode": "View Code",
"usedAt": "Used on:",
"claimedAt": "Claimed on:",
"editProfile": "Edit Profile",
"photoOptional": "Optional photo",
"nameLabel": "Full Name",
"namePlaceholder": "Your name",
"passwordOptional": "New Password (Optional)",
"passwordPlaceholder": "Minimum 6 characters",
"passwordHint": "Leave blank if you don't want to change it.",
"cancel": "Cancel",
"save": "Save Changes",
"saving": "Saving...",
"qrTitle": "Discount Coupon",
"qrCode": "REDEMPTION CODE",
"qrInstructions": "Show this code to the establishment manager to validate your promotion.",
"understood": "Understood",
"pending": "Pending",
"redeemed": "Redeemed",
"expired": "Expired",
"updateSuccess": "Profile updated successfully",
"updateError": "Update error:",
"user": "User",
"logoutTitle": "Logout"
},
"auth": {
"back": "Back",
"brandingSubtitle": "Public Transport System",
"loginTab": "Login",
"registerTab": "Create Account",
"sessionExpired": "Your session has expired. Please log in again.",
"footer": "SIBU © 2026 • Chiriquí Transport System",
"googleLogin": "Continue with Google",
"googleRegister": "Sign up with Google",
"orEmail": "or with email",
"emailLabel": "Email address",
"emailPlaceholder": "you@email.com",
"passLabel": "Password",
"keepSession": "Keep me logged in",
"loggingIn": "Logging in...",
"creatingAccount": "Creating account...",
"noAccount": "Don't have an account?",
"registerHere": "Register here",
"hasAccount": "Already have an account?",
"loginHere": "Login",
"successTitle": "Successful registration!",
"fullNameLabel": "Full name",
"fullNamePlaceholder": "Your name",
"passMin8": "Minimum 8 characters",
"smartLocation": "Allow to detect my location automatically (Smart Location)",
"emailRegistered": "Email is already registered.",
"invalidCreds": "Incorrect email or password."
},
"routesView": {
"title": "Transport",
"busTab": "Bus Routes",
"taxiTab": "Local Taxis",
"originPlaceholder": "Origin City",
"destPlaceholder": "Destination City",
"searchBtn": "Search Routes",
"allCorregimientos": "All corregimientos",
"english": "English",
"availableRoutes": "Available Routes",
"recommendedDrivers": "Recommended Drivers",
"active": "ACTIVE",
"minutes": "min",
"km": "km",
"findSchedules": "View Schedules",
"contact": "Contact",
"noTaxis": "No taxis available in this area.",
"noRoutes": "No routes found for your search."
},
"splash": {
"subtitle": "Boquete Public Transport",
"starting": "Starting SIBU...",
"offline": "Starting offline mode...",
"verifying": "Verifying data...",
"ready": "Ready to use"
},
"report": {
"title": "Send Report",
"instruction": "Tell us what's happening or send us a suggestion. The administrative team will review your message.",
"placeholder": "Write your message here...",
"success": "Report sent successfully! Thanks for your collaboration.",
"error": "There was an error sending the report. Please try again.",
"cancel": "Cancel",
"send": "Send Report"
}
}

View File

@ -5,7 +5,11 @@
"noData": "No hay datos disponibles",
"select": "Seleccionar",
"clear": "Limpiar",
"clearSelection": "Limpiar selección"
"clearSelection": "Limpiar selección",
"notAvailable": "No disponible",
"back": "Volver",
"all": "Todos",
"retry": "Reintentar"
},
"navigation": {
"map": "Mapa",
@ -17,6 +21,24 @@
"discover": "Descubrir",
"profile": "Perfil"
},
"menu": {
"management": "GESTIÓN",
"adminPanel": "Panel Administración",
"driverPanel": "Panel de Conductores",
"operations": "OPERACIONES",
"favorites": "Favoritos",
"support": "SOPORTE",
"sendReport": "Enviar Reporte",
"login": "INICIAR SESIÓN",
"logout": "CERRAR SESIÓN",
"welcome": "HOLA,",
"guest": "INVITADO",
"lightMode": "Modo Claro",
"darkMode": "Modo Oscuro",
"translate": "Translate (EN)",
"admin": "ADMIN",
"driver": "CONDUCTOR"
},
"favorites": {
"title": "Mis Favoritos",
"subtitle": "Guarda tus rutas, taxis y negocios preferidos para acceder rápido.",
@ -32,18 +54,26 @@
"coupons": "Eventos"
},
"empty": {
"title": "Nada guardado aún",
"subtitle": "Aún no tienes favoritos",
"description": "Explora rutas, taxis y negocios para guardar tus favoritos aquí",
"routes": "No tienes rutas favoritas guardadas.",
"taxis": "No tienes taxis favoritos guardados.",
"businesses": "No tienes negocios favoritos guardados.",
"coupons": "No tienes eventos favoritos guardados."
"coupons": "No tienes eventos favoritos guardados.",
"noResultsCategory": "No tienes favoritos en esta categoría"
},
"cta": {
"exploreNow": "Explorar ahora",
"routes": "Explorar Rutas",
"taxis": "Ver Directorio",
"businesses": "Descubrir Negocios",
"coupons": "Ver Eventos"
}
},
"count": "{count} guardado | {count} guardados",
"removeTitle": "Quitar de favoritos",
"availability": "Ver disponibilidad",
"details": "Ver detalles →"
},
"header": {
"title": "SIBU",
@ -64,7 +94,15 @@
"selectRoute": "Seleccionar una ruta",
"route": "Ruta",
"stops": "paradas",
"stop": "parada"
"stop": "parada",
"calculatingRoute": "Calculando ruta real...",
"viewRoutes": "ver rutas",
"arrivalTime": "Tiempo de llegada",
"availableRoutes": "Rutas Disponibles",
"busRoute": "Ruta de Autobús",
"showMyLocation": "Mostrar mi ubicación",
"promo": "PROMO",
"search": "Buscar"
},
"schedules": {
"title": "Horarios",
@ -78,6 +116,12 @@
"schedules": "horarios",
"schedule": "horario",
"departureTime": "Hora de salida",
"today": "Hoy",
"tomorrow": "Mañana",
"loading": "Cargando horarios...",
"viewAll": "Ver todos los horarios",
"departing": "SALIENDO",
"daily": "Diario",
"types": {
"weekday": "Entre semana",
"weekend": "Fin de semana",
@ -88,19 +132,23 @@
"title": "Ofertas",
"loadingCoupons": "Cargando ofertas...",
"noCouponsAvailable": "No hay ofertas disponibles",
"noResults": "No se encontraron resultados para tu búsqueda.",
"off": "DESCUENTO",
"searchPlaceholder": "Buscar ofertas...",
"filterByCategory": "Filtrar por categoría",
"apply": "Aplicar",
"offerDetails": "Detalles de la Oferta",
"description": "Descripción",
"noDescription": "Sin descripción adicional.",
"validity": "Validez",
"category": "Categoría",
"viewLocation": "Ver ubicación",
"validUntil": "Válido hasta",
"tomorrow": "Mañana",
"active": "Activo",
"offersCount": "{count} oferta | {count} ofertas"
"offersCount": "{count} oferta | {count} ofertas",
"viewDetails": "Ver detalles",
"restaurant": "Restaurante"
},
"taxi": {
"title": "Centro de Transporte",
@ -116,7 +164,8 @@
"allZones": "Todas las zonas",
"dayShift": "Día",
"afternoonShift": "Tarde",
"nightShift": "Noche"
"nightShift": "Noche",
"errorLoading": "Error al cargar la sección de transporte"
},
"shuttle": {
"title": "Viajes Turísticos & Shuttles",
@ -131,7 +180,19 @@
"tripType": "Tipo de viaje",
"oneWay": "Ida",
"roundTrip": "Vuelta",
"both": "Ambos"
"both": "Ambos",
"detailTitle": "Detalle del viaje",
"origin": "Origen",
"destination": "Destino",
"departureTimes": "Horas de salida",
"languages": "Idiomas",
"pricePerPerson": "Precio por pasajero",
"private": "Privado",
"bookingInfo": "Reserva e Información",
"contactOperator": "Contacta directamente al operador para confirmar disponibilidad.",
"bookWhatsapp": "Reservar por WhatsApp",
"callOperator": "Llamar al Operador",
"errorLoading": "No se pudo cargar la información del viaje"
},
"busStop": {
"loadingDetails": "Cargando detalles de la parada...",
@ -141,14 +202,149 @@
"accessible": "Accesible"
},
"discover": {
"title": "Descubrir",
"subtitle": "Explora los mejores lugares de Chiriquí",
"searchPlaceholder": "Explora los mejores lugares en Chiriquí",
"title": "¡Explora Chiriquí! 🌿",
"subtitle": "Descubre los mejores lugares cerca de ti",
"searchPlaceholder": "Buscar restaurantes, hoteles...",
"filterLabel": "Filtrar por área:",
"allAreas": "Todas",
"loading": "Buscando tesoros...",
"empty": "No se encontraron lugares en esta área todavía.",
"loading": "Cargando lugares...",
"error": "No se pudieron cargar los lugares. Revisa tu conexión.",
"empty": "No hay lugares aún",
"emptyDesc": "Pronto habrá negocios y lugares turísticos disponibles aquí.",
"noResults": "Sin resultados",
"noResultsDesc": "No encontramos lugares con ese filtro.",
"viewAll": "Ver todos los lugares",
"exploreMore": "Explorar Lugar",
"tourism": "Turismo"
"tourism": "Turismo",
"results": "{count} lugar | {count} lugares",
"in": "en",
"lookingMore": "¿Buscas algo más?",
"exploreWithoutFilters": "Explora sin filtros para descubrir todo",
"sections": {
"byArea": "🗺️ Por Área",
"featured": "✨ Destacados",
"allPlaces": "🏙️ Todos los lugares"
},
"categories": {
"all": "Todas",
"restaurant": "Restaurante",
"hotel": "Hotel",
"cafe": "Café",
"commerce": "Comercio",
"tourism": "Turismo",
"drinks": "Bebidas"
}
},
"business": {
"detailsTitle": "Explora Nuestra Historia Para Una Cocina Refinada Y Un Ambiente Atemporal",
"detailsDescription": "Nuestra historia es una de crecimiento, exploración y recuerdos culinarios inflamables, donde cada capítulo se sirve con elegancia.",
"timelessHeritage": "Herencia Atemporal",
"timelessHeritageDesc": "Platos de autor que evolucionan con inspiración y cultura local.",
"worldClassDishes": "Platos de Clase Mundial",
"worldClassDishesDesc": "Experiencia gastronómica diseñada para deleitar los sentidos más exigentes.",
"emotionElegance": "Emoción y Elegancia",
"emotionEleganceDesc": "Veladas realzadas por el encanto atemporal de un ambiente exclusivo.",
"unmatchedExperience": "Experiencia Inigualable",
"unmatchedExperienceDesc": "Servicio personalizado desde un anfitrión dedicado para tu comodidad.",
"address": "Dirección",
"contact": "Contacto",
"socialMedia": "Redes Sociales",
"availableOffers": "Ofertas Disponibles",
"viewBusiness": "Ver Negocio",
"loadingPremium": "Cargando experiencia premium..."
},
"profile": {
"title": "Perfil",
"myCoupons": "Mis Cupones",
"emptyCoupons": "No tienes cupones",
"exploreOffers": "Explora los beneficios que tenemos para ti por usar SIBU.",
"viewOffers": "Ver Ofertas",
"viewCode": "Ver Código",
"usedAt": "Usado el:",
"claimedAt": "Reclamado el:",
"editProfile": "Editar Perfil",
"photoOptional": "Foto opcional",
"nameLabel": "Nombre Completo",
"namePlaceholder": "Tu nombre",
"passwordOptional": "Nueva Contraseña (Opcional)",
"passwordPlaceholder": "Mínimo 6 caracteres",
"passwordHint": "Déjalo en blanco si no quieres cambiarla.",
"cancel": "Cancelar",
"save": "Guardar Cambios",
"saving": "Guardando...",
"qrTitle": "Cupón de Descuento",
"qrCode": "CÓDIGO DE REDENCIÓN",
"qrInstructions": "Muestra este código al encargado del establecimiento para validar tu promoción.",
"understood": "Entendido",
"pending": "Pendiente",
"redeemed": "Canjeado",
"expired": "Vencido",
"updateSuccess": "Perfil actualizado correctamente",
"updateError": "Error al actualizar:",
"user": "Usuario",
"logoutTitle": "Cerrar Sesión"
},
"auth": {
"back": "Volver",
"brandingSubtitle": "Sistema de Transporte Público",
"loginTab": "Iniciar Sesión",
"registerTab": "Crear Cuenta",
"sessionExpired": "Tu sesión ha expirado. Por favor, inicia sesión nuevamente.",
"footer": "SIBU © 2026 • Sistema de Transporte de Chiriquí",
"googleLogin": "Continuar con Google",
"googleRegister": "Registrarse con Google",
"orEmail": "o con correo",
"emailLabel": "Correo electrónico",
"emailPlaceholder": "tu@correo.com",
"passLabel": "Contraseña",
"keepSession": "Mantener sesión iniciada",
"loggingIn": "Ingresando...",
"creatingAccount": "Creando cuenta...",
"noAccount": "¿No tienes cuenta?",
"registerHere": "Regístrate aquí",
"hasAccount": "¿Ya tienes cuenta?",
"loginHere": "Inicia sesión",
"successTitle": "¡Registro exitoso!",
"fullNameLabel": "Nombre completo",
"fullNamePlaceholder": "Tu nombre",
"passMin8": "Mínimo 8 caracteres",
"smartLocation": "Permitir detectar mi ubicación automáticamente (Smart Location)",
"emailRegistered": "El correo ya está registrado.",
"invalidCreds": "Correo o contraseña incorrectos."
},
"routesView": {
"title": "Transporte",
"busTab": "Rutas de Bus",
"taxiTab": "Taxis Locales",
"originPlaceholder": "Ciudad de Origen",
"destPlaceholder": "Ciudad de Destino",
"searchBtn": "Buscar Rutas",
"allCorregimientos": "Todos los corregimientos",
"english": "Inglés",
"availableRoutes": "Rutas Disponibles",
"recommendedDrivers": "Conductores Recomendados",
"active": "ACTIVA",
"minutes": "min",
"km": "km",
"findSchedules": "Ver Horarios",
"contact": "Contactar",
"noTaxis": "No hay taxis disponibles en esta zona.",
"noRoutes": "No se encontraron rutas para tu búsqueda."
},
"splash": {
"subtitle": "Transporte Público Boquete",
"starting": "Iniciando SIBU...",
"offline": "Iniciando modo sin conexión...",
"verifying": "Verificando datos...",
"ready": "Listo para usar"
},
"report": {
"title": "Enviar Reporte",
"instruction": "Cuéntanos qué sucede o envíanos una sugerencia. El equipo administrativo revisará tu mensaje.",
"placeholder": "Escribe tu mensaje aquí...",
"success": "¡Reporte enviado con éxito! Gracias por tu colaboración.",
"error": "Hubo un error al enviar el reporte. Por favor, intenta de nuevo.",
"cancel": "Cancelar",
"send": "Enviar Reporte"
}
}