From a39f54dbb0dc0a8b23a64a92d393f8788ef6051a Mon Sep 17 00:00:00 2001 From: Stef Date: Sun, 29 Jun 2025 08:39:25 +0200 Subject: [PATCH] Add food item management and improve barcode workflow Implemented routes and forms for adding and viewing food items by barcode, including templates for displaying and entering nutritional information. Enhanced the scan workflow to redirect to food item details or entry form. Added admin ability to delete food items. Improved UI for login and scan pages. Updated FoodItem model and form fields for consistency and accuracy. --- app.py | 66 +++++++++++++++- application/admin/routes.py | 12 ++- application/admin/templates/food_items.html | 7 ++ application/templates/add_food_item.html | 49 ++++++++++++ application/templates/base.html | 8 +- application/templates/food_item.html | 44 +++++++++++ application/templates/login.html | 38 ++++++++-- application/templates/scan.html | 84 +++++---------------- forms.py | 22 +++++- models.py | 20 ++--- 10 files changed, 260 insertions(+), 90 deletions(-) create mode 100644 application/templates/add_food_item.html create mode 100644 application/templates/food_item.html diff --git a/app.py b/app.py index 359383d..ab86701 100644 --- a/app.py +++ b/app.py @@ -5,10 +5,11 @@ from flask_login import ( login_user, current_user, ) -from forms import LoginForm +from forms import LoginForm, FoodItemForm from models import User, FoodItem from application import db, app, login_manager from application.admin.routes import admin_bp +from typing import Optional # Config app.config["SECRET_KEY"] = "Iman" @@ -28,7 +29,16 @@ app.register_blueprint(admin_bp) # Routes +def default_return(next_page: Optional[str] = None): + if next_page: + return redirect(next_page) + if current_user.is_admin: + return redirect(url_for("admin.food_items")) + return redirect(url_for("dashboard")) + + @app.route("/") +@login_required def index(): return render_template("index.html") @@ -36,7 +46,7 @@ def index(): @app.route("/login", methods=["GET", "POST"]) def login(): if current_user.is_authenticated: - return redirect(url_for("dashboard")) + return default_return() form = LoginForm() if form.validate_on_submit(): @@ -45,7 +55,7 @@ def login(): # User found and password correct next_page = request.args.get("next") # Get next page if given login_user(user) # Log in the user - return redirect(next_page or url_for("dashboard")) + return default_return(next_page=next_page) else: pass # invalid user @@ -81,6 +91,56 @@ def nutri(barcode): return jsonify({}) +@app.route("/food_item/", methods=["GET"]) +@login_required +def food_item(barcode): + food = FoodItem.query.filter_by(barcode=barcode).first() + if food: + return render_template("food_item.html", item=food) + else: + return render_template( + "add_food_item.html", + barcode=barcode, + form=FoodItemForm(barcode=barcode), + ) + + +@app.route("/add_food_item", methods=["POST"]) +@login_required +def add_food_item(): + form = FoodItemForm() + + if form.validate_on_submit(): + print("[DEBUG] Valid form") + if FoodItem.query.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, + energy=form.energy.data, + protein=form.protein.data, + carbs=form.carbs.data, + fats=form.fat.data, + barcode=form.barcode.data, + saturated_fats=form.saturated_fat.data, + sugar=form.sugar.data, + ) + ) + db.session.commit() + print("[DEBUG] New item added") + else: + print("[DEBUG] Invalid form") + if form.barcode.data: + return redirect(url_for("food_item", barcode=form.barcode.data)) + else: + return redirect(url_for("scan")) + + # Run if __name__ == "__main__": diff --git a/application/admin/routes.py b/application/admin/routes.py index 8b0a855..47bb3f1 100644 --- a/application/admin/routes.py +++ b/application/admin/routes.py @@ -1,6 +1,7 @@ -from flask import Blueprint, render_template, abort +from flask import Blueprint, render_template, abort, redirect, url_for from flask_login import current_user from models import FoodItem +from application import db admin_bp = Blueprint( "admin", @@ -25,3 +26,12 @@ def food_items(): @admin_bp.route("/barcode_test", methods=["GET"]) def barcode_test(): return render_template("barcode_test.html") + + +@admin_bp.route("/delete_food/", methods=["POST"]) +def delete_food(id): + item = FoodItem.query.get(id) + if item: + db.session.delete(item) + db.session.commit() + return redirect(url_for("admin.food_items")) diff --git a/application/admin/templates/food_items.html b/application/admin/templates/food_items.html index 852e825..b3a240f 100644 --- a/application/admin/templates/food_items.html +++ b/application/admin/templates/food_items.html @@ -18,6 +18,7 @@ Food Nutritional Info Sugars (g) Carbs (g) Protein (g) + Actions @@ -30,6 +31,12 @@ Food Nutritional Info {{ food.sugar_100g }} {{ food.carbs_100g }} {{ food.protein_100g }} + +
+ +
+ {% endfor %} diff --git a/application/templates/add_food_item.html b/application/templates/add_food_item.html new file mode 100644 index 0000000..c00b17d --- /dev/null +++ b/application/templates/add_food_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", readonly=true, style="background-color: #e9ecef; cursor: not-allowed;") }} +
+ +
+ {{ 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/templates/base.html b/application/templates/base.html index b4cecc9..72b110e 100644 --- a/application/templates/base.html +++ b/application/templates/base.html @@ -10,7 +10,7 @@ - +