fix: shopping list ingredient UUID parsing for prices/aisles; feat: interactive checkboxes with localStorage persistence

This commit is contained in:
2026-05-17 13:12:18 -07:00
parent 2f6ab006de
commit 879768f72b
3 changed files with 133 additions and 52 deletions
+17 -11
View File
@@ -10,10 +10,20 @@ from app.schemas import ShoppingListResponse, ShoppingListItem
from datetime import date
from typing import List
from collections import defaultdict
from uuid import UUID
router = APIRouter()
def _parse_uuid(value):
if not value:
return None
try:
return UUID(value) if isinstance(value, str) else value
except ValueError:
return None
@router.get("", response_model=ShoppingListResponse)
def get_shopping_list(db: Session = Depends(get_db)):
profile = db.query(FamilyProfile).first()
@@ -51,8 +61,9 @@ def get_shopping_list(db: Session = Depends(get_db)):
recipe = db.query(Recipe).filter(Recipe.id == item.recipe_id).first()
if recipe and recipe.ingredients:
for ing in recipe.ingredients:
if ing.get('ingredient_id'):
all_ingredient_ids.add(ing['ingredient_id'])
ing_id = _parse_uuid(ing.get('ingredient_id'))
if ing_id:
all_ingredient_ids.add(ing_id)
if all_ingredient_ids:
ingredients = db.query(Ingredient).filter(
@@ -71,19 +82,14 @@ def get_shopping_list(db: Session = Depends(get_db)):
aggregated = defaultdict(lambda: {"quantity": 0.0, "unit": None, "name": ""})
# Build ingredient name lookup from IDs
ingredient_names = {}
if all_ingredient_ids:
ingredient_names = {str(i.id): i.name for i in ingredients}
for plan_item in current_plan.items:
recipe = db.query(Recipe).filter(Recipe.id == plan_item.recipe_id).first()
if recipe and recipe.ingredients:
for ing in recipe.ingredients:
ing_id = ing.get('ingredient_id')
ing_id = _parse_uuid(ing.get('ingredient_id'))
name = ing.get('name')
if not name and ing_id:
name = ingredient_names.get(str(ing_id))
if not name and ing_id and ing_id in ingredient_map:
name = ingredient_map[ing_id].name
if not name:
name = 'Unknown'
quantity = ing.get('quantity', 1.0) or 1.0
@@ -104,7 +110,7 @@ def get_shopping_list(db: Session = Depends(get_db)):
in_pantry = ingredient_id and ingredient_id in pantry_items
ing_obj = ingredient_map.get(ingredient_id) if ingredient_id else None
price = ing_obj.typical_price if ing_obj else None
price = float(ing_obj.typical_price) if ing_obj and ing_obj.typical_price is not None else None
sale_price = None
is_on_sale = False