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 type { BusStop } from '@/types'
import { useRouteStore } from '@/stores/route'
import { useGoogleMaps } from './useGoogleMaps'
export const useFlujoPrincipal = () => {
const { limpiarMapa } = useMapState()
@ -30,6 +29,7 @@ export const useFlujoPrincipal = () => {
_ruta: { id: string },
paradas: BusStop[],
map: google.maps.Map | undefined,
addCleanMarker: Function,
skipGuidedZoom = false
) => {
if (!map) return
@ -40,7 +40,6 @@ export const useFlujoPrincipal = () => {
cargando.value = true
// ── PASO 2: Obtener ubicación ──
// Paradas ya vienen precargadas desde store para evitar doble fetch
let ubicacion: { lat: number, lng: number } | null = null;
try {
ubicacion = await obtenerUbicacion();
@ -48,7 +47,6 @@ export const useFlujoPrincipal = () => {
console.warn('SIBU | No se pudo obtener ubicación', err);
}
// Format Paradas for trazarRuta
const paradasFormateadas = paradas.map((p, i) => ({
id: typeof p.id === 'string' ? parseInt(p.id) || i : p.id || i,
nombre: p.name,
@ -57,11 +55,9 @@ export const useFlujoPrincipal = () => {
orden: i
}));
// Si no hay paradas o muy pocas, abortar
if (paradasFormateadas.length < 2) return;
if (!ubicacion) {
// Fallback: solo dibujar la ruta sin parada cercana (o podríamos no hacer zoom guiado)
await trazarRuta(paradasFormateadas, map, false);
return;
}
@ -71,7 +67,6 @@ export const useFlujoPrincipal = () => {
// ── PASO 4: Calcular parada más cercana (Omitir si skipGuidedZoom) ───────────────
if (skipGuidedZoom) {
// Si omitimos el zoom guiado, solo hacemos un zoom general a la ruta
const bounds = new google.maps.LatLngBounds()
paradasFormateadas.forEach(p => bounds.extend(new google.maps.LatLng(p.latitud, p.longitud)))
map.fitBounds(bounds, { top: 100, bottom: 100, left: 60, right: 60 })
@ -79,21 +74,13 @@ export const useFlujoPrincipal = () => {
}
await encontrarParadaCercana(ubicacion, paradas, map)
const paradaCercanaFound = paradaCercana.value
if (!paradaCercanaFound) {
return;
}
if (!paradaCercanaFound) return;
const routeStore = useRouteStore()
if (routeStore.selectedRouteId !== _ruta.id) {
console.log('Abortando flujo: el mapa fue limpiado o cambió de ruta.')
return;
}
if (routeStore.selectedRouteId !== _ruta.id) return;
// ── 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 samePos = Math.abs(p.longitud - paradaCercanaFound.longitude) < 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) ──────────
const { addCleanMarker } = useGoogleMaps()
// ── PASO 6: Dibujar marcadores de todas las paradas ──────────
paradasFormateadas.forEach((p, i) => {
const esCercana = i === idx;
const esPasada = idx !== -1 && i < idx;
@ -123,10 +109,7 @@ export const useFlujoPrincipal = () => {
);
});
// ── PASO 7: Pulso animado en ubicación del usuario ───
dibujarPulsoUsuario(ubicacion, map)
// ── PASO 8: Zoom centrado en usuario + parada cercana ─
// ── PASO 7: Zoom centrado en usuario + parada cercana
hacerZoomAlTramoRelevante(ubicacion, paradaCercanaFound, map)
} 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:
const hacerZoomAlTramoRelevante = (
ubicacion: { lat: number, lng: number },

View File

@ -32,7 +32,7 @@ const mapStore = useMapStore();
const couponStore = useCouponStore();
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 { encontrarParadaCercana, paradaCercana, distanciaMetros, duracionCaminata } = useParadaCercana();
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 };
await procesarSeleccionDeRuta(selectedRouteObj, stops as BusStop[], map.value, skipZoom);
await procesarSeleccionDeRuta(selectedRouteObj, stops as BusStop[], map.value, addCleanMarker, skipZoom);
reDrawUserMarker();
if (routeStore.selectedRouteId !== currentRequestRouteId) return;
@ -553,6 +553,7 @@ watch(() => authStore.userProfile?.auto_location, (canLocate) => {
flex-direction: column;
gap: 16px;
z-index: 1001;
align-items: flex-end; /* Alinea botones a la derecha */
}
.offers-fab {