diff --git a/app.py b/app.py index 93d892b..b57b369 100644 --- a/app.py +++ b/app.py @@ -10,6 +10,7 @@ from models import User from application import db, app, login_manager from application.admin.routes import admin_bp from application.user.routes import user_bp +from application.add_meal.routes import bp as add_meal_bp from typing import Optional # Config @@ -26,6 +27,7 @@ def load_user(user_id: int): # Register blueprints app.register_blueprint(admin_bp) app.register_blueprint(user_bp) +app.register_blueprint(add_meal_bp) # Routes diff --git a/application/add_meal/routes.py b/application/add_meal/routes.py new file mode 100644 index 0000000..2af491c --- /dev/null +++ b/application/add_meal/routes.py @@ -0,0 +1,131 @@ +from flask import ( + Blueprint, + redirect, + url_for, + render_template, + session, +) +from flask_login import current_user +from forms import FoodItemForm, FoodLogForm +from application import db +from models import FoodItem, FoodLog + +bp = Blueprint( + "add_meal", + __name__, + url_prefix="/add_meal", + template_folder="templates", +) + + +@bp.before_request +def login_required(): + if not current_user.is_authenticated: + return redirect(url_for("login")) + + +@bp.route("/select_meal/", methods=["GET"]) +def step1(meal_type: int): + assert type(meal_type) is int + assert 0 <= meal_type <= 3 + session["meal_type"] = meal_type + return redirect(url_for("add_meal.step2")) + + +@bp.route("/get_barcode", methods=["GET"]) +def step2(): + return render_template("scan_barcode.html") + + +@bp.route("/step3/", methods=["GET"]) +def step3(barcode: str): + if "meal_type" not in session: + return redirect("/") + assert barcode.isdigit() + item = current_user.food_items.filter_by(barcode=barcode).first() + if item is None: + # Does not exist, add item + return redirect(url_for("add_meal.step3_alt1", barcode=barcode)) + else: + session["item_id"] = item.id + return redirect(url_for("add_meal.step4")) + + +@bp.route("/step3_alt1/", methods=["GET", "POST"]) +def step3_alt1(barcode: str): + form = FoodItemForm() + if form.validate_on_submit(): + print("[DEBUG] Valid form") + if ( + current_user.food_items.filter_by( + barcode=form.barcode.data + ).first() + is None + ): + assert form.name.data is not None + assert form.energy.data is not None + assert form.protein.data is not None + assert form.carbs.data is not None + assert form.fat.data is not None + assert form.barcode.data is not None + db.session.add( + FoodItem( + name=form.name.data, + owner_id=current_user.id, + energy=form.energy.data, + protein=form.protein.data, + carbs=form.carbs.data, + fat=form.fat.data, + barcode=( + form.barcode.data + if form.barcode.data.isdigit() + else None + ), + saturated_fat=form.saturated_fat.data, + sugar=form.sugar.data, + ) + ) + db.session.commit() + print("[DEBUG] New item added") + return redirect(url_for("add_meal.step3", barcode=form.barcode.data)) + print("[DEBUG] Invalid form") + if barcode.isdigit(): + form.barcode.data = barcode + return render_template("add_item.html", form=form) + + +@bp.route("/step4", methods=["GET", "POST"]) +def step4(): + if "item_id" not in session: + return redirect(url_for("add_meal.step2")) + form = FoodLogForm() + item = db.session.get(FoodItem, session["item_id"]) + + assert item + if form.validate_on_submit(): + assert form.amount.data + db.session.add( + FoodLog( + food_item_id=item.id, + user_id=current_user.id, + amount=form.amount.data, + part_of_day=session["meal_type"], + ) + ) + db.session.commit() + session.pop("meal_type") + session.pop("item_id") + return redirect("/") + + match session["meal_type"]: + case 0: + tod = "Breakfast" + case 1: + tod = "Lunch" + case 2: + tod = "Dinner" + case 3: + tod = "Snack" + case _: + tod = "Unknown" + return render_template("step4.html", tod=tod, item=item, form=form) diff --git a/application/add_meal/templates/add_item.html b/application/add_meal/templates/add_item.html new file mode 100644 index 0000000..04b77bc --- /dev/null +++ b/application/add_meal/templates/add_item.html @@ -0,0 +1,49 @@ +{% extends "base.html" %} + +{% block content %} +
+ {{ form.hidden_tag() }} + +
+ {{ form.barcode.label(class="form-label") }} + {{ form.barcode(class="form-control-plaintext", readonly=true) }} +
+ +
+ {{ form.name.label(class="form-label") }} + {{ form.name(class="form-control") }} +
+ +
+ {{ form.energy.label(class="form-label") }} + {{ form.energy(class="form-control") }} +
+ +
+ {{ form.protein.label(class="form-label") }} + {{ form.protein(class="form-control") }} +
+ +
+ {{ form.carbs.label(class="form-label") }} + {{ form.carbs(class="form-control") }} +
+ +
+ {{ form.sugar.label(class="form-label") }} + {{ form.sugar(class="form-control") }} +
+ +
+ {{ form.fat.label(class="form-label") }} + {{ form.fat(class="form-control") }} +
+ +
+ {{ form.saturated_fat.label(class="form-label") }} + {{ form.saturated_fat(class="form-control") }} +
+ + {{ form.submit(class="btn btn-primary") }} +
+{% endblock%} \ No newline at end of file diff --git a/application/add_meal/templates/scan_barcode.html b/application/add_meal/templates/scan_barcode.html new file mode 100644 index 0000000..a62dfd9 --- /dev/null +++ b/application/add_meal/templates/scan_barcode.html @@ -0,0 +1,62 @@ +{% extends "base.html" %} + +{% block content %} +
+
+

Barcode Scanner

+

Use your camera to scan barcodes

+
+ +
+ +
+ +
+ + +
+
+ + + +{% endblock %} \ No newline at end of file diff --git a/application/add_meal/templates/step4.html b/application/add_meal/templates/step4.html new file mode 100644 index 0000000..85cd332 --- /dev/null +++ b/application/add_meal/templates/step4.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% block content %} +

{{ tod }}

+

{{ item.name }}

+ +
+ {{ form.hidden_tag() }} + +
+
+ {{item_id}} +
+
+ +
+ {{ form.amount.label(class="form-label") }} + {{ form.amount(class="form-control") }} +
+ + {{ form.submit(class="btn btn-primary") }} +
+{% endblock%} \ No newline at end of file diff --git a/application/user/routes.py b/application/user/routes.py index b376641..f980988 100644 --- a/application/user/routes.py +++ b/application/user/routes.py @@ -47,21 +47,10 @@ def delete_food_item(id: int): return redirect(url_for("user.dashboard")) -fields = [ - "barcode", - "name", - "energy", - "protein", - "carbs", - "sugar", - "fat", - "saturated_fat", -] - - @user_bp.route("/add_food_item/", methods=["GET", "POST"]) def add_food_item(barcode): form = FoodItemForm(barcode=barcode) + print(form) if form.validate_on_submit(): print("[DEBUG] Valid form") @@ -92,6 +81,7 @@ def add_food_item(barcode): else: print("[DEBUG] Invalid form") if form.barcode.data: + print("1") return render_template("add_food_item.html", form=form) else: return redirect("/") @@ -217,7 +207,7 @@ def add_meal(): @user_bp.route("/", methods=["GET"]) -def test(): +def daily_log(): today = datetime.now(timezone.utc).date() logs_today = current_user.food_logs.filter_by(date_=today).all() logs = [[], [], [], []] @@ -225,7 +215,7 @@ def test(): logs[log.part_of_day].append(log) print(logs) return render_template( - "test.html", date=(today.strftime("%d/%m/%y")), logs=logs + "daily_log.html", date=(today.strftime("%d/%m/%y")), logs=logs ) diff --git a/application/user/templates/test.html b/application/user/templates/daily_log.html similarity index 70% rename from application/user/templates/test.html rename to application/user/templates/daily_log.html index 2b26b5c..6769d6a 100644 --- a/application/user/templates/test.html +++ b/application/user/templates/daily_log.html @@ -25,11 +25,11 @@ Food Nutritional Info

Breakfast

- Add + Add
{% for log in logs[0] %} -

{{log.food_item.name}}

+

{{log.food_item.name}} - {{log.amount}}

{% endfor %}
@@ -37,33 +37,33 @@ Food Nutritional Info

Lunch

- Add + Add
{% for log in logs[1] %} -

{{log.food_item.name}}

+

{{log.food_item.name}} - {{log.amount}}

{% endfor %}

Dinner

- Add + Add
{% for log in logs[2] %} -

{{log.food_item.name}}

+

{{log.food_item.name}} - {{log.amount}}

{% endfor %}

Snacks

- Add + Add
{% for log in logs[3] %} -

{{log.food_item.name}}

+

{{log.food_item.name}} - {{log.amount}}

{% endfor %}
diff --git a/application/user/templates/get_item.html b/application/user/templates/get_item.html index 51d3b9a..6fac4cf 100644 --- a/application/user/templates/get_item.html +++ b/application/user/templates/get_item.html @@ -55,7 +55,7 @@ if (!response.ok) { throw new Error('Network response was not OK'); } - return response.json(); // or response.text(), response.blob(), etc. + return response.json(); }) .then(data => { const baseURL2 = "{{url_for('user.select_item', item_id='0')}}" diff --git a/forms.py b/forms.py index 7dcd4f4..f5781eb 100644 --- a/forms.py +++ b/forms.py @@ -16,17 +16,19 @@ class LoginForm(FlaskForm): class FoodItemForm(FlaskForm): - barcode = StringField("Barcode", validators=[Optional()]) + barcode = StringField("Barcode", validators=[InputRequired()]) name = StringField("Product Name", validators=[DataRequired()]) energy = IntegerField("Energy per 100g", validators=[InputRequired()]) protein = FloatField("protein per 100g", validators=[InputRequired()]) carbs = FloatField("carbs per 100g", validators=[InputRequired()]) sugar = FloatField("sugar per 100g", validators=[Optional()]) fat = FloatField("fat per 100g", validators=[InputRequired()]) - saturated_fat = FloatField("saturated_fat per 100g") + saturated_fat = FloatField( + "saturated_fat per 100g", validators=[Optional()] + ) submit = SubmitField("Add Item") class FoodLogForm(FlaskForm): - amount = IntegerField("amount of food (g/ml)") + amount = FloatField("amount of food (g/ml)", validators=[DataRequired()]) submit = SubmitField("Log Item") diff --git a/models.py b/models.py index cb5292b..d3b7500 100644 --- a/models.py +++ b/models.py @@ -120,13 +120,13 @@ class FoodLog(db.Model): ) part_of_day = db.Column(db.Integer, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) - amount = db.Column(db.Integer, nullable=False) + amount = db.Column(db.Float, nullable=False) def __init__( self, food_item_id: int, user_id: int, - amount: int, + amount: float, part_of_day: int, date_: Optional[date] = None, ):