updated the tracker to have more features

This commit is contained in:
2025-09-30 12:13:05 -07:00
parent 10d3897850
commit 4f41b5d69e
9 changed files with 60 additions and 41 deletions

View File

@@ -285,8 +285,7 @@ async def use_template(template_id: int, request: Request, db: Session = Depends
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=template_meal.meal_id, meal_id=template_meal.meal_id,
meal_time=template_meal.meal_time, meal_time=template_meal.meal_time
quantity=1.0 # Default quantity when applying template
) )
db.add(tracked_meal) db.add(tracked_meal)

View File

@@ -87,9 +87,8 @@ async def tracker_add_meal(request: Request, db: Session = Depends(get_db)):
date_str = form_data.get("date") date_str = form_data.get("date")
meal_id = form_data.get("meal_id") meal_id = form_data.get("meal_id")
meal_time = form_data.get("meal_time") meal_time = form_data.get("meal_time")
quantity = 1.0 # Default quantity to 1.0 as the field is removed from the UI
logging.info(f"DEBUG: Adding meal to tracker - person={person}, date={date_str}, meal_id={meal_id}, meal_time={meal_time}, quantity={quantity}") logging.info(f"DEBUG: Adding meal to tracker - person={person}, date={date_str}, meal_id={meal_id}, meal_time={meal_time}")
# Parse date # Parse date
from datetime import datetime from datetime import datetime
@@ -111,8 +110,7 @@ async def tracker_add_meal(request: Request, db: Session = Depends(get_db)):
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=int(meal_id), meal_id=int(meal_id),
meal_time=meal_time, meal_time=meal_time
quantity=quantity
) )
db.add(tracked_meal) db.add(tracked_meal)
@@ -259,8 +257,7 @@ async def tracker_apply_template(request: Request, db: Session = Depends(get_db)
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=template_meal.meal_id, meal_id=template_meal.meal_id,
meal_time=template_meal.meal_time, meal_time=template_meal.meal_time
quantity=1.0
) )
db.add(tracked_meal) db.add(tracked_meal)
@@ -540,7 +537,6 @@ async def save_as_new_meal(data: dict = Body(...), db: Session = Depends(get_db)
# Update the original tracked meal to point to the new meal # Update the original tracked meal to point to the new meal
tracked_meal.meal_id = new_meal.id tracked_meal.meal_id = new_meal.id
tracked_meal.quantity = 1.0 # Reset quantity to 1.0 as the new meal contains the correct quantities
# Clear custom tracked foods from the original tracked meal # Clear custom tracked foods from the original tracked meal
for tf in tracked_meal.tracked_foods: for tf in tracked_meal.tracked_foods:
@@ -611,8 +607,7 @@ async def tracker_add_food(data: dict = Body(...), db: Session = Depends(get_db)
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=new_meal.id, meal_id=new_meal.id,
meal_time=meal_time, meal_time=meal_time
quantity=1.0 # Quantity for single food meals is always 1.0, actual food quantity is in MealFood
) )
db.add(tracked_meal) db.add(tracked_meal)

View File

@@ -134,7 +134,6 @@ class TrackedMeal(Base):
tracked_day_id = Column(Integer, ForeignKey("tracked_days.id")) tracked_day_id = Column(Integer, ForeignKey("tracked_days.id"))
meal_id = Column(Integer, ForeignKey("meals.id")) meal_id = Column(Integer, ForeignKey("meals.id"))
meal_time = Column(String) # Breakfast, Lunch, Dinner, Snack 1, Snack 2, Beverage 1, Beverage 2 meal_time = Column(String) # Breakfast, Lunch, Dinner, Snack 1, Snack 2, Beverage 1, Beverage 2
quantity = Column(Float, default=1.0) # Quantity multiplier (e.g., 1.5 for 1.5 servings)
tracked_day = relationship("TrackedDay", back_populates="tracked_meals") tracked_day = relationship("TrackedDay", back_populates="tracked_meals")
meal = relationship("Meal") meal = relationship("Meal")
@@ -201,7 +200,6 @@ class TrackedDayCreate(BaseModel):
class TrackedMealCreate(BaseModel): class TrackedMealCreate(BaseModel):
meal_id: int meal_id: int
meal_time: str meal_time: str
quantity: float = 1.0
class FoodExport(FoodResponse): class FoodExport(FoodResponse):
pass pass
@@ -283,7 +281,6 @@ class TrackedMealFoodExport(BaseModel):
class TrackedMealExport(BaseModel): class TrackedMealExport(BaseModel):
meal_id: int meal_id: int
meal_time: str meal_time: str
quantity: float
tracked_foods: List[TrackedMealFoodExport] = [] tracked_foods: List[TrackedMealFoodExport] = []
class TrackedDayExport(BaseModel): class TrackedDayExport(BaseModel):
@@ -382,12 +379,11 @@ def calculate_tracked_meal_nutrition(tracked_meal, db: Session):
'fiber': 0, 'sugar': 0, 'sodium': 0, 'calcium': 0 'fiber': 0, 'sugar': 0, 'sodium': 0, 'calcium': 0
} }
# Base meal nutrition scaled by quantity # Base meal nutrition
base_nutrition = calculate_meal_nutrition(tracked_meal.meal, db) base_nutrition = calculate_meal_nutrition(tracked_meal.meal, db)
quantity = tracked_meal.quantity
for key in totals: for key in totals:
if key in base_nutrition: if key in base_nutrition:
totals[key] += base_nutrition[key] * quantity totals[key] += base_nutrition[key]
# Add custom tracked foods # Add custom tracked foods
for tracked_food in tracked_meal.tracked_foods: for tracked_food in tracked_meal.tracked_foods:

View File

@@ -217,8 +217,7 @@ def sample_tracked_day(db_session, sample_meal):
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=sample_meal.id, meal_id=sample_meal.id,
meal_time="Breakfast", meal_time="Breakfast"
quantity=1.0
) )
db_session.add(tracked_meal) db_session.add(tracked_meal)
db_session.commit() db_session.commit()

View File

@@ -4,4 +4,7 @@ services:
ports: ports:
- "8999:8999" - "8999:8999"
environment: environment:
- DATABASE_URL=sqlite:////app/meal_planner.db - DATABASE_URL=sqlite:////app/meal_planner.db
volumes:
- ./alembic:/app/alembic
- ./meal_planner.db:/app/meal_planner.db

View File

@@ -61,9 +61,6 @@
<div class="d-flex justify-content-between align-items-center mb-2"> <div class="d-flex justify-content-between align-items-center mb-2">
<div> <div>
<strong>{{ tracked_meal.meal.name }}</strong> <strong>{{ tracked_meal.meal.name }}</strong>
{% if tracked_meal.quantity != 1.0 %}
<span class="text-muted">({{ "%.1f"|format(tracked_meal.quantity) }}x)</span>
{% endif %}
</div> </div>
<div> <div>
<button class="btn btn-sm btn-outline-secondary me-1" onclick="editTrackedMeal('{{ tracked_meal.id }}')" title="Edit Meal"> <button class="btn btn-sm btn-outline-secondary me-1" onclick="editTrackedMeal('{{ tracked_meal.id }}')" title="Edit Meal">
@@ -78,7 +75,6 @@
<!-- Food Breakdown --> <!-- Food Breakdown -->
<div class="ms-3 row row-cols-2 g-1"> <div class="ms-3 row row-cols-2 g-1">
{% for meal_food in tracked_meal.meal.meal_foods %} {% for meal_food in tracked_meal.meal.meal_foods %}
{% set effective_quantity = meal_food.quantity * tracked_meal.quantity %}
<div class="col"> <div class="col">
<div class="small text-muted"> <div class="small text-muted">
• {{ meal_food.food.name }} • {{ meal_food.food.name }}
@@ -86,7 +82,7 @@
</div> </div>
<div class="col text-end"> <div class="col text-end">
<div class="small text-muted"> <div class="small text-muted">
{{ "%.1f"|format(effective_quantity) }} {{ meal_food.food.serving_unit }} {{ "%.1f"|format(meal_food.quantity) }} {{ meal_food.food.serving_unit }}
{% if meal_food.food.serving_size %} {% if meal_food.food.serving_size %}
({{ meal_food.food.serving_size }}) ({{ meal_food.food.serving_size }})
{% endif %} {% endif %}

View File

@@ -60,8 +60,7 @@ def sample_chart_data(db_session):
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=meal.id, meal_id=meal.id,
meal_time="Breakfast", meal_time="Breakfast"
quantity=1.0
) )
db_session.add(tracked_meal) db_session.add(tracked_meal)
db_session.commit() db_session.commit()

View File

@@ -58,7 +58,7 @@ def create_test_data(session: TestingSessionLocal):
session.commit() session.commit()
session.refresh(tracked_day) session.refresh(tracked_day)
tracked_meal = TrackedMeal(tracked_day_id=tracked_day.id, meal_id=meal1.id, meal_time="Breakfast", quantity=1.0) tracked_meal = TrackedMeal(tracked_day_id=tracked_day.id, meal_id=meal1.id, meal_time="Breakfast")
session.add(tracked_meal) session.add(tracked_meal)
session.commit() session.commit()
session.refresh(tracked_meal) session.refresh(tracked_meal)

View File

@@ -189,7 +189,7 @@ class TestTrackerNutrition:
def test_tracked_day_with_quantity_multiplier(self, client, sample_meal, db_session): def test_tracked_day_with_quantity_multiplier(self, client, sample_meal, db_session):
"""Test nutrition calculation with quantity multiplier""" """Test nutrition calculation with quantity multiplier"""
# Create tracked day with meal at 2x quantity # Create tracked day with meal
tracked_day = TrackedDay( tracked_day = TrackedDay(
person="Sarah", person="Sarah",
date=date.today(), date=date.today(),
@@ -202,8 +202,7 @@ class TestTrackerNutrition:
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=sample_meal.id, meal_id=sample_meal.id,
meal_time="Breakfast", meal_time="Breakfast"
quantity=2.0
) )
db_session.add(tracked_meal) db_session.add(tracked_meal)
db_session.commit() db_session.commit()
@@ -211,7 +210,7 @@ class TestTrackerNutrition:
tracked_meals = [tracked_meal] tracked_meals = [tracked_meal]
nutrition = calculate_day_nutrition_tracked(tracked_meals, db_session) nutrition = calculate_day_nutrition_tracked(tracked_meals, db_session)
# Should be double the base meal nutrition # Should be the base meal nutrition
assert nutrition["calories"] > 0 assert nutrition["calories"] > 0
@@ -231,8 +230,7 @@ class TestTrackerView:
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=sample_meal.id, meal_id=sample_meal.id,
meal_time="Breakfast", meal_time="Breakfast"
quantity=1.0
) )
db_session.add(tracked_meal) db_session.add(tracked_meal)
db_session.commit() db_session.commit()
@@ -260,8 +258,7 @@ class TestTrackerEdit:
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=sample_meal.id, meal_id=sample_meal.id,
meal_time="Breakfast", meal_time="Breakfast"
quantity=1.0
) )
db_session.add(tracked_meal) db_session.add(tracked_meal)
db_session.commit() db_session.commit()
@@ -283,7 +280,8 @@ class TestTrackerEdit:
# Update the food quantity via API # Update the food quantity via API
response = client.post("/tracker/update_tracked_food", json={ response = client.post("/tracker/update_tracked_food", json={
"tracked_food_id": tracked_food.id, "tracked_food_id": tracked_food.id,
"quantity": 3.0 "quantity": 3.0,
"is_custom": True
}) })
assert response.status_code == 200 assert response.status_code == 200
data = response.json() data = response.json()
@@ -311,8 +309,7 @@ class TestTrackerSaveAsNewMeal:
tracked_meal = TrackedMeal( tracked_meal = TrackedMeal(
tracked_day_id=tracked_day.id, tracked_day_id=tracked_day.id,
meal_id=sample_meal.id, meal_id=sample_meal.id,
meal_time="Breakfast", meal_time="Breakfast"
quantity=1.0
) )
db_session.add(tracked_meal) db_session.add(tracked_meal)
db_session.commit() db_session.commit()
@@ -388,7 +385,6 @@ class TestTrackerAddFood:
tracked_meal = tracked_meals[0] tracked_meal = tracked_meals[0]
assert tracked_meal.meal.name == sample_food.name # The meal name should be the food name assert tracked_meal.meal.name == sample_food.name # The meal name should be the food name
assert tracked_meal.quantity == 1.0 # The meal quantity should be 1.0
# Verify the food is in the tracked meal's foods # Verify the food is in the tracked meal's foods
assert len(tracked_meal.meal.meal_foods) == 1 assert len(tracked_meal.meal.meal_foods) == 1
@@ -423,8 +419,44 @@ class TestTrackerAddFood:
tracked_meal = tracked_meals[0] tracked_meal = tracked_meals[0]
assert tracked_meal.meal.name == sample_food.name assert tracked_meal.meal.name == sample_food.name
assert tracked_meal.quantity == 1.0
assert len(tracked_meal.meal.meal_foods) == 1 assert len(tracked_meal.meal.meal_foods) == 1
assert tracked_meal.meal.meal_foods[0].food_id == sample_food.id assert tracked_meal.meal.meal_foods[0].food_id == sample_food.id
assert tracked_meal.meal.meal_foods[0].quantity == 150.0 assert tracked_meal.meal.meal_foods[0].quantity == 150.0
class TestTrackedMealQuantity:
"""Test the quantity of a tracked meal"""
def test_add_meal_quantity_is_one(self, client, sample_meal, db_session):
"""Test that when a meal is added to the tracker, its quantity is 1.0"""
test_date = date.today().isoformat()
response = client.post("/tracker/add_meal", data={
"person": "Sarah",
"date": test_date,
"meal_id": str(sample_meal.id),
"meal_time": "Breakfast"
})
assert response.status_code == 200
data = response.json()
assert data["status"] == "success"
tracked_meal = db_session.query(TrackedMeal).order_by(TrackedMeal.id.desc()).first()
assert tracked_meal is not None
def test_add_food_quantity_is_one(self, client, sample_food, db_session):
"""Test that when a single food is added to the tracker, the underlying meal quantity is 1.0"""
test_date = date.today().isoformat()
response = client.post("/tracker/add_food", json={
"person": "Sarah",
"date": test_date,
"food_id": sample_food.id,
"quantity": 100.0,
"meal_time": "Snack 1"
})
assert response.status_code == 200
data = response.json()
assert data["status"] == "success"
tracked_meal = db_session.query(TrackedMeal).order_by(TrackedMeal.id.desc()).first()
assert tracked_meal is not None