Commit Graph

192 Commits

Author SHA1 Message Date
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
021d308a71 feat(staples): A3/D3 — Pantry staples toggle UI 2026-04-03 09:35:03 +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
09333ccc0a test(auth): verify security context is stored in session after login and signup
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:55:25 +02:00
93ce1eaeac refactor(auth): add comments, clearContext on logout, explain session auth
- Add comment to SecurityConfig explaining why CSRF is disabled
- Add SecurityContextHolder.clearContext() to logout for clean thread state
- Add Javadoc on authenticateInSession() explaining manual session setup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 18:52:16 +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
b3607ca47a test(auth): add password length boundary tests (7 fails, 8 passes)
Parameterized test verifying the exact boundary of the 8-character
minimum password requirement.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:07:42 +02:00
7de18740f2 test(auth): add multi-error test for empty form submission
Verifies all three validation errors (name, email, password) appear
simultaneously when submitting a completely empty form.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:07:07 +02:00
6d0f00c8fb feat(auth): add use:enhance and server error display to signup form
SignupForm now uses use:enhance for progressive enhancement.
Accepts form prop for server-side error display. Shows general
form errors in a banner and field-specific errors inline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:06:21 +02:00
bd9e1334e0 feat(auth): add server-side validation to signup form action
Validates displayName, email, password server-side before calling
the backend API. Handles null from formData.get() safely.
Returns structured field errors via fail(400, { errors }).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:02:33 +02:00
82840bb420 fix(auth): center signup form on wide desktop screens
Form container now horizontally centered on md+ viewports,
left-aligned on mobile for full-width usage.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:01:03 +02:00
845e669cde feat(auth): add page title to signup screen
Sets <title>Konto erstellen — Mealprep</title> via svelte:head
for browser tab and accessibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 15:00:02 +02:00
afcea6590d feat(auth): add autocomplete attributes to signup form inputs
name, email, new-password for better browser/password-manager support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 14:58:59 +02:00