feat: D1 — Shopping list (Issue #30) #43

Merged
marcel merged 24 commits from feat/issue-30-shopping-list into master 2026-04-08 22:22:02 +02:00

24 Commits

Author SHA1 Message Date
f6265efa92 test(shopping): add component tests for ShoppingHeader, ChecklistItem, AddCustomItem
25 tests covering counts, planner guard, aria-checked, strikethrough,
recipe labels, expand/collapse, and form submission.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:58:28 +02:00
3cd9154550 refactor(shopping): extract ShoppingChecklist.svelte to eliminate mobile/desktop duplication
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:55:54 +02:00
be43fe94b6 fix(shopping): address frontend review concerns
- ChecklistItem: use:enhance with reset:false, role=checkbox, aria-checked, focus ring
- RecipeReferencePanel: day abbreviation text-[12px] (was 11px)
- ShoppingHeader: generating pending state disables button during submit
- AddCustomItem: only collapse form on successful submission

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:54:25 +02:00
e3afe1b4f2 test(shopping): add HTTP-level role guard test and blank customName validation test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:52:09 +02:00
eb5ee1ab5a test(shopping): add missing service tests for stale items, dedup, and household isolation
- generateFromPlan removes stale generated items
- sourceRecipes deduplicates when same recipe appears in two slots
- checkItem throws ResourceNotFoundException on household mismatch

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:50:27 +02:00
9d210befa1 fix(security): add @Valid constraints on AddItemRequest to prevent oversized input
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:49:06 +02:00
40a6a0e92d fix(security): use generic forbidden message to avoid leaking required role
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:46:24 +02:00
40ee4dad53 refactor(shopping): extract mergeKey helper to eliminate duplicate key construction
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 19:44:44 +02:00
741141168b feat(shopping): build main +page.svelte with responsive layout and empty states
Mobile/desktop responsive shopping list page with:
- Three empty states (no plan, no list, all checked)
- Unchecked/checked item sections with divider
- Add custom item form
- Desktop right panel with recipe references
- Filtered staples info

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:56:42 +02:00
6cc79836d5 feat(shopping): add RecipeReferencePanel.svelte component
Desktop right panel showing this week's recipe cards with day
abbreviation, filtered staples count, and link to edit pantry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:55:31 +02:00
5ac8f1768f feat(shopping): add AddCustomItem.svelte component
Expandable inline form for adding custom items to the shopping list.
Includes name, quantity, and unit fields with cancel/submit actions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:54:47 +02:00
7bdadbe962 feat(shopping): add ChecklistItem.svelte component
Checkbox row with name, quantity/unit, recipe source label, and
strikethrough styling when checked. Each toggle submits a form action.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:54:12 +02:00
2151dff4db feat(shopping): add ShoppingHeader.svelte component
Displays title, eyebrow counts (remaining/checked), generation
timestamp, and planner-only generate/regenerate button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:53:36 +02:00
e831480860 feat(shopping): add +page.server.ts with load function and form actions
Load function fetches shopping list and week plan for the current week.
Form actions: check (toggle item), addItem (custom item), generate
(planner-only shopping list generation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-04 18:52:44 +02:00
92922533ac feat(shopping): finalize GET /v1/shopping-list endpoint and regenerate OpenAPI types
Renamed endpoint to /v1/shopping-list to avoid Springdoc path conflict.
Added @RequiresHouseholdRole("planner") on generate. Regenerated
frontend OpenAPI schema with all new shopping list endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:49:08 +02:00
16b70bd818 feat(shopping): add GET /v1/shopping-lists endpoint and planner-only guard
New week-based lookup endpoint with optional weekStart param (defaults
to current week). Generate endpoint now enforced with @RequiresHouseholdRole.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:35:31 +02:00
5325f4827e feat(shopping): refactor generateFromPlan to merge strategy
When a shopping list already exists for the week plan, regeneration
now merges: custom items and check states are preserved, existing
generated items are updated, removed recipes' items are deleted,
and new ingredients are added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:33:15 +02:00
c26c2e1973 feat(shopping): add getByWeekStart to ShoppingService
Returns the shopping list for a given week, defaulting to the current
week's Monday when no weekStart is provided. Returns null when no
list exists.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:30:41 +02:00
93e8bf9e41 feat(shopping): extend response with generatedAt, filteredStaplesCount, RecipeRef
Shopping list response now includes generatedAt timestamp, count of
filtered staples, and recipe names (not just UUIDs) in source references.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:29:07 +02:00
7e254fc280 feat(shopping): add week-based shopping list repository query
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:23:43 +02:00
3be9f502c6 feat(auth): add @RequiresHouseholdRole annotation with interceptor
Reusable annotation for planner-only endpoints. Uses a
HandlerInterceptor that resolves the household role from the
authenticated user and throws 403 if the role doesn't match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:22:47 +02:00
2f690eb3cb feat(common): add ForbiddenException with 403 handler
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:18:27 +02:00
2253c76287 feat(shopping): add generated_at column to shopping_list
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 18:17:12 +02:00
e12fb72fc2 refactor(specs): remove real-time sync from D1 shopping list spec
Replace WebSocket/SSE liveness model with server-authoritative sync
(form actions + page refresh). Remove "members online" indicator.

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