From d08e0370ac1451584a9b2be13c2f70e4e1d7ffdb Mon Sep 17 00:00:00 2001 From: jableader Date: Sat, 1 Nov 2025 20:25:18 +1100 Subject: [PATCH] =?UTF-8?q?docs:=20finalize=20Person=E2=86=92Member=20migr?= =?UTF-8?q?ation,=20add=20Google=20sign-in=20button,=20and=20align=20style?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend-spec.md | 19 ++++++++++++------- src/components/LoginPage.vue | 18 +++++++++++++++++- src/components/meals/EditMealPage.vue | 8 ++++---- src/components/meals/MemberList.vue | 24 ++++++++++++------------ 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/frontend-spec.md b/frontend-spec.md index 12e859c..fea20e1 100644 --- a/frontend-spec.md +++ b/frontend-spec.md @@ -1,9 +1,12 @@ ## 0. Current State (Nov 1, 2025) +All core features are migrated to multi-tenancy with path-scoped endpoints and token-based auth. The codebase no longer uses the `X-Household-Slug` header. Tests and type checks are fully green. +## 0. Current State (Nov 1, 2025) + All core features are migrated to multi-tenancy with path-scoped endpoints and token-based auth. The codebase no longer uses the `X-Household-Slug` header. Tests and type checks are fully green. Status of tests and typing -- All tests pass: 29 files, 49 tests (slug-only routes; memory history fallback in non-browser envs; unauthenticated and refresh-401 guard redirects covered). +- All tests pass: 27 files, 46 tests (slug-only routes; memory history fallback in non-browser envs; unauthenticated and refresh-401 guard redirects covered). - `tsc` and `vue-tsc` pass with no errors. # Frontend Specification: Household Multi-Tenancy (v2) @@ -123,15 +126,17 @@ What exists now - `src/router/index.ts`: slug-only nesting under `/:householdSlug/...`; public routes include `/create-account`, `/welcome`, and `/invitations/accept`. - Guard fetches households, redirects root `/` to the first household's `mealplan`, and uses memory history in tests (hash in browser). - SDK/API - - `src/api/sdk.ts`: recipes, meals, and shopping are migrated to `/api/v1/households/{householdSlug}/...` typed endpoints. Persons and parse use temporary raw fetch endpoints where OpenAPI lacks coverage. + - `src/api/sdk.ts`: recipes, meals, and shopping are migrated to `/api/v1/households/{householdSlug}/...` typed endpoints. Person endpoints removed; parse uses a temporary raw fetch endpoint until typed coverage is available. - `src/api/client.ts`: Authorization header provider only; household header injection removed. - Domain & UI - - Member arrays (`chefs`, `consumers`, `cleanup`) normalized to MemberRef `{ id, displayName }` with decoders handling legacy shapes gracefully. + - Member arrays (`chefs`, `consumers`, `cleanup`) normalized to `MemberRef` `{ id, displayName }` with decoders handling legacy shapes gracefully. + - `MemberRef` is exported from `src/domain/types.ts` and used by components (per axioms). + - `PersonList.vue` renamed to `MemberList.vue`; it sources from typed household members and emits `add`/`remove`. - Invitation Accept flow implemented; Household Settings supports sending invitations and listing members using typed endpoints. - MyShopping: page remains as in master with editable panel backed by legacy v1 stubs (`getMyShoppingList/saveMyShoppingList`) pending backend ad-hoc item endpoints. Status of tests and typing -- All tests pass: 29 files, 49 tests. +- All tests pass: 27 files, 46 tests. - `tsc` and `vue-tsc` pass with no errors. --- @@ -166,7 +171,7 @@ Progress Log (Nov 1, 2025) - Backend updated OpenAPI and codegen has been run: - Many endpoints are now path-scoped with `{householdSlug}` (recipes, meals, shopping, invitations (create), whoami). - Auth endpoints (login/register/refresh/logout) are fully typed; `refresh` returns only `{ accessToken, tokenType }`. - - Completed migration to typed path parameters; header injection removed; only small raw fetch helpers remain for endpoints not yet in OpenAPI (persons, parse). + - Completed migration to typed path parameters; header injection removed; only small raw fetch helpers remain for endpoints not yet in OpenAPI (parse only). --- @@ -212,7 +217,7 @@ SDK - Persons and parse endpoints are still raw until they are added to the OpenAPI. UI -- Login Page: Refactored to show email/password form when multitenant flag is enabled; legacy person list retained otherwise. Link to Create Account added. + - Login Page: Refactored to show email/password form; Google sign-in planned. Link to Create Account added. - Add `HouseholdSwitcher.vue` to app chrome and wire with router. - Update components that navigate using string paths to use named routes with slug. - `src/views/HouseholdSettings.vue`: Invite members form wired to `sendInvitation(email)`. Members list rendered from `listMembers()` using the typed endpoint. (Completed) @@ -235,7 +240,7 @@ Tests 1) Remove X-Household-Slug header injection in `api/client.ts` and refactor services to accept `householdSlug` via typed params. (Completed) 2) Replace temporary raw fetch calls with generated typed endpoints where available: invitations and members listing are now typed; migrate usages. Persons and parse remain raw for now. 3) Integrate the new `POST /shopping/current/ingredients` endpoint into the SDK (`requestIngredient(ingredientId: number)`) and expose via `useShopping`; refactor `MyShoppingPage.vue` accordingly and remove legacy stubs. (SDK + composable done; UI refactor next) - 4) Legacy identity: continue using `User` as the primary identity. Keep `Person` in meal-related UIs where required by backend, but remove Person as the login/identity concept. + 4) Identity: `User` remains the primary identity. `Person` has been removed; meal-related UIs use `MemberRef` exclusively. --- diff --git a/src/components/LoginPage.vue b/src/components/LoginPage.vue index 6118b86..564c83d 100644 --- a/src/components/LoginPage.vue +++ b/src/components/LoginPage.vue @@ -28,6 +28,13 @@ > Sign in + import { ref, onMounted, computed } from 'vue' import { useRouter, useRoute } from 'vue-router' -import { loginWithPassword } from '@/api/auth' +import { loginWithPassword, handleGoogleLogin } from '@/api/auth' import { useAuth } from '@/composables/useAuth' const props = defineProps({ @@ -82,6 +89,15 @@ async function onSubmitLogin() { } } +async function onGoogleLogin() { + try { + await handleGoogleLogin() + } catch (e) { + // Surface the placeholder message for now; real implementation will redirect + alert(e instanceof Error ? e.message : 'Google login not available') + } +} + // legacy login removed diff --git a/src/components/meals/EditMealPage.vue b/src/components/meals/EditMealPage.vue index 1dc814f..443083a 100644 --- a/src/components/meals/EditMealPage.vue +++ b/src/components/meals/EditMealPage.vue @@ -5,7 +5,7 @@ :date="meal.suggestedDate ?? new Date()" @date-selected="selectDate" /> -
+
Cooked by - +