Add the customer ordering page

Builds the main customer-facing flow: browse the Brand's menu, add
items to a cart, and check out either as a guest (name + contact) or,
if signed in, as the account customer — both call the existing
placeOrder server function, which already distinguishes the two. On
success, navigates to a new /orders/$orderId status page showing each
Order Item's Preparation Steps, queue position, ETA, and (per the
domain rules already established) a Cancel button while cancellable
and a pickup-confirmation button once ready.

Styled with SCSS Modules per CLAUDE.md; added the sass dependency and
the src/styles/ structure it describes (globals.scss imported once in
__root.tsx, alongside the existing Tailwind stylesheet the not-yet-
mounted header-user.tsx component depends on).

Verified end-to-end against a throwaway local Postgres: menu renders
with seeded items, cart quantities update, guest checkout places a
real order, and the status page reflects a real cancellation.

Also fixes CLAUDE.md's Commands section, which documented pnpm even
though this repo only has npm (package-lock.json, no pnpm installed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-09 20:31:32 +02:00
co-authored by Claude Sonnet 5
parent b7fdbd4779
commit ea459e72b3
19 changed files with 1118 additions and 24 deletions
+21 -3
View File
@@ -10,6 +10,7 @@
import { Route as rootRouteImport } from './routes/__root'
import { Route as IndexRouteImport } from './routes/index'
import { Route as OrdersOrderIdRouteImport } from './routes/orders/$orderId'
import { Route as ApiAuthSplatRouteImport } from './routes/api/auth/$'
const IndexRoute = IndexRouteImport.update({
@@ -17,6 +18,11 @@ const IndexRoute = IndexRouteImport.update({
path: '/',
getParentRoute: () => rootRouteImport,
} as any)
const OrdersOrderIdRoute = OrdersOrderIdRouteImport.update({
id: '/orders/$orderId',
path: '/orders/$orderId',
getParentRoute: () => rootRouteImport,
} as any)
const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({
id: '/api/auth/$',
path: '/api/auth/$',
@@ -25,27 +31,31 @@ const ApiAuthSplatRoute = ApiAuthSplatRouteImport.update({
export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/orders/$orderId': typeof OrdersOrderIdRoute
'/api/auth/$': typeof ApiAuthSplatRoute
}
export interface FileRoutesByTo {
'/': typeof IndexRoute
'/orders/$orderId': typeof OrdersOrderIdRoute
'/api/auth/$': typeof ApiAuthSplatRoute
}
export interface FileRoutesById {
__root__: typeof rootRouteImport
'/': typeof IndexRoute
'/orders/$orderId': typeof OrdersOrderIdRoute
'/api/auth/$': typeof ApiAuthSplatRoute
}
export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/api/auth/$'
fullPaths: '/' | '/orders/$orderId' | '/api/auth/$'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/api/auth/$'
id: '__root__' | '/' | '/api/auth/$'
to: '/' | '/orders/$orderId' | '/api/auth/$'
id: '__root__' | '/' | '/orders/$orderId' | '/api/auth/$'
fileRoutesById: FileRoutesById
}
export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
OrdersOrderIdRoute: typeof OrdersOrderIdRoute
ApiAuthSplatRoute: typeof ApiAuthSplatRoute
}
@@ -58,6 +68,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexRouteImport
parentRoute: typeof rootRouteImport
}
'/orders/$orderId': {
id: '/orders/$orderId'
path: '/orders/$orderId'
fullPath: '/orders/$orderId'
preLoaderRoute: typeof OrdersOrderIdRouteImport
parentRoute: typeof rootRouteImport
}
'/api/auth/$': {
id: '/api/auth/$'
path: '/api/auth/$'
@@ -70,6 +87,7 @@ declare module '@tanstack/react-router' {
const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
OrdersOrderIdRoute: OrdersOrderIdRoute,
ApiAuthSplatRoute: ApiAuthSplatRoute,
}
export const routeTree = rootRouteImport