Spaces:
Running
Running
| /** | |
| * Geolocation Service | |
| * Migrated from Angular geolocation.service.ts | |
| */ | |
| const geolocationService = { | |
| /** | |
| * Get current GPS coordinates | |
| */ | |
| async getCurrentPosition() { | |
| return new Promise((resolve, reject) => { | |
| if (!navigator.geolocation) { | |
| reject(new Error('Geolocation no est谩 soportada por este navegador')); | |
| return; | |
| } | |
| navigator.geolocation.getCurrentPosition( | |
| (position) => { | |
| resolve({ | |
| latitude: position.coords.latitude, | |
| longitude: position.coords.longitude, | |
| accuracy: position.coords.accuracy, | |
| timestamp: new Date(position.timestamp) | |
| }); | |
| }, | |
| (error) => { | |
| let errorMessage = 'Error obteniendo ubicaci贸n'; | |
| switch (error.code) { | |
| case error.PERMISSION_DENIED: | |
| errorMessage = 'Permiso de ubicaci贸n denegado'; | |
| break; | |
| case error.POSITION_UNAVAILABLE: | |
| errorMessage = 'Ubicaci贸n no disponible'; | |
| break; | |
| case error.TIMEOUT: | |
| errorMessage = 'Tiempo de espera agotado'; | |
| break; | |
| } | |
| reject(new Error(errorMessage)); | |
| }, | |
| { | |
| enableHighAccuracy: true, | |
| timeout: 60000, // 60 seconds for full hardware satellite lock | |
| maximumAge: 0 // Force fresh location every time | |
| } | |
| ); | |
| }); | |
| }, | |
| /** | |
| * Watch position for continuous tracking | |
| */ | |
| watchPosition(onSuccess, onError) { | |
| if (!navigator.geolocation) { | |
| onError(new Error('Geolocation no est谩 soportada')); | |
| return null; | |
| } | |
| return navigator.geolocation.watchPosition( | |
| (position) => { | |
| onSuccess({ | |
| latitude: position.coords.latitude, | |
| longitude: position.coords.longitude, | |
| accuracy: position.coords.accuracy, | |
| timestamp: new Date(position.timestamp) | |
| }); | |
| }, | |
| (error) => { | |
| onError(error); | |
| }, | |
| { | |
| enableHighAccuracy: true, | |
| timeout: 60000, | |
| maximumAge: 0 | |
| } | |
| ); | |
| }, | |
| /** | |
| * Clear position watch | |
| */ | |
| clearWatch(watchId) { | |
| if (watchId && navigator.geolocation) { | |
| navigator.geolocation.clearWatch(watchId); | |
| } | |
| }, | |
| /** | |
| * Get address name from coordinates using OpenStreetMap Nominatim | |
| */ | |
| async getAddress(latitude, longitude) { | |
| try { | |
| if (!navigator.onLine) return null; | |
| const response = await fetch( | |
| `https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&zoom=18&addressdetails=1` | |
| ); | |
| if (!response.ok) throw new Error('Error al consultar el servicio de direcciones'); | |
| const data = await response.json(); | |
| // Try to get a meaningful name | |
| const address = data.address; | |
| if (!address) return data.display_name || null; | |
| // Enhanced Marine-aware priority: search for natural features first | |
| const place = address.natural || address.water || address.beach || | |
| address.island || address.islet || address.sea || | |
| address.suburb || address.neighbourhood || address.village || | |
| address.town || address.city || address.county || address.state; | |
| return place ? `${place}, RD` : data.display_name; | |
| } catch (error) { | |
| console.warn('Geocoding error:', error); | |
| return null; | |
| } | |
| } | |
| }; | |