> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/Braian551/viax/llms.txt
> Use this file to discover all available pages before exploring further.

# Trip Lifecycle

> Complete walkthrough of how trips work in Viax from request to completion

# Trip Lifecycle

Understand the complete journey of a trip request in Viax, from the moment a user requests a ride to trip completion and payment.

## Lifecycle Overview

```mermaid theme={null}
stateDiagram-v2
    [*] --> Request: User initiates
    Request --> Searching: System finds drivers
    Searching --> Pending: Drivers notified
    Pending --> Accepted: Driver accepts
    Pending --> Cancelled: No driver / User cancels
    Accepted --> EnRoute: Driver navigating
    EnRoute --> PickedUp: User in vehicle
    PickedUp --> InProgress: Trip started
    InProgress --> Arrived: Reached destination
    Arrived --> Completed: Payment confirmed
    Completed --> [*]
    Cancelled --> [*]
```

***

## Phase 1: Trip Request

### User Actions

<Steps>
  <Step title="Select Pickup Location">
    User taps on map or uses current GPS location to set pickup point.

    **Data Captured:**

    ```json theme={null}
    {
      "latitud_origen": -34.603722,
      "longitud_origen": -58.381592,
      "direccion_origen": "Av. Corrientes 1234, Buenos Aires"
    }
    ```
  </Step>

  <Step title="Select Destination">
    User taps on map or searches for address to set dropoff point.

    **Data Captured:**

    ```json theme={null}
    {
      "latitud_destino": -34.613722,
      "longitud_destino": -58.391592,
      "direccion_destino": "Av. Santa Fe 5678, Buenos Aires"
    }
    ```
  </Step>

  <Step title="Choose Service Type">
    User selects between:

    * **Viaje** (Ride): Personal transportation
    * **Paquete** (Package): Delivery service
  </Step>

  <Step title="Select Vehicle Type">
    User chooses from available options:

    * 🏍️ Moto (Motorcycle)
    * 🚗 Carro (Car)
    * 🏍️ Moto Carga (Cargo Motorcycle)
    * 🚙 Carro Carga (Cargo Car)
  </Step>

  <Step title="View Estimate">
    System calculates and displays:

    * Route distance (km)
    * Estimated duration (minutes)
    * Price estimate (COP)

    **Calculation:**

    ```dart theme={null}
    final baseFare = vehicleType.baseFare; // e.g., 5000 COP
    final distanceCost = distance * pricePerKm; // e.g., 12.5 km * 1000
    final timeCost = duration * pricePerMin; // e.g., 25 min * 100
    final total = baseFare + distanceCost + timeCost;
    ```
  </Step>

  <Step title="Confirm Request">
    User taps "Solicitar viaje" button to submit request.
  </Step>
</Steps>

### Backend Processing

<CodeGroup>
  ```php Create Trip Request theme={null}
  // backend/user/create_trip_request.php
  $stmt = $pdo->prepare("
      INSERT INTO solicitudes_servicio (
          usuario_id, 
          latitud_origen, longitud_origen, direccion_origen,
          latitud_destino, longitud_destino, direccion_destino,
          tipo_servicio, tipo_vehiculo,
          distancia_km, duracion_minutos, precio_estimado,
          estado, fecha_solicitud
      ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pendiente', NOW())
  ");

  $stmt->execute([
      $usuario_id,
      $lat_origen, $lng_origen, $dir_origen,
      $lat_destino, $lng_destino, $dir_destino,
      $tipo_servicio, $tipo_vehiculo,
      $distancia, $duracion, $precio,
  ]);

  $solicitud_id = $pdo->lastInsertId();
  ```

  ```sql Initial State theme={null}
  INSERT INTO solicitudes_servicio VALUES (
    123,                    -- id
    42,                     -- usuario_id
    -34.603722,             -- latitud_origen
    -58.381592,             -- longitud_origen
    'Av. Corrientes 1234',  -- direccion_origen
    -34.613722,             -- latitud_destino
    -58.391592,             -- longitud_destino  
    'Av. Santa Fe 5678',    -- direccion_destino
    'viaje',                -- tipo_servicio
    'carro',                -- tipo_vehiculo
    12.5,                   -- distancia_km
    25,                     -- duracion_minutos
    17500.00,               -- precio_estimado
    'pendiente',            -- estado
    '2024-11-01 10:30:00'   -- fecha_solicitud
  );
  ```
</CodeGroup>

***

## Phase 2: Driver Search

### Automatic Driver Discovery

<Info>
  The system automatically searches for available drivers within a 5km radius of the pickup location.
</Info>

**Search Query:**

```sql theme={null}
SELECT 
    c.id,
    c.nombre_completo,
    c.telefono,
    c.tipo_vehiculo,
    c.calificacion_promedio,
    c.latitud_actual,
    c.longitud_actual,
    (
        6371 * acos(
            cos(radians(?)) * cos(radians(c.latitud_actual)) *
            cos(radians(c.longitud_actual) - radians(?)) +
            sin(radians(?)) * sin(radians(c.latitud_actual))
        )
    ) AS distancia_km
FROM conductores c
WHERE 
    c.disponibilidad = 1
    AND c.estado_verificacion = 'aprobado'
    AND c.tipo_vehiculo = ?
    AND c.latitud_actual IS NOT NULL
    AND c.longitud_actual IS NOT NULL
HAVING distancia_km <= 5
ORDER BY distancia_km ASC
LIMIT 10;
```

**Parameters:**

* `?` placeholders: latitud\_origen, longitud\_origen (3 times for Haversine formula)
* `tipo_vehiculo`: Matches requested vehicle type
* **Radius**: 5 kilometers
* **Limit**: Top 10 closest drivers

### Driver Matching Criteria

<CardGroup cols={2}>
  <Card title="Location" icon="location-dot">
    * Within 5km of pickup point
    * GPS coordinates updated \< 5 min ago
    * Calculated using Haversine formula
  </Card>

  <Card title="Availability" icon="circle-check">
    * disponibilidad = 1 (online)
    * Not currently on another trip
    * Active in the system
  </Card>

  <Card title="Verification" icon="shield-check">
    * estado\_verificacion = 'aprobado'
    * Documents validated
    * Background check passed
  </Card>

  <Card title="Vehicle Match" icon="car">
    * tipo\_vehiculo matches request
    * Vehicle registered and insured
    * Passed vehicle inspection
  </Card>
</CardGroup>

### Notification to Drivers

**Push Notification** (Future):

```json theme={null}
{
  "title": "Nueva solicitud de viaje",
  "body": "Av. Corrientes 1234 → Av. Santa Fe 5678 (12.5 km)",
  "data": {
    "solicitud_id": 123,
    "tipo": "viaje",
    "distancia": 12.5,
    "precio": 17500
  }
}
```

**Current Implementation**:

* Drivers poll server every 5 seconds for new requests
* Requests appear in driver's "Pending Requests" screen

***

## Phase 3: Driver Acceptance

### Driver Views Request

**Driver sees:**

<Tabs>
  <Tab title="Request Card">
    ```dart theme={null}
    TripRequestCard(
      origen: "Av. Corrientes 1234",
      destino: "Av. Santa Fe 5678",
      distancia: 12.5,
      duracion: 25,
      precio: 17500,
      usuarioNombre: "Juan Pérez",
      tipoServicio: "Viaje",
    )
    ```
  </Tab>

  <Tab title="Map Preview">
    * Pickup marker (green)
    * Dropoff marker (red)
    * Route preview
    * Current driver location (blue)
    * Distance to pickup
  </Tab>
</Tabs>

### Driver Actions

<Steps>
  <Step title="Review Request">
    Driver evaluates:

    * Distance to pickup
    * Route complexity
    * Estimated earnings
    * Current traffic conditions
  </Step>

  <Step title="Accept or Decline">
    **If Accept:**

    ```php theme={null}
    // backend/conductor/accept_trip_request.php

    // 1. Update trip status
    UPDATE solicitudes_servicio 
    SET estado = 'aceptada'
    WHERE id = ?

    // 2. Create assignment
    INSERT INTO asignaciones_conductor (
        solicitud_id, conductor_id, fecha_asignacion, estado
    ) VALUES (?, ?, NOW(), 'aceptado')

    // 3. Set driver offline
    UPDATE conductores
    SET disponibilidad = 0
    WHERE id = ?
    ```

    **If Decline:**

    * Request remains in pending state
    * Shown to other nearby drivers
  </Step>

  <Step title="Navigate to Pickup">
    Driver receives:

    * Pickup address
    * GPS coordinates
    * Navigation link (Google Maps/Waze)
    * User contact number (for coordination)
  </Step>
</Steps>

### User Notification

**User sees:**

```dart theme={null}
DriverAssignedScreen(
  driverName: "Carlos Rodríguez",
  driverPhoto: "url",
  driverRating: 4.8,
  vehicleType: "Toyota Corolla",
  vehiclePlate: "ABC123",
  vehicleColor: "Gris",
  eta: "5 minutos",
)
```

***

## Phase 4: En Route to Pickup

### Driver Status Updates

<Tabs>
  <Tab title="Location Tracking">
    Driver's location updated every 10 seconds:

    ```php theme={null}
    // backend/conductor/update_location.php
    UPDATE conductores
    SET 
        latitud_actual = ?,
        longitud_actual = ?,
        ultima_actualizacion = NOW()
    WHERE id = ?
    ```

    User sees driver approaching on map in real-time.
  </Tab>

  <Tab title="ETA Calculation">
    ```dart theme={null}
    // Recalculated every 30 seconds
    final distanceToPickup = calculateDistance(
      driverLat, driverLng,
      pickupLat, pickupLng,
    );

    final eta = calculateETA(
      distance: distanceToPickup,
      trafficFactor: currentTraffic, // from TomTom API
      averageSpeed: 30, // km/h urban
    );
    ```
  </Tab>

  <Tab title="Status Milestones">
    Driver manually updates status:

    | Status      | Description       |
    | ----------- | ----------------- |
    | `aceptada`  | Trip accepted     |
    | `en_camino` | Heading to pickup |
    | `llegado`   | Arrived at pickup |
    | `recogido`  | User picked up    |
  </Tab>
</Tabs>

### Communication

**In-App Features** (Future):

* Chat between user and driver
* Quick messages ("I'm here", "5 minutes away")
* Voice call button

**Current**:

* Phone call via displayed number

***

## Phase 5: Trip in Progress

### Pickup Confirmation

<Steps>
  <Step title="Driver Arrives">
    Driver taps "He llegado" button

    ```dart theme={null}
    updateTripStatus(solicitudId, 'llegado');
    ```
  </Step>

  <Step title="User Enters Vehicle">
    Driver confirms: "Pasajero a bordo"

    ```dart theme={null}
    updateTripStatus(solicitudId, 'recogido');
    ```
  </Step>

  <Step title="Start Trip">
    Driver taps "Iniciar viaje"

    ```php theme={null}
    // Create actual trip record
    INSERT INTO viajes (
        solicitud_id,
        conductor_id,
        usuario_id,
        hora_inicio,
        latitud_inicio,
        longitud_inicio,
        estado
    ) VALUES (?, ?, ?, NOW(), ?, ?, 'en_curso')

    // Update request status
    UPDATE solicitudes_servicio
    SET estado = 'en_curso'
    WHERE id = ?
    ```
  </Step>
</Steps>

### During Trip

<CardGroup cols={2}>
  <Card title="Driver View" icon="car">
    * Route to destination
    * Current traffic
    * Updated ETA
    * Trip timer
    * Distance counter
  </Card>

  <Card title="User View" icon="user">
    * Real-time driver location
    * Route visualization
    * ETA to destination
    * Trip details
    * Share trip with contacts
  </Card>
</CardGroup>

**Location Tracking:**

```dart theme={null}
// Updated every 10 seconds while in progress
streamController.add(
  DriverLocation(
    latitude: currentLat,
    longitude: currentLng,
    heading: currentHeading,
    speed: currentSpeed,
    timestamp: DateTime.now(),
  )
);
```

***

## Phase 6: Trip Completion

### Arrival at Destination

<Steps>
  <Step title="Driver Marks Arrival">
    ```dart theme={null}
    updateTripStatus(solicitudId, 'llegado_destino');
    ```
  </Step>

  <Step title="Calculate Final Fare">
    ```dart theme={null}
    // Actual distance and duration
    final actualDistance = calculateTripDistance(routePoints);
    final actualDuration = endTime.difference(startTime).inMinutes;

    // Recalculate fare
    final baseFare = 5000;
    final distanceCost = actualDistance * 1000;
    final timeCost = actualDuration * 100;
    final totalFare = baseFare + distanceCost + timeCost;

    // Compare with estimate
    if (totalFare > estimatedFare * 1.2) {
      // Fare increased > 20%, notify user
      showFareChangeDialog();
    }
    ```
  </Step>

  <Step title="Complete Trip">
    ```php theme={null}
    // backend/conductor/complete_trip.php

    // 1. Update trip record
    UPDATE viajes
    SET 
        hora_fin = NOW(),
        latitud_fin = ?,
        longitud_fin = ?,
        distancia_real = ?,
        duracion_real = ?,
        precio_final = ?,
        estado = 'completado'
    WHERE id = ?

    // 2. Update request
    UPDATE solicitudes_servicio
    SET estado = 'completada'
    WHERE id = ?

    // 3. Set driver back online
    UPDATE conductores
    SET disponibilidad = 1
    WHERE id = ?
    ```
  </Step>
</Steps>

### Payment Processing

<Tabs>
  <Tab title="Current (Manual)">
    * Driver confirms cash payment received
    * Or payment marked as pending for later processing
    * Receipt generated
  </Tab>

  <Tab title="Future (Automated)">
    ```dart theme={null}
    // Charge user's saved payment method
    final paymentResult = await PaymentService.charge(
      userId: trip.usuarioId,
      amount: trip.precioFinal,
      description: 'Viaje ${trip.id}',
      method: user.defaultPaymentMethod,
    );

    if (paymentResult.success) {
      // Calculate driver earnings
      final commission = amount * 0.20; // 20%
      final driverEarnings = amount - commission;
      
      // Update balances
      updateDriverBalance(driverId, driverEarnings);
      updatePlatformRevenue(commission);
    }
    ```
  </Tab>
</Tabs>

### Trip Summary

**User Receives:**

```json theme={null}
{
  "trip_summary": {
    "viaje_id": 123,
    "fecha": "2024-11-01 10:30:00",
    "origen": "Av. Corrientes 1234",
    "destino": "Av. Santa Fe 5678",
    "conductor": "Carlos Rodríguez",
    "vehiculo": "Toyota Corolla - ABC123",
    "distancia_km": 12.8,
    "duracion_minutos": 27,
    "precio_final": 17800,
    "metodo_pago": "Efectivo",
    "recibo_url": "https://viax.com/receipts/123.pdf"
  }
}
```

**Driver Receives:**

```json theme={null}
{
  "trip_earnings": {
    "viaje_id": 123,
    "precio_total": 17800,
    "comision_plataforma": 3560,
    "ganancia_conductor": 14240,
    "metodo_pago": "Efectivo"
  }
}
```

***

## Phase 7: Post-Trip

### Rating & Review

<Tabs>
  <Tab title="User Rates Driver">
    ```dart theme={null}
    RatingDialog(
      driverName: "Carlos Rodríguez",
      tripId: 123,
      fields: [
        RatingField('Puntualidad', 1-5 stars),
        RatingField('Conducción', 1-5 stars),
        RatingField('Amabilidad', 1-5 stars),
        RatingField('Vehículo limpio', 1-5 stars),
      ],
      commentField: true,
      tipOption: true,
    )
    ```

    Stored in database:

    ```sql theme={null}
    INSERT INTO calificaciones (
        viaje_id, usuario_id, conductor_id,
        calificacion, comentario, fecha
    ) VALUES (?, ?, ?, ?, ?, NOW())
    ```
  </Tab>

  <Tab title="Driver Rates User">
    ```dart theme={null}
    RatingDialog(
      userName: "Juan Pérez",
      tripId: 123,
      rating: 1-5 stars,
      comment: "Buen pasajero, puntual",
    )
    ```
  </Tab>

  <Tab title="Update Averages">
    ```php theme={null}
    // Update driver's average rating
    UPDATE conductores
    SET calificacion_promedio = (
        SELECT AVG(calificacion)
        FROM calificaciones
        WHERE conductor_id = ?
    )
    WHERE id = ?

    // Update user's average rating
    UPDATE usuarios
    SET calificacion_promedio = (
        SELECT AVG(calificacion)
        FROM calificaciones_usuarios
        WHERE usuario_id = ?
    )
    WHERE id = ?
    ```
  </Tab>
</Tabs>

### Trip History

**Stored for:**

* User's trip history
* Driver's trip log
* Platform analytics
* Financial records
* Dispute resolution
* Tax reporting

***

## Cancellation Flows

### User Cancellation

<AccordionGroup>
  <Accordion title="Before Driver Accept (Free)">
    ```php theme={null}
    UPDATE solicitudes_servicio
    SET estado = 'cancelada',
        motivo_cancelacion = 'Usuario canceló antes de asignación'
    WHERE id = ? AND estado = 'pendiente'
    ```

    No penalty for user.
  </Accordion>

  <Accordion title="After Accept, Before Pickup (Fee)">
    ```php theme={null}
    // Charge cancellation fee
    $cancellationFee = 2000; // COP

    UPDATE solicitudes_servicio
    SET 
        estado = 'cancelada',
        motivo_cancelacion = ?,
        tarifa_cancelacion = ?
    WHERE id = ?

    // Compensate driver
    INSERT INTO compensaciones_conductor (
        conductor_id, viaje_id, monto, razon
    ) VALUES (?, ?, ?, 'Cancelación de usuario')
    ```

    User charged ₡2,000 cancellation fee.
  </Accordion>

  <Accordion title="After Pickup (Full Charge)">
    User cannot cancel once trip has started. Must complete trip or contact support.
  </Accordion>
</AccordionGroup>

### Driver Cancellation

<AccordionGroup>
  <Accordion title="Before Pickup (Penalty)">
    ```php theme={null}
    UPDATE solicitudes_servicio
    SET estado = 'pendiente' // Back to pending
    WHERE id = ?

    // Track driver cancellation
    INSERT INTO cancelaciones_conductor (
        conductor_id, solicitud_id, razon, fecha
    ) VALUES (?, ?, ?, NOW())

    // Check cancellation rate
    $rate = getCancellationRate($conductorId);
    if ($rate > 0.15) { // > 15%
        // Warn or suspend driver
        notifyDriverHighCancellationRate($conductorId);
    }
    ```

    Trip returned to pending state, shown to other drivers.
  </Accordion>

  <Accordion title="After Pickup (Support Required)">
    Driver must contact support. Emergency cancellation only for valid reasons (safety, emergency).
  </Accordion>
</AccordionGroup>

***

## State Transitions Summary

**Valid State Flow:**

```
pendiente → aceptada → en_camino → llegado → recogido → 
  en_curso → llegado_destino → completada
```

**Cancellation Paths:**

```
pendiente → cancelada (user/system)
aceptada → cancelada (user with fee)
en_camino → cancelada (user with fee)
aceptada → pendiente (driver cancels, back to pool)
```

**Database Enum:**

```sql theme={null}
CREATE TYPE estado_solicitud AS ENUM (
    'pendiente',
    'aceptada',
    'en_camino',
    'llegado',
    'recogido',
    'en_curso',
    'llegado_destino',
    'completada',
    'cancelada'
);
```

<Check>
  The trip lifecycle in Viax is designed for reliability, transparency, and user satisfaction with clear state transitions and comprehensive tracking.
</Check>
