Skip to content

Café

PreviousNext

Space's Business Café — QR ordering at the seat, a counter POS, a bar display and member tabs.

Space runs a café inside the building. Guests order from their phone by scanning a QR code at their seat; the counter rings up walk-ins on a POS; the bar works from its own display; members can run a tab and settle it later.

Who does what

ScreenRouteRoles
Menu (QR target)/{lang}/cafe?spot=<code>Guests
Checkout/{lang}/cafe/checkoutGuests
Order tracking/{lang}/cafe/order/<token>Guests
Counter queue/{lang}/dashboard/cafeAdmin, Cashier
POS (new order)/{lang}/dashboard/cafe/newAdmin, Cashier
Bar display/{lang}/dashboard/cafe/barEveryone on staff
Member tabs/{lang}/dashboard/cafe/tabsAdmin, Cashier
Menu, options, seats & QR, settings/{lang}/dashboard/cafe/menu …Admin
Sales/{lang}/dashboard/cafe/salesAdmin

An order's life

Placed

A QR order starts NEW and waits for the counter to confirm it — that confirmation is the check against pranks. A POS order starts CONFIRMED.

Made

The bar moves it CONFIRMED → PREPARING → READY. Guests watch the change on their tracking page (a 10-second poll; staff screens poll every 5 seconds and chime on new orders).

Handed over

READY → COMPLETED when it is picked up at the counter or brought to the seat. Any open order can be CANCELLED with a reason.

The state machine and who may move what live in src/lib/cafe/status.ts. Every write is conditional on the status the staff member saw, so two taps at once never skip a step.

Money

  • Amounts are whole Sudanese pounds (Int, SDG) — never floats.
  • Prices come only from the database. The cart shows totals with the same computeLine the server uses (src/lib/cafe/pricing.ts).
  • Orders snapshot item names (Arabic and English), options and prices. Editing the menu never rewrites history.
  • A retried checkout returns the same order: each attempt carries an idempotency key.

Payment

Payment status is separate from order status — completing an order doesn't mark it paid.

MethodHow it works
CashPaid at the counter; the cashier marks it paid.
BankakThe guest transfers to the café's Bankak account (shown at checkout and on tracking) and may type the transaction number; the cashier checks it and marks it paid.
Member tabCharged to the open tab registered to the guest's phone. It stays unpaid until the tab is settled in one cash or Bankak payment.

The menu

The seeded menu is a placeholder: typical Port Sudan café drinks and snacks, all unpublished at price 0. Nothing reaches guests until someone sets a price and publishes the item in Admin → Café menu. Items have two switches: published (on the menu at all) and available (in stock right now — the bar can flip it during the day).

pnpm cafe:seed     # create-only; safe to re-run, never overwrites edits

Seats and QR codes

Each seat or area (coworking, meeting room, training room…) is a CafeSpot with a short code. Its QR code opens /ar/cafe?spot=<code>, so "bring it to my seat" orders know where to go. Admin → Café menu → Seats & QR prints cut-out cards.