MySHopping spec updates
This commit is contained in:
parent
53f8909924
commit
290ad06f0c
2 changed files with 96 additions and 8 deletions
|
|
@ -128,7 +128,7 @@ What exists now
|
|||
- `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.
|
||||
- Invitation Accept flow implemented; Household Settings supports sending invitations and listing members (members via temporary raw fetch path-scoped endpoint until typed spec lands).
|
||||
- Invitation Accept flow implemented; Household Settings supports sending invitations and listing members using typed endpoints.
|
||||
|
||||
Status of tests and typing
|
||||
- All tests pass: 27 files, 48 tests.
|
||||
|
|
@ -201,13 +201,21 @@ API client
|
|||
|
||||
SDK
|
||||
- `src/api/sdk.ts`:
|
||||
- Recipes, meals, shopping fully path-scoped to households. Persons/parse remain via raw fetch until typed coverage.
|
||||
- Recipes, meals, shopping fully path-scoped to households.
|
||||
- Newly typed endpoints (post-latest codegen):
|
||||
- `GET /api/v1/households/{householdSlug}/shopping/current` — current aggregated list.
|
||||
- `GET /api/v1/households/{householdSlug}/shopping/{list_id}` — purchased list by id.
|
||||
- `POST /api/v1/households/{householdSlug}/shopping` — purchase items (storeName + items).
|
||||
- `POST /api/v1/households/{householdSlug}/shopping/current/meals/me` — request a meal.
|
||||
- `DELETE /api/v1/households/{householdSlug}/shopping/current/meals/{meal_id}` — unrequest a meal.
|
||||
- `POST /api/v1/households/{householdSlug}/shopping/current/ingredients` — request an ingredient (by id) for shopping.
|
||||
- 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.
|
||||
- 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()`; guarded for backends that don’t yet support the endpoint.
|
||||
- `src/views/HouseholdSettings.vue`: Invite members form wired to `sendInvitation(email)`. Members list rendered from `listMembers()` using the typed endpoint.
|
||||
- Adjust pages that call SDK/API to pass `{ householdSlug }` path params once client services are migrated.
|
||||
|
||||
Tests
|
||||
|
|
@ -223,9 +231,10 @@ Tests
|
|||
- Household scoping: use typed path params (`{ params: { path: { householdSlug } } }`); do not mutate path strings.
|
||||
- Auth refresh: returns `{ accessToken, tokenType }`. After refresh, call user/household endpoints to populate app state. Use `whoami` to validate the active route’s slug when needed.
|
||||
- Cleanup/migration tasks:
|
||||
1) Remove X-Household-Slug header injection in `api/client.ts` and refactor services to accept `householdSlug` via typed params.
|
||||
2) Replace temporary raw fetch for invitations (both accept and create) and members listing with generated typed endpoints. Invitations are now typed; members listing remains pending.
|
||||
3) Legacy identity: continue using `User` as the primary identity. Keep `Person` in meal-related UIs where the backend requires it, but remove Person as the login/identity concept.
|
||||
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.
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -252,6 +261,21 @@ Google OAuth is planned next.
|
|||
- Add a user profile endpoint and load it post-refresh to populate `currentUser()` with real data instead of a placeholder.
|
||||
- Replace temporary raw fetch calls (persons, parse, members listing) with typed endpoints when available.
|
||||
- Implement Google OAuth login and account creation flows.
|
||||
- Review `MyShoppingPage` usage and remove legacy `getMyShoppingList/saveMyShoppingList` stubs when UI is refactored or removed.
|
||||
- MyShopping ad-hoc item requests (planned):
|
||||
- The v2 OpenAPI spec is being updated to include endpoints for creating, listing, updating, and deleting ad-hoc requested items on the current shopping list (independent of meals), scoped under `/api/v1/households/{householdSlug}/shopping/current/items`.
|
||||
- Once available, add typed SDK methods:
|
||||
- `createRequestedItem(input: { name: string; line?: string; quantity?: number; unit?: Unit })`
|
||||
- `updateRequestedItem(id: number, patch: { name?: string; line?: string; quantity?: number; unit?: Unit })`
|
||||
- `deleteRequestedItem(id: number)`
|
||||
- `listRequestedItems()` (if provided separately; otherwise rely on `getCurrentShoppingList()`)
|
||||
- Refactor `src/components/shopping/MyShoppingPage.vue` to use the above methods and remove legacy stubs `getMyShoppingList/saveMyShoppingList` from the SDK and `useShopping` composable.
|
||||
- Update tests to drive TDD:
|
||||
- MSW handlers for the new endpoints with path-scoped URLs and Authorization.
|
||||
- Component tests to add, edit, and delete an ad-hoc requested item and verify it appears under outstanding items in `getCurrentShoppingList()`.
|
||||
- Acceptance criteria:
|
||||
- Users can add an item without associating it to a meal.
|
||||
- Users can edit and delete such items.
|
||||
- All calls use typed path-scoped endpoints; no header injection; Authorization still via provider.
|
||||
- Note: No temporary measures required; proceed directly once backend ships endpoints.
|
||||
- Remove the legacy username login shim (`login(username: string)`) and any fallback UI; standardize on email/password (and Google) only.
|
||||
- Rollout flag: default `VUE_APP_MULTITENANT_ENABLED` to true across environments and plan removal of legacy flat routes and related tests once stable.
|
||||
|
|
|
|||
|
|
@ -365,6 +365,23 @@ export interface paths {
|
|||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/v1/households/{householdSlug}/shopping/current/ingredients": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
/** Request an ingredient for shopping (scoped) */
|
||||
post: operations["requestIngredientV2"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/healthz": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
|
@ -481,6 +498,11 @@ export interface components {
|
|||
mealId?: number | null;
|
||||
product?: components["schemas"]["Product"] | null;
|
||||
};
|
||||
/** IngredientIdWrapper */
|
||||
IngredientIdWrapper: {
|
||||
/** Ingredientid */
|
||||
ingredientId: number;
|
||||
};
|
||||
/** IngredientPurchaseItemIn */
|
||||
IngredientPurchaseItemIn: {
|
||||
/** Ingredientid */
|
||||
|
|
@ -822,6 +844,12 @@ export interface components {
|
|||
imageUrls: string[];
|
||||
/** Ingredients */
|
||||
ingredients: components["schemas"]["Ingredient"][];
|
||||
/** Createdbyid */
|
||||
createdById: number;
|
||||
createdBy?: components["schemas"]["MemberRef"] | null;
|
||||
/** Hiddenbyid */
|
||||
hiddenById?: number | null;
|
||||
hiddenBy?: components["schemas"]["MemberRef"] | null;
|
||||
};
|
||||
/** RefreshResponse */
|
||||
RefreshResponse: {
|
||||
|
|
@ -882,7 +910,7 @@ export interface components {
|
|||
storeName: "woolworths" | "coles" | "home";
|
||||
/** Purchasedbyid */
|
||||
purchasedById: number;
|
||||
purchasedBy?: components["schemas"]["Person"] | null;
|
||||
purchasedBy?: components["schemas"]["MemberRef"] | null;
|
||||
/** Items */
|
||||
items: components["schemas"]["ListIngredientItem"][];
|
||||
};
|
||||
|
|
@ -1812,6 +1840,42 @@ export interface operations {
|
|||
};
|
||||
};
|
||||
};
|
||||
requestIngredientV2: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
householdSlug: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["IngredientIdWrapper"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["ListIngredientItem"];
|
||||
};
|
||||
};
|
||||
403: components["responses"]["Problem403"];
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
healthz_healthz_get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
|
|
|||
Loading…
Reference in a new issue