import 'package:miler/data/api_config.dart'; /// ───────────────────────────────────────────────────────────────────────── /// EVERY URL THE DELIVERY LINE CALLS /// /// ── Why this file exists ── /// /// The delivery screens under `lib/xpress` are a verbatim port of the /// Xpress-rider app, which talked to a different backend entirely: /// `jupiter.nearle.app` for reads and `queue.workolik.com` for writes, with the /// URLs scattered inline across `homepage.dart`, `cartpage.dart`, /// `deliveries.dart`, `summary.dart` and three controllers. Repointing that at /// Doormile by find/replacing hostnames is exactly the class of change that /// produced the `deliver`→`Pick up` corruption this repo has already had to /// undo once. /// /// So every delivery-line URL is named here, once, and the call sites read a /// getter. Repointing the line is now one file. /// /// ── What it points at ── /// /// `https://api.doormile.com/api/v1` — the same host and the same bearer token /// as the parcel line, via [ApiConfig]. There is one Doormile backend and the /// delivery rider signs in to it with the same credentials as everyone else. /// /// ── What is real and what is not ── /// /// The Doormile backend (`doormile_backend/routes/routes.go`) does **not** /// expose a delivery queue. It exposes a miler API built around bookings and /// consignments. Each constant below is therefore marked: /// /// • **LIVE** — a route that exists on the backend today, verified against /// `routes.go`. Called for real. /// • **MAPPED** — no exact counterpart, but a route that answers the same /// question, so the screen has something true to draw. /// • **ABSENT** — no counterpart at all. The call will 404 until the route is /// built. Listed rather than hidden, because a rider seeing an /// empty list needs someone to know why. /// /// The ABSENT set is the delivery *queue* — the list of drops a rider is /// holding. `/miler/assignments` and `/miler/bookings` are the nearest real /// things and are what [deliveryQueue] and [currentDeliveries] use, but they /// return the booking shape (a first-mile pickup), not the delivery shape the /// ported cards read. Until the backend grows a delivery contract, the delivery /// line will render whatever those return through the existing adapter and will /// be thin. /// /// This is a known, accepted gap: it was chosen deliberately over keeping the /// working Nearle hosts. See the note in `docs/` if one is added. /// ───────────────────────────────────────────────────────────────────────── class DeliveryApi { DeliveryApi._(); /// The one host. Shared with the parcel line — see [ApiConfig.newBase]. static String url(String path) => ApiConfig.url(path); /// Headers for every authenticated delivery call: the same bearer token the /// parcel line uses, because it is the same rider account on the same server. static Future> headers() => ApiConfig.authHeaders(); // ───────────────────────── the work list ───────────────────────── /// **MAPPED** — the drops this rider is holding. /// /// Was `/api/v2/deliveries/getdeliveryqueues`. The backend has no queue, so /// this is the assignment list, which is the same question asked of a /// different noun: "what has the hub given me?" static String get deliveryQueue => url('/miler/assignments'); /// **MAPPED** — the rider's own accepted work. /// /// Was `/api/v2/deliveries/getdeliveries` (and the v1 and v3 date-bounded /// variants, which collapsed to the same call with different params). static String get currentDeliveries => url('/miler/bookings'); /// **LIVE** — full detail for one assignment. static String assignmentDetail(Object id) => url('/miler/assignments/$id'); /// **LIVE** — accept a job. /// /// Keyed on the **bookingassignmentid**, not the bookingid. Passing the wrong /// one is the first of the two structural breaks recorded against this repo: /// the handler reads `bookingassignmentid` and the app used to send a /// bookingid, so every accept silently missed. The id comes from /// [deliveryQueue]'s rows. static String accept(Object assignmentId) => url('/miler/assignments/$assignmentId/accept'); /// **LIVE** — decline a job. static String reject(Object assignmentId) => url('/miler/assignments/$assignmentId/reject'); // ───────────────────────── working a stop ───────────────────────── /// **LIVE** — the rider is at the door. static String reached(Object bookingId) => url('/miler/bookings/$bookingId/reached'); /// **LIVE** — hand the consignment over. The one genuine delivery verb the /// backend has. static String deliver(Object consignmentId) => url('/miler/consignments/$consignmentId/deliver'); /// **LIVE** — money changed hands. static String payment(Object bookingId) => url('/miler/bookings/$bookingId/payment'); /// **ABSENT** — the generic status write the ported flow uses for every /// transition (accepted → active → arrived → delivered → skipped). /// /// Was `queue.workolik.com/live/api/v1/deliveries/updatedelivery`. There is no /// single status-write route on Doormile; the transitions above are separate /// endpoints. Call sites that still post a bare status change land here and /// will 404 until either they are split or the route is built. static String get updateDelivery => url('/miler/bookings/status'); // ───────────────────────── rider logs and duty ───────────────────────── /// **LIVE** — periodic location/telemetry log. /// /// Was `queue.workolik.com/live/api/v2/partners/createriderlog`. static String get createRiderLog => url('/miler/logs'); /// **LIVE** — read them back. static String get getRiderLog => url('/miler/logs'); /// **LIVE** — on/off duty. static String get startDuty => url('/miler/duty/start'); static String get endDuty => url('/miler/duty/end'); static String get currentDuty => url('/miler/duty/current'); /// **LIVE** — break start/end. Was the `createbreaklog`/`updatebreaklog` /// pair on the queue host. static String get startBreak => url('/miler/breaks/start'); static String get endBreak => url('/miler/breaks/end'); /// **LIVE** — availability toggle, which is what the duty slider on the /// delivery home screen actually means to the server. static String get availability => url('/miler/availability'); /// **LIVE** — live location ping. static String get location => url('/miler/location'); /// **ABSENT** — per-delivery event log. /// /// Was `queue.workolik.com/live/api/v2/deliveries/createdeliverylog`. The /// closest real thing is consignment logs, which key on a consignmentid the /// delivery flow does not always hold. static String get createDeliveryLog => url('/miler/consignments/logs'); // ───────────────────────── earnings and profile ───────────────────────── /// **LIVE** — the Summary tab's figures. Was `/api/v2/partners/...`. static String get earnings => url('/miler/earnings'); /// **ABSENT** — the weekly kilometre chart on Summary. /// /// Was `/api/v1/partners/getriderweeklykms`. Doormile tracks distance through /// the periodic logs but exposes no aggregate, so the chart has no source. static String get weeklyKms => url('/miler/earnings/weekly-kms'); /// **ABSENT** — the bonus/rewards summary behind the rewards card. static String get bonusSummary => url('/miler/earnings/bonus'); /// **LIVE** — rider profile. static String get profile => url('/miler/profile'); // ───────────────────────── support ───────────────────────── /// **LIVE** — raise and list support tickets. static String get createSupportTicket => url('/miler/support'); static String get getSupportTickets => url('/miler/support'); /// **ABSENT** — image upload for a support ticket attachment. /// /// Was `/api/v1/partners/uploadimage/`, with the result served back from /// `images.nearle.app`. Doormile has no upload route and no image host, so /// attachments cannot be sent. static String get uploadImage => url('/miler/support/upload'); /// Public base for an uploaded image. **ABSENT** — see [uploadImage]. static String image(String objectPath) => 'https://images.doormile.com/$objectPath'; // ───────────────────────── notifications ───────────────────────── /// **LIVE** static String get notifications => url('/miler/notifications'); static String markNotificationRead(Object id) => url('/miler/notifications/$id/read'); }