--- app/api/routes/plans.py.orig +++ app/api/routes/plans.py.fixed @@ -1,7 +1,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request, Form, Body from fastapi.responses import HTMLResponse, RedirectResponse -from sqlalchemy.orm import Session +from sqlalchemy.orm import Session, joinedload from datetime import date, datetime, timedelta import logging from typing import List, Optional @@ -9,7 +9,7 @@ # Import database module from app.database import get_db, Food, Meal, MealFood, Plan, Template, TemplateMeal, WeeklyMenu, WeeklyMenuDay, TrackedDay, TrackedMeal, calculate_meal_nutrition, calculate_day_nutrition from main import templates - +from app.database import calculate_tracked_meal_nutrition, calculate_day_nutrition_tracked router = APIRouter() # Plan tab @@ -156,6 +156,7 @@ """render detailed view for a specific day or template""" from datetime import datetime, date import logging + from sqlalchemy.orm import joinedload logging.info(f"debug: detailed page requested url: {request.url.path}, query_params: {request.query_params}") logging.info(f"debug: detailed page requested person={person}, plan_date={plan_date}, template_id={template_id}") @@ -189,6 +190,20 @@ for tm in template_meals: meal_nutrition = calculate_meal_nutrition(tm.meal, db) meal_details.append({ + 'plan': {'meal': tm.meal, 'meal_time': tm.meal_time}, + 'nutrition': meal_nutrition, + 'foods': [] # Template view should show individual foods + }) + # ADD FOOD BREAKDOWN FOR TEMPLATES + foods = [] + for mf in tm.meal.meal_foods: + foods.append({ + 'name': mf.food.name, + 'quantity': mf.quantity, + 'serving_size': mf.food.serving_size, + 'serving_unit': mf.food.serving_unit, + }) + meal_details[-1]['foods'] = foods + # Accumulate nutrition totals + for key in template_nutrition: + if key in meal_nutrition: + template_nutrition[key] += meal_nutrition[key] @@ -232,42 +247,64 @@ plan_date_obj = datetime.fromisoformat(plan_date).date() except ValueError: logging.error(f"debug: invalid date format plan_date: {plan_date}") - return templates.TemplateResponse("detailed.html", { + return templates.TemplateResponse(request, "detailed.html", { "request": request, "title": "Invalid date", "error": "Invalid date format. Please use YYYY-MM-DD.", "day_totals": {}, "templates": templates_list, - "person": person + "person": person, + "is_tracked_view": True }) - logging.info(f"debug: loading plan for {person} on {plan_date_obj}") - plans = db.query(Plan).filter(Plan.person == person, Plan.date == plan_date_obj).all() - logging.info(f"debug: found {len(plans)} plans for {person} on {plan_date_obj}") - - day_totals = calculate_day_nutrition(plans, db) + logging.info(f"debug: loading TRACKED meals for {person} on {plan_date_obj}") + + # Get tracked day and meals instead of planned meals + tracked_day = db.query(TrackedDay).filter( + TrackedDay.person == person, + TrackedDay.date == plan_date_obj + ).first() + meal_details = [] - for plan in plans: - meal_nutrition = calculate_meal_nutrition(plan.meal, db) - foods = [] - for mf in plan.meal.meal_foods: - foods.append({ - 'name': mf.food.name, - 'quantity': mf.quantity, - 'serving_size': mf.food.serving_size, - 'serving_unit': mf.food.serving_unit, - 'calories': mf.food.calories * mf.quantity, - 'protein': mf.food.protein * mf.quantity, - 'carbs': mf.food.carbs * mf.quantity, - 'fat': mf.food.fat * mf.quantity, - 'fiber': (mf.food.fiber or 0) * mf.quantity, - 'sodium': (mf.food.sodium or 0) * mf.quantity, - }) - meal_details.append({ - 'plan': plan, - 'nutrition': meal_nutrition, - 'foods': foods - }) + day_totals = {'calories': 0, 'protein': 0, 'carbs': 0, 'fat': 0, 'fiber': 0, 'sugar': 0, 'sodium': 0, 'calcium': 0} + + if tracked_day: + tracked_meals = db.query(TrackedMeal).filter( + TrackedMeal.tracked_day_id == tracked_day.id + ).options(joinedload(TrackedMeal.meal).joinedload(Meal.meal_foods).joinedload(MealFood.food)).all() + + logging.info(f"debug: found {len(tracked_meals)} tracked meals for {person} on {plan_date_obj}") + + for tracked_meal in tracked_meals: + meal_nutrition = calculate_tracked_meal_nutrition(tracked_meal, db) + foods = [] + + # Show base meal foods + for 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, + }) + + # Show custom tracked foods (overrides/additions) + for tracked_food in tracked_meal.tracked_foods: + foods.append({ + 'name': f"{tracked_food.food.name} {'(override)' if tracked_food.is_override else '(addition)'}", + 'quantity': tracked_food.quantity, + 'serving_size': tracked_food.food.serving_size, + 'serving_unit': tracked_food.food.serving_unit, + }) + + meal_details.append({ + 'plan': tracked_meal, # Use tracked_meal instead of plan + 'nutrition': meal_nutrition, + 'foods': foods + }) + + # Accumulate day totals + for key in day_totals: + if key in meal_nutrition: + day_totals[key] += meal_nutrition[key] context = { "request": request, @@ -276,10 +313,11 @@ "day_totals": day_totals, "person": person, "plan_date": plan_date_obj, - "templates": templates_list + "templates": templates_list, + "is_tracked_view": True # Add flag to indicate this is tracked view } - - if not meal_details: - context["message"] = "No meals planned for this day." + + if not meal_details and tracked_day: + context["message"] = "No meals tracked for this day." logging.info(f"debug: rendering plan details context: {context}")