9adf786b8f
test(variety): extract and test sub-score/warnings pure functions
...
- Extract computeSubScores() and computeWarnings() to variety.ts
- 18 unit tests covering formulas, boundaries, clamping, edge cases:
- proteinDiversity: repeats × 2 penalty, clamped to 0
- ingredientOverlap: overlaps × 1.5 penalty, clamped to 0
- effortBalance: easy-hard diff × 1.5, total=0 → 10
- warnings: repeat≥2 days, overlap≥2 days, duplicates
Addresses QA blockers: untested business logic in sub-score derivations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 11:32:20 +02:00
1bf929280b
test(variety): add all-zero edge case test for EffortBar
...
Addresses QA concern: renders no segments when easy=0, medium=0, hard=0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 11:30:19 +02:00
75c860a62b
test(variety): add boundary tests for VarietyScoreHero (score=0,4,7,10)
...
Addresses QA concern: boundary values (0, 4, 7, 9, 10) now have
explicit tests covering description labels and aria-valuenow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 11:29:26 +02:00
8ad636f825
feat(variety): implement C3 variety review screen (Issue #28 )
...
- Add /planner/variety route with mobile stacked + desktop 2-column layout
- Implement VarietyScoreHero: Fraunces score display + progress bar + color-coded description
- Implement ScoreBreakdownList: 3 sub-score rows (protein diversity, ingredient overlap, effort balance)
- Implement VarietyWarningCards: yellow-tint warning cards derived from API tagRepeats/ingredientOverlaps
- Implement EffortBar: proportional colored segments (Easy/Medium/Hard) with ×N labels
- Desktop: protein grid (7 columns, repeat highlight with yellow ring) + effort bar in right panel
- Client-side sub-score derivation from VarietyScoreResponse (tagged for TODO to move to API)
- 26 new tests across 5 components + server load function; 455 tests total, 0 type errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 11:23:29 +02:00
7c07bc443b
feat(suggestions): C2 — Meal suggestions (variety-aware) ( #40 )
...
feat(suggestions): implement C2 meal suggestion screen (Issue #27 )
Co-authored-by: Marcel Raddatz <marcel@raddatz.cloud >
Co-committed-by: Marcel Raddatz <marcel@raddatz.cloud >
2026-04-03 11:18:45 +02:00
5d2bb9e84e
fix(planner): address all PR review blockers
...
- Fix logic bug `{#if !isPlanner === false}` - view/cook buttons now visible for all roles, swap only for planner
- Convert Tauschen from dead button to link with suggestions href
- Add week.ts unit tests (23 tests covering getWeekStart Sunday edge case, prevWeek/nextWeek, weekDays, isToday, formatWeekRange)
- Fix isToday to use UTC consistently (.toISOString().slice(0,10)) instead of local date
- Add server-side role guard to createPlan action (403 for members)
- Add weekStart format validation in createPlan action
- Add isSelected prop to DayMealCard with green treatment
- Make variety banner sticky on mobile (always visible per spec)
- Add day name abbreviation above date badge in desktop column headers
- Remove placeholder Navigation text from desktop sidebar
- Add aria-label to desktop empty tile buttons
- Add variety score partial failure test, multiple overlaps test, WeekStrip today+selected test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 11:07:47 +02:00
e3f8d8ad73
feat(planner): implement C1 weekly planner home screen ( #26 )
...
Three-breakpoint layout (mobile/tablet/desktop) with VarietyScoreCard,
WeekStrip, DayMealCard components. Server loads week plan and variety
score via API; read-only role behavior derived from benutzer.rolle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 11:01:17 +02:00
33f3b30cb4
feat(recipes): style RecipeForm with design system + split-panel layout
...
- Full design system tokens: inputs, labels, chips, buttons
- Effort and category chips as pill-style radio/checkbox
- Desktop two-column split-panel: form left, categories right (280px)
- Ingredient rows: quantity/unit/name flex layout with remove ghost button
- Steps with numbered circle indicator
- Add use:enhance for SPA experience without full page reload
- Footer: cancel link left, primary save button right
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 10:35:35 +02:00
e4d3008139
feat(recipes): display form error from \$page.form in RecipeForm
...
- Import page store and render role="alert" error banner
- Add mock for \$app/stores and \$app/forms in RecipeForm tests
- Add tests: error banner shown when form.error set, hidden when null
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 10:31:18 +02:00
6505cb4251
test(recipes): add action tests and harden create/update form actions
...
- Add try-catch around JSON.parse with fail(400) for malformed input
- Validate effort against allowed values ['Easy','Medium','Hard']
- Fix NaN risk: Number(serves)||undefined instead of Number(serves)
- Add action tests for create/update: validation, JSON.parse crash, success, API error
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-03 10:27:54 +02:00
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