Commit Graph

19 Commits

Author SHA1 Message Date
0ae1767649 feat(planner): align tile design with spec
Front face:
- Full dual gradient overlay (dark top 32% → transparent → dark bottom 55%)
- Day abbreviation + date number pill at top of each tile
- Recipe name 13px/weight-300 with text-shadow
- Meta line (cookTimeMin · effort) below name
- Glassmorphism tag pills (protein + cuisine only)
- State rings via box-shadow (yellow for today, green for selected)
- Dimming (opacity 0.42) on non-selected filled tiles

Back face:
- Koch-Modus as green primary button
- Entfernen as red outline (transparent bg)
- All buttons 11px / weight 500

EmptyDayTile: add day header + spec-aligned suggestion list layout
Page: remove external column header (now rendered inside each tile)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 12:29:58 +02:00
ed4cdbf230 fix(planner): merge recipe tags into slotMap from data.recipes
SlotRecipe from the week-plan API carries no tags, so the protein
gradient lookup in DesktopDayTile always fell through to --color-surface.
Build a recipeById lookup from data.recipes and spread tags onto each
slot's recipe when constructing slotMap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:55:55 +02:00
f97cf49bd0 feat(planner): overhaul desktop layout — flip tiles, no right panel
Replaces 3-panel layout with 2-panel (sidebar + full-width grid):
- Remove persistent right panel and toolbar + Gericht hinzufügen button
- grid-cols-7 tiles use DesktopDayTile (CSS 3D card flip)
- RecipePickerDrawer slides in on tile CTA / Gericht tauschen
- Page-owned activeSlotId + drawerOpen/drawerSlotId state
- Single Escape handler: drawer > flip priority
- Extend server load to forward recipe tags from /v1/recipes API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 11:04:26 +02:00
148f6a7b5b refactor(planner): remove dead SwapSuggestionList import and sortedRecipes derived
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 15:01:37 +02:00
f4503b0220 feat(planner): show variety score in swap menu via RecipePicker
Replace SwapSuggestionList with RecipePicker in both mobile and desktop
swap contexts. RecipePicker now accepts excludeRecipeId, replacingRecipe,
and isDisabled props. Mobile swap sheet also triggers suggestion fetch
via activePickerDate so green/yellow/red score badges appear during swap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 13:40:17 +02:00
1de9dfc314 feat(planner): add remove meal with undo; fix RecipePicker badge for neutral delta
- MealActionSheet: new onremove prop + Entfernen button (guarded by #if)
- +page.svelte: handleRemoveMeal submits delete form, shows undo bar;
  undo re-adds via addSlot form; refactored handleUndo to undoCallback
  pattern; desktop day-detail panel also gets Entfernen button
- RecipePicker: only show green +delta badge when scoreDelta > 0;
  neutral (scoreDelta = 0) shows no badge instead of ⚠ Variationskonflikt
- Tests: page.test.ts remove-meal describe, RecipePicker neutral badge test

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 12:47:53 +02:00
f7a239655a refactor(planner): extract Suggestion type to $lib/planner/types.ts
Removes the inline interface from RecipePicker.svelte and replaces
any[] in +page.svelte with Suggestion[] — compile-time safety.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 12:16:02 +02:00
539ca5d231 feat(planner): add AbortController to suggestion fetch $effect
Cancels the inflight request when activePickerDate changes or picker
closes, preventing stale responses from overwriting suggestions.
Adds page.test.ts covering fetch trigger, suggestion rendering,
and AbortSignal presence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 12:15:17 +02:00
ab66269131 feat(planner): lazy-fetch variety suggestions in RecipePicker for empty slots
Derives activePickerDate from mobile pickerOpen/selectedDay and desktop
recipe-picker panel state, then uses $effect to fetch /planner?planId&date
on demand — wires suggestions and isLoading into both RecipePicker instances.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 11:46:25 +02:00
f0bbb3b009 fix(planner): exclude current recipe from swap suggestions
Adds excludeRecipeId prop to SwapSuggestionList so the meal being
replaced is not offered as a swap candidate.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 10:38:30 +02:00
b4fa3ca23e feat(planner): add isLoading prop to SwapSuggestionList — disables Pick buttons during PATCH
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 10:32:59 +02:00
dd9a86d4e9 feat(planner): wire J4 swap flow — mobile action sheet + desktop inline panel
Mobile: DayMealCard tap opens MealActionSheet; Swap → SwapSuggestionsSheet
(BottomSheet + SwapSuggestionList, easiest-first). Empty slots still open
RecipePicker directly.

Desktop: recipe-picker panel detects swap context (slot has recipe) and
renders SwapSuggestionList; empty slots continue to show RecipePicker.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 10:13:45 +02:00
5b8d336d21 fix(planner): map backend role 'planner' to 'planer' and enlarge nav buttons to 40px touch targets
- hooks.server.ts: replace type-cast with actual mapping so isPlanner works
- planner page: set min-h/min-w 40px on prev/next/heute week buttons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 09:51:32 +02:00
e5d96cd85a fix(frontend): address all PR review concerns
- Fix 7px → 11px font-size on section headers in RecipePicker
- Extract shared slotActions.ts with UUID validation for planId/slotId/recipeId
- Load full recipe list in planner page load (was placeholder current-week slots)
- Update planner/+page.svelte to pass data.recipes as allRecipes to RecipePicker
- Update planner and recipes page.server.ts to use shared slot action helpers
- Fix planner page.server tests: add recipes mock for parallel GET load
- Update action tests to use valid UUIDs (were 'plan-1'/'r1' style strings)
- Add validation-path tests for blank/invalid input on all slot actions
- Add tests for recipes/+server.ts GET endpoint (DayPicker week navigation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 08:19:37 +02:00
4333dc0d84 refactor(planner): remove C2 suggestions route, replace with callback-based DayMealCard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 23:25:35 +02:00
cbafe783e9 feat(planner): integrate C4 RecipePicker with PanelState machine + slot actions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-08 23:23:26 +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
9626bde694 feat(shell): add route groups, layout server load, redirect, and placeholder pages
- (app) group with AppShell layout, loads user/household from locals
- (public) group with full-viewport split layout, /login placeholder
- Root / redirects to /planner for authenticated users
- Placeholder stubs for planner, recipes, shopping, settings, members

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 13:22:34 +02:00