- 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>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
// Guests have no account to list Orders under, so their Order history is
|
|
// tracked client-side instead: each placed guest Order's id + access token
|
|
// is remembered here so `/orders` can look them back up without a sign-in.
|
|
const STORAGE_KEY = 'ghost-kitchen-guest-orders'
|
|
|
|
export type GuestOrderRef = { orderId: number; guestAccessToken: string }
|
|
|
|
const isGuestOrderRef = (value: unknown): value is GuestOrderRef =>
|
|
typeof value === 'object' &&
|
|
value !== null &&
|
|
typeof (value as GuestOrderRef).orderId === 'number' &&
|
|
typeof (value as GuestOrderRef).guestAccessToken === 'string'
|
|
|
|
export const getGuestOrderRefs = (): Array<GuestOrderRef> => {
|
|
try {
|
|
const raw = window.localStorage.getItem(STORAGE_KEY)
|
|
if (!raw) return []
|
|
const parsed: unknown = JSON.parse(raw)
|
|
return Array.isArray(parsed) ? parsed.filter(isGuestOrderRef) : []
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
export const addGuestOrderRef = (ref: GuestOrderRef) => {
|
|
try {
|
|
const existing = getGuestOrderRefs().filter(
|
|
(stored) => stored.orderId !== ref.orderId,
|
|
)
|
|
window.localStorage.setItem(
|
|
STORAGE_KEY,
|
|
JSON.stringify([ref, ...existing]),
|
|
)
|
|
} catch {
|
|
// Unavailable (private mode, quota) — the order still works via its
|
|
// own link, it just won't show up in the local Orders list.
|
|
}
|
|
}
|