docs: Sprint 11 — wire the dead "Generate Meal Plan" CTA across all 6 running docs

Sprint 11 (commit 41154e9) wires the previously-dead
"Generate Meal Plan" empty-state CTA on the Dashboard to two
existing endpoints (POST /api/meals + POST /api/meals/{id}/fill-
empty-slots). No backend changes; no new dependencies. The
handler lives on the client for now; future F8 (Spoonacular) +
F9 (Ollama) will swap the fillEmptySlots call for an LLM call
without changing the DOM. F8 + F9 remain in the §Future backlog.

This commit updates the 6 running docs that track the sprint:

- .agent/plan.md — Sprint 11 section (S11.1-S11.3) added.
- .agent/context.md — Sprint 11 (D1-D6, Q1-Q3) added; file:line
  references; key takeaways.
- Review/sprint11-verification.md — new file: 4-step browser
  smoke + race test + 2 API curls + a11y check + risks + future
  work section.
- Review/ui-nielsen-audit.md — Sprint 11 status block (T5.1-T5.3)
  at the top, after the Sprint 10 block.
- fix-ui-audit.md — Sprint 11 section (T5.1-T5.5) added after the
  Sprint 10 section.
- Review/handoff-ui-audit.md — Batch G added to the deploy
  instructions; Sprint 11 section added after Sprint 10; TL;DR
  table row 11 added; Last-updated footer updated.
- docs/HANDOFF.md — Sprint 11 section added after the Sprint 10
  section, with a path-forward paragraph for F8/F9.

All 6 docs now reflect Sprint 11. §Future backlog remaining: F8
(Spoonacular) + F9 (Ollama) proposals, both full backend work.
This commit is contained in:
2026-06-05 15:36:26 -07:00
parent 41154e934a
commit dac1364c29
7 changed files with 307 additions and 6 deletions
+41
View File
@@ -605,3 +605,44 @@ User direction 2026-06-05: "Proceed with the next phase in the redesign. Also ad
### T4.9 · `Review/sprint10-verification.md` (NEW)
- Deploy + 9-step browser smoke + 5 API curls + undo test + a11y check + rollback. Source of truth for the operator deploy + smoke flow.
---
## Sprint 11 — Wire the dead "Generate Meal Plan" CTA — ✅ COMPLETE, awaiting deploy
User direction 2026-06-05: "Proceed." Selected from the question menu as the smallest remaining §Future item. F1 (Sprint 9) is shipped, F8 (Spoonacular) + F9 (Ollama) are full backend proposals, and the dead `Generate Meal Plan` CTA at `Dashboard.tsx:553-560` was the last piece. The button has been rendered with `onClick: () => {}` since Sprint 1; clicking it did nothing.
**Status (2026-06-05):** ✅ Code complete. `npm run build` green (tsc 0 errors, vite 0 errors). Bundle: 495.64 → 496.48 kB. Awaiting user commit + deploy. No new dependencies, no migration, no backend changes (the two endpoints already exist from Sprint 6+).
### T5.1 · Frontend — `handleGenerateFirstPlan` in `Dashboard.tsx`
- **File:** `frontend/src/pages/Dashboard.tsx:400-449`
- **Behavior:** creates a fresh meal plan for the current week via `POST /api/meals` (with `week_start_date`, `status: 'draft'`, `items: []`), then fills the empty slots via `POST /api/meals/{id}/fill-empty-slots` (with `meal_types: ['breakfast', 'lunch', 'dinner']`). Two requests, but they reuse existing endpoints.
- **Race handling:** if `meals.create` returns 400 with `detail: "Meal plan for this week already exists"` (another tab created one first), the handler falls through to `getPlanned(weekStart)` to get the existing plan's id, then calls `fillEmptySlots` against it. No error toast in this case.
- **State:** tracks `generatingFirstPlan` (line ~365). Re-enabled on `finally` to handle the race. Mirrors the existing `planningWeek` state at `Dashboard.tsx:363`.
### T5.2 · Frontend — `EmptyState.action.disabled?: boolean`
- **File:** `frontend/src/components/ui/EmptyState.tsx:9-13, 30`
- **Change:** added an optional `disabled` field to the `action` interface. Backward-compatible: the 5 other `EmptyState` usages (`Dashboard.tsx`, `Recipes.tsx`, `ShoppingList.tsx`, `Pantry.tsx`, `NotFound.tsx`) don't pass it. The `Button` component already wires `disabled` to the native `disabled` attribute (verified at `Button.tsx:37`), so no other component changes needed.
- **Wired in `Dashboard.tsx:553-560`:** `action={{ label: generatingFirstPlan ? 'Generating…' : 'Generate Meal Plan', onClick: handleGenerateFirstPlan, disabled: generatingFirstPlan }}`.
### T5.3 · Frontend — toast UX
- Reuses the partial-success toast pattern from `handlePlanWeek` (Sprint 6 F4):
- 0 filled + 0 failed → `Plan created — no recipes to add yet` (green, success)
- N filled + 0 failed → `Planned N meals` (green, success)
- N filled + K failed → `Planned N of N+K meals — K failed (e.g. <reason>)` (red, error)
- Any unhandled exception → `Failed to generate meal plan` (red, error, via `showApiError`)
### T5.4 · Sprint 11 verification gate
- [x] `npm run build` green for Sprint 11 (tsc 0 errors, vite 0 errors). Bundle: 495.64 → 496.48 kB.
- [x] No backend changes; both endpoints already exist and are tested.
- [ ] Browser smoke (4 steps) on `http://100.108.208.56:8082/` per `Review/sprint11-verification.md`.
- [ ] Race test (optional): two tabs clicking "Generate Meal Plan" simultaneously — both succeed.
- [ ] No regression in Sprints 1-10.
### T5.5 · `Review/sprint11-verification.md` (NEW)
- Deploy + 4-step browser smoke + race test + 2 API curls + a11y check + risks. Source of truth for the operator deploy + smoke flow. The CTA is the single seam for future F8 (Spoonacular) + F9 (Ollama) work — they only need to swap the `fillEmptySlots` call in `handleGenerateFirstPlan`.