Commit Graph
6 Commits
Author SHA1 Message Date
admin d78bd1864e feat(ui): URL week selector + aisle-migration 0015 cast fix (Sprint 5 F5)
F5 — Persistent week selector in URL (the audit's F5 / H7 finding).

Backend:
- GET /api/meals and GET /api/shopping-list now accept an optional
  ?week_start=YYYY-MM-DD query param. When set, the response is the
  MealPlan for that week (any status). When omitted, behaviour is
  unchanged: meals returns the latest plan; shopping-list returns
  the latest approved/locked plan with fallback to latest.
- No new dependencies; uses FastAPI's Optional[date] Query type
  which auto-validates the YYYY-MM-DD format.
- Files: backend/app/api/meals.py:30-57, shopping_list.py:27-60.

Frontend:
- New week helpers in lib/utils.ts: isoMonday(), parseIsoDate(),
  shiftIsoDate(), formatIsoDate(). All UTC-based to match the
  backend's date column. isoMonday returns the ISO date of the
  Monday of a given date's week.
- api/index.ts: meals.getPlanned(weekStart?) and
  shoppingList.get(weekStart?) take an optional ISO date string.
  Axios drops undefined params, so callers can omit them.
- Dashboard: useSearchParams('week') reads the URL; if absent or
  invalid, falls back to this week's Monday (so the default URL is
  empty). The queryKey now includes weekStart, so navigating weeks
  fetches the right plan. A new segmented control in the header
  (chevron-left | 'This week' / 'Current' jump button | chevron-
  right) lets the user step weeks; the jump button highlights
  primary-50 when the displayed week IS the current week. 'This
  week' clears the ?week param. Mutations (move/approve/deny/
  delete/generate) now invalidate ['mealPlan', weekStart] so the
  right week refetches.
- ShoppingList: same URL sync, same segmented control, same
  weekStart in queryKey. The 'no plan' empty state branches on
  isCurrentWeek: 'No shopping list yet' (current) vs 'No plan for
  that week' (any other week). The local-storage check-state key
  naturally isolates per week (it uses shoppingList.week_start_date
  which is the server's view of the current plan's week).

Migration 0015 cast fix:
- Discovered while smoke-testing on the local dev DB: the
  CASE expression in 0015_normalize_pantry_aisles.py failed
  with 'operator does not exist: text = boolean' on the
  varchar(100) aisle column. Root cause: the CASE branches were
  inferred as different types (string vs NULL) so the SET
  target type couldn't be unified.
- Fix: explicit ::varchar(100) cast on the CASE expression.
  Also simplified the WHEN '' branch (was NULLIF(...) IS NULL
  with implicit bool comparison). Tested on local dev DB:
  alembic upgrade head now succeeds; the 21196 rows that the
  Sprint 2 dry-run predicted actually normalize correctly.
  This means Sprint 2's deploy was blocked on the same bug
  (the deployment host would have hit the same error).
- Verified via curl: /api/shopping-list?week_start=2026-05-15
  returns 25 items with aisles 'Meat & Seafood', 'Pantry',
  'Produce', 'Dairy & Eggs' (the canonical labels the migration
  produces). Pre-migration aisles like 'meat_seafood' are gone.

Build: tsc 0 errors, vite 0 errors. 7 files, +196/-22.
2026-06-04 12:30:49 -07:00
admin 879768f72b fix: shopping list ingredient UUID parsing for prices/aisles; feat: interactive checkboxes with localStorage persistence 2026-05-17 13:12:18 -07:00
admin 2f6ab006de fix: enrich ingredient names in shopping list API
Same root cause as meal detail: recipe JSONB stores ingredient_id but
not name. Shopping list now looks up names from the Ingredient table
before aggregating quantities, so items show "3 cups onion" instead
of "Unknown".
2026-05-15 14:21:51 -07:00
adminandClaude Opus 4.7 8e89f793d5 feat: phase r1+r2 recovery + r3-0 swiftly api ingestion
R1 stabilization: pytest harness with transactional db fixture, smoke
+ alembic + auth + scrape + approval + swiftly tests, github actions
ci yaml. Bearer-token admin auth + signed-cookie session for family
ui mutations. Async POST /api/admin/scrape (BackgroundTasks, returns
202). Path canonicalization (no /list, /planned suffixes). DATABASE_URL
fail-fast on empty.

R2 deferred-risk spikes: live lucky california fetch (R2-A), full
email+per-voter approval click round trip with single-use enforcement
(R2-B, console email backend, sendgrid stub).

R3-0 phase 3 redesign: replaced playwright html scraper with requests
based swiftly json api client. 17 categories, ~10k products per scrape,
upsert by (source, external_id). 401 surfaces actionable token-refresh
message via ScrapeLog.error_message.

Pre-existing defects fixed: shopping_list.py syntax error blocking app
import, MealPlan.votes orphan relationship, JSONB(astext=True) invalid
kwarg, missing requests dep, calorie_target schema drift, every SQLEnum
needed values_callable, 0001 had empty downgrade(), seed had duplicate
ingredient rows.

Migrations added: 0003 grocery_item.description, 0004 family_profile.
calorie_target, 0005 grocery_item.external_id + source + composite index.

Verified: 31/31 pytest green, alembic upgrade->downgrade->upgrade clean,
frontend npm run build clean, live scrape 9,960 grocery_item rows in 36s.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 14:08:19 -07:00
admin c735d21661 feat: implement Phase 2 - Alembic migrations, Pydantic schemas, and real API endpoints
- Add initial Alembic migration with full PostgreSQL schema (enums, tables, indexes, constraints)
- Add seed data migration with basic ingredients (70+) and family profile
- Add Pydantic schemas for all models (FamilyProfile, Recipe, MealPlan, etc.)
- Implement /api/profile endpoints (CRUD, family member management)
- Implement /api/recipes endpoints (CRUD, ingredients, filtering)
- Implement /api/meals endpoints (meal plans, voting, approval tokens)
- Implement /api/pantry endpoints (CRUD for home pantry)
- Implement /api/shopping-list endpoints (aggregation, print-ready HTML)
- Implement /api/admin endpoints (scrape trigger, logs, stats)
- Update ORIENTATION.md with Phase 2 progress
2026-05-04 20:21:20 -07:00
admin 1328ec359d feat: add Phase 1 infrastructure skeleton
Backend (FastAPI):
- docker-compose with all 4 services
- FastAPI app with health endpoints
- SQLAlchemy models for all tables
- Placeholder API endpoints for all routes
- Config and database modules
- requirements.txt with all dependencies

Frontend (React):
- package.json with React, Tailwind, React Query, React Router
- Vite config with API proxy
- Tailwind and TypeScript configs
- Basic App with routing skeleton
- Placeholder pages (Dashboard, MealDetail, Pantry)

Infrastructure:
- nginx config for reverse proxy
- Dockerfile for backend and frontend
2026-05-04 19:29:35 -07:00