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>
This commit is contained in:
2026-09-10 11:58:24 +02:00
co-authored by Claude Sonnet 5
parent 5059f40d4c
commit 79bd64ce8c
54 changed files with 3514 additions and 301 deletions
+67 -24
View File
@@ -1,33 +1,64 @@
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
import {
HeadContent,
Link,
Scripts,
createRootRoute,
} from '@tanstack/react-router'
import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'
import { TanStackDevtools } from '@tanstack/react-devtools'
import '../styles/globals.scss'
import { BasketLink } from '#/components/basket/BasketLink.tsx'
import { Logo } from '#/components/ui/Logo.tsx'
import BetterAuthHeader from '#/integrations/better-auth/header-user.tsx'
import { BasketProvider } from '#/lib/basket.tsx'
import { getBrand } from '#/server/brand.ts'
const RootDocument = ({ children }: { children: React.ReactNode }) => (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
{children}
<TanStackDevtools
config={{
position: 'bottom-right',
}}
plugins={[
{
name: 'Tanstack Router',
render: <TanStackRouterDevtoolsPanel />,
},
]}
/>
<Scripts />
</body>
</html>
)
import '../styles/globals.scss'
import styles from './__root.module.scss'
const RootDocument = ({ children }: { children: React.ReactNode }) => {
const { brand } = Route.useLoaderData()
return (
<html lang="en">
<head>
<HeadContent />
</head>
<body>
<BasketProvider>
<div
className={styles.topBar}
style={{ viewTransitionName: 'site-header' }}
>
<Link to="/" className={styles.brand}>
<Logo name={brand.name} />
</Link>
<div className={styles.actions}>
<BasketLink />
<BetterAuthHeader />
</div>
</div>
{children}
</BasketProvider>
<TanStackDevtools
config={{
position: 'bottom-right',
}}
plugins={[
{
name: 'Tanstack Router',
render: <TanStackRouterDevtoolsPanel />,
},
]}
/>
<Scripts />
</body>
</html>
)
}
export const Route = createRootRoute({
loader: async () => ({ brand: await getBrand() }),
head: () => ({
meta: [
{
@@ -41,6 +72,18 @@ export const Route = createRootRoute({
title: 'Ghost Kitchen',
},
],
links: [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossOrigin: 'anonymous',
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;700&display=swap',
},
],
}),
shellComponent: RootDocument,
})