import { ref } from 'vue'; import { useMapState } from './useMapState'; export interface Parada { id: number; nombre: string; latitud: number; longitud: number; orden: number; } export function useDirectionsRoute() { const estasCargando = ref(false); const errorRuta = ref(null); const { registrarPolyline, polylines } = useMapState(); // Limpia los tramos anteriores dibujados en el mapa const limpiarRuta = () => { if (polylines.value.length > 0) { polylines.value.forEach((polyline) => { polyline.setMap(null); }); polylines.value = []; } errorRuta.value = null; }; // Función utilitaria para pausar ejecución const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); const trazarRuta = async (paradas: Parada[], map: google.maps.Map, isPast: boolean = false) => { if (!paradas || paradas.length < 2) { errorRuta.value = 'Se requieren al menos 2 paradas para trazar una ruta.'; return; } // NOTA: No llamamos a limpiarRuta() aquí para poder encadenar llamadas (dibujar fondo + trazado activo) estasCargando.value = true; errorRuta.value = null; try { // Importar librerías necesarias de la nueva API const { RoutesService } = await google.maps.importLibrary("routes") as any; const routeService = new RoutesService(); // Límite de la API de Google Maps Routes: Origen, Destino, y hasta 25 intermediates const maxPuntosPorChunk = 25; const overlaps = 1; for (let i = 0; i < paradas.length - 1; i += (maxPuntosPorChunk - overlaps)) { const chunk = paradas.slice(i, i + maxPuntosPorChunk); if (chunk.length < 2) break; const origin = { location: { latLng: { latitude: chunk[0]!.latitud, longitude: chunk[0]!.longitud } } }; const destination = { location: { latLng: { latitude: chunk[chunk.length - 1]!.latitud, longitude: chunk[chunk.length - 1]!.longitud } } }; const intermediates = chunk.slice(1, -1).map(p => ({ location: { latLng: { latitude: p.latitud, longitude: p.longitud } } })); try { const response = await routeService.computeRoutes({ origin, destination, intermediates, travelMode: 'DRIVE' as any, // 'DRIVE' es el nuevo estandar en computeRoutes routingPreference: 'TRAFFIC_UNAWARE' as any, polylineQuality: 'HIGH_QUALITY' as any, polylineEncoding: 'ENCODED_POLYLINE' as any, }); if (response.routes && response.routes.length > 0) { const route = response.routes[0]; if (route.polyline && route.polyline.encodedPolyline) { const path = google.maps.geometry.encoding.decodePath(route.polyline.encodedPolyline); const polyline = new google.maps.Polyline({ path: path, map: map, strokeColor: isPast ? '#9CA3AF' : '#FBBF24', // Gris para lo lejano, Amarillo para lo cercano strokeWeight: isPast ? 4 : 6, strokeOpacity: isPast ? 0.6 : 1.0, icons: isPast ? [{ icon: { path: 'M 0,-1 0,1', strokeOpacity: 1, scale: 2 }, offset: '0', repeat: '10px' }] : [] }); registrarPolyline(polyline); } } } catch (err: any) { console.warn(`SIBU | Tramo ${i} falló con Routes API: `, err); } await delay(200); } } catch (err: any) { errorRuta.value = `Error crítico al trazar la ruta: ${err.message || String(err)}`; console.error(errorRuta.value); } finally { estasCargando.value = false; } }; return { trazarRuta, limpiarRuta, estasCargando, errorRuta }; }