Skip to main content

Overview

Trip Monitoring provides real-time visibility into all ride requests and active trips on the platform, allowing administrators to track operations and intervene when necessary.
Trip monitoring is essential for platform operations, customer support, and quality assurance.

Trip Entity Structure

Trips are tracked with comprehensive data:
trips/domain/entities/trip.dart
class Trip {
  final int id;
  final int clienteId;
  final int? conductorId;
  final String origenDireccion;
  final double origenLatitud;
  final double origenLongitud;
  final String destinoDireccion;
  final double destinoLatitud;
  final double destinoLongitud;
  final TripStatus estado;
  final String? tipoVehiculo;
  final double? distanciaKm;
  final int? duracionMinutos;
  final double? precioEstimado;
  final double? precioFinal;
  final DateTime? fechaSolicitud;
  final DateTime? fechaInicio;
  final DateTime? fechaFin;
  final String? metodoPago;
  final String? notasCliente;
  final String? notasConductor;
  final double? calificacionCliente;
  final double? calificacionConductor;
  final String? comentarioCliente;
  final String? comentarioConductor;
}

Trip Status Flow

1

Requested

Status: solicitadoClient has requested a trip, waiting for driver acceptance
2

Accepted

Status: aceptadoDriver accepted the request and is heading to pickup
3

In Progress

Status: en_procesoDriver picked up client and trip is underway
4

Completed

Status: completadoTrip finished successfully
5

Cancelled

Status: canceladoTrip cancelled by client or driver

Status Enum

trips/domain/entities/trip.dart
enum TripStatus {
  solicitado('solicitado', 'Solicitado'),
  aceptado('aceptado', 'Aceptado'),
  enProceso('en_proceso', 'En Proceso'),
  completado('completado', 'Completado'),
  cancelado('cancelado', 'Cancelado');

  final String value;
  final String displayName;
  
  const TripStatus(this.value, this.displayName);

  static TripStatus fromString(String? value) {
    return TripStatus.values.firstWhere(
      (e) => e.value == value,
      orElse: () => TripStatus.solicitado,
    );
  }
}

Trip Status Colors

StatusColorHex CodeIcon
SolicitadoYellow#FFFF00Clock
AceptadoBlue#667eeaCheck
En ProcesoOrange#ffa726Route
CompletadoGreen#11998eCheck Circle
CanceladoRed#f5576cX Circle

Real-Time Trip Data

The dashboard displays live trip statistics:
{
  "solicitudes": {
    "total_solicitudes": 5840,
    "completadas": 5200,
    "canceladas": 540,
    "en_proceso": 100,
    "solicitudes_hoy": 120
  }
}

Active Trips

Trips currently in progress

Today's Trips

Total trip requests today

Completed

Successfully finished trips

Cancelled

Cancelled or failed trips

Viewing Trip Details

Admins can view comprehensive trip information:

Trip Summary

Container(
  child: Column(
    children: [
      // Client information
      ListTile(
        title: Text('Cliente'),
        subtitle: Text('${trip.clienteNombre}'),
        trailing: Text(trip.clienteTelefono ?? ''),
      ),
      
      // Driver information (if assigned)
      if (trip.conductorId != null)
        ListTile(
          title: Text('Conductor'),
          subtitle: Text('${trip.conductorNombre}'),
          trailing: Row(
            children: [
              Icon(Icons.star, color: Colors.yellow),
              Text('${trip.conductorCalificacion}'),
            ],
          ),
        ),
      
      // Route information
      ListTile(
        title: Text('Origen'),
        subtitle: Text(trip.origenDireccion),
      ),
      ListTile(
        title: Text('Destino'),
        subtitle: Text(trip.destinoDireccion),
      ),
      
      // Trip metrics
      Row(
        children: [
          _buildMetric('Distancia', '${trip.distanciaKm} km'),
          _buildMetric('Duración', '${trip.duracionMinutos} min'),
          _buildMetric('Precio', '\$${trip.precioFinal}'),
        ],
      ),
    ],
  ),
)

Trip Timeline

Column(
  children: [
    _buildTimelineItem(
      'Solicitado',
      trip.fechaSolicitud,
      Icons.request_quote,
      AppColors.primary,
    ),
    if (trip.fechaAceptacion != null)
      _buildTimelineItem(
        'Aceptado',
        trip.fechaAceptacion,
        Icons.check_circle,
        AppColors.blue600,
      ),
    if (trip.fechaInicio != null)
      _buildTimelineItem(
        'Iniciado',
        trip.fechaInicio,
        Icons.play_circle,
        AppColors.warning,
      ),
    if (trip.fechaFin != null)
      _buildTimelineItem(
        'Finalizado',
        trip.fechaFin,
        Icons.flag_circle,
        AppColors.success,
      ),
  ],
)

Filtering Trips

Filter by solicitado, aceptado, en_proceso, completado, or cancelado
Search trips by various criteria:
TextField(
  decoration: InputDecoration(
    hintText: 'Buscar por ID, cliente, conductor, dirección...',
    prefixIcon: Icon(Icons.search),
  ),
  onSubmitted: (query) {
    // Search trips matching:
    // - Trip ID
    // - Client name/email/phone
    // - Driver name/plate
    // - Origin/destination address
  },
)

Map View Integration

Display active trips on a real-time map:
// Show all active trips with:
// - Driver current location
// - Client pickup location
// - Destination marker
// - Route polyline

MapboxMap(
  markers: [
    // Driver marker (moving)
    Marker(
      position: LatLng(trip.conductorLat, trip.conductorLng),
      icon: driverIcon,
    ),
    // Pickup marker
    Marker(
      position: LatLng(trip.origenLat, trip.origenLng),
      icon: pickupIcon,
    ),
    // Destination marker
    Marker(
      position: LatLng(trip.destinoLat, trip.destinoLng),
      icon: destinationIcon,
    ),
  ],
  polylines: [
    Polyline(
      points: trip.routeCoordinates,
      color: AppColors.primary,
      width: 4,
    ),
  ],
)

Handling Trip Issues

Cancel Trip (Admin Override)

Future<void> cancelTrip(int tripId, String reason) async {
  final result = await tripRepository.cancelTrip(
    tripId: tripId,
    cancelledBy: 'admin',
    reason: reason,
  );

  result.fold(
    (failure) => showError('Error al cancelar viaje'),
    (success) {
      // Log admin action
      auditLog(
        action: 'cancel_trip',
        tripId: tripId,
        reason: reason,
      );
      showSuccess('Viaje cancelado');
    },
  );
}

Reassign Driver

Future<void> reassignDriver(int tripId, int newDriverId) async {
  // Remove from current driver
  // Assign to new driver
  // Notify both drivers
  // Log action in audit
  
  final result = await tripRepository.reassignDriver(
    tripId: tripId,
    newDriverId: newDriverId,
  );

  result.fold(
    (failure) => showError('Error al reasignar conductor'),
    (success) => showSuccess('Conductor reasignado correctamente'),
  );
}

Adjust Price

Future<void> adjustTripPrice(int tripId, double newPrice, String reason) async {
  final result = await tripRepository.updateTripPrice(
    tripId: tripId,
    newPrice: newPrice,
    adjustedBy: adminId,
    reason: reason,
  );

  result.fold(
    (failure) => showError('Error al ajustar precio'),
    (success) {
      auditLog(
        action: 'adjust_trip_price',
        tripId: tripId,
        oldPrice: trip.precioFinal,
        newPrice: newPrice,
        reason: reason,
      );
      showSuccess('Precio ajustado');
    },
  );
}

Trip Metrics

Key performance indicators for trip monitoring:

Average Trip Duration

Calculate median time from request to completion

Completion Rate

Percentage of trips completed vs cancelled

Average Distance

Mean distance traveled per trip

Peak Hours

Times with highest trip volume

Popular Routes

Most frequently requested origin-destination pairs

Driver Acceptance Rate

Percentage of requests accepted by drivers

Trip Repository

trips/domain/repositories/trip_repository.dart
abstract class TripRepository {
  /// Get all trips with filters
  Future<Result<List<Trip>>> getTrips({
    TripStatus? status,
    DateTime? startDate,
    DateTime? endDate,
    int? clientId,
    int? driverId,
    int? companyId,
    int? page,
    int? limit,
  });

  /// Get trip by ID
  Future<Result<Trip>> getTripById(int id);

  /// Get active trips (in progress)
  Future<Result<List<Trip>>> getActiveTrips();

  /// Cancel trip (admin override)
  Future<Result<void>> cancelTrip({
    required int tripId,
    required String cancelledBy,
    required String reason,
  });

  /// Reassign driver
  Future<Result<void>> reassignDriver({
    required int tripId,
    required int newDriverId,
  });

  /// Update trip price
  Future<Result<void>> updateTripPrice({
    required int tripId,
    required double newPrice,
    required int adjustedBy,
    required String reason,
  });

  /// Get trip statistics
  Future<Result<Map<String, dynamic>>> getTripStats({
    DateTime? startDate,
    DateTime? endDate,
  });
}

Real-Time Updates

Trip monitoring screen updates automatically:
// WebSocket or polling for live updates
Timer.periodic(Duration(seconds: 10), (timer) {
  if (mounted) {
    _loadActiveTrips();
  }
});

// Or WebSocket connection
final channel = WebSocketChannel.connect(
  Uri.parse('ws://api.viax.com/ws/trips'),
);

channel.stream.listen((data) {
  final update = jsonDecode(data);
  if (update['type'] == 'trip_update') {
    _updateTripInList(update['trip']);
  }
});

Export Trip Data

Export functionality is planned for future releases. Will support CSV and Excel formats.

Best Practices

Regularly check active trips to identify delays or issues that may require intervention.
Analyze cancelled trips to identify problematic routes, times, or drivers.
Use trip details to quickly resolve customer support inquiries.
Always provide clear reasons when adjusting trip prices for transparency.
Identify high-demand periods to optimize driver availability.

Reports

Analyze trip statistics and trends

Driver Management

Review driver performance

User Management

View client trip history

Build docs developers (and LLMs) love