diff --git a/app/api/routes/meals.py b/app/api/routes/meals.py index d17ae7c..1c27f89 100644 --- a/app/api/routes/meals.py +++ b/app/api/routes/meals.py @@ -14,10 +14,23 @@ router = APIRouter() # Meals tab @router.get("/meals", response_class=HTMLResponse) async def meals_page(request: Request, db: Session = Depends(get_db)): - meals = db.query(Meal).all() - foods = db.query(Food).all() - return templates.TemplateResponse("meals.html", - {"request": request, "meals": meals, "foods": foods}) + try: + from sqlalchemy.orm import joinedload + logging.info("DEBUG: Starting meals query with eager loading") + meals = db.query(Meal).options(joinedload(Meal.meal_foods).joinedload(MealFood.food)).all() + logging.info(f"DEBUG: Retrieved {len(meals)} meals") + foods = db.query(Food).all() + logging.info(f"DEBUG: Retrieved {len(foods)} foods") + + # Test template rendering with a simple test + logging.info("DEBUG: Testing template rendering...") + test_data = {"request": request, "meals": meals, "foods": foods} + return templates.TemplateResponse("meals.html", test_data) + + except Exception as e: + logging.error(f"DEBUG: Error in meals_page: {str(e)}", exc_info=True) + # Return a simple error response for debugging + return HTMLResponse(f"
{str(e)}{type(e).__name__}")
@router.post("/meals/upload")
async def bulk_upload_meals(file: UploadFile = File(...), db: Session = Depends(get_db)):
diff --git a/app/api/routes/plans.py b/app/api/routes/plans.py
index e916204..d8ee05c 100644
--- a/app/api/routes/plans.py
+++ b/app/api/routes/plans.py
@@ -228,10 +228,10 @@ async def detailed(request: Request, person: str = "Sarah", plan_date: str = Non
'num_servings': num_servings,
'serving_size': mf.food.serving_size,
'serving_unit': mf.food.serving_unit,
- 'calories': mf.food.calories * num_servings,
- 'protein': mf.food.protein * num_servings,
- 'carbs': mf.food.carbs * num_servings,
- 'fat': mf.food.fat * num_servings,
+ 'calories': (mf.food.calories or 0) * num_servings,
+ 'protein': (mf.food.protein or 0) * num_servings,
+ 'carbs': (mf.food.carbs or 0) * num_servings,
+ 'fat': (mf.food.fat or 0) * num_servings,
'fiber': (mf.food.fiber or 0) * num_servings,
'sodium': (mf.food.sodium or 0) * num_servings,
})
@@ -317,10 +317,10 @@ async def detailed(request: Request, person: str = "Sarah", plan_date: str = Non
'num_servings': num_servings,
'serving_size': mf.food.serving_size,
'serving_unit': mf.food.serving_unit,
- 'calories': mf.food.calories * num_servings,
- 'protein': mf.food.protein * num_servings,
- 'carbs': mf.food.carbs * num_servings,
- 'fat': mf.food.fat * num_servings,
+ 'calories': (mf.food.calories or 0) * num_servings,
+ 'protein': (mf.food.protein or 0) * num_servings,
+ 'carbs': (mf.food.carbs or 0) * num_servings,
+ 'fat': (mf.food.fat or 0) * num_servings,
'fiber': (mf.food.fiber or 0) * num_servings,
'sodium': (mf.food.sodium or 0) * num_servings,
})
@@ -339,10 +339,10 @@ async def detailed(request: Request, person: str = "Sarah", plan_date: str = Non
'num_servings': num_servings,
'serving_size': tracked_food.food.serving_size,
'serving_unit': tracked_food.food.serving_unit,
- 'calories': tracked_food.food.calories * num_servings,
- 'protein': tracked_food.food.protein * num_servings,
- 'carbs': tracked_food.food.carbs * num_servings,
- 'fat': tracked_food.food.fat * num_servings,
+ 'calories': (tracked_food.food.calories or 0) * num_servings,
+ 'protein': (tracked_food.food.protein or 0) * num_servings,
+ 'carbs': (tracked_food.food.carbs or 0) * num_servings,
+ 'fat': (tracked_food.food.fat or 0) * num_servings,
'fiber': (tracked_food.food.fiber or 0) * num_servings,
'sodium': (tracked_food.food.sodium or 0) * num_servings,
})
@@ -403,10 +403,10 @@ async def detailed(request: Request, person: str = "Sarah", plan_date: str = Non
'num_servings': num_servings,
'serving_size': mf.food.serving_size,
'serving_unit': mf.food.serving_unit,
- 'calories': mf.food.calories * num_servings,
- 'protein': mf.food.protein * num_servings,
- 'carbs': mf.food.carbs * num_servings,
- 'fat': mf.food.fat * num_servings,
+ 'calories': (mf.food.calories or 0) * num_servings,
+ 'protein': (mf.food.protein or 0) * num_servings,
+ 'carbs': (mf.food.carbs or 0) * num_servings,
+ 'fat': (mf.food.fat or 0) * num_servings,
'fiber': (mf.food.fiber or 0) * num_servings,
'sodium': (mf.food.sodium or 0) * num_servings,
})
diff --git a/fix_detailed.md b/fix_detailed.md
new file mode 100644
index 0000000..0d1a824
--- /dev/null
+++ b/fix_detailed.md
@@ -0,0 +1,158 @@
+Fix Detailed View Food Breakdown - Implementation Plan
+Problem Statement
+The detailed view (/detailed route) is incorrectly calculating and displaying per-food nutrition values:
+
+Display Issue: Shows "34.0 × 34.0g" instead of "34.0g" in the Serving column
+Calculation Issue: Multiplies nutrition by quantity directly instead of calculating proper multiplier (quantity ÷ serving_size)
+
+Current incorrect calculation:
+python'calories': mf.food.calories * mf.quantity # Wrong: 125cal * 34g = 4250cal
+Should be:
+pythonmultiplier = mf.quantity / mf.food.serving_size # 34g / 34g = 1.0
+'calories': mf.food.calories * multiplier # 125cal * 1.0 = 125cal
+
+Files to Modify
+
+app/api/routes/plans.py - Fix calculation logic in detailed() function
+templates/detailed.html - Update serving column display
+
+
+Implementation Steps
+Step 1: Fix Template View Calculation (plans.py)
+Location: app/api/routes/plans.py, in the detailed() function around lines 190-220
+Find this section (for template meals):
+pythonfor mf in tm.meal.meal_foods:
+ try:
+ serving_size_value = float(mf.food.serving_size)
+ num_servings = mf.quantity / serving_size_value if serving_size_value != 0 else 0
+ except (ValueError, TypeError):
+ num_servings = 0
+
+ foods.append({
+ 'name': mf.food.name,
+ 'total_grams': mf.quantity,
+ 'num_servings': num_servings,
+ 'serving_size': mf.food.serving_size,
+ 'serving_unit': mf.food.serving_unit,
+ 'calories': mf.food.calories * num_servings, # May be wrong
+ 'protein': mf.food.protein * num_servings,
+ # ... etc
+ })
+Replace with:
+pythonfor mf in tm.meal.meal_foods:
+ try:
+ serving_size = float(mf.food.serving_size)
+ multiplier = mf.quantity / serving_size if serving_size > 0 else 0
+ except (ValueError, TypeError):
+ multiplier = 0
+
+ foods.append({
+ 'name': mf.food.name,
+ 'quantity': mf.quantity, # Grams used in this meal
+ 'serving_unit': mf.food.serving_unit,
+ # Calculate nutrition for the actual amount used
+ 'calories': (mf.food.calories or 0) * multiplier,
+ 'protein': (mf.food.protein or 0) * multiplier,
+ 'carbs': (mf.food.carbs or 0) * multiplier,
+ 'fat': (mf.food.fat or 0) * multiplier,
+ 'fiber': (mf.food.fiber or 0) * multiplier,
+ 'sodium': (mf.food.sodium or 0) * multiplier,
+ })
+Step 2: Fix Tracked Day View Calculation (plans.py)
+Location: Same file, around lines 247-280 (in the tracked meals section)
+Find this section:
+pythonfor mf in tracked_meal.meal.meal_foods:
+ foods.append({
+ 'name': mf.food.name,
+ 'quantity': mf.quantity,
+ 'serving_size': mf.food.serving_size,
+ 'serving_unit': mf.food.serving_unit,
+ })
+Replace with (add nutrition calculations):
+pythonfor mf in tracked_meal.meal.meal_foods:
+ try:
+ serving_size = float(mf.food.serving_size)
+ multiplier = mf.quantity / serving_size if serving_size > 0 else 0
+ except (ValueError, TypeError):
+ multiplier = 0
+
+ foods.append({
+ 'name': mf.food.name,
+ 'quantity': mf.quantity,
+ 'serving_unit': mf.food.serving_unit,
+ 'calories': (mf.food.calories or 0) * multiplier,
+ 'protein': (mf.food.protein or 0) * multiplier,
+ 'carbs': (mf.food.carbs or 0) * multiplier,
+ 'fat': (mf.food.fat or 0) * multiplier,
+ 'fiber': (mf.food.fiber or 0) * multiplier,
+ 'sodium': (mf.food.sodium or 0) * multiplier,
+ })
+Step 3: Fix Template Display
+Location: templates/detailed.html
+Find the Serving column display (likely something like):
+html