Commit Graph
12 Commits
Author SHA1 Message Date
lukasandClaude Opus 5.5 440f9e5696 Keep the closed box visible and tidy the order item card
- After closing, the box button stays disabled as "Box N closed" for
  5 minutes, timed from a new picked_up_at so it survives a reload
- Picked-up items keep showing their pickup box number
- Hide the steps toggle on ready and picked-up items
- Move "Buy again" and "Get help" into a dots menu in the item header

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 23:11:47 +02:00
lukasandClaude Opus 5.5 edd34a00a7 Collect ready items from pickup boxes instead of "I picked this up"
A ready Order Item now gets the lowest-numbered free Pickup Box (or waits
for one to free up), shown as "Pickup box N" on its status. The customer
opens the box from their order and closes it again; closing marks the
item picked up and hands the box to the next waiting item.

On the order card the box button comes first, full width on mobile, with
a padlock that lifts on open and snaps shut before the button collapses
away.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:31:23 +02:00
lukasandClaude Opus 5.5 ac2aa770fb Make "Buy again" add the item to the basket
The order status view now carries each item's menu item id and the ids of
its current Options matching the ordered ones by name, since editing a
Menu Item recreates its Options under new ids. Options no longer on the
menu are left out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:07:13 +02:00
lukasandClaude Opus 5.5 1dae53f90a Animate the ETA, hide delays, and tidy the order card actions
- Slide the "Ready in about" value when it changes (new EtaMessage)
- Drop the "Running late" banner; delays only move the ETA now
- Remove the cancel-info tooltip and its icon button
- Shorten the steps toggle to "Steps" / "Hide"
- Add icons and more padding to the order card action buttons

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 11:02:35 +02:00
lukasandClaude Opus 5.5 a6ac32d783 Show live order progress, delays, and kitchen cancellations
- Order cards derive their label from item progress (Not Started,
  Preparing, Partly Ready, Ready, Picked Up, Cancelled) instead of the
  order's own status; final states are coloured
- Order page: animated status banner per item (ready/picked up check,
  cancelled cross, running-late clock), steps collapse once an item is
  settled with a Show/Hide steps toggle, done steps are faded instead
  of struck through, and the per-item status badge is gone
- New Delay concept: machines can report extra time on a claimed step
  (preparation_step_instances.delay_seconds), which counts toward the ETA
- The kitchen can cancel an item at any point before it's ready, with a
  refund (order_items.cancelled_by records who cancelled)
- Dev kitchen simulation now runs server-side across every order, so a
  step nobody is watching no longer blocks the queue; each settled step
  may randomly be delayed or cancelled
- Humanize snake_case statuses in the UI

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:11:08 +02:00
lukasandClaude Sonnet 5 c8d1721358 Add an admin panel: orders dashboard, menu management, kitchen status
Introduces a role-gated /admin section (sidebar layout, requireAdmin
checked both in route loaders and independently in every admin server
function) with three sections:
- Orders: every order across all customers, and an admin-only order
  detail view nested under /admin so the sidebar persists and admin
  access bypasses the guest-token check.
- Menu: create/edit/delete menu items, their options, and their
  preparation steps; deleting an item with past orders is refused
  (protected by the orderItems FK) instead of crashing.
- Kitchen: read-only live view of every machine's busy/idle status and
  per-tag queue depth, with a manual refresh.

Also:
- Adds a `role` field to the user table (Better Auth additionalFields,
  input:false so it can't be self-assigned) and a db:seed-admin script
  to create/promote an admin account.
- Fixes a real bug found while building this: src/server/auth.ts's
  shared session helpers were plain exported functions using a
  server-only import, which the framework couldn't tree-shake out of
  the client bundle once shared across multiple server/*.ts modules —
  this silently broke hydration app-wide. Fixed with createServerOnlyFn.
- Removes the now-fully-unused @tanstack/devtools-vite plugin.
- Disables view transitions for in-admin navigation so the persistent
  sidebar doesn't cross-fade/shift on every click.
- Gives the "your orders" empty state the same visual treatment as the
  basket page's.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 23:14:28 +02:00
lukasandClaude Sonnet 5 d66e09f515 Add menu item customization/detail pages and configurable currency formatting
Lets customers pick options on a menu item detail page before adding to the
basket, and makes displayed prices respect a configurable currency/locale
via VITE_CURRENCY/VITE_LOCALE. Also crossfades the basket's empty/filled
states with AnimatePresence in wait mode instead of animating both at once.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 21:00:45 +02:00
lukasandClaude Sonnet 5 79bd64ce8c Add guest/account auth flows, order tracking, and order history UI
- Wire up Better Auth (email/password + Google/Apple SSO) with a
  sign-in/sign-up UI, header account menu, and a basket that follows
  the signed-in-or-guest state.
- Give the order status page a vertical timeline per preparation step
  (with a distinct customer-facing name separate from the machine tag,
  a done/in-progress/queued/pending look, and a sonar-ping highlight on
  the active step), a formatted ETA (relative under 3h, absolute clock
  time beyond that), and Buy again / Get help / Cancel actions.
- Expand Pizza's recipe into 6 steps across a shared prep station and
  the existing oven/assembly stations, with matching schema, seed, and
  domain changes plus updated/added test coverage.
- Add an Orders list (account orders via session, guest orders via a
  locally remembered access-token list) with a shared getOrdersForCustomer
  domain summary, and remember a guest's name/contact after their first
  order so checkout doesn't ask again.
- Improve page transitions with the View Transitions API: a shared
  element morph between an order card and its detail page, a stable
  (non-jumping) header across navigations, and reduced-motion handling.
- Add a Ghost Kitchen wordmark (Space Grotesk, faded "Ghost", ghost
  icon standing in for the "o") and shrink the basket icon to match
  the rest of the header controls.
- Add a run-ghost-kitchen agent skill documenting local setup, the
  dev-server driver, and the gotchas hit along the way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 11:58:24 +02:00
lukasandClaude Sonnet 5 b7fdbd4779 Don't let a compensating payment call swallow the original error
Both placeOrder and cancelOrderItem call a compensating payment action
(refund / re-charge) after catching a failure, then rethrow. If that
compensating call itself threw, its error replaced the original one,
hiding the actual root cause behind whatever the payment provider
happened to fail with on the second attempt. Wrap each compensation in
its own try/catch, log the compensation failure, and always rethrow
the original error.

Also fixes a stale comment left over from renaming
createFirstStepForOrderItem to initializeOrderItemRecipe.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 20:07:14 +02:00
lukasandClaude Sonnet 5 506319ce4f Refund before cancelling, not after, with compensation on failure
cancelOrderItem committed the cancellation (freeing the Machine slot,
marking the item cancelled) before calling the payment provider's
refund — so a refund failure (gateway timeout, provider outage) left
the item cancelled with no refund ever issued, and no record that one
was owed. placeOrder already avoids the equivalent problem by charging
before its DB transaction and refunding if the transaction then fails;
apply the same pattern here for consistency.

Refund now happens first; the DB transaction's atomic queued-status
check (added for the earlier cancellation race) doubles as the signal
that the refund needs to be undone if this transaction loses the race
or otherwise fails, so the catch block re-charges to compensate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 20:01:55 +02:00
lukasandClaude Sonnet 5 9c3ad51686 Freeze an Order Item's Recipe at order time
Price was already snapshotted per Order Item so later menu changes
don't rewrite history, but the Recipe (Step list) wasn't: advancing an
Order Item looked up its next Step from the live menuItemSteps table,
so an operator editing a Menu Item's Recipe mid-cook could silently
reshape an Order already in flight (different Machine Tag, duration,
or Step order than what the customer paid for).

Adds order_item_steps as a per-Order-Item copy of the Recipe, taken at
placement time; placeOrder, advanceOrderItemStep, and getOrderStatus
now all read from that snapshot instead of the live menu. Recorded as
docs/adr/0005 and added Recipe as a formal CONTEXT.md term.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 19:55:05 +02:00
lukasandClaude Sonnet 5 456c3acda5 Implement ordering MVP domain layer per spec (issue #1)
Scaffolds the TanStack Start + Drizzle/Postgres + Better Auth app and
implements the core ordering domain: menu browsing, guest/account order
placement with online payment, per-Order-Item independent cooking and
cancellation, dynamic Machine-Tag pool assignment, and multi-step recipes
(see docs/adr/0001-0003). Adds a guest-access-token / session-based
ownership check on every read/mutation so an order can't be viewed,
cancelled, or picked up by anyone but its owner.

Covered by 14 tests running the domain layer directly against a real,
ephemeral Postgres (testcontainers) — createServerFn couldn't be called
outside a real request context, so tests exercise the domain functions the
server functions thinly wrap instead of the server functions themselves.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 18:46:58 +02:00