DocHub
Driver interface, order claiming, delivery fees, ETA, proof of delivery

Delivery & Driver System

Drivers use a web-based interface at /delivery to claim available orders, pick up food, and deliver to customers. The system is claim-based — drivers choose which orders to accept.

Driver Interface

Main page at src/app/delivery/page.tsx (2343 lines):

  • Available orders: Unassigned delivery orders with status accepted or ready
  • My deliveries: Orders assigned to this driver
  • Real-time notifications: Browser push + sound alerts for new orders
  • GPS integration: Location tracking for ETA and proof of delivery

Navigation sidebar links to /delivery (active orders) and /delivery/history (past deliveries).

Order Claiming Flow

  1. Restaurant accepts order → status becomes accepted
  2. System sends “New delivery available” notification to all drivers
  3. Driver views available orders at /api/driver/orders/available
  4. Driver claims order → POST /api/driver/orders/{id}/claim
  5. System checks max active deliveries (default: 1, configurable via DRIVER_MAX_ACTIVE_DELIVERIES)
  6. Atomic update: only succeeds if driver_user_id IS NULL (prevents double-claims)
  7. Notifications sent to customer, restaurant staff, and admins

Admins can also manually assign drivers via PATCH /api/admin/orders/{id}.

Delivery Lifecycle

1. CLAIMED — Driver accepts order (driver_user_id set)
2. PICKED UP — Driver at restaurant, marks pickup
   → Status: out_for_delivery, picked_up_at set
   → Optional: bag verification (pickup_verified_at)
3. DELIVERED — Driver at customer, captures proof
   → Status: delivered, delivered_at set
   → Proof: photo + GPS location + optional signature

Resignation

Drivers can resign before pickup (statuses: accepted, ready):

  • Sets driver_user_id = null
  • Records driver_released_at, driver_released_by_uid
  • Order returns to available pool

Cannot resign after out_for_delivery.

Admin Release

Admins can forcibly unassign a driver. If order was out_for_delivery, it reverts to ready.

Delivery Fee Calculation

src/utils/distance.ts:

Base fee: $3.00 USD
Per-km (beyond 1km): $0.50 USD
Formula: $3 + max(distance - 1, 0) × $0.50
Converted to HNL cents using exchange rate from config

Example: 3km delivery = $3 + (2 × $0.50) = $4.00 USD → ~10,400 HNL cents at 2600 rate.

Distance calculated using haversine formula between restaurant and delivery address coordinates.

ETA Calculation

Two methods:

  1. Google Maps Distance Matrix (/api/driver/eta): Real-time ETA from driver’s current GPS location to restaurant. Requires GOOGLE_MAPS_SERVER_KEY.

  2. Simple estimate (src/utils/distance.ts): max(5, 5 + distance_km × 4) minutes. Used as fallback and for customer-facing estimates.

Customer ETA combines prep time + delivery time (src/utils/eta.ts).

Proof of Delivery

POST /api/driver/orders/{id}/proof:

{
  captured_at: string       // ISO timestamp
  captured_by_uid: string   // Driver's auth UID
  note?: string             // Delivery notes
  photo_file_id?: string    // Uploaded photo reference
  signature_file_id?: string // Customer signature
  location?: {
    lat: number
    lng: number
    accuracy_meters?: number
  }
}

Photos uploaded via /api/uploads, stored on Cloudflare R2.

Driver Notifications

src/lib/driverNotifications.ts:

  • Web Push API with VAPID keys
  • Custom alert sound (880Hz + 1108Hz tones)
  • Vibration pattern: [120ms, 60ms, 120ms]
  • Shows order number, pickup restaurant, dropoff address

API Routes

Route Method Purpose
/api/driver/orders GET List driver’s assigned orders
/api/driver/orders/available GET List unclaimed delivery orders
/api/driver/orders/{id}/claim POST Claim an order
/api/driver/orders/{id}/pickup POST Mark as picked up
/api/driver/orders/{id}/resign POST Release order
/api/driver/orders/{id}/proof POST Submit proof of delivery
/api/driver/eta GET Calculate ETA to restaurant
/api/driver/max-deliveries GET Get max active delivery limit
/api/admin/drivers GET List all drivers with busy/idle status

Key Files

File Purpose
src/app/delivery/page.tsx Main driver UI
src/components/delivery/DriverSidebar.tsx Driver navigation
src/app/api/driver/orders/available/route.ts Available orders endpoint
src/app/api/driver/orders/[orderId]/claim/route.ts Order claiming
src/app/api/driver/orders/[orderId]/pickup/route.ts Pickup confirmation
src/app/api/driver/orders/[orderId]/proof/route.ts Proof of delivery
src/app/api/driver/orders/[orderId]/resign/route.ts Order resignation
src/app/api/driver/eta/route.ts ETA calculation
src/utils/distance.ts Haversine distance, delivery fee calc
src/utils/eta.ts Customer ETA estimation
src/lib/driverNotifications.ts Push notifications + sounds
src/lib/driverLimits.ts Max active deliveries config
src/app/admin/drivers/page.tsx Admin driver management