Sprint 6 (F3 + F4) is now documented across the project: - Review/sprint6-verification.md: new deploy + smoke-check doc. Backend + frontend deploy (no migration). 5 smoke-check sections: A) ShoppingList bulk-add end-to-end, B) F3 partial- failure edge case, C) F4 'Plan the week' button + dropdown, D) F4 edge cases (no empty slots, all recipes used, invalid meal_types), E) Sprints 1-5 regression spot-check. Rollback section covers revert (no migration to undo). - fix-ui-audit.md: new Sprint 6 section (S6.1 F3, S6.2 F4, S6.3 verification gate). 'Done when' block updated to 6 sprints / 10 commits / 20 findings closed. - Review/handoff-ui-audit.md: updated to a 6-sprint cycle. TL;DR table includes the8ad4ef6row. File list includes sprint6- verification.md. File-level diff summary gains 8 new rows for Sprint 6 (F3 backend + F4 backend + 3 new schemas + 2 api bindings + 2 page changes). §Future list now strikethroughs F3 and F4. Follow-up tickets section added: the no-op 'Generate Meal Plan' empty-state CTA, the (now-narrower) Pantry bulk-add ticket, and the 'Sprints 2-5 + Sprint 6 separate batch' deploy note. - Review/ui-nielsen-audit.md: new Sprint 6 status block at the top. F3 + F4 documented with the design-decision context (ShoppingList-only scope; dropdown for All/Dinners; partial- success with detailed report). - docs/HANDOFF.md: Last-updated line bumped to 6 sprints / 10 commits / 20 findings / 6 §Future items. Header commit list gains the8ad4ef6row. New 'Sprint 6' subsection in the 2026-06-04 session block. Commit table gained the8ad4ef6row. Files-modified + Files-added lists updated. No code changes; the 3 pre-existing WIP files (backend/app/api/ recipes.py, schemas/recipe.py, nginx/nginx.conf) are deliberately not staged.
6.2 KiB
Sprint 6 — Deploy & smoke-check (F3 + F4)
Goal: verify the bulk pantry add (F3) and the plan-the-week button (F4) work end-to-end on http://100.108.208.56:8082/.
Commit: 8ad4ef6 (feat(ui): bulk pantry add + plan-the-week button (Sprint 6 F3+F4))
Sprint scope: F3 (ShoppingList bulk add) + F4 (Dashboard plan-the-week button)
Backend changes: pantry.py (new bulk endpoint), meals.py (new fill-empty-slots endpoint), schemas/__init__.py (3 new schemas)
Frontend changes: api/index.ts (2 new bindings), Dashboard.tsx (Plan the week button + dropdown), ShoppingList.tsx (Add to pantry button)
1. Deploy
Sprint 6 has both backend and frontend changes. No migrations needed.
# On deployment host (100.108.224.12)
cd /path/to/MealPlanner
git pull
docker compose -f docker-compose.yml up -d --build backend frontend
2. Build verification (already green locally)
$ cd frontend && npm run build
> tsc && vite build
✓ 1894 modules transformed.
dist/index.html 0.54 kB │ gzip: 0.31 kB
dist/assets/index-DBX6fwsX.css 38.10 kB │ gzip: 6.82 kB
dist/assets/index-CTd7xPlC.js 478.22 kB │ gzip: 147.53 kB
✓ built in 7.02s
tsc 0 errors, vite 0 errors.
3. Backend smoke (local dev, already verified)
# F3 — bulk pantry add with an unknown ingredient
curl -s -X POST http://100.108.208.56:8082/api/pantry/bulk \
-H 'Content-Type: application/json' \
-d '{"items":[{"ingredient_id":"00000000-0000-0000-0000-000000000001"}]}'
# Expected: {"added":0,"updated":0,"skipped":1,"results":[{"ingredient_id":"...","status":"skipped","id":null,"reason":"Unknown ingredient"}]}
# F4 — fill empty slots for dinners only
PLAN_ID=$(curl -s http://100.108.208.56:8082/api/meals | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('id','') if d else '')")
curl -s -X POST "http://100.108.208.56:8082/api/meals/$PLAN_ID/fill-empty-slots" \
-H 'Content-Type: application/json' \
-d '{"meal_types":["dinner"]}'
# Expected: {"filled":[...],"failed":[]} (filled has the newly-inserted dinner slots; failed is empty if there were empty dinner slots and recipes available)
# F4 — invalid meal_type
curl -s -X POST "http://100.108.208.56:8082/api/meals/$PLAN_ID/fill-empty-slots" \
-H 'Content-Type: application/json' \
-d '{"meal_types":["brunch"]}'
# Expected: {"filled":[],"failed":[{"day_of_week":0,"meal_type":"brunch","reason":"Unknown meal_type: brunch"}]}
4. UI smoke checks
S6.A — F3 ShoppingList "Add checked to pantry"
- Open
http://100.108.208.56:8082/shopping-list. - Confirm a shopping list is displayed (current week has a plan).
- Tick 3-5 checkboxes in different aisles. The header should show a primary
Add 5 to pantrybutton next to the Reset button. - Click the
Add 5 to pantrybutton. - Toast should appear:
Pantry: added 3, updated 1, skipped 1(counts will vary). - Open
http://100.108.208.56:8082/pantryin a new tab. The 4 successfully added items should be there. - Return to the ShoppingList. The 4 items should now be unchecked; the 1 skipped item (if any) should still be checked.
S6.B — F3 partial-failure edge case
To force a "skipped" count, you'd need a shopping list item without an ingredient_id. The seed data may not include any. If your DB does have such an item:
- Tick one such item + one normal item.
- Click
Add 2 to pantry. - Toast should show
skipped 1and the un-skipped item should be added.
If your DB has no such items, the toast will show only added / updated and that's correct.
S6.C — F4 Dashboard "Plan the week"
- Open
http://100.108.208.56:8082/. - The header should show a primary
Plan the weekbutton (with a Sparkles icon and a chevron-down caret) next to the week-nav control. - Click the button. A dropdown should appear with two options:
Dinners only(subtitle: "Fill every empty dinner slot this week")All meals(subtitle: "Fill every empty slot (breakfast, lunch, dinner) this week")
- Click
Dinners only. The button should show a spinner +Planning…and be disabled. - After 1-2 seconds, a toast should appear:
Planned N meal slots(orPlanned N of M meal slots — X failed (e.g. <reason>)). - The weekly grid should refresh and the previously-empty dinner slots should now show generated meals.
- Click
Plan the weekagain, chooseAll meals. The grid should fill in any remaining empty breakfast/lunch slots too.
S6.D — F4 edge cases
- No empty slots: if every slot is already filled, the toast should say
No empty meal slots to fill. - All recipes used: the backend reuses recipes when the un-used pool is empty. If your family has very few recipes, the toast might say
Planned 21 of 21 meal slots(with recipes repeated across days). That's expected. - Invalid meal_types: the frontend only sends
dinnerorbreakfast+lunch+dinner, so the backend'sUnknown meal_typefailure mode is not triggerable from the UI. (Documented in the backend test for completeness.)
S6.E — Regression check: Sprints 1-5 still work
Quick spot-check:
/recommendedredirects to/recipes/recommended(Sprint 1 B4)- Recipe detail shows ingredients with proper spacing (Sprint 1 B1)
- Meal detail shows
$X.XX per serving(Sprint 1 B3) - Pantry aisle
<select>has all 9 canonical options (Sprint 2 B8) - Shopping list section headers are sentence-case (Sprint 2 B9)
- Recipes filter panel has Apply/Reset and active count badge (Sprint 2 B11)
- Dashboard mobile viewport shows empty meal slots (Sprint 1 B5)
- Dashboard delete shows the Undo toast (Sprint 3 B12)
- Failed mutations show a toast with the FastAPI detail (Sprint 4 F7)
- URL week selector:
?week=2026-05-15works (Sprint 5 F5) - Keyboard shortcuts:
g d/g p/?(Sprint 5 F2)
5. Acceptance criteria
Sprint 6 is done when:
git pull+ container rebuild on the deployment host succeeds- S6.A bulk pantry add works
- S6.C plan-the-week button works
- No regression in S6.E
6. Rollback
git revert 8ad4ef6
docker compose -f docker-compose.yml up -d --build backend frontend
No migrations to revert. No data loss possible — both endpoints only insert or upsert user-controlled data.