feat(map): implement navigation phases and premium ETACard design
This commit is contained in:
@ -41,6 +41,7 @@ const { procesarSeleccionDeRuta } = useFlujoPrincipal();
|
||||
const { limpiarMapa: limpiarTodoCentralizado } = useMapState();
|
||||
|
||||
const showETACard = ref(false);
|
||||
const routePhase = ref<'idle' | 'eta' | 'navigating'>('idle');
|
||||
|
||||
// PERFORMANCE FIX: Use shallowRef for heavy object arrays and Map objects
|
||||
const promoMarkers = shallowRef<any[]>([]);
|
||||
@ -104,6 +105,7 @@ async function animateAndReload() {
|
||||
clearMapMarkers();
|
||||
limpiarCaminata();
|
||||
showETACard.value = false;
|
||||
routePhase.value = 'idle';
|
||||
|
||||
// Recentrar en el usuario si está disponible (soft-reset)
|
||||
if (userCoords.value) {
|
||||
@ -412,25 +414,35 @@ watch([etaCargando, () => busesActivos.value.length], ([loading, count]) => {
|
||||
});
|
||||
*/
|
||||
|
||||
// Cuando el usuario hace drag-down en el ETACard → pasar a fase 'navigating'
|
||||
// Esto muestra el ArrivalBanner arriba y las paradas quedan en el mapa
|
||||
function handleETACardDismiss() {
|
||||
showETACard.value = false;
|
||||
routePhase.value = 'navigating';
|
||||
}
|
||||
|
||||
function handleBannerClick() {
|
||||
// Solo abrir el ETACard, NO borrar paradas ni ruta
|
||||
// Al tocar el banner superior, volver a mostrar el ETACard
|
||||
showETACard.value = true;
|
||||
routePhase.value = 'eta';
|
||||
}
|
||||
|
||||
// Watch for route selection changes
|
||||
watch(() => routeStore.selectedRouteId, (routeId) => {
|
||||
if (routeId) {
|
||||
if (routeStore.wasSelectedFromMap) {
|
||||
// Iniciar dibujo y búsqueda de disponibilidad en paralelo
|
||||
// ETACard se abrirá cuando paradaCercana sea calculada (ver watcher abajo)
|
||||
showETACard.value = false;
|
||||
// Al seleccionar ruta: dibujar mapa + mostrar ETACard (fase 'eta')
|
||||
updateMapMarkers(false);
|
||||
updateActiveUnits();
|
||||
updateActiveUnits();
|
||||
showETACard.value = true;
|
||||
routePhase.value = 'eta';
|
||||
} else {
|
||||
clearMapMarkers();
|
||||
}
|
||||
} else {
|
||||
clearMapMarkers();
|
||||
showETACard.value = false;
|
||||
routePhase.value = 'idle';
|
||||
}
|
||||
});
|
||||
|
||||
@ -439,7 +451,6 @@ watch(() => routeStore.selectedRouteId, (routeId) => {
|
||||
watch(paradaCercana, (newStop) => {
|
||||
if (newStop && routeStore.selectedRouteId) {
|
||||
updateActiveUnits();
|
||||
showETACard.value = true; // Abrir ahora que sí tenemos datos reales
|
||||
}
|
||||
});
|
||||
|
||||
@ -514,7 +525,7 @@ watch([() => authStore.userProfile?.auto_location, isLoaded], ([canLocate, loade
|
||||
>
|
||||
<template #extra-triggers>
|
||||
<ArrivalBanner
|
||||
:is-visible="!!(paradaCercana && routeStore.selectedRouteId && !isBannerClosing && routeStore.wasSelectedFromMap)"
|
||||
:is-visible="routePhase === 'navigating' && !!(paradaCercana && routeStore.selectedRouteId && !isBannerClosing)"
|
||||
:stop-name="paradaCercana?.name || ''"
|
||||
:is-loading="etaCargando"
|
||||
:has-active-buses="busesActivos.length > 0"
|
||||
@ -570,7 +581,7 @@ watch([() => authStore.userProfile?.auto_location, isLoaded], ([canLocate, loade
|
||||
:walk-duration="duracionCaminata"
|
||||
:buses="busesActivos"
|
||||
:is-loading="etaCargando"
|
||||
@close="animateAndReload"
|
||||
@close="handleETACardDismiss"
|
||||
@refresh="paradaCercana && routeStore.selectedRouteId ? calcularETA(routeStore.selectedRouteId, paradaCercana) : null"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user