erp-transportistas-v2/docs/20-frontend/MAPA-TRACKING-RT.md
Adrian Flores Cortes 6ed7f9e2ec [BACKUP] Pre-restructure workspace backup 2026-01-29
- Updated docs and inventory files
- Added new architecture docs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 17:35:54 -06:00

6.9 KiB

Mapa de Tracking en Tiempo Real - Documentacion Tecnica

Feature: tracking Sprint: S7 Estado: Funcional (mapas pendientes) Fecha: 2026-01-28


1. Vision General

El sistema de tracking en tiempo real permite:

  • Visualizar posicion actual de unidades en mapa
  • Ver historial de ruta recorrida
  • Monitorear eventos y alertas
  • Calcular y mostrar ETA dinamico
  • Recibir actualizaciones via WebSocket

2. Arquitectura de Componentes

ViajeTrackingView
├── MapSection (mapa con ruta)
│   ├── RoutePolyline (ruta planificada)
│   ├── HistoryPolyline (ruta recorrida)
│   ├── CurrentPositionMarker
│   ├── OriginMarker
│   └── DestinationMarker
├── ETAProgressBar
│   ├── MilestoneIndicators
│   └── ProgressLine
└── EventTimeline
    ├── EventCards (17 tipos)
    └── TimelineConnector

3. Tipos Principales

3.1 ENUMs

enum TipoEventoTracking {
  // GPS
  POSICION = 'POSICION',
  GPS_POSICION = 'GPS_POSICION',

  // Geocercas
  GEOCERCA_ENTRADA = 'GEOCERCA_ENTRADA',
  GEOCERCA_SALIDA = 'GEOCERCA_SALIDA',

  // Flujo de viaje
  INICIO_VIAJE = 'INICIO_VIAJE',
  ARRIBO_ORIGEN = 'ARRIBO_ORIGEN',
  INICIO_CARGA = 'INICIO_CARGA',
  FIN_CARGA = 'FIN_CARGA',
  SALIDA = 'SALIDA',
  ARRIBO_DESTINO = 'ARRIBO_DESTINO',
  INICIO_DESCARGA = 'INICIO_DESCARGA',
  FIN_DESCARGA = 'FIN_DESCARGA',
  ENTREGA_POD = 'ENTREGA_POD',
  FIN_VIAJE = 'FIN_VIAJE',

  // Incidentes
  PARADA = 'PARADA',
  DESVIO = 'DESVIO',
  INCIDENTE = 'INCIDENTE'
}

enum FuenteEvento {
  GPS = 'GPS',
  APP_OPERADOR = 'APP_OPERADOR',
  SISTEMA = 'SISTEMA',
  MANUAL = 'MANUAL',
  GEOCERCA = 'GEOCERCA'
}

3.2 Interfaces

interface PosicionActual {
  lat: number;
  lng: number;
  velocidad: number;
  rumbo: number;
  timestamp: string;
  precision: number;
}

interface EventoTracking {
  id: string;
  viajeId: string;
  tipo: TipoEventoTracking;
  fuente: FuenteEvento;
  timestampEvento: string;
  ubicacion: { lat: number; lng: number } | null;
  descripcion: string;
  metadata: Record<string, unknown>;
}

interface TrackingData {
  viajeId: string;
  posicionActual: PosicionActual;
  rutaPlanificada: [number, number][];
  rutaRecorrida: [number, number][];
  eventos: EventoTracking[];
  eta: {
    llegadaEstimada: string;
    distanciaRestante: number;
    tiempoRestante: string;
  };
}

4. WebSocket Integration

4.1 Hook useTrackingWebSocket

// hooks/useTrackingWebSocket.ts
export function useTrackingWebSocket(viajeId: string) {
  const [isConnected, setIsConnected] = useState(false);
  const [lastPosition, setLastPosition] = useState<PosicionActual | null>(null);
  const [eventos, setEventos] = useState<EventoTracking[]>([]);

  useEffect(() => {
    const ws = new WebSocket(`${WS_URL}/tracking/${viajeId}`);

    ws.onmessage = (event) => {
      const data = JSON.parse(event.data);
      if (data.type === 'position') {
        setLastPosition(data.payload);
      } else if (data.type === 'event') {
        setEventos(prev => [...prev, data.payload]);
      }
    };

    // Auto-reconnect logic included
  }, [viajeId]);

  return { isConnected, lastPosition, eventos };
}

4.2 Mensajes WebSocket

// Posicion
{
  type: 'position',
  payload: {
    lat: 19.4326,
    lng: -99.1332,
    velocidad: 85,
    rumbo: 45,
    timestamp: '2026-01-28T10:30:00Z'
  }
}

// Evento
{
  type: 'event',
  payload: {
    id: 'evt-123',
    tipo: 'ARRIBO_DESTINO',
    fuente: 'GPS',
    timestamp: '2026-01-28T10:30:00Z',
    descripcion: 'Unidad arribo a destino'
  }
}

5. ETAProgressBar Component

5.1 Milestones

const milestones = [
  { id: 'origin', label: 'Origen', icon: 'MapPin' },
  { id: 'loaded', label: 'Cargado', icon: 'Package' },
  { id: 'transit', label: 'En Transito', icon: 'Truck' },
  { id: 'destination', label: 'Destino', icon: 'Flag' },
  { id: 'delivered', label: 'Entregado', icon: 'CheckCircle' }
];

5.2 Progress Calculation

function calculateProgress(eventos: EventoTracking[]): number {
  const weights = {
    INICIO_VIAJE: 0,
    ARRIBO_ORIGEN: 10,
    FIN_CARGA: 25,
    SALIDA: 30,
    EN_TRANSITO: 50,  // Interpolado por distancia
    ARRIBO_DESTINO: 80,
    FIN_DESCARGA: 90,
    ENTREGA_POD: 100
  };

  const lastEvent = eventos[eventos.length - 1];
  return weights[lastEvent?.tipo] || 0;
}

6. EventTimeline Component

6.1 Iconos por Tipo

const eventIcons: Record<TipoEventoTracking, React.ComponentType> = {
  POSICION: MapPin,
  GPS_POSICION: Satellite,
  GEOCERCA_ENTRADA: LogIn,
  GEOCERCA_SALIDA: LogOut,
  INICIO_VIAJE: PlayCircle,
  ARRIBO_ORIGEN: MapPin,
  INICIO_CARGA: Package,
  FIN_CARGA: PackageCheck,
  SALIDA: Truck,
  ARRIBO_DESTINO: Flag,
  INICIO_DESCARGA: PackageOpen,
  FIN_DESCARGA: PackageCheck,
  ENTREGA_POD: FileCheck,
  FIN_VIAJE: CheckCircle,
  PARADA: PauseCircle,
  DESVIO: AlertTriangle,
  INCIDENTE: AlertOctagon
};

6.2 Colores por Tipo

const eventColors: Record<TipoEventoTracking, string> = {
  INICIO_VIAJE: 'bg-green-500',
  FIN_VIAJE: 'bg-green-600',
  INCIDENTE: 'bg-red-500',
  PARADA: 'bg-yellow-500',
  DESVIO: 'bg-orange-500',
  // ... otros
  default: 'bg-blue-500'
};

7. API Endpoints

Endpoint Metodo Descripcion
/api/v1/tracking/viajes/:id GET Datos de tracking de viaje
/api/v1/tracking/viajes/:id/eventos GET Historial de eventos
/api/v1/tracking/viajes/:id/ruta GET Ruta planificada y recorrida
/api/v1/gps/posiciones/ultima/:dispositivoId GET Ultima posicion
WS /tracking/:viajeId WS Streaming de posiciones

8. Integracion con Mapas (Pendiente)

8.1 Estado Actual

  • Mapa placeholder con CSS gradient
  • Polylines simplificados con SVG
  • Marcadores posicionados con % relativo

8.2 Implementacion con Leaflet

import { MapContainer, Polyline, Marker, Popup } from 'react-leaflet';

const TrackingMap = ({ data }: { data: TrackingData }) => (
  <MapContainer center={data.posicionActual} zoom={12}>
    <TileLayer url="..." />

    {/* Ruta planificada */}
    <Polyline
      positions={data.rutaPlanificada}
      color="blue"
      dashArray="5,10"
    />

    {/* Ruta recorrida */}
    <Polyline
      positions={data.rutaRecorrida}
      color="green"
      weight={4}
    />

    {/* Posicion actual */}
    <Marker position={[data.posicionActual.lat, data.posicionActual.lng]}>
      <Popup>
        <span>Velocidad: {data.posicionActual.velocidad} km/h</span>
      </Popup>
    </Marker>
  </MapContainer>
);

9. Performance Considerations

  1. Throttle WebSocket updates: Maximo 1 update por segundo en UI
  2. Virtualized EventTimeline: Para viajes con 100+ eventos
  3. Route simplification: Usar Douglas-Peucker para rutas largas
  4. Map tile caching: Service worker para tiles frecuentes

Sprint S7 - TASK-007 | Sistema SIMCO v4.0.0