diff --git a/.env.example b/.env.example index a770113..5bda7e3 100644 --- a/.env.example +++ b/.env.example @@ -11,3 +11,10 @@ VITE_DEV_DIRECTUS_URL=http://localhost:8055 # Processor live-position WebSocket. Defaults to ws://localhost:8081 # (the LIVE_WS_PORT default in the processor's Phase 1.5 task spec). VITE_DEV_PROCESSOR_WS_URL=ws://localhost:8081 + +# Local-dev login form prefill. The login page populates these into the +# email/password fields on render when import.meta.env.DEV is true. Skip +# the manual typing during dev iteration. Production builds ignore them +# (the prefill is gated on import.meta.env.DEV). +# VITE_ADMIN_EMAIL=admin@example.com +# VITE_ADMIN_PASSWORD=your-local-admin-password diff --git a/.gitignore b/.gitignore index 2de043f..4fdfae0 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ src/routeTree.gen.ts *.njsproj *.sln *.sw? +*.env diff --git a/.planning/phase-1-foundation/08-logout-flow.md b/.planning/phase-1-foundation/08-logout-flow.md index 62316f7..32e462e 100644 --- a/.planning/phase-1-foundation/08-logout-flow.md +++ b/.planning/phase-1-foundation/08-logout-flow.md @@ -140,9 +140,10 @@ This is the right trade-off: logout that fails should _not_ leave the user appea **Bonus from this task** — caught a missing `"strict": true` in `tsconfig.app.json`. TanStack Router emits a `"strictNullChecks must be enabled"` conditional-type error in editors when strict mode is off; CI's `tsc -b` was lenient. Added `strict: true` (along with the existing strict-adjacent flags); typecheck still green. -**Smoke check:** `pnpm typecheck`, `pnpm lint`, `pnpm format:check`, `pnpm build` all green. Bundle: 353KB main + same per-route chunks as 1.7 (login 37KB, _authed 1.4KB grew slightly with the LogoutButton). No measurable bundle impact from the logout orchestration. +**Smoke check:** `pnpm typecheck`, `pnpm lint`, `pnpm format:check`, `pnpm build` all green. Bundle: 353KB main + same per-route chunks as 1.7 (login 37KB, \_authed 1.4KB grew slightly with the LogoutButton). No measurable bundle impact from the logout orchestration. **Browser smoke pending:** + 1. Sign in. Click "Sign out". Watch button show "Signing out…", then redirect to `/login`. Hard refresh on `/login` stays on `/login`. 2. Sign in in tab A. Open tab B (same SPA). Sign out in tab A. Tab B's home page should redirect to `/login` on next interaction (or immediately, depending on whether the storage event triggers re-render). 3. With DevTools "Network: offline", click sign out. Should still navigate to `/login` (server call fails, local state forced to anonymous). diff --git a/src/ui/pages/login.tsx b/src/ui/pages/login.tsx index ba61b7d..9525a00 100644 --- a/src/ui/pages/login.tsx +++ b/src/ui/pages/login.tsx @@ -23,6 +23,17 @@ const LoginFormSchema = z.object({ type LoginForm = z.infer; +/** + * Dev-only prefill from `VITE_ADMIN_EMAIL` / `VITE_ADMIN_PASSWORD`. + * Production builds get empty strings regardless of build-time env values. + */ +const devDefaults = import.meta.env.DEV + ? { + email: import.meta.env.VITE_ADMIN_EMAIL ?? '', + password: import.meta.env.VITE_ADMIN_PASSWORD ?? '', + } + : { email: '', password: '' }; + export type LoginPageProps = { /** Called once the auth store transitions to `'authenticated'`. */ onAuthenticated?: () => void; @@ -35,7 +46,7 @@ export function LoginPage({ onAuthenticated }: LoginPageProps) { const form = useForm({ resolver: zodResolver(LoginFormSchema), - defaultValues: { email: '', password: '' }, + defaultValues: devDefaults, }); // If the auth store flips to authenticated (e.g. login succeeds, or another diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts new file mode 100644 index 0000000..ee15fce --- /dev/null +++ b/src/vite-env.d.ts @@ -0,0 +1,16 @@ +/// + +interface ImportMetaEnv { + /** Local-dev convenience: prefill the login form's email field. Only consumed when import.meta.env.DEV. */ + readonly VITE_ADMIN_EMAIL?: string; + /** Local-dev convenience: prefill the login form's password field. Only consumed when import.meta.env.DEV. */ + readonly VITE_ADMIN_PASSWORD?: string; + /** Override the dev proxy's Directus target. See vite.config.ts. */ + readonly VITE_DEV_DIRECTUS_URL?: string; + /** Override the dev proxy's Processor WS target. See vite.config.ts. */ + readonly VITE_DEV_PROCESSOR_WS_URL?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +}