HabitTracker/app.py
2024-01-26 11:17:09 +01:00

402 lines
10 KiB
Python

import datetime
import hashlib
from flask import Flask, render_template, redirect, url_for, request
from flask_login import login_required, LoginManager, login_user, logout_user, current_user
from models.Habit import Habit
from models.HabitTrackings import HabitTrackings
from models.User import User
from utils import anonymous_required
# Create a new Flask instance
app = Flask(__name__)
app.secret_key = 'PSSSSSHHHT!'
# Initialize the Flask-Login extension
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
@app.context_processor
def inject_user():
return dict(user=current_user)
@app.route('/login')
@anonymous_required
def login():
return render_template('auth/login.html', errors={})
@app.route('/signup')
@anonymous_required
def signup():
return render_template('auth/signup.html', errors={})
@app.route('/login', methods=['POST'])
def login_post():
email = request.form.get('email')
password = request.form.get('password')
# Check for errors
errors = {}
if not email:
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
if not password:
errors['password'] = 'Das Passwort ist erforderlich.'
# Check if user exists
user = User.get_by_email(email)
if not user:
errors['email'] = 'E-Mail Adresse nicht gefunden.'
elif user.password is None or hashlib.sha256(password.encode()).hexdigest() != user.password:
errors['password'] = 'Das Passwort ist falsch.'
if errors:
return render_template(
'auth/login.html',
email=email,
password=password,
errors=errors
)
login_user(user)
# Redirect to login page
return redirect(url_for('index'))
@app.route('/signup', methods=['POST'])
def signup_post():
email = request.form.get('email')
name = request.form.get('name')
password = request.form.get('password')
# Check for errors
errors = {}
if not email:
errors['email'] = 'Die E-Mail Adresse ist erforderlich.'
if not name:
errors['name'] = 'Der Name ist erforderlich.'
if not password:
errors['password'] = 'Das Passwort ist erforderlich.'
if errors:
return render_template(
'auth/signup.html',
email=email,
name=name,
password=password,
errors=errors
)
# Save user to database. Maybe log the user in directly.
user = User.create(name, email, password)
login_user(user)
# Redirect to login page
return redirect(url_for('index'))
@app.route('/logout')
@login_required
def logout():
# Log out functionality
logout_user()
return redirect(url_for('index'))
# Create a new route
@app.route('/')
def index():
if current_user.is_authenticated:
habits = current_user.get_habits()
name = "Hallo " + current_user.name
else:
habits = []
name = "Bitte melde dich an."
# old code
"""trackings = habit.get_habitTrackings()
for tracking in trackings:
# day
if habit.unit == 0:
if tracking.created_at.date() == datetime.date.today():
habit.checked = True
break
# week
elif habit.unit == 1:
if tracking.created_at.date().isocalendar()[1] == datetime.date.today().isocalendar()[1]:
habit.checked = True
break
# month
elif habit.unit == 2:
if tracking.created_at.date().month == datetime.date.today().month:
habit.checked = True
break
# year
elif habit.unit == 3:
if tracking.created_at.date().year == datetime.date.today().year:
habit.checked = True
break
else:
habit.checked = False"""
# Add checked attribute to habits (if they have been checked today)
for habit in habits:
trackings = habit.get_habitTrackings()
for tracking in trackings:
if tracking.created_at.date() == datetime.date.today():
habit.checked = True
break
else:
habit.checked = False
# Sort habits by whether they have been checked today and then by slot
habits.sort(key=lambda habit: (habit.checked, habit.slot))
return render_template(
'index.html',
title=name,
utc_dt=datetime.datetime.now().strftime("%d.%m.%Y %H:%M %A"),
habits=habits,
errors={},
)
@app.route('/habit')
@login_required
def habit_creation():
return render_template(
'habit.html',
title='Erstelle ein Habit',
unit="Woche",
errors={},
)
@app.route('/habit', methods=['POST'])
@login_required
def habit_create():
name = request.form.get('name')
note = request.form.get('note')
times = request.form.get('times')
unit = request.form.get('unit')
# Check for errors
errors = {}
if not name:
errors['name'] = 'Der Name ist erforderlich.'
if not times:
errors['times'] = 'Die Anzahl ist erforderlich.'
if not note:
note = ''
if not unit:
errors['unit'] = 'Die Einheit ist erforderlich.'
# Check if times is an integer
try:
times = int(times)
# Check that times is greater than 0
if times <= 0:
errors['times'] = 'Die Anzahl muss größer als 0 sein.'
except ValueError:
errors['times'] = 'Die Anzahl muss eine Zahl sein.'
# Check that unit is valid
if unit not in ['Tag', 'Woche', 'Monat', 'Jahr']:
errors['unit'] = 'Die Einheit ist ungültig.'
if errors:
return render_template(
'habit.html',
title='Erstelle ein Habit',
name=name,
note=note,
times=times,
unit=unit,
errors=errors
)
# Map unit to integer
if unit == 'Tag':
unit = 0
elif unit == 'Woche':
unit = 1
elif unit == 'Monat':
unit = 2
elif unit == 'Jahr':
unit = 3
else:
unit = 1
# Save habit to database
habit = Habit.create(current_user.id, name, times, note, unit)
# Back to index
return redirect(url_for('index'))
"""return render_template(
'habit.html',
title='Erstelle ein Habit',
name=name,
note=note,
times=times,
unit=unit,
errors=errors,
)"""
@app.route('/profile')
@login_required
def profile():
return render_template(
"profile.html",
name=current_user.name,
email=current_user.email,
errors={}
)
@app.route('/profile', methods=['POST'])
@login_required
def profile_change():
newName = request.form.get('newName')
newEmail = request.form.get('newEmail')
newPassword = request.form.get('newPassword')
oldPassword = request.form.get('oldPassword')
# Check for errors
errors = {}
if not newName:
errors['newName'] = 'Der Name ist erforderlich.'
if not newEmail:
errors['newEmail'] = 'Die E-Mail Adresse ist erforderlich.'
if not oldPassword:
errors['oldPassword'] = 'Du musst dein aktuelles Passwort angeben.'
else:
if hashlib.sha256(oldPassword.encode()).hexdigest() != current_user.password:
errors['oldPassword'] = 'Das Passwort ist falsch.'
if errors:
return render_template(
"profile.html",
name=current_user.name,
email=current_user.email,
errors=errors
)
# Update user
current_user.name = newName
current_user.email = newEmail
if newPassword:
current_user.password = hashlib.sha256(newPassword.encode()).hexdigest()
current_user.update()
# Back to profile
return render_template(
"profile.html",
name=current_user.name,
email=current_user.email,
errors={}
)
@app.route('/check', methods=['POST'])
@login_required
def check_habit():
habit_id = request.get_json()["habitId"]
habit = Habit.get(habit_id)
if habit is None:
return {"error": "Habit not found"}
# Check if habit belongs to user
if habit.user_id != current_user.id:
return {"error": "Habit does not belong to user"}
trackings = habit.get_habitTrackings()
# Check if habit has been tracked today
"""delete_tracking = None
for tracking in trackings:
# day
if habit.unit == 0:
if tracking.created_at.date() == datetime.date.today():
delete_tracking = tracking
break
# week
elif habit.unit == 1:
if tracking.created_at.date().isocalendar()[1] == datetime.date.today().isocalendar()[1]:
delete_tracking = tracking
break
# month
elif habit.unit == 2:
if tracking.created_at.date().month == datetime.date.today().month:
delete_tracking = tracking
break
# year
elif habit.unit == 3:
if tracking.created_at.date().year == datetime.date.today().year:
delete_tracking = tracking
break
if not delete_tracking:
HabitTrackings.create(habit_id, 1)
else:
delete_tracking.delete()"""
delete_tracking = None
for tracking in trackings:
if tracking.created_at.date() == datetime.date.today():
delete_tracking = tracking
break
if not delete_tracking:
HabitTrackings.create(habit_id, 1)
else:
delete_tracking.delete()
return {
"habitId": habit_id,
"unchecked": not delete_tracking
}
@app.route('/delete', methods=['POST'])
@login_required
def delete_habit():
habit_id = request.get_json()["habitId"]
habit = Habit.get(habit_id)
if habit is None:
return {"error": "Habit not found"}
# Check if habit belongs to user
if habit.user_id != current_user.id:
return {"error": "Habit does not belong to user"}
habit.delete()
return {}
# Run the application
if __name__ == '__main__':
app.run(port=5000, debug=True)