/** * ETA Progress Bar * ERP Transportistas * Sprint S7 - TASK-007 * * Visual progress indicator for trip ETA. */ import { TipoEventoTracking } from '../types'; interface ETAProgressBarProps { progreso: number; etaOriginal: string; etaActual: string; ultimoEvento?: TipoEventoTracking; } const etapaLabels: Record = { [TipoEventoTracking.POSICION]: 'En ruta', [TipoEventoTracking.SALIDA]: 'Salida', [TipoEventoTracking.ARRIBO_ORIGEN]: 'En origen', [TipoEventoTracking.INICIO_CARGA]: 'Cargando', [TipoEventoTracking.FIN_CARGA]: 'Carga lista', [TipoEventoTracking.ARRIBO_DESTINO]: 'En destino', [TipoEventoTracking.INICIO_DESCARGA]: 'Descargando', [TipoEventoTracking.FIN_DESCARGA]: 'Descarga lista', [TipoEventoTracking.ENTREGA_POD]: 'Entregado', [TipoEventoTracking.DESVIO]: 'Desvío', [TipoEventoTracking.PARADA]: 'Detenido', [TipoEventoTracking.INCIDENTE]: 'Incidente', [TipoEventoTracking.GPS_POSICION]: 'En ruta', [TipoEventoTracking.GEOCERCA_ENTRADA]: 'Entrando zona', [TipoEventoTracking.GEOCERCA_SALIDA]: 'Saliendo zona', }; export function ETAProgressBar({ progreso, etaOriginal, etaActual, ultimoEvento, }: ETAProgressBarProps) { const etaOriginalDate = new Date(etaOriginal); const etaActualDate = new Date(etaActual); const diferenciaMinutos = Math.round( (etaActualDate.getTime() - etaOriginalDate.getTime()) / 60000 ); const getStatusColor = () => { if (diferenciaMinutos <= 0) return 'bg-green-500'; if (diferenciaMinutos <= 30) return 'bg-yellow-500'; return 'bg-red-500'; }; const getStatusText = () => { if (diferenciaMinutos <= 0) return 'A tiempo'; if (diferenciaMinutos <= 30) return `+${diferenciaMinutos} min`; const horas = Math.floor(diferenciaMinutos / 60); const mins = diferenciaMinutos % 60; return horas > 0 ? `+${horas}h ${mins}m` : `+${mins} min`; }; const milestones = [ { label: 'Salida', position: 0 }, { label: 'Carga', position: 25 }, { label: 'En ruta', position: 50 }, { label: 'Descarga', position: 75 }, { label: 'POD', position: 100 }, ]; return (
{/* Status row */}
Progreso: {ultimoEvento && ( {etapaLabels[ultimoEvento] || ultimoEvento} )}
{getStatusText()}
{/* Progress bar */}
{/* Milestone markers */}
{milestones.map((milestone, index) => (
= milestone.position ? 'border-white bg-white' : 'border-gray-400 bg-gray-200' }`} />
))}
{/* Milestone labels */}
{milestones.map((milestone) => (
{milestone.label}
))}
{/* ETA comparison */}
ETA Original: {etaOriginalDate.toLocaleString('es-MX', { dateStyle: 'short', timeStyle: 'short', })}
ETA Actual: 0 ? 'text-red-600' : 'text-green-600'}`}> {etaActualDate.toLocaleString('es-MX', { dateStyle: 'short', timeStyle: 'short', })}
); }