fix: extend past bus window to 90min and compact card layout
This commit is contained in:
@ -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(() => {
|
||||
|
||||
@ -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;
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user