chore: apply finalized MapView and ETA card fixes

This commit is contained in:
2026-02-27 12:22:15 -05:00
parent bddb8916ba
commit 504e61bfb2
4 changed files with 158 additions and 57 deletions

View File

@ -107,23 +107,24 @@ function closeUberSearch() {
}
async function clearAllMapData() {
console.log('🤖 JARVIS: Iniciando PURGA nuclear con tolerancia a fallos...');
// 1. Respuesta inmediata en UI
console.log('🤖 JARVIS: Iniciando PURGA nuclear...');
// 1. UI inmediata
showUberSearch.value = false;
showRoutesToggle.value = false;
destinationQuery.value = "";
stopSearchQuery.value = "";
showETACard.value = false;
// 2. Invalidar cualquier hilo de dibujo en curso
// 2. Invalidar hilos en curso
mappingSequenceId.value++;
try {
// 3. Resetear Store
// 3. Resetear stores
routeStore.clearSelection();
lastProcessedRouteId.value = null;
// 4. Limpieza manual protegida de marcadores
// 4. Limpiar markers locales
const sweep = (arrayRef: any) => {
if (!arrayRef.value) return;
arrayRef.value.forEach((m: any) => {
@ -134,8 +135,8 @@ async function clearAllMapData() {
sweep(markers);
sweep(promoMarkers);
// Limpiar Unidades de transporte
// Limpiar unidades de transporte
if (unitMarkers.value) {
unitMarkers.value.forEach((m: any) => {
try { if (m && m.setMap) m.setMap(null); } catch (e) {}
@ -143,37 +144,75 @@ async function clearAllMapData() {
unitMarkers.value.clear();
}
// 5. Barrido profundo de Google
// 5. Limpiar polilíneas (CORREGIDO: agregar walkingPolylineBorder)
if (polyline.value) {
polyline.value.setMap(null);
polyline.value = null;
}
if (walkingPolyline.value) {
walkingPolyline.value.setMap(null);
walkingPolyline.value = null;
}
// ✅ NUEVO: limpiar el borde blanco de la ruta caminando
if (walkingPolylineBorder.value) {
walkingPolylineBorder.value.setMap(null);
walkingPolylineBorder.value = null;
}
// 6. Limpiar pulso de parada óptima (CORREGIDO)
if (optimalStopPulse.value) {
try {
// Intentar setMap primero
if (typeof optimalStopPulse.value.setMap === 'function') {
optimalStopPulse.value.setMap(null);
}
// Si es un overlay HTML, también intentar remove()
if (typeof optimalStopPulse.value.remove === 'function') {
optimalStopPulse.value.remove();
}
// Si tiene onRemove (OverlayView pattern)
if (typeof optimalStopPulse.value.onRemove === 'function') {
optimalStopPulse.value.onRemove();
}
} catch(e) {
console.warn('SIBU | No se pudo limpiar optimalStopPulse:', e);
}
optimalStopPulse.value = null;
}
// 7. Limpiar composables
limpiarCaminata();
// 8. Barrido profundo de Google Maps overlays
if (typeof clearAllOverlays === 'function') {
try { clearAllOverlays(); } catch (e) {}
}
// 6. Limpiar polilíneas y pulsos
if (polyline.value) { polyline.value.setMap(null); polyline.value = null; }
if (walkingPolyline.value) { walkingPolyline.value.setMap(null); walkingPolyline.value = null; }
if (optimalStopPulse.value) {
try { if (optimalStopPulse.value.setMap) optimalStopPulse.value.setMap(null); } catch(e){}
optimalStopPulse.value = null;
}
limpiarCaminata();
showETACard.value = false;
// Nueva Purgación Centralizada:
// 9. Purgación centralizada (useMapState)
limpiarTodoCentralizado();
// 7. Restaurar Solo Usuario tras un breve respiro
// 10. Restaurar SOLO el marcador del usuario
await nextTick();
if (userCoords.value) {
const { lat, lng } = userCoords.value;
if (userMarker.value && userMarker.value.setMap) {
try { userMarker.value.setMap(null); } catch(e){}
// Limpiar marcador anterior del usuario
if (userMarker.value) {
try {
if (userMarker.value.setMap) userMarker.value.setMap(null);
if (userMarker.value.remove) userMarker.value.remove();
} catch(e) {}
}
userMarker.value = addHtmlMarker({ lat, lng }, sonarHtml, { x: -30, y: -30 });
// Redibujar solo el sonar del usuario
userMarker.value = addHtmlMarker(
{ lat, lng },
sonarHtml,
{ x: -30, y: -30 }
);
}
console.log('🤖 JARVIS: Purga completada con éxito.');
console.log('🤖 JARVIS: Purga completada. Solo queda el usuario ✓');
} catch (err) {
console.error('❌ JARVIS: Error crítico en purga, pero el mapa debería estar limpio:', err);
console.error('❌ JARVIS: Error en purga:', err);
}
}
@ -344,6 +383,11 @@ async function initializeMap() {
map.value.addListener('zoom_changed', () => {
updateMarkersStyles();
});
map.value.addListener('click', () => {
if (showETACard.value) {
showETACard.value = false;
}
});
}
// If we have a selected route, show its stops
@ -626,9 +670,18 @@ async function highlightOptimalStopForRoute() {
{ x: -30, y: -30 }
);
// Calcular ETAs
// PASO 1: Mostrar ETACard inferior primero
await calcularETA(routeStore.selectedRouteId!, stopObj);
showETACard.value = true;
// PASO 2: Esperar 2 segundos antes de mostrar el banner superior
// para que no saturen la pantalla al mismo tiempo
await new Promise(resolve => setTimeout(resolve, 2000));
// PASO 3: Mostrar banner superior solo si ETACard sigue abierto
// (si el usuario ya cerró el ETACard, no mostrar el banner)
// paradaCercana ya tiene el valor, el banner aparece automáticamente
// porque usa v-if="paradaCercana && routeStore.selectedRouteId && !showETACard"
}
}
@ -756,26 +809,22 @@ function calculateWalkingPath(origin: { lat: number, lng: number }, targetStop:
<!-- Banner de Parada Más Cercana Inteligente -->
<div
v-if="paradaCercana && routeStore.selectedRouteId"
v-if="paradaCercana && routeStore.selectedRouteId && !showETACard"
class="fixed left-0 right-0 z-40 px-3 transition-transform duration-300 pointer-events-none"
:style="{ top: alturaNavbar + 'px' }"
>
<div class="bg-white dark:bg-gray-900 rounded-b-2xl shadow-xl border-t-4 border-blue-600 border-t-blue-600 p-3 flex items-center gap-3 pointer-events-auto">
<div class="bg-blue-100 dark:bg-blue-900/40 rounded-full p-2 shrink-0">
<span class="material-icons text-blue-600 dark:text-blue-400">directions_bus</span>
</div>
<div class="flex-1 min-w-0">
<p class="text-[11px] text-gray-500 font-bold uppercase">Parada más cercana</p>
<p class="text-sm font-bold text-gray-800 dark:text-white truncate">
{{ paradaCercana?.name }}
</p>
<p class="text-xs text-blue-600 dark:text-blue-400 font-medium whitespace-nowrap overflow-hidden text-ellipsis">
{{ (distanciaMetros && distanciaMetros < 1000) ? Math.round(distanciaMetros) + ' m' : (distanciaMetros ? (distanciaMetros / 1000).toFixed(1) + ' km' : '') }}
<span v-if="duracionCaminata">· {{ Math.round(duracionCaminata / 60) }} min caminando</span>
</p>
</div>
<button @click="paradaCercana = null" class="text-gray-400 hover:text-gray-600 shrink-0 p-1">
<span class="material-icons">close</span>
<!-- Solo mostrar cuando ETACard está CERRADO -->
<!-- v-if agrega condición: && !showETACard -->
<div class="bg-white/90 dark:bg-gray-900/90 backdrop-blur-sm rounded-b-2xl shadow-lg border-t-2 border-yellow-400 px-4 py-2 flex items-center gap-2 pointer-events-auto">
<span class="material-icons text-yellow-500 text-sm">directions_bus</span>
<span class="text-sm font-bold text-gray-800 dark:text-white truncate flex-1">
{{ paradaCercana?.name }}
</span>
<span class="text-xs text-gray-500 whitespace-nowrap">
{{ (distanciaMetros && distanciaMetros < 1000) ? Math.round(distanciaMetros) + 'm' : (distanciaMetros ? (distanciaMetros / 1000).toFixed(1) + 'km' : '') }}
</span>
<button @click="paradaCercana = null" class="text-gray-400 hover:text-gray-600 shrink-0 p-0.5 ml-1">
<span class="material-icons text-sm">close</span>
</button>
</div>
</div>