Dispatch Offer
A courier-side job offer with pickup and drop-off, fee, cash to collect, distance, ETA and a ring that counts down to expiry, with accept and decline.
Code
<DispatchOffer pickup={{ name: "Al-Quds Bakery" }} dropoff={{ name: "Sara Odeh" }} feeMinor={1500} expiresAt={Date.now() + 30_000} onAccept={accept} onDecline={decline}/>Delivery · beta
Live examples and controls: Dispatch Offer in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/dispatch-offer.jsonThe card a courier sees when an order is offered. A ring counts down the response window; when it runs out the offer
calls onExpire and the buttons turn off.
When to use
- Pushing a job to a courier who must answer quickly.
When not to use
- Assigning from the dispatcher side: use
CourierCard. - A plain timer: use
TimerRing.
Import
import { DispatchOffer } from "@fadymondy/nasaq/web";
// inside this monorepo: "@nasaq/web"Quick start
<DispatchOffer
pickup={{ name: "Al-Quds Bakery" }}
dropoff={{ name: "Sara Odeh" }}
feeMinor={1500}
expiresAt={Date.now() + 30_000}
onAccept={accept}
onDecline={decline}
/>Anatomy
DispatchOffer data-slot="dispatch-offer" data-expired
├─ TimerRing + seconds left
├─ pickup → drop-off
├─ fee, cash to collect, distance, ETA, order count
├─ children slot
└─ Decline / AcceptAPI
| Prop | Type | Default | Description |
|---|---|---|---|
pickup / dropoff | OfferPlace | required | name, nameAr, address, addressAr. |
feeMinor | number | none | Courier fee in minor units. |
cashToCollectMinor | number | none | Cash due from the customer. |
currency | string | "USD" ("SAR" in Arabic) | ISO currency. |
distanceMeters / etaSeconds | number | none | Trip size. |
orderCount | number | 1 | More than one shows a multi-order badge. |
expiresAt | number | none | Epoch ms when the offer lapses. Optional: without it there is no countdown and the offer never expires. |
mode | "courier" | "dispatcher" | "courier" | "dispatcher" is the dispatcher's view of an offer about to be sent: no countdown, "Driver earns" as the fee label, a Cancel button (onDecline) and an "Offer to driver" button (onOffer). |
onOffer | () => void | none | Dispatcher mode: the "Offer to driver" action. |
windowSeconds | number | 30 | Full window, for the ring fraction. |
now | number | clock | Override the clock, for tests. |
onAccept / onDecline / onExpire | () => void | none | Outcomes. |
children | ReactNode | none | Extra content. |
locale / labels | "en" | "ar" / partial strings | context | Language and overrides. |
Examples
Lab stories: default, multi-order, no cash, nearly expired, expired, Arabic.
Accessibility
The remaining time is text inside a role="timer" region, announced only at coarse steps. Buttons are native and
disabled after expiry. Colour is never the only signal.
RTL & i18n
Logical layout, built-in Arabic. The route arrow flips in RTL.
Styling & tokens
Ring tones come from timerToneText; the danger phase maps to the warning token. Target [data-expired].
Do / Don't
- Do keep the window short and visible.
- Don't auto-accept on expiry.
Related
Countdown, CashCollect, RouteStops.
Lab
https://docs.nasaqui.com/?path=/docs/components-delivery-dispatch-offer--docs
Delivery Tracker
A customer-facing order tracker - five delivery steps with times, an ETA, the courier with call and message actions, a map slot, and cancelled or failed outcomes.
Route Stops
An ordered multi-order trip - pickups and drop-offs with done, current and failed states, cash per stop, a trip summary and a per-stop action slot.