fix: extend past bus window to 90min and compact card layout

This commit is contained in:
2026-03-29 07:45:31 -05:00
parent f0cbfe8ae7
commit 81e6046357
2 changed files with 35 additions and 28 deletions

View File

@ -78,7 +78,7 @@
</div>
<!-- Contenido de buses -->
<div class="flex flex-col gap-3 py-2">
<div class="flex flex-col gap-2 py-1">
<!-- Estado de carga -->
<div v-if="isLoading" class="flex flex-col items-center justify-center py-8">
<div class="w-10 h-10 border-4 border-blue-500 border-t-transparent rounded-full animate-spin"></div>
@ -100,61 +100,66 @@
<div
v-for="bus in displayBuses"
:key="bus.horario_id"
class="group bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-2xl p-4 flex items-center justify-between transition-all"
class="group bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-2xl p-3 flex items-center justify-between transition-all"
:class="{
'ring-2 ring-green-500/50 dark:ring-green-400/50 bg-green-50/30 dark:bg-green-900/10': bus.estado === 'en_camino',
'opacity-60 grayscale-[0.5]': bus.estado === 'pasó'
'opacity-55 grayscale': bus.estado === 'pasó'
}"
>
<div class="flex items-center gap-4">
<div class="flex items-center gap-3">
<!-- Icono dinámico según estado -->
<div
class="w-12 h-12 rounded-full flex items-center justify-center text-white shrink-0"
class="w-10 h-10 rounded-full flex items-center justify-center text-white shrink-0"
:class="{
'bg-green-500': bus.estado === 'en_camino',
'bg-blue-500': bus.estado === 'próximo',
'bg-gray-400 dark:bg-gray-600': bus.estado === 'pasó'
}"
>
<span class="material-icons">{{ bus.estado === 'pasó' ? 'history' : 'directions_bus' }}</span>
<span class="material-icons text-[20px]">{{ bus.estado === 'pasó' ? 'history' : 'directions_bus' }}</span>
</div>
<div class="flex flex-col">
<span class="text-sm font-bold text-gray-900 dark:text-white line-clamp-1">
<span class="text-xs font-bold text-gray-900 dark:text-white line-clamp-1">
{{ bus.label }}
</span>
<div class="flex flex-col mt-0.5 gap-0.5">
<span class="text-xs font-semibold text-gray-500 dark:text-gray-400 flex items-center gap-1">
<span class="material-icons" style="font-size: 14px">schedule</span>
{{ (bus.estado === 'en_camino' || bus.estado === 'pasó') ? 'Salió a las' : 'Sale a las' }} {{ bus.hora_salida }}
<div class="flex flex-col gap-0">
<span class="text-[11px] font-semibold text-gray-500 dark:text-gray-400 flex items-center gap-1">
<span class="material-icons" style="font-size: 12px">schedule</span>
{{ (bus.estado === 'en_camino' || bus.estado === 'pasó') ? 'Salió' : 'Sale' }} {{ bus.hora_salida }}
</span>
<span class="text-[11px] font-medium text-gray-500 dark:text-gray-400 pl-4">
<span v-if="bus.estado === 'pasó'">Pasó por tu parada a las</span>
<span v-else>Llega a tu parada ~</span>
<span class="text-[10px] font-medium text-gray-500 dark:text-gray-400 pl-4">
<span v-if="bus.estado === 'pasó'">Pasó ~</span>
<span v-else>Llega ~</span>
{{ bus.horaLlegadaParada }}
</span>
</div>
</div>
</div>
<div class="flex flex-col items-end text-right shrink-0 ml-4">
<!-- ETA gigante -->
<div v-if="bus.estado !== 'pasó'" class="text-2xl font-black text-gray-900 dark:text-white flex items-baseline gap-1" :class="{ 'text-green-600 dark:text-green-400': bus.estado === 'en_camino' }">
<div class="flex flex-col items-end text-right shrink-0 ml-2">
<!-- ETA -->
<div v-if="bus.estado !== 'pasó'" class="text-xl font-black text-gray-900 dark:text-white flex items-baseline gap-0.5" :class="{ 'text-green-600 dark:text-green-400': bus.estado === 'en_camino' }">
<span>~{{ formatDurationMinutes(bus.etaMinutos) }}</span>
<span class="text-sm font-bold text-gray-500 dark:text-gray-400">min</span>
<span class="text-xs font-bold text-gray-500 dark:text-gray-400">min</span>
</div>
<!-- Para pasó: mostrar cuántos minutos hace -->
<div v-else class="text-xl font-black text-gray-400 dark:text-gray-500 flex items-baseline gap-0.5">
<span>{{ Math.abs(bus.etaMinutos) }}</span>
<span class="text-xs font-bold text-gray-400 dark:text-gray-500">min</span>
</div>
<!-- Badges de estado -->
<div class="mt-1">
<span v-if="bus.estado === 'en_camino'" class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-lg bg-green-100 dark:bg-green-900/40 text-green-700 dark:text-green-400 text-[10px] font-black uppercase tracking-wider">
<div class="mt-0.5">
<span v-if="bus.estado === 'en_camino'" class="inline-flex items-center gap-1 px-2 py-0.5 rounded-lg bg-green-100 dark:bg-green-900/40 text-green-700 dark:text-green-400 text-[9px] font-black uppercase tracking-wider">
<span class="w-1.5 h-1.5 bg-green-500 rounded-full animate-ping"></span>
En Vía
</span>
<span v-else-if="bus.estado === 'próximo'" class="inline-flex px-2.5 py-1 rounded-lg bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-400 text-[10px] font-black uppercase tracking-wider">
<span v-else-if="bus.estado === 'próximo'" class="inline-flex px-2 py-0.5 rounded-lg bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-400 text-[9px] font-black uppercase tracking-wider">
Programado
</span>
<span v-else class="inline-flex px-2.5 py-1 rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400 text-[10px] font-black uppercase tracking-wider">
Ya pasó
<span v-else class="inline-flex px-2 py-0.5 rounded-lg bg-gray-100 dark:bg-gray-800 text-gray-400 dark:text-gray-500 text-[9px] font-black uppercase tracking-wider">
Hace poco
</span>
</div>
</div>
@ -197,8 +202,8 @@ const showTooltip = ref(false);
const upcomingBuses = computed(() => props.buses.filter(b => b.estado !== 'pasó'));
const lastPastBus = computed(() => {
const pastBuses = props.buses.filter(b => b.estado === 'pasó');
// useETA ordena por etaMinutos asc, así que en negativos (-20, -10, -5) el último es el más reciente
return pastBuses.length > 0 ? pastBuses[pastBuses.length - 1] : null;
// useETA ordena pasó descendente (más reciente primero), tomamos [0]
return pastBuses.length > 0 ? pastBuses[0] : null;
});
const displayBuses = computed(() => {

View File

@ -159,9 +159,9 @@ export function useETA() {
estado = 'pasó';
}
// Conservar buses que pasaron hace poco (ej: últimos 30 minutos)
// para que el usuario sepa que acaba de perder uno
if (etaMinutos < -30) continue;
// Conservar buses que pasaron en la última hora y media
// para que el usuario siempre vea el bus anterior
if (etaMinutos < -90) continue;
resultados.push({
horario_id: h.id,
@ -175,6 +175,8 @@ export function useETA() {
resultados.sort((a, b) => {
const prioridad = { 'en_camino': 0, 'próximo': 1, 'pasó': 2 };
if (prioridad[a.estado] !== prioridad[b.estado]) return prioridad[a.estado] - prioridad[b.estado];
// Para pasó: ordenar descendente (menos negativo primero = más reciente primero)
if (a.estado === 'pasó') return b.etaMinutos - a.etaMinutos;
return a.etaMinutos - b.etaMinutos;
});