feat: Phase 8 Feedback UI + API endpoints

- New backend/app/api/feedback.py: GET/POST for meal_plan_item feedback
- MealDetail.tsx: star rating, never-suggest checkbox, reason dropdown,
  free-text comments, displays saved feedback
- frontend/src/api/index.ts + types: feedback API + TypeScript interface
- backend/app/schemas/__init__.py: model_validator maps qty→quantity for
  RecipeIngredient (fixes Pydantic validation on recipe JSONB)
- docs/HANDOFF.md: mark Phase 8 complete, update file map and date
This commit is contained in:
2026-05-14 09:54:25 -07:00
parent e618b2bd5a
commit f7ed10651b
8 changed files with 353 additions and 26 deletions
+12 -20
View File
@@ -2,13 +2,11 @@
You are taking over a project in mid-flight. Read `docs/ORIENTATION.md` first for the high-level. This file is the deep dive: what's real, what's stubbed, where the bodies are buried, and what to do next.
**Date of handoff: 2026-05-12. Last commits before handoff:**
**Date of handoff: 2026-05-14. Last commits before handoff:**
```
[pending] feat: Phase 8 Feedback UI + API endpoints
[pending] fix: RecipeIngredient schema qty→quantity model_validator
b522760 fix: cast qty/unit to str before html.escape in vote email shopping preview
dbc26bc feat: LLM-powered second-pass ingredient matcher + matcher improvements
b03e7f8 feat: Spoonacular recipe enrichment — images + descriptions for 25/30 recipes
a98f0dc docs: update HANDOFF.md for 2026-05-10 session
2373883 fix: exact-name fast path in matcher + save priceless produce in scraper
```
---
@@ -182,8 +180,9 @@ The Swiftly API is the same for ALL product categories, not just the weekly ad:
- These show "—" in shopping list — correct behavior (better than wrong match)
- **Approved plan:** Ollama LLM matcher as a second pass using Lucky's product search API (`luckysupermarkets.com/search/products?q=<ingredient>`) to find items outside the Swiftly weekly ad
### Phase 8 — Feedback UI (not started)
- `feedback` table exists; no UI reads/writes it
### Phase 8 — Feedback UI (done)
- `feedback` table now read/written via REST API
- Meal detail page shows star rating, never-suggest, reason dropdown, free-text comments
---
@@ -274,18 +273,11 @@ Next Friday at 02:00 PT the scheduler runs automatically. No action needed. All
## File map (additions from this session)
```
backend/app/scraper/lucky_ca_scraper.py — removed price guard in map_product()
backend/app/services/matcher.py — full rewrite: ingredient-centric, precision×recall
backend/app/services/orchestrator/
steps.py — vote email: ingredient list + cooking steps
shopping list: grouped by meal, current_price fix
nginx/nginx.conf — Docker DNS resolver, proxy via set $var pattern
frontend/src/pages/Login.tsx — password form (Login page)
frontend/src/App.tsx — /login route, Sign out button
frontend/src/api/index.ts — 401 interceptor
scripts/seed_family.py — Woolery family + real emails
docs/superpowers/plans/
2026-05-09-mvp-login.md — MVP login plan (executed, merged)
backend/app/api/feedback.py — new: GET/POST feedback endpoints
frontend/src/pages/MealDetail.tsx — added Feedback section (rating, never-suggest, reasons)
frontend/src/api/index.ts — added feedback API methods
frontend/src/types/index.ts — added Feedback interface
backend/app/schemas/__init__.py — RecipeIngredient model_validator qty→quantity
```
---
@@ -294,4 +286,4 @@ docs/superpowers/plans/
Trust the tests. Trust the live runs. Don't trust prose claims that something is "complete" without running the verification gate yourself.
**Last updated: 2026-05-12** — Spoonacular enrichment (102/107 recipes), LLM matcher built (Ollama Cloud kimi-k2.6), AUTO matcher improved (plural normalization, precision floor 0.45→0.30), vote email confirmed polished by Peter. Next: run Spoonacular script again for 5 remaining recipes; Phase 8 Feedback UI.
**Last updated: 2026-05-14** — Spoonacular enrichment complete (102/107 matched, 5 unmatched). Phase 8 Feedback UI built: REST API + frontend. Pydantic validation fixed for recipe ingredients (qty↔quantity schema drift). .env restored after accidental overwrite.