Nasaq
Components

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.

PreviewOpen ↗

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.json

The 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

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 / Accept

API

PropTypeDefaultDescription
pickup / dropoffOfferPlacerequiredname, nameAr, address, addressAr.
feeMinornumbernoneCourier fee in minor units.
cashToCollectMinornumbernoneCash due from the customer.
currencystring"USD" ("SAR" in Arabic)ISO currency.
distanceMeters / etaSecondsnumbernoneTrip size.
orderCountnumber1More than one shows a multi-order badge.
expiresAtnumbernoneEpoch 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() => voidnoneDispatcher mode: the "Offer to driver" action.
windowSecondsnumber30Full window, for the ring fraction.
nownumberclockOverride the clock, for tests.
onAccept / onDecline / onExpire() => voidnoneOutcomes.
childrenReactNodenoneExtra content.
locale / labels"en" | "ar" / partial stringscontextLanguage 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.

Countdown, CashCollect, RouteStops.

Lab

https://docs.nasaqui.com/?path=/docs/components-delivery-dispatch-offer--docs

On this page