mirror of
https://github.com/StefBuwalda/cal_counter.git
synced 2025-10-30 03:10:00 +00:00
Refactored add_meal_v2 routes to simplify and clarify the meal addition process, including renaming endpoints and templates, and introducing decorators for date and item selection. Updated daily_log2 to use user's timezone and display the selected date. Adjusted templates and barcode scan logic to match new routes and improved user experience.
179 lines
5.0 KiB
Python
179 lines
5.0 KiB
Python
from flask import (
|
|
Blueprint,
|
|
redirect,
|
|
url_for,
|
|
render_template,
|
|
session,
|
|
request,
|
|
jsonify,
|
|
)
|
|
from flask_login import current_user
|
|
from forms import FoodItemForm, FoodLogForm
|
|
from application import db
|
|
from models import FoodItem, FoodLog
|
|
from sqlalchemy import and_, or_
|
|
from datetime import datetime
|
|
from sqlalchemy.sql.elements import BinaryExpression
|
|
from typing import cast
|
|
|
|
bp = Blueprint(
|
|
"add_meal_v2",
|
|
__name__,
|
|
url_prefix="/add_meal_v2",
|
|
template_folder="templates",
|
|
)
|
|
|
|
|
|
def date_present(func):
|
|
def check_date():
|
|
if "selected_date" not in session:
|
|
return redirect(url_for("user.daily_log2"))
|
|
|
|
|
|
def item_selected(func):
|
|
def check_item():
|
|
if check_item():
|
|
if "item_id" not in session:
|
|
return redirect(url_for("add_meal_v2.get_barcode"))
|
|
|
|
|
|
@bp.before_request
|
|
def login_required():
|
|
if not current_user.is_authenticated:
|
|
return redirect(url_for("auth.login"))
|
|
|
|
|
|
@date_present
|
|
@bp.route("/get_barcode", methods=["GET"])
|
|
def get_barcode():
|
|
return render_template("scan_barcode_v2.html")
|
|
|
|
|
|
@date_present
|
|
@bp.route("/add_existing/<string:input>", methods=["GET"])
|
|
def add_existing(input: str):
|
|
# Check if input is a barcode
|
|
if input.isdigit():
|
|
item = current_user.food_items.filter_by(barcode=input).first()
|
|
|
|
else:
|
|
item = current_user.food_items.filter_by(name=input).first()
|
|
|
|
if item is None:
|
|
# Does not exist, add item
|
|
return redirect(url_for("add_meal_v2.add_new", input=input))
|
|
|
|
# Track item to add and continue to next step
|
|
session["item_id"] = item.id
|
|
return redirect(url_for("add_meal_v2.step4"))
|
|
|
|
|
|
@date_present
|
|
@bp.route("/add_new/<string:input>", methods=["GET"])
|
|
def add_new(input: str):
|
|
form = FoodItemForm()
|
|
|
|
if input.isdigit():
|
|
form.barcode.data = input
|
|
else:
|
|
form.name.data = input
|
|
return render_template("add_item.html", form=form)
|
|
|
|
|
|
@date_present
|
|
@bp.route("/add_new/<string:input>", methods=["POST"])
|
|
def add_new_post(input: str):
|
|
form = FoodItemForm()
|
|
|
|
if form.validate_on_submit():
|
|
# Form has valid input
|
|
barcode = form.barcode.data
|
|
name = form.name.data
|
|
assert name
|
|
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
|
|
|
|
# Check if name or barcode already exists
|
|
name_filter = cast(BinaryExpression, FoodItem.name == name)
|
|
barcode_filter = cast(BinaryExpression, FoodItem.barcode == barcode)
|
|
filter_exp = or_(name_filter, barcode_filter)
|
|
item = current_user.food_items.filter(filter_exp).first()
|
|
|
|
if item is None:
|
|
# Item does not exist, add to DB
|
|
barcode = (
|
|
barcode if barcode else None
|
|
) # Turn empty strings into None
|
|
db.session.add(
|
|
FoodItem(
|
|
name=name,
|
|
owner_id=current_user.id,
|
|
energy=form.energy.data,
|
|
protein=form.protein.data,
|
|
carbs=form.carbs.data,
|
|
fat=form.fat.data,
|
|
barcode=barcode,
|
|
saturated_fat=form.saturated_fat.data,
|
|
sugar=form.sugar.data,
|
|
)
|
|
)
|
|
db.session.commit()
|
|
print("[DEBUG] New FoodItem Added")
|
|
input = barcode if barcode else name # update input
|
|
else:
|
|
print(f"Item exists: {item.barcode} {item.name}")
|
|
|
|
# Item added or already present, return to step 3.
|
|
return redirect(url_for("add_meal_v2.step3", input=input))
|
|
else:
|
|
print("[DEBUG] Form Invalid")
|
|
return redirect(url_for("add_meal_v2.step3_alt1", input=input))
|
|
|
|
|
|
@date_present
|
|
@item_selected
|
|
@bp.route("/step4", methods=["GET", "POST"])
|
|
def step4():
|
|
form = FoodLogForm()
|
|
item = db.session.get(FoodItem, session["item_id"])
|
|
if not item:
|
|
return redirect(url_for("add_meal_v2.get_barcode"))
|
|
|
|
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=0,
|
|
date_=datetime.strptime(
|
|
session["selected_date"], "%Y-%m-%d"
|
|
).date(),
|
|
)
|
|
)
|
|
db.session.commit()
|
|
session.pop("item_id")
|
|
session.pop("selected_date")
|
|
return redirect(url_for("user.daily_log2"))
|
|
|
|
return render_template("step4.html", tod="idk", item=item, form=form)
|
|
|
|
|
|
@date_present
|
|
@bp.route("/query", methods=["GET"])
|
|
def query():
|
|
q = request.args.get("q", "").strip().lower()
|
|
if not q:
|
|
return jsonify([])
|
|
|
|
words = q.split()
|
|
filters = [
|
|
FoodItem.name.ilike(f"%{word}%") for word in words # type: ignore
|
|
]
|
|
|
|
results = current_user.food_items.filter(and_(*filters)).all()
|
|
return jsonify([item.name for item in results])
|