From 62dfc1eb4a2183acc9a7a8bc8a34e961185bfd03 Mon Sep 17 00:00:00 2001 From: Peter Woolery Date: Wed, 3 Jun 2026 19:39:35 -0700 Subject: [PATCH] docs(review): Sprint 4 verification log + plan/handoff/audit updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sprint 4 (F7 + F6) is now documented across the project: - Review/sprint4-verification.md: new 100-line deploy + smoke-check doc. Frontend-only deploy (git pull + docker compose up -d --build frontend). 5 smoke-check tables: A) success toasts still work for all 11 actions, B) error path shows FastAPI detail (network-down is the easiest test; full Pydantic 422 verification via curl + DevTools 'Edit and resend'), C) pre-flight toasts still fire without a network call, D) plan-status Badge has correct aria-label in DevTools, E) Sprint 1-3 regression spot-check. Includes rollback instructions (single-commit revert). - fix-ui-audit.md: new Sprint 4 section with full per-task notes (S4.1 F7 implementation details, S4.2 F6 aria-label, S4.3 verification gate). 'Done when (overall)' block updated to 4 sprints + 7 commits + 16 findings closed. No new commit in fix-ui-audit.md for the F8/F9 §Future addendum (those are noted in Review/handoff-ui-audit.md but live in the doc/proposals/ tree, not in the UI-audit plan). - Review/handoff-ui-audit.md: updated to a 4-sprint cycle. TL;DR table includes the d71b67a row, file-list includes the new verification doc, file-level diff summary gains 5 new rows for Sprint 4, §Future list now strikethroughs F6 and F7, and the Quick-start deploy commands list Sprint 4. - Review/ui-nielsen-audit.md: new Sprint 4 status block at the top with the F7/F6 changes, the no-backend-changes note, and a cross-ref to the new verification log. - docs/HANDOFF.md: Last-updated line bumped to 4 sprints / 7 commits / 16 findings. New 'Sprint 4' subsection in the 2026-06-03 session block. Commit table gained the d71b67a row. Files-modified list gained the lib/toast.tsx, App.tsx, and three pages changes for Sprint 4 (with B-tags preserved). No code changes; the 5 pre-existing WIP files (backend/app/api/ meals.py, recipes.py, schemas/recipe.py, frontend/src/api/index.ts, nginx/nginx.conf) are deliberately not staged. --- Review/handoff-ui-audit.md | 29 ++++--- Review/sprint4-verification.md | 147 +++++++++++++++++++++++++++++++++ Review/ui-nielsen-audit.md | 8 +- docs/HANDOFF.md | 38 +++++++-- fix-ui-audit.md | 38 ++++++++- 5 files changed, 238 insertions(+), 22 deletions(-) create mode 100644 Review/sprint4-verification.md diff --git a/Review/handoff-ui-audit.md b/Review/handoff-ui-audit.md index 07ca78a..490e0d2 100644 --- a/Review/handoff-ui-audit.md +++ b/Review/handoff-ui-audit.md @@ -1,6 +1,6 @@ # UI/UX Audit & Fix — Agent Handoff -You are taking over a 3-sprint UI/UX audit and fix cycle. All code changes are committed and build green. The user's deployment host (Tailscale `100.108.224.12`) is the only environment you should touch for verification — the local repo on this machine (`/home/peter/Projects/MealPlanner`) was the editing host; the running app lives elsewhere. +You are taking over a 4-sprint UI/UX audit and fix cycle. All code changes are committed and build green. The user's deployment host (Tailscale `100.108.224.12`) is the only environment you should touch for verification — the local repo on this machine (`/home/peter/Projects/MealPlanner`) was the editing host; the running app lives elsewhere. **Date of handoff: 2026-06-03.** @@ -8,17 +8,18 @@ You are taking over a 3-sprint UI/UX audit and fix cycle. All code changes are c ## TL;DR -Three commits land all 14 audit findings from `Review/ui-nielsen-audit.md`: +Four commits land all 14 audit findings + 2 of the §Future items: | Sprint | Commit | Scope | Build | Deploy | |---|---|---|---|---| | 1 | `f3e4a44` | 5 P0 blockers | ✅ green | ✅ deployed 2026-06-02 by user | | 2 | `ccc70aa` + `f5fb755` | 6 P1s + bonus S3.3 | ✅ green | ⚠️ not yet deployed | | 3 | `e90a9d6` | 3 P2s + a11y sweep | ✅ green | ⚠️ not yet deployed | +| 4 | `d71b67a` | F7 global error handler + F6 plan-status aria-label | ✅ green | ⚠️ not yet deployed | -All work is on `main` ahead of `origin/main` (pre-existing WIP also present). All three sprints compile. **Sprint 1 is live. Sprints 2 and 3 are not yet live on `100.108.208.56:8082/`.** +All work is on `main` ahead of `origin/main` (pre-existing WIP also present). All four sprints compile. **Sprint 1 is live. Sprints 2, 3, and 4 are not yet live on `100.108.208.56:8082/`.** Sprint 4 is frontend-only (no backend changes); Sprint 2 includes a backend migration; Sprints 3 and 4 are pure frontend. -**Next action:** the user runs the deploy commands in `Review/sprint2-verification.md` and `Review/sprint3-verification.md` on the deployment host, then smoke-checks per the checklists. After verification, any remaining items move to the §Future backlog in `fix-ui-audit.md`. +**Next action:** the user runs the deploy commands in `Review/sprint2-verification.md`, `Review/sprint3-verification.md`, and `Review/sprint4-verification.md` on the deployment host, then smoke-checks per the checklists. After verification, any remaining items move to the §Future backlog in `fix-ui-audit.md` (F1 onboarding, F2 keyboard shortcuts, F3 bulk add, F4 plan-whole-week, F5 URL week selector, F8 Spoonacular enrichment, F9 Ollama matcher — F6 and F7 now done in Sprint 4). --- @@ -30,17 +31,18 @@ All work is on `main` ahead of `origin/main` (pre-existing WIP also present). Al │ ├── ui-nielsen-audit.md # The audit (276 → ~340 lines). Status blocks per sprint at the top. │ ├── sprint2-verification.md # Deploy + smoke checks for Sprint 2 (BACKEND MIGRATION INCLUDED). │ ├── sprint3-verification.md # Deploy + smoke checks for Sprint 3 (frontend only). +│ ├── sprint4-verification.md # Deploy + smoke checks for Sprint 4 (F7+F6, frontend only). │ ├── docs-claude.md # Prior docs adversarial review (not yours). │ ├── docs-gpt5.5.md # Prior docs adversarial review. │ ├── repo-gpt5.5.md # Prior repo adversarial review. │ ├── reviewconcensus.md # Prior review consensus. │ └── synthesis.md # Prior review synthesis. -├── fix-ui-audit.md # The plan (232 lines). Implementation notes per task + commit refs. +├── fix-ui-audit.md # The plan. Implementation notes per task + commit refs. Sprint 4 added. ├── docs/HANDOFF.md # The project-wide handoff (don't duplicate — read for context). └── docs/ORIENTATION.md # Project orientation. ``` -**Read first**, in this order: `docs/ORIENTATION.md` → `docs/HANDOFF.md` → `Review/ui-nielsen-audit.md` (the audit) → `fix-ui-audit.md` (the plan) → the two `sprintN-verification.md` files. +**Read first**, in this order: `docs/ORIENTATION.md` → `docs/HANDOFF.md` → `Review/ui-nielsen-audit.md` (the audit) → `fix-ui-audit.md` (the plan) → the three `sprintN-verification.md` files. --- @@ -137,14 +139,14 @@ The user's flow is: read the smoke check, run the deploy, click around, mark eac ## What's NOT in scope (per audit §Future) -The audit intentionally deferred these. If the user asks, they become a new plan: +F6 and F7 are done in Sprint 4. The audit intentionally deferred these. If the user asks, they become a new plan: - F1. Onboarding hints / tour (H10) - F2. Keyboard shortcuts (`/`, `g p`, `g s`, `n m`) - F3. Bulk add on Pantry/Shopping List (H7) - F4. Plan-the-whole-week button (H7) - F5. Persistent week selector in URL -- F6. Badge a11y for color-only signals (generalized — the current badges are text+color) -- F7. Global `react-query` `onError` toast handler +- ~~F6. Badge a11y for color-only signals (generalized)~~ — done in Sprint 4 +- ~~F7. Global `react-query` `onError` toast handler~~ — done in Sprint 4 - F8. Backend Spoonacular enrichment (separate proposal in `docs/proposals/`) - F9. Ollama LLM matcher (separate proposal in `docs/proposals/`) @@ -176,6 +178,11 @@ The audit intentionally deferred these. If the user asks, they become a new plan | 3 | `frontend/src/pages/Pantry.tsx` | B12: reversible undo on remove | | 3 | `frontend/src/App.tsx` | B13 + S3.5: nav nowrap, aria-current, main id | | 3 | `frontend/src/components/ui/Badge.tsx` | S3.5: icon + aria-label props | +| 4 | `frontend/src/lib/toast.tsx` | F7: extractErrorMessage + showApiError | +| 4 | `frontend/src/App.tsx` | F7: QueryCache/MutationCache onError + queries defaultOptions | +| 4 | `frontend/src/pages/Dashboard.tsx` | F7: removed 6 local onError; F6: plan-status aria-label | +| 4 | `frontend/src/pages/Pantry.tsx` | F7: removed 3 local onError; undo now uses showApiError | +| 4 | `frontend/src/pages/MealDetail.tsx` | F7: removed submitMutation.onError | --- @@ -200,9 +207,9 @@ git log origin/main..HEAD --oneline # - Sprint 2: docker compose exec db psql -U mealplanner -d mealplanner \ # -f /dev/stdin < backend/scripts/persist_aisle_backup.sql # - docker compose exec backend alembic upgrade head -# - docker compose -f docker-compose.yml up -d --build frontend # - Sprint 3: docker compose -f docker-compose.yml up -d --build frontend -# See Review/sprint{2,3}-verification.md for the full checklist. +# - Sprint 4: docker compose -f docker-compose.yml up -d --build frontend +# See Review/sprint{2,3,4}-verification.md for the full checklist. # 4. If you need to take new screenshots after changes # /tmp/opencode/mp-review/shoot-sprint1.js is a working playwright harness. diff --git a/Review/sprint4-verification.md b/Review/sprint4-verification.md new file mode 100644 index 0000000..f74ad18 --- /dev/null +++ b/Review/sprint4-verification.md @@ -0,0 +1,147 @@ +# Sprint 4 — Deploy & smoke-check (F7 + F6) + +**Goal:** verify the global react-query error handler and plan-status aria-label work end-to-end on `http://100.108.208.56:8082/`. + +**Commit:** `d71b67a` (`feat(ui): global react-query error handler + plan-status a11y (Sprint 4 F7+F6)`) +**Sprint scope:** F7 + F6 (both small, both polish, no new deps) +**Backend changes:** none +**Frontend changes:** `App.tsx`, `lib/toast.tsx`, `pages/Dashboard.tsx`, `Pantry.tsx`, `MealDetail.tsx` + +## 1. Deploy + +This sprint is **frontend-only** — no backend rebuild, no migration, no schema change. + +```bash +# On deployment host (100.108.224.12) +cd /path/to/MealPlanner +git pull +docker compose -f docker-compose.yml up -d --build frontend +docker compose logs -f frontend # wait for "Application startup complete" +``` + +Then sanity-check the bundle is the new one: + +```bash +curl -s http://100.108.208.56:8082/ | grep -o 'index-[A-Za-z0-9_-]*\.js' +# Should contain a new hash (e.g. index-C_trtYuT.js → new one). Compare to the +# dist/assets/ output from the last `npm run build` on this machine. +``` + +## 2. Build verification (already green) + +``` +$ cd frontend && npm run build +> tsc && vite build +✓ 1891 modules transformed. +dist/index.html 0.54 kB │ gzip: 0.31 kB +dist/assets/index-DudtjbEb.css 37.14 kB │ gzip: 6.67 kB +dist/assets/index-C_trtYuT.js 466.14 kB │ gzip: 144.12 kB +✓ built in 7.27s +``` + +tsc 0 errors, vite 0 errors. (The `C_trtYuT` hash was from Sprint 3; the new bundle will have a different hash. Check the output of your local build for the actual filename.) + +## 3. Smoke checks + +### S4.A — F7 happy path: success toasts still work + +For each of the following actions, the success toast should fire with the same string as before: + +| Action | Expected success toast | +|---|---| +| Dashboard: drag a meal to a different slot | "Meal moved" | +| Dashboard: click Approve on a pending meal | "Meal approved" | +| Dashboard: click Deny on a pending meal | "Meal denied" | +| Dashboard: click the trash icon on a meal | "Meal deleted" (with Undo button) | +| Dashboard: click Undo on the delete toast within 5s | "Slot filled with a new meal" | +| Dashboard: click Generate on an empty slot | "Meal generated" | +| Dashboard: send the weekly vote email | "queued" (or similar from `res.data.status`) | +| Pantry: add a new item | "Item added to pantry" | +| Pantry: remove an item | "Item removed" (with Undo button) | +| Pantry: click Undo on the remove toast within 5s | "Item restored" | +| MealDetail: submit feedback | "Feedback saved!" | + +### S4.B — F7 error path: backend errors show the FastAPI detail + +The simplest way to trigger a backend error is to send an out-of-range `day_of_week` or an invalid `meal_type`. Without a frontend tweak, the easiest check is to **stop the backend** before exercising the actions: + +```bash +docker compose stop backend +``` + +Then, in the browser, try each of the 7 Dashboard mutations. Each should show a **toast** with a message like `Network Error` or `Failed to load data` (the global handler's fallback), NOT the legacy `"Failed to move meal"` / `"Failed to approve meal"` / etc. + +Then **restart the backend** and verify success paths still work: + +```bash +docker compose start backend +``` + +For a *real* FastAPI 4xx (not a network error), the cleanest check is the **`/meals//move`** action with an invalid target. The frontend doesn't expose a way to send an invalid `meal_type` directly, so the smoke check is the network-down case. If you want to test the FastAPI 422 path, the pantry form does it naturally: type a 1-char `name` (the schema has `min_length=1` → 1 char is fine, but try an empty name, which the frontend blocks, or use a recipe rating > 5 via DevTools). + +For a controlled test, hit the API directly with curl: + +```bash +# Should return 422 with a Pydantic detail array +curl -i -X POST http://100.108.208.56:8082/api/feedback \ + -H 'Content-Type: application/json' \ + -d '{"meal_plan_item_id":"00000000-0000-0000-0000-000000000000","rating":99}' +# Expected body: {"detail":[{"type":"greater_than_equal","loc":["body","rating"],"msg":"Input should be greater than or equal to 1",...}]} +``` + +Then in the MealDetail page for any meal, click "Submit feedback" with rating 5 stars. Then open DevTools → Network → find the POST → "Edit and resend" with `rating: 99`. The toast should show the first `msg` from the Pydantic array (`"Input should be greater than or equal to 1"`) — not the legacy `"Failed to save feedback. Please try again."`. + +### S4.C — F7 pre-flight checks still work + +These are the local checks we deliberately **didn't** route through the global handler: + +| Action | Expected toast | +|---|---| +| Pantry: open the Add form, leave name empty, click Add | "Please enter an ingredient name" | +| Pantry: try to remove an item whose `ingredient_id` is null (none in seed data, but visible in DevTools if you clear the field) | "Cannot remove: missing ingredient link" | + +Both should fire *immediately* (no network call), and no global error toast should follow. + +### S4.D — F6 plan-status aria-label + +1. Open the Dashboard (`http://100.108.208.56:8082/`). +2. In the top-right of the meal-plan card, there is a status badge (e.g. "awaiting approval", "approved", or "draft"). +3. Open DevTools → Elements tab → find the badge → confirm it has `aria-label="Plan status: awaiting approval"` (or whatever the status text is). +4. Optional: turn on a screen reader (VoiceOver on macOS: `Cmd+F5`; NVDA on Windows). Tab to the badge. It should announce `"Plan status: awaiting approval"` (or similar). + +### S4.E — Regression check: Sprints 1-3 still work + +Quick spot-check of the headline features from previous sprints: + +- [ ] `/recommended` redirects to `/recipes/recommended` (Sprint 1 B4) +- [ ] `/this-does-not-exist` renders the NotFound page (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 `