fix: corregir paradas faltantes, duplicado de ubicación y alineación de botones

This commit is contained in:
2026-03-02 09:23:29 -05:00
parent 9c90a175cc
commit 5fb6ab812a
2 changed files with 8 additions and 65 deletions

View File

@ -4,7 +4,6 @@ import { useDirectionsRoute } from './useDirectionsRoute'
import { useParadaCercana } from './useParadaCercana' import { useParadaCercana } from './useParadaCercana'
import type { BusStop } from '@/types' import type { BusStop } from '@/types'
import { useRouteStore } from '@/stores/route' import { useRouteStore } from '@/stores/route'
import { useGoogleMaps } from './useGoogleMaps'
export const useFlujoPrincipal = () => { export const useFlujoPrincipal = () => {
const { limpiarMapa } = useMapState() const { limpiarMapa } = useMapState()
@ -30,6 +29,7 @@ export const useFlujoPrincipal = () => {
_ruta: { id: string }, _ruta: { id: string },
paradas: BusStop[], paradas: BusStop[],
map: google.maps.Map | undefined, map: google.maps.Map | undefined,
addCleanMarker: Function,
skipGuidedZoom = false skipGuidedZoom = false
) => { ) => {
if (!map) return if (!map) return
@ -40,7 +40,6 @@ export const useFlujoPrincipal = () => {
cargando.value = true cargando.value = true
// ── PASO 2: Obtener ubicación ── // ── PASO 2: Obtener ubicación ──
// Paradas ya vienen precargadas desde store para evitar doble fetch
let ubicacion: { lat: number, lng: number } | null = null; let ubicacion: { lat: number, lng: number } | null = null;
try { try {
ubicacion = await obtenerUbicacion(); ubicacion = await obtenerUbicacion();
@ -48,7 +47,6 @@ export const useFlujoPrincipal = () => {
console.warn('SIBU | No se pudo obtener ubicación', err); console.warn('SIBU | No se pudo obtener ubicación', err);
} }
// Format Paradas for trazarRuta
const paradasFormateadas = paradas.map((p, i) => ({ const paradasFormateadas = paradas.map((p, i) => ({
id: typeof p.id === 'string' ? parseInt(p.id) || i : p.id || i, id: typeof p.id === 'string' ? parseInt(p.id) || i : p.id || i,
nombre: p.name, nombre: p.name,
@ -57,11 +55,9 @@ export const useFlujoPrincipal = () => {
orden: i orden: i
})); }));
// Si no hay paradas o muy pocas, abortar
if (paradasFormateadas.length < 2) return; if (paradasFormateadas.length < 2) return;
if (!ubicacion) { if (!ubicacion) {
// Fallback: solo dibujar la ruta sin parada cercana (o podríamos no hacer zoom guiado)
await trazarRuta(paradasFormateadas, map, false); await trazarRuta(paradasFormateadas, map, false);
return; return;
} }
@ -71,7 +67,6 @@ export const useFlujoPrincipal = () => {
// ── PASO 4: Calcular parada más cercana (Omitir si skipGuidedZoom) ─────────────── // ── PASO 4: Calcular parada más cercana (Omitir si skipGuidedZoom) ───────────────
if (skipGuidedZoom) { if (skipGuidedZoom) {
// Si omitimos el zoom guiado, solo hacemos un zoom general a la ruta
const bounds = new google.maps.LatLngBounds() const bounds = new google.maps.LatLngBounds()
paradasFormateadas.forEach(p => bounds.extend(new google.maps.LatLng(p.latitud, p.longitud))) paradasFormateadas.forEach(p => bounds.extend(new google.maps.LatLng(p.latitud, p.longitud)))
map.fitBounds(bounds, { top: 100, bottom: 100, left: 60, right: 60 }) map.fitBounds(bounds, { top: 100, bottom: 100, left: 60, right: 60 })
@ -79,21 +74,13 @@ export const useFlujoPrincipal = () => {
} }
await encontrarParadaCercana(ubicacion, paradas, map) await encontrarParadaCercana(ubicacion, paradas, map)
const paradaCercanaFound = paradaCercana.value const paradaCercanaFound = paradaCercana.value
if (!paradaCercanaFound) return;
if (!paradaCercanaFound) {
return;
}
const routeStore = useRouteStore() const routeStore = useRouteStore()
if (routeStore.selectedRouteId !== _ruta.id) { if (routeStore.selectedRouteId !== _ruta.id) return;
console.log('Abortando flujo: el mapa fue limpiado o cambió de ruta.')
return;
}
// ── PASO 5: Dibujar tramo relevante (Amarillo Vivo) ─────── // ── PASO 5: Dibujar tramo relevante (Amarillo Vivo) ───────
// Usar una comparación más robusta que incluya proximidad o nombre
const idx = paradasFormateadas.findIndex(p => { const idx = paradasFormateadas.findIndex(p => {
const samePos = Math.abs(p.longitud - paradaCercanaFound.longitude) < 0.0001 && const samePos = Math.abs(p.longitud - paradaCercanaFound.longitude) < 0.0001 &&
Math.abs(p.latitud - paradaCercanaFound.latitude) < 0.0001; Math.abs(p.latitud - paradaCercanaFound.latitude) < 0.0001;
@ -107,8 +94,7 @@ export const useFlujoPrincipal = () => {
} }
} }
// ── PASO 6: Dibujar marcadores de todas las paradas (Restaurado) ────────── // ── PASO 6: Dibujar marcadores de todas las paradas ──────────
const { addCleanMarker } = useGoogleMaps()
paradasFormateadas.forEach((p, i) => { paradasFormateadas.forEach((p, i) => {
const esCercana = i === idx; const esCercana = i === idx;
const esPasada = idx !== -1 && i < idx; const esPasada = idx !== -1 && i < idx;
@ -123,10 +109,7 @@ export const useFlujoPrincipal = () => {
); );
}); });
// ── PASO 7: Pulso animado en ubicación del usuario ─── // ── PASO 7: Zoom centrado en usuario + parada cercana
dibujarPulsoUsuario(ubicacion, map)
// ── PASO 8: Zoom centrado en usuario + parada cercana ─
hacerZoomAlTramoRelevante(ubicacion, paradaCercanaFound, map) hacerZoomAlTramoRelevante(ubicacion, paradaCercanaFound, map)
} catch (error) { } catch (error) {
@ -137,47 +120,6 @@ export const useFlujoPrincipal = () => {
} }
} }
// PULSO ANIMADO EN LA UBICACIÓN DEL USUARIO:
const dibujarPulsoUsuario = (
ubicacion: { lat: number, lng: number },
map: google.maps.Map
) => {
const { registrarCircle, registrarMarker } = useMapState()
// Círculo exterior pulsante (efecto ripple)
registrarCircle(
new google.maps.Circle({
map,
center: ubicacion,
radius: 80, // metros
fillColor: '#3B82F6',
fillOpacity: 0.15,
strokeColor: '#3B82F6',
strokeOpacity: 0.4,
strokeWeight: 1,
zIndex: 1
})
)
// Punto central sólido del usuario
registrarMarker(
new google.maps.Marker({
position: ubicacion,
map,
icon: {
path: google.maps.SymbolPath.CIRCLE,
fillColor: '#3B82F6', // azul
fillOpacity: 1,
strokeColor: '#FFFFFF',
strokeWeight: 3,
scale: 9
},
title: 'Tu ubicación',
zIndex: 20 // encima de todo
})
)
}
// ZOOM QUE MUESTRA USUARIO Y PARADA CERCANA: // ZOOM QUE MUESTRA USUARIO Y PARADA CERCANA:
const hacerZoomAlTramoRelevante = ( const hacerZoomAlTramoRelevante = (
ubicacion: { lat: number, lng: number }, ubicacion: { lat: number, lng: number },

View File

@ -32,7 +32,7 @@ const mapStore = useMapStore();
const couponStore = useCouponStore(); const couponStore = useCouponStore();
const authStore = useAuthStore(); const authStore = useAuthStore();
const { map, isLoaded, error: mapsError, initMap, addHtmlMarker, setCenter, setZoom, addMarker } = useGoogleMaps(); const { map, isLoaded, error: mapsError, initMap, addHtmlMarker, setCenter, setZoom, addMarker, addCleanMarker } = useGoogleMaps();
const { estasCargando: estasCargandoRuta, errorRuta } = useDirectionsRoute(); const { estasCargando: estasCargandoRuta, errorRuta } = useDirectionsRoute();
const { encontrarParadaCercana, paradaCercana, distanciaMetros, duracionCaminata } = useParadaCercana(); const { encontrarParadaCercana, paradaCercana, distanciaMetros, duracionCaminata } = useParadaCercana();
const { calcularETA, busesActivos, cargando: etaCargando } = useETA(); const { calcularETA, busesActivos, cargando: etaCargando } = useETA();
@ -202,7 +202,7 @@ async function updateMapMarkers(skipZoom = false) {
} }
const selectedRouteObj = routeStore.allRoutes.find(r => r.id === currentRequestRouteId) || { id: currentRequestRouteId, short_name: currentRequestRouteId }; const selectedRouteObj = routeStore.allRoutes.find(r => r.id === currentRequestRouteId) || { id: currentRequestRouteId, short_name: currentRequestRouteId };
await procesarSeleccionDeRuta(selectedRouteObj, stops as BusStop[], map.value, skipZoom); await procesarSeleccionDeRuta(selectedRouteObj, stops as BusStop[], map.value, addCleanMarker, skipZoom);
reDrawUserMarker(); reDrawUserMarker();
if (routeStore.selectedRouteId !== currentRequestRouteId) return; if (routeStore.selectedRouteId !== currentRequestRouteId) return;
@ -553,6 +553,7 @@ watch(() => authStore.userProfile?.auto_location, (canLocate) => {
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
z-index: 1001; z-index: 1001;
align-items: flex-end; /* Alinea botones a la derecha */
} }
.offers-fab { .offers-fab {