# Booking Flow API Guide

This document explains the full booking flow for Passenger app modes shown in UI: `Ride`, `Per Hour`, and `Delivery`, and maps each step to backend APIs.

## 1. End-to-End Booking Lifecycle

1. Open booking screen
2. Load vehicle categories
3. Select mode (`Ride` / `Per Hour` / `Delivery`)
4. Fill pickup/drop and options
5. Get fare estimate
6. Confirm booking
7. Track ride and bids
8. Accept bid and complete ride lifecycle
9. View ride history

## 2. APIs Used

### Core Passenger APIs
- `GET /api/v1/rides/categories`
- `POST /api/v1/rides/estimate`
- `POST /api/v1/rides/book`
- `GET /api/v1/passenger/rides/active`
- `GET /api/v1/rides/{ride_id}`
- `GET /api/v1/rides/{ride_id}/bids`
- `POST /api/v1/rides/{ride_id}/bids/{bid_id}/accept`
- `POST /api/v1/rides/{ride_id}/cancel`
- `GET /api/v1/passenger/rides`

### Real-time
- `WS /api/v1/ws/rides/live?token=<access_token>`

## 3. Step-by-Step Mapping (UI -> API)

## Step 1: Load categories and vehicle cards

**API:** `GET /api/v1/rides/categories`  
**Why:** Populate dynamic vehicle list and pricing/capacity fields.

Used response fields:
- `id`, `display_name`
- `base_fare`, `per_km_rate`, `per_minute_rate`, `minimum_fare`
- `max_passengers`
- `max_luggage`, `luggage_capacity`

## Step 2: Select mode

No immediate API call required.  
Frontend changes form rules locally based on selected mode.

Supported `ride_type` values:
- `one_way`
- `round_trip`
- `scheduled`
- `per_hour`
- `delivery`

## Step 3: Fill booking form

Collected in UI state:
- pickup
- dropoff (where applicable)
- date/time
- return way options
- adults + children
- duration chips (per hour)
- comments

## Step 4: Fare preview

**API:** `POST /api/v1/rides/estimate`  
**Why:** Calculate fare breakdown before booking.

Required (current contract):
- `pickup.latitude`, `pickup.longitude`
- `dropoff.latitude`, `dropoff.longitude`
- `ride_type`
- `vehicle_category_id`
- `passenger_count`

Optional:
- `children`
- `promo_code`
- `scheduled_at`
- `duration_minutes` (required for `per_hour`)

## Step 5: Confirm booking

**API:** `POST /api/v1/rides/book`  
**Why:** Create ride request in DB and start driver matching/bids.

Required:
- `pickup`
- `dropoff`
- `ride_type`
- `vehicle_category_id`
- `payment_method`
- `passenger_count`

Optional:
- `children`
- `promo_code`
- `is_scheduled`, `scheduled_at`
- `return_location`
- `return_scheduled_at`
- `duration_minutes` (required for `per_hour`)
- `end_scheduled_at`
- `passenger_notes`

Key response fields:
- `id` (ride_id)
- `ride_code`
- `status`

## Step 6: Track active ride

**APIs:**
- `GET /api/v1/passenger/rides/active`
- `GET /api/v1/rides/{ride_id}`
- websocket `ws/rides/live`

**Why:** Sync ride status, assignment, lifecycle changes.

## Step 7: Handle bids

**APIs:**
- `GET /api/v1/rides/{ride_id}/bids`
- `POST /api/v1/rides/{ride_id}/bids/{bid_id}/accept`

**Why:** Passenger views offers and confirms selected driver.

## Step 8: In-trip lifecycle

Status changes are observed via websocket (preferred), with REST fallback.  
Optional cancellation:
- `POST /api/v1/rides/{ride_id}/cancel`

## Step 9: History

**API:** `GET /api/v1/passenger/rides`  
**Why:** Render paginated ride history.

## 4. Ride vs Per Hour: Required vs Optional

## Ride Category (Point-to-Point)

Ride is a fixed-route trip from A to B. It is not valid without both ends of the route.

Required fields:
- Pickup location (`pickup`) -> required to determine where driver should arrive and where fare starts.
- Drop-off location (`dropoff`) -> required to determine destination, route distance, and final fare estimate.
- `vehicle_category_id`
- `passenger_count`
- `payment_method` (for booking)

Optional fields:
- `children`
- `return_location`
- `return_scheduled_at` (for round-trip style scheduling)
- `promo_code`
- `passenger_notes`

Why Ride cannot work without both pickup and drop-off:
- Driver assignment needs a clear start and destination context.
- Fare estimation depends on route distance/time between two points.
- Trip intent is point-to-point; no destination means no fixed route.

APIs used:
- Estimate: `POST /api/v1/rides/estimate`
- Book: `POST /api/v1/rides/book`

## Per Hour Category (Time-Based)

Per Hour is a flexible time-bound trip. Its core meaning is "reserve driver + vehicle for duration", not strictly "fixed destination".

Business-required fields (intended product behavior):
- Pickup location (`pickup`) -> REQUIRED
- `duration_minutes` -> REQUIRED
- `vehicle_category_id` -> REQUIRED
- `passenger_count` -> REQUIRED
- `payment_method` -> REQUIRED for booking

Business-optional fields (intended behavior):
- Drop-off location (`dropoff`) -> OPTIONAL
- Additional stops ("Add Another Location") -> OPTIONAL
- Add Return Way -> OPTIONAL
- `end_scheduled_at` -> OPTIONAL
- `children`, `promo_code`, `passenger_notes` -> OPTIONAL

Current backend contract note:
- `dropoff` is currently required by request schema for both `/rides/estimate` and `/rides/book`.
- To fully support open Per Hour trips without destination, schema should be adjusted in backend.

## Delivery

Compulsory (current backend):
- pickup
- dropoff
- vehicle_category_id
- passenger_count
- payment_method
- `ride_type=delivery`

Optional:
- children
- notes/comments

Note: delivery-specific package/recipient fields are not yet in contract.

## 5. Key Per Hour Scenarios

## A) Per Hour without drop-off

Intended behavior:
- System treats it as an open trip (time-based reservation).
- Booking remains valid because duration controls billing instead of fixed destination distance.
- Driver starts from pickup and follows rider instructions during reserved time.

Current backend behavior:
- Request fails today if `dropoff` is missing due to current schema requirement.

## B) Add Return Way checkbox

Meaning:
- Rider intends to return toward original pickup area/end point.

If selected:
- UI should include return context (for example `return_location` or `return_scheduled_at`).
- Pricing may include additional estimated distance/time and can increase fare.

If not selected:
- Trip remains one-direction flexible within booked duration.
- No return leg assumed in pricing logic.

Impact:
- Affects expected route complexity and estimate/booking metadata.

## C) Add Another Location (Stops)

Meaning:
- Multiple intermediate waypoints between pickup and final movement pattern.

Use cases:
- Errand trips
- Multiple quick drop points
- In-city multi-stop travel

Difference summary:
- Only pickup: open roaming trip starting at pickup.
- Pickup + stops: guided multi-stop route during booked duration.
- Pickup + return way: go out and come back pattern.

## 6. Why Pickup is Always Required

Pickup is mandatory in all categories because it is needed for:
- Driver assignment (where to dispatch driver).
- Pricing anchor (trip start for time/distance calculations).
- Operational start point (trip cannot begin without location).

## 7. API Mapping by Category

## Ride -> `/rides/estimate`

Required (current and intended):
- `pickup`
- `dropoff`
- `ride_type` (`one_way` or `round_trip`)
- `vehicle_category_id`
- `passenger_count`

Optional:
- `children`
- `promo_code`
- `scheduled_at`

## Ride -> `/rides/book`

Required:
- `pickup`
- `dropoff`
- `ride_type`
- `vehicle_category_id`
- `payment_method`
- `passenger_count`

Optional:
- `children`
- `promo_code`
- `return_location`
- `return_scheduled_at`
- `passenger_notes`

## Per Hour -> `/rides/estimate`

Required (intended):
- `pickup`
- `ride_type=per_hour`
- `vehicle_category_id`
- `passenger_count`
- `duration_minutes`

Optional (intended):
- `dropoff`
- `children`
- `promo_code`
- `scheduled_at`

Current backend note:
- `dropoff` still required by schema today.

## Per Hour -> `/rides/book`

Required (intended):
- `pickup`
- `ride_type=per_hour`
- `vehicle_category_id`
- `payment_method`
- `passenger_count`
- `duration_minutes`

Optional (intended):
- `dropoff`
- `end_scheduled_at`
- `children`
- `passenger_notes`
- return way/stops metadata

Current backend note:
- `dropoff` still required by schema today.

## 8. Data Flow: UI -> API -> UI

1. UI form state -> `/rides/estimate`
2. Estimate response -> fare preview UI
3. Same validated form -> `/rides/book`
4. Book response returns `ride_id`
5. `ride_id` is used for:
   - `/rides/{ride_id}`
   - `/rides/{ride_id}/bids`
   - `/rides/{ride_id}/bids/{bid_id}/accept`
   - `/rides/{ride_id}/cancel`
   - websocket ride events correlation

## 9. Edge Cases

Expected business behavior:
- Missing pickup -> should fail.
- Missing drop-off in Ride -> should fail.
- Missing drop-off in Per Hour -> should pass.
- No stops -> valid.
- Return way not selected -> valid.

Current backend behavior:
- Missing pickup -> fails (validation).
- Missing drop-off in Ride -> fails (validation).
- Missing drop-off in Per Hour -> currently fails (schema still requires dropoff).
- No stops -> valid.
- Return way not selected -> valid.

## Estimate failure
- Cause: invalid coordinates/category, missing `duration_minutes` for per-hour, etc.
- UI: show error, keep form, allow retry.

## Book failure
- Cause: validation/business errors.
- UI: keep form data, show actionable error, retry.

## No drivers/no bids
- Ride may remain requested/bidding or move to no-driver state.
- UI: show waiting state + cancel/retry options.

## Websocket disconnect
- Reconnect automatically.
- Poll `/rides/{ride_id}` or `/passenger/rides/active` until reconnected.

## Loading states
- Categories loading skeleton
- Estimate button loading/debounce
- Book submit disabled during request
- Bid list loading/empty state

## 10. Quick Sequence Checklist

1. `GET /rides/categories`
2. `POST /rides/estimate`
3. `POST /rides/book`
4. `GET /passenger/rides/active`
5. `GET /rides/{ride_id}`
6. `GET /rides/{ride_id}/bids`
7. `POST /rides/{ride_id}/bids/{bid_id}/accept`
8. websocket tracking (`ws/rides/live`)
9. `GET /passenger/rides`

