Skip to main content

Overview

The TripStore is an Angular injectable service that manages the driver’s trip state using Angular signals. It tracks trip phases, offer countdowns, passenger information, and dynamic fare calculations including waiting time penalties.

State Interface

DriverTripState

status
'idle' | 'loading' | 'success' | 'error'
Current loading status of trip operations
error
string | null
Error message if any operation failed
activeTripId
string | null
ID of the currently active trip
trip
TripDto | null
Complete trip data object from the API
phase
TripPhase
Current trip phase: 'idle', 'assigned', 'arriving', 'in_progress', 'completed', 'cancelled', or 'no_drivers_found'
offerAssignmentId
string | null
ID of the current trip offer assignment
offerExpiresAt
string | null
ISO timestamp when the current offer expires
remainingSec
number | null
Remaining seconds on the offer countdown timer
modalOpen
boolean
Whether the trip offer modal is currently open
handledAssignments
string[]
Array of assignment IDs that have already been accepted or declined
passengerSlim
object | null
Passenger information subset:
  • id (string): Passenger ID
  • name (string | null): Passenger name
  • phoneMasked (string | null): Masked phone number
  • photoUrl (string | null): Profile photo URL
arrivedPickupAt
string | null
ISO timestamp when driver marked arrival at pickup location

Pricing and Waiting Time Fields

baseFare
number | null
Initial base fare for the trip
baseCurrency
string | null
Currency code (e.g., “CUP”)
liveFare
number | null
Current fare including any waiting penalties
waitingSinceAt
string | null
ISO timestamp when waiting period started
waitingSeconds
number
Total seconds driver has been waiting at pickup
waitingPenaltyApplied
boolean
Whether a waiting time penalty has been applied
waitingPenaltyText
string | null
Description text for the waiting penalty
waitingExtraFare
number | null
Additional fare amount from waiting penalty
waitingReason
string | null
Reason for the waiting charge

Computed Signals

state

readonly state = computed(() => this._s())
Returns the complete state object.

trip

readonly trip = computed(() => this._s().trip)
Returns the current trip data.

phase

readonly phase = computed(() => this._s().phase)
Returns the current trip phase.

remainingSec

readonly remainingSec = computed(() => this._s().remainingSec)
Returns remaining seconds on offer countdown.

modalOpen

readonly modalOpen = computed(() => this._s().modalOpen)
Returns modal open state.

baseFare

readonly baseFare = computed(() => this._s().baseFare)
Returns the base fare amount.

liveFare

readonly liveFare = computed(() => this._s().liveFare ?? this._s().baseFare)
Returns the current live fare, falling back to base fare if not set.

waitingSeconds

readonly waitingSeconds = computed(() => this._s().waitingSeconds)
Returns total waiting seconds.

waitingPenaltyApplied

readonly waitingPenaltyApplied = computed(() => this._s().waitingPenaltyApplied)
Returns whether waiting penalty has been applied.

waitingPenaltyText

readonly waitingPenaltyText = computed(() => this._s().waitingPenaltyText)
Returns the waiting penalty description text.

modalVm

readonly modalVm = computed(() => ({ ... }))
Computed view model for the trip offer modal, includes:
  • phase: Current trip phase
  • remainingSec: Countdown timer
  • originLabel: Formatted pickup address or coordinates
  • destinationLabel: Formatted destination address or coordinates
  • distanceText: Formatted distance (e.g., “5.2 km”)
  • durationText: Formatted duration (e.g., ”≈ 15 min”)
  • priceText: Formatted price (e.g., “250 CUP”)
  • Raw values: distanceKm, durationMin, total, currency

State Mutation Methods

setLoading()

setLoading(): void
Sets loading state and clears any errors.

setError(msg)

msg
string
required
Error message to display
setError(msg: string): void
Sets error state with the provided message.

setTrip(trip)

trip
TripDto | null
required
Trip data object or null to clear
setTrip(trip: TripDto | null): void
Updates the trip data and sets status to success.

setActiveTripId(id)

id
string | null
required
Trip ID or null to clear
setActiveTripId(id: string | null): void
Sets the active trip ID.

setPhase(phase)

phase
TripPhase
required
New trip phase
setPhase(phase: TripPhase): void
Updates the current trip phase.

setOfferAssignmentId(id)

id
string | null
required
Assignment ID or null to clear
setOfferAssignmentId(id: string | null): void
Sets the current offer assignment ID.

setOfferCountdown(expiresAtIso, remaining)

expiresAtIso
string | null
ISO timestamp when offer expires
remaining
number | null
Remaining seconds
setOfferCountdown(expiresAtIso?: string | null, remaining?: number | null): void
Sets the offer expiration time and countdown.

tickCountdown()

tickCountdown(): void
Decrements the countdown timer by 1 second (minimum 0).

setModalOpen(open)

open
boolean
required
Whether modal should be open
setModalOpen(open: boolean): void
Sets the modal open state.

setPassengerSlim(passenger)

passenger
object | null
required
Passenger information object or null
setPassengerSlim(p: DriverTripState['passengerSlim']): void
Sets the passenger information subset.

markAssignmentHandled(id)

id
string | null
required
Assignment ID to mark as handled
markAssignmentHandled(id: string | null): void
Adds the assignment ID to the handled list (prevents duplicate processing).

isAssignmentHandled(id)

id
string | null
required
Assignment ID to check
isAssignmentHandled(id: string | null): boolean
Checks if an assignment has already been handled.

setArrivedPickup(at)

at
string
required
ISO timestamp of arrival
setArrivedPickup(at: string): void
Marks the timestamp when driver arrived at pickup location.

setInitialFare(total, currency)

total
number | null
required
Initial fare amount
currency
string | null
required
Currency code (e.g., “CUP”)
setInitialFare(total: number | null, currency: string | null): void
Sets the base fare and currency, initializes live fare if not already set.

startWaiting(atIso)

atIso
string
required
ISO timestamp when waiting started
startWaiting(atIso: string): void
Initializes waiting period tracking. Sets waitingSinceAt and resets all waiting-related fields.

tickWaiting(deltaSec)

deltaSec
number
default:"1"
Seconds to increment (default: 1)
tickWaiting(deltaSec = 1): void
Increments the waiting seconds counter.

applyWaitingPenalty(extra, text)

extra
number
required
Additional fare amount to charge
text
string
required
Description of the penalty
applyWaitingPenalty(extra: number, text: string): void
Applies a waiting penalty to the fare. Updates liveFare = baseFare + extra.

setWaitingReason(reason)

reason
string | null
required
Reason for the waiting charge
setWaitingReason(reason: string | null): void
Sets the waiting charge reason.

reset()

reset(): void
Resets the entire state to initial values.

Usage Example

import { Component, inject } from '@angular/core';
import { TripStore } from '@/app/store/trip/trip.store';

@Component({
  selector: 'app-trip-status',
  template: `
    <div>
      <p>Phase: {{ tripStore.phase() }}</p>
      <p>Base Fare: {{ tripStore.baseFare() }} {{ trip()?.fareFinalCurrency }}</p>
      <p>Live Fare: {{ tripStore.liveFare() }}</p>
      
      @if (tripStore.waitingPenaltyApplied()) {
        <p class="warning">
          {{ tripStore.waitingPenaltyText() }}
        </p>
      }
      
      <p>Waiting: {{ tripStore.waitingSeconds() }}s</p>
    </div>
  `
})
export class TripStatusComponent {
  tripStore = inject(TripStore);
  
  trip = this.tripStore.trip;
}

State Flow Example

// 1. Receive offer
tripStore.setActiveTripId('trip-123');
tripStore.setOfferAssignmentId('assignment-456');
tripStore.setPhase('assigned');
tripStore.setOfferCountdown(expiresAt, 30);

// 2. Accept offer
tripStore.markAssignmentHandled('assignment-456');
tripStore.setPhase('assigned');

// 3. Arrive at pickup
tripStore.setArrivedPickup(new Date().toISOString());
tripStore.startWaiting(new Date().toISOString());
tripStore.setPhase('arriving');

// 4. Tick waiting timer every second
setInterval(() => {
  tripStore.tickWaiting(1);
  
  // Apply penalty after threshold
  if (tripStore.waitingSeconds() >= 300 && !tripStore.waitingPenaltyApplied()) {
    const extra = 50;
    tripStore.applyWaitingPenalty(extra, 'Recargo por espera prolongada');
    tripStore.setWaitingReason('Pasajero no se presentó a tiempo');
  }
}, 1000);

// 5. Start trip
tripStore.setPhase('in_progress');

// 6. Complete trip
tripStore.setPhase('completed');

// 7. Reset for next trip
tripStore.reset();

Build docs developers (and LLMs) love