diff --git a/frontend-spec.md b/frontend-spec.md index 3cf4c07..039b4b8 100644 --- a/frontend-spec.md +++ b/frontend-spec.md @@ -81,11 +81,11 @@ This plan is adapted to the existing codebase, focusing on refactoring rather th - Ensures `activeHousehold` is set when navigating within a household. - **Nest existing routes**: Implemented behind feature flag. -3. **[ ] Implement Onboarding and Invitation Flows**: +3. **[~] Implement Onboarding and Invitation Flows**: - Build the `Welcome.vue` view for creating the first household. - Build the `CreateAccount.vue` view. - Build the "Accept Invitation" page (`/invitations/accept?token=...`). It should take the token from the URL, call the API, and redirect on success. - - Status: Placeholder views created for all three; logic pending. Household creation endpoint available. + - Status: Welcome page now implements create-household flow using `POST /api/v1/households` and redirects to `/:slug/mealplan`. Create Account and Invitation Accept remain TODO. 4. **[~] Integrate Household Context into the App**: - **Create `src/composables/useHousehold.ts`**: Implemented. Extracts `householdSlug` from route and binds provider to API client. diff --git a/src/composables/useAuth.ts b/src/composables/useAuth.ts index fd0f9e7..c4b6bd3 100644 --- a/src/composables/useAuth.ts +++ b/src/composables/useAuth.ts @@ -60,5 +60,15 @@ export function useAuth() { return hs } - return { user, households, activeHousehold, loadUser, login, loginWithPassword, logout, setHouseholds, setActiveHousehold, fetchHouseholds } + async function createHousehold(name: string): Promise { + const res = await api.POST('/api/v1/households', { body: { name } }) + if (!res.response.ok || !res.data) throw new Error('Failed to create household') + const h: Household = { id: res.data.id, name: res.data.name, slug: res.data.slug } + // Update local state: append and set active + setHouseholds([...households.value, h]) + setActiveHousehold(h) + return h + } + + return { user, households, activeHousehold, loadUser, login, loginWithPassword, logout, setHouseholds, setActiveHousehold, fetchHouseholds, createHousehold } } diff --git a/src/views/Welcome.vue b/src/views/Welcome.vue index 9facc91..fd91ee5 100644 --- a/src/views/Welcome.vue +++ b/src/views/Welcome.vue @@ -1,10 +1,35 @@ diff --git a/tests/households.create.test.ts b/tests/households.create.test.ts new file mode 100644 index 0000000..8097596 --- /dev/null +++ b/tests/households.create.test.ts @@ -0,0 +1,21 @@ +import { describe, it, expect } from 'vitest' +import { server, http, HttpResponse } from './test-setup' +import { useAuth } from '@/composables/useAuth' + +describe('useAuth createHousehold', () => { + it('creates a new household and sets activeHousehold', async () => { + server.use( + http.post('*/api/v1/households', async ({ request }) => { + const body = await request.json() + expect(body).toEqual({ name: 'The Smiths' }) + return HttpResponse.json({ id: 10, name: 'The Smiths', slug: 'the-smiths' }) + }) + ) + const { households, activeHousehold, createHousehold } = useAuth() + expect(households.value).toEqual([]) + const h = await createHousehold('The Smiths') + expect(h.slug).toBe('the-smiths') + expect(activeHousehold.value?.slug).toBe('the-smiths') + expect(households.value.find((x) => x.slug === 'the-smiths')).toBeTruthy() + }) +})