Commit Graph

87 Commits

Author SHA1 Message Date
3d49e6b7bf feat(recipes): add /recipes/[id]/edit route with update action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:20:45 +02:00
4e2b0b5727 feat(recipes): add /recipes/new route with create action
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:19:27 +02:00
2cef8a1169 feat(recipes): add RecipeForm component — add/edit two-state form
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:17:17 +02:00
0256b4360b fix(recipes): address B2 review — tags, sort, edit link, types, a11y, tests
- RecipeHero: render tag pills, min-h-[200px/240px], fix back link styling, remove font-[400]
- IngredientList: sort by sortOrder ascending
- StepList: aria-hidden on step circles
- types.ts: add Tag, Ingredient, Step, RecipeDetail shared types
- +page.svelte: add Edit link → /recipes/[id]/edit (desktop topbar)
- Tests: tag pills, sortOrder sort, edit link, image variant, 403-as-404 documented

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:07:19 +02:00
00c48a7c96 feat(recipes): implement B2 recipe detail page with mobile/desktop layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:02:20 +02:00
ce860d68e4 feat(recipes): add recipe detail load function with 404 handling
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 10:00:02 +02:00
b39d04acce feat(recipes): add StepList component with numbered circles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:58:39 +02:00
c7e56a173d feat(recipes): add IngredientList component (read-only)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:57:36 +02:00
86a25eb038 feat(recipes): add RecipeHero component with image/no-image variants
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:56:35 +02:00
9bb6293d9f fix(recipes): address review feedback — shared type, design system tokens, test coverage
- Extract RecipeSummary type to $lib/recipes/types.ts (was duplicated in 3 files)
- Fix +page.svelte header link: replace Skeleton UI classes with design system tokens
- Fix h1: use font-[var(--font-display)] and correct size
- Fix FilterChipRow: text-[11px] → text-[13px] + tracking-[0.04em] per design system
- Fix RecipeCard metadata: text-[11px] → text-[12px] for readability
- Remove unused imports (vi, beforeEach, afterEach) from page.test.ts
- Add combined search + effort filter test
- Add reset-to-Alle filter test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:53:32 +02:00
47c748145d feat(recipes): implement recipe library page with search and effort filtering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:49:39 +02:00
a25286e385 feat(recipes): load recipe list from API in page server
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:45:43 +02:00
a733e8dd66 feat(recipes): add RecipeGrid with 2/4-col responsive grid and empty state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:44:05 +02:00
35ed6ca878 feat(recipes): add FilterChipRow with effort filter chips
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:43:06 +02:00
dc99459a2e feat(recipes): add RecipeCard component with compact/full image variants
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:41:56 +02:00
df95462094 refactor(staples): convert dynamic userEvent import to static in CategorySection test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:30:19 +02:00
2d6ddf0e48 fix(staples): apply design-system styles to nav links and settings heading
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:29:53 +02:00
73b33ee956 fix(staples): apply design-system button spec to StapleChip (13px, tracking, font-sans)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:28:50 +02:00
8daaa0e21d fix(staples): pass ctx from URL through load function; fix script order in page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:27:43 +02:00
45b7e7b003 fix(staples): add role guard — only planer role can toggle staples
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:25:40 +02:00
3581af2bf9 fix(staples): forward backend error status code instead of always 500
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:25:06 +02:00
21b873b85b fix(staples): validate isStaple is boolean before forwarding to backend
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:24:35 +02:00
65f18cfb43 test(staples): cover API failure fallback in page load
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:24:07 +02:00
7b497be1c1 test(staples): add empty categories edge case to StaplesManager
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 09:23:48 +02:00
7979076f5e feat(invite): stub household invite page as onboarding Continue target
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:16:46 +02:00
d68a9d9312 refactor(setup): redirect to /household/staples?ctx=onboarding after household creation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:16:33 +02:00
97175e7d9d feat(staples): add staples page with onboarding and settings layouts
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:16:08 +02:00
3550d681dc feat(staples): load categories and ingredients, group by category
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:14:25 +02:00
54df70a442 feat(staples): add PATCH proxy server route for ingredient staple toggle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:13:02 +02:00
d577e0231c feat(staples): add StaplesManager with optimistic toggle and debounced PATCH
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:11:51 +02:00
376dc03646 feat(staples): add CategorySection component with eyebrow heading and chip row
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:07:51 +02:00
7bdc049461 feat(staples): add StapleChip component with aria-pressed toggle and focus ring
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 20:06:32 +02:00
7c66dcad3a refactor(onboarding): clarify test comment and remove unused response mock
HouseholdSetupForm.test.ts: explain that touched+empty drives the $derived
error, not a submit event on the disabled button.
page.server.test.ts: remove unused response key from mockSuccess() —
household creation doesn't set a session cookie.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:32:44 +02:00
01a321caa9 test(onboarding): add ProgressSidebar test for currentStep=3 (all prior steps completed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:31:56 +02:00
2d1604492d feat(onboarding): add max-length validation for household name (100 chars)
Fails fast before the API call with a clear German error message.
Tests boundary: 100 chars accepted, 101 rejected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:31:13 +02:00
3742364956 fix(onboarding): make HouseholdSetupForm subtitle responsive (12px mobile, 14px desktop)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:30:23 +02:00
36dfea34cc fix(onboarding): make HouseholdSetupForm heading responsive and use font-medium
text-[18px] md:text-[28px] matches auth form pattern.
font-medium (500) replaces font-semibold (600) per design system rules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:29:52 +02:00
66525484a6 fix(onboarding): correct Tailwind arbitrary font-family syntax in HouseholdSetupForm
font-['var(--font-display)'] → font-[var(--font-display)] so Fraunces
display font is applied correctly to the h1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:29:21 +02:00
e5614ccf30 refactor(onboarding): remove aria-hidden workaround from progress sidebar
Replace getByText with getByRole(heading) in page test to disambiguate
the duplicate "Haushalt benennen" text between sidebar and form.
Revert defaultIgnore change in test-setup.ts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:28:46 +02:00
6de7f5a9b5 feat(onboarding): add A2 household setup page with responsive progress sidebar layout
Desktop: 300px ProgressSidebar (step 1 active) + flex form area.
Mobile: "Schritt 1 von 3" eyebrow + HouseholdSetupForm.
Also stubs /household/staples as redirect target for A3.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:20:02 +02:00
e85a7ca313 feat(onboarding): add household setup page server action and load guard
Creates household via POST /v1/households, redirects to /household/staples.
Load guard redirects users who already have a household to /planner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:14:39 +02:00
175bfbe7dd feat(onboarding): add HouseholdSetupForm component with disabled-until-valid continue button
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:13:41 +02:00
b9ef06fd73 feat(onboarding): add ProgressSidebar component with 3-step active/completed/future states
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 19:08:38 +02:00
61249af086 feat(auth): add secure flag to JSESSIONID cookie and test JSESSIONID cookie setting
- Add secure: true to cookies.set() in login and signup actions
- Add tests verifying JSESSIONID is forwarded to browser on successful
  login and signup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:50:34 +02:00
16f0feb8d5 fix(auth): fix mock responses in tests and block open redirect in login
- Add response object to mockSuccess() in login and signup tests so
  response.headers.get() no longer throws
- Validate ?redirect= param: must start with / and not // to prevent
  redirecting users to external domains

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:48:48 +02:00
0aa65214fc fix(auth): resolve broken signup/login flow end-to-end
Three root causes fixed:

1. CSRF blocked all backend POSTs — Spring Security's CSRF filter ran
   before permitAll() authorization, returning 401 for signup and login.
   Disabled CSRF since SvelteKit is the only client (never the browser
   directly) and handles its own CSRF via Origin header checks.

2. Login/signup didn't establish Spring Security authentication — they
   stored email in the HTTP session manually but never set the
   SecurityContext, so Principal in /v1/auth/me was always null and
   hooks.server.ts redirected every authenticated request to /login.
   Fixed with authenticateInSession() helper that sets and persists
   the SecurityContext under SPRING_SECURITY_CONTEXT_KEY. Login also
   now invalidates the old session before creating a new one to prevent
   session fixation.

3. redirect() missing throw in hooks.server.ts, signup action, and
   login action — SvelteKit never saw the redirect, so pages silently
   reloaded with no navigation. Also forward JSESSIONID from backend
   response to browser explicitly, since SvelteKit does not
   auto-forward Set-Cookie for cross-origin server-side fetches.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 17:31:29 +02:00
ab3363eeec refactor(auth): use shared BrandPanel on login page
Login page now uses the same BrandPanel component as signup
instead of an inline brand panel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:45:22 +02:00
999e54de86 feat(auth): build login page with LoginForm, brand panel, and title
Replaces placeholder with full login page: brand panel left,
LoginForm right, svelte:head title, signup link, no-nav-chrome.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:21:31 +02:00
73acc0c638 feat(auth): add login server action with validation and redirect
POSTs to /v1/auth/login, validates email/password server-side,
redirects to ?redirect param or /planner on success.
Returns generic error on bad credentials to prevent enumeration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:20:02 +02:00
c27c97ff7d feat(auth): add LoginForm component with validation and password toggle
Email/password fields, client-side validation, password show/hide,
server error display via form prop, signup link.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 16:18:49 +02:00