feat: task 1.6 login page
src/ui/pages/login.tsx — LoginPage component: - Centred card on muted background. - shadcn Form + FormField with react-hook-form + zodResolver. FormMessage renders field-level zod errors automatically. - Email + password with proper autocomplete attrs for password managers. autoFocus on email. - Submit calls useAuthStore.getState().login(); errors render in a destructive Alert above the form. - In-flight via the auth store's 'authenticating' status (cross-tab safe). - onAuthenticated callback fires on store transition to authenticated; 1.7 wires this to a router redirect. src/App.tsx branches on auth status: - unknown / authenticating -> "Signing you in..." placeholder (avoids flashing the login page on hard refresh while the boot probe runs) - anonymous -> <LoginPage /> - authenticated -> home placeholder (1.7 replaces with router shell) Deviation: skipped src/routes/login.tsx — requires the router plugin to have generated routeTree.gen.ts, which is 1.7's territory. The page works standalone via App.tsx's status branch. Search-param redirect (?redirect=...) also deferred to 1.7 — no router yet to expose useSearch. onAuthenticated callback is the seam.
This commit is contained in:
@@ -54,7 +54,7 @@ These rules govern every task. Any deviation must be discussed and documented as
|
||||
| 1.3 | [Vite dev proxy + path aliases + tsconfig hardening](./phase-1-foundation/03-vite-dev-proxy.md) | 🟩 | `39b60c9` |
|
||||
| 1.4 | [Runtime config endpoint](./phase-1-foundation/04-runtime-config.md) | 🟩 | `8e2151a` |
|
||||
| 1.5 | [Directus auth client (cookie mode + refresh)](./phase-1-foundation/05-directus-auth-client.md) | 🟩 | `38fe2e3` |
|
||||
| 1.6 | [Login page](./phase-1-foundation/06-login-page.md) | ⬜ | — |
|
||||
| 1.6 | [Login page](./phase-1-foundation/06-login-page.md) | 🟩 | `PENDING_SHA` |
|
||||
| 1.7 | [Routing skeleton (TanStack Router + role-aware guards)](./phase-1-foundation/07-routing-skeleton.md) | ⬜ | — |
|
||||
| 1.8 | [Logout flow](./phase-1-foundation/08-logout-flow.md) | ⬜ | — |
|
||||
| 1.9 | [Gitea CI + Dockerfile + nginx static serve](./phase-1-foundation/09-gitea-ci-and-dockerfile.md) | ⬜ | — |
|
||||
|
||||
@@ -160,4 +160,27 @@ useEffect(() => {
|
||||
|
||||
## Done
|
||||
|
||||
(Filled in when the task lands.)
|
||||
`src/ui/pages/login.tsx` — `LoginPage` component:
|
||||
|
||||
- Centred card on muted background, max-width sm.
|
||||
- shadcn `Form` + `FormField` primitives with react-hook-form + zodResolver. `FormMessage` renders field-level zod errors automatically.
|
||||
- Email + password inputs with `autoComplete="username"` / `current-password"` so password managers populate correctly. `autoFocus` on email.
|
||||
- Submit handler calls `useAuthStore.getState().login()`; on `{ ok: false }` populates a top-of-card destructive `Alert` with the humanised error.
|
||||
- In-flight indication via the auth store's `'authenticating'` status (cross-tab safe — no separate local state needed).
|
||||
- `onAuthenticated` callback prop fires when the store transitions to `'authenticated'` (covers both successful login and concurrent-tab login). The actual redirect lands in 1.7 alongside the router.
|
||||
|
||||
`src/App.tsx` updated to branch on auth status:
|
||||
|
||||
- `'unknown'` / `'authenticating'` → "Signing you in…" placeholder (avoids flashing the login page on hard refresh while the boot probe runs).
|
||||
- `'anonymous'` → `<LoginPage />`.
|
||||
- `'authenticated'` → home placeholder (1.7 replaces this branch with the TanStack Router shell).
|
||||
|
||||
**Deviation from spec:**
|
||||
|
||||
The spec called for `src/routes/login.tsx` (TanStack Router file-based route). Skipped that here — the route file requires the router plugin to have generated `routeTree.gen.ts`, which is 1.7's territory. For 1.6 the page works standalone via App.tsx's status branch; 1.7 will carve out `routes/login.tsx` and rewire App.tsx to render the router instead.
|
||||
|
||||
Search-param redirect (`?redirect=...`) also deferred to 1.7 — there's no router yet to expose `useSearch`. The `onAuthenticated` callback is the seam that 1.7 will use to navigate to the redirect target.
|
||||
|
||||
**Smoke check:** `pnpm typecheck`, `pnpm lint`, `pnpm format:check`, `pnpm build` all green. Bundle: 330KB / 102KB gzipped (up from 261KB / 80KB; react-hook-form + radix-ui from the shadcn `Form` primitive are now in the runtime path). Browser-side login against a stage Directus is the operational gate — pending until 1.10 deploys the SPA there.
|
||||
|
||||
Landed in `PENDING_SHA`.
|
||||
|
||||
Reference in New Issue
Block a user