diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/routes/__init__.py | 4 | ||||
| -rw-r--r-- | app/routes/api.py | 17 | ||||
| -rw-r--r-- | app/routes/basic.py | 12 | ||||
| -rw-r--r-- | app/routes/user.py | 53 | ||||
| -rw-r--r-- | app/routes/workout.py (renamed from app/routes.py) | 73 | ||||
| -rw-r--r-- | app/static/js/record.js | 74 | ||||
| -rw-r--r-- | app/templates/base/form.html | 2 | ||||
| -rw-r--r-- | app/templates/base/layout.html | 2 | ||||
| -rw-r--r-- | app/templates/home.html | 2 | ||||
| -rw-r--r-- | app/templates/workout/record.html | 73 | ||||
| -rw-r--r-- | app/templates/workout/select.html | 23 |
11 files changed, 244 insertions, 91 deletions
diff --git a/app/routes/__init__.py b/app/routes/__init__.py new file mode 100644 index 0000000..09fcbf3 --- /dev/null +++ b/app/routes/__init__.py @@ -0,0 +1,4 @@ +from routes.api import * +from routes.user import * +from routes.workout import * +from routes.basic import * diff --git a/app/routes/api.py b/app/routes/api.py new file mode 100644 index 0000000..58b4732 --- /dev/null +++ b/app/routes/api.py @@ -0,0 +1,17 @@ +from app import app, db +from flask import redirect, request +from flask_login import current_user, login_required +from tables import Workout + +@app.route("/api/workout/delete", methods=['GET']) +@login_required +def api_workout_delete(): + if 'id' not in request.args: + return redirect('/home'); + + workout = Workout.query.filter_by(id=int(request.args['id']), user_id=current_user.id).first() + if workout: + db.session.delete(workout) + db.session.commit() + + return redirect('/home') diff --git a/app/routes/basic.py b/app/routes/basic.py new file mode 100644 index 0000000..5883b97 --- /dev/null +++ b/app/routes/basic.py @@ -0,0 +1,12 @@ +from app import app, db +from flask import render_template +from flask_login import login_required + +@app.route("/", methods=["GET"]) +def index(): + return render_template('index.html') + +@app.route("/home", methods=["GET"]) +@login_required +def home(): + return render_template('home.html') diff --git a/app/routes/user.py b/app/routes/user.py new file mode 100644 index 0000000..d218738 --- /dev/null +++ b/app/routes/user.py @@ -0,0 +1,53 @@ +from app import app, db +from flask import render_template, redirect, request, url_for, flash +from flask_login import current_user, login_user, login_required, logout_user +from forms import LoginForm, RegisterForm +from tables import User + +@app.route("/login", methods=['GET', 'POST']) +def login(): + form = LoginForm() + username = form.username.data + password = form.password.data + + if form.validate_on_submit(): + # Valid submission + user = User.query.filter_by(username=username).first() + + # TODO: show user if login succeeded + if user and user.verify_password(password): + login_user(user) + return redirect(url_for('home')) + else: + flash("Invalid username or password", "danger") + + return render_template('user/login.html', form=form) + +@app.route("/logout", methods=['GET', 'POST']) +@login_required +def logout(): + logout_user() + return redirect('/') + +@app.route("/register", methods=['GET', 'POST']) +def register(): + form = RegisterForm() + # Load data from form + username = form.username.data + password = form.password.data + email = form.email.data + + if form.validate_on_submit(): + # Valid submission + user = User.query.filter_by(username=username).first() + if not user: + # No user with this username + user = User(username, password, email) + db.session.add(user) + db.session.commit() + return redirect(url_for('login')) + else: + flash("User already exists", "danger") + + return render_template('user/register.html', form=form) + diff --git a/app/routes.py b/app/routes/workout.py index 7ee3986..8615156 100644 --- a/app/routes.py +++ b/app/routes/workout.py @@ -1,64 +1,9 @@ from app import app, db from flask import render_template, redirect, request, url_for, flash -from flask_login import current_user, login_user, login_required, logout_user +from flask_login import current_user, login_required from forms import LoginForm, RegisterForm, WorkoutCreateForm from tables import User, Workout -@app.route("/", methods=["GET"]) -def index(): - return render_template('index.html') - -@app.route("/home", methods=["GET"]) -@login_required -def home(): - return render_template('home.html') - -@app.route("/login", methods=['GET', 'POST']) -def login(): - form = LoginForm() - username = form.username.data - password = form.password.data - - if form.validate_on_submit(): - # Valid submission - user = User.query.filter_by(username=username).first() - - # TODO: show user if login succeeded - if user and user.verify_password(password): - login_user(user) - return redirect(url_for('home')) - else: - flash("Invalid username or password", "danger") - - return render_template('user/login.html', form=form) - -@app.route("/logout", methods=['GET', 'POST']) -def logout(): - logout_user() - return redirect('/') - -@app.route("/register", methods=['GET', 'POST']) -def register(): - form = RegisterForm() - # Load data from form - username = form.username.data - password = form.password.data - email = form.email.data - - if form.validate_on_submit(): - # Valid submission - user = User.query.filter_by(username=username).first() - if not user: - # No user with this username - user = User(username, password, email) - db.session.add(user) - db.session.commit() - return redirect(url_for('login')) - else: - flash("User already exists", "danger") - - return render_template('user/register.html', form=form) - @app.route("/workout/create", methods=['GET', 'POST']) @login_required def createWorkout(): @@ -115,4 +60,18 @@ def editWorkout(): @app.route("/workout/record", methods=['GET']) @login_required def recordWorkout(): - return render_template('workout/record.html') + # Id is required + if 'id' not in request.args: + return redirect(url_for('home')) + + # Matching workout required + workout = Workout.query.filter_by(id=int(request.args['id']), user_id=current_user.id).first() + if not workout: + return redirect(url_for('home')); + + return render_template('workout/record.html', workout=workout, form=None) + +@app.route("/workout/select", methods=['GET']) +@login_required +def selectWorkout(): + return render_template('workout/select.html') diff --git a/app/static/js/record.js b/app/static/js/record.js new file mode 100644 index 0000000..aba6785 --- /dev/null +++ b/app/static/js/record.js @@ -0,0 +1,74 @@ + +// Register 'Enter' listeners on all inputs +Array.from(document.getElementsByClassName('input')) + .filter(e => e.type == 'number') + .forEach(e => e.addEventListener('keyup', function(event) { + if (event.key == 'Enter') { + // TODO implement + console.log("ENTER") + } + })) + +function setReset(row, values=true) { + let lbsInput = row.children[1].children[0]; + let repsInput = row.children[2].children[0]; + let doneButton = row.children[3].children[0]; + + // Enable inputs + lbsInput.disabled = false; + repsInput.disabled = false; + + // Remove classes + lbsInput.classList.remove('is-success'); + lbsInput.classList.remove('is-danger'); + repsInput.classList.remove('is-success'); + repsInput.classList.remove('is-danger'); + + doneButton.classList.remove('is-success'); + + if (values) { + lbsInput.value = ''; + repsInput.value = ''; + } +} + +function setSetid(row, id) { + let setNumber = row.children[0]; + let lbsInput = row.children[1].children[0]; + let repsInput = row.children[2].children[0]; + let doneButton = row.children[3].children[0]; + + setNumber.textContent = id + 1; +} + +function setCheck(row) { + // Disable input editing + row.children[1].firstChild.disabled = true; + row.children[2].firstChild.disabled = true; + + // Add is-success to inputs + row.children[1].firstChild.classList.add('is-success') + row.children[2].firstChild.classList.add('is-success') +} + +// Called when the check at the end of a set line is clicked +function onClickSetCheck(elem) { + if (elem.classList.contains('is-success')) { + setReset(elem.parentElement.parentElement, false); + } else { + elem.classList.add('is-success'); + + setCheck(elem.parentElement.parentElement); + } +} + +function onClickAddSet(elem) { + // Create the new row + let tableBody = elem.parentElement.parentElement.children[1].children[1]; + let row = tableBody.children[0].cloneNode(true); + + // Add new row to table + setReset(row); + setSetid(row, tableBody.children.length) + tableBody.appendChild(row) +} diff --git a/app/templates/base/form.html b/app/templates/base/form.html index 72083ae..9f356e0 100644 --- a/app/templates/base/form.html +++ b/app/templates/base/form.html @@ -4,7 +4,7 @@ <div class="container"> <div class="columns is-centered"> <div class="column {{ column_classes }}"> - <h1 class="title is-2">{{ title }}</h1> + <h1 class="title is-2">{% block title %}{% endblock %}</h1> <!-- TODO: render errors --> {% with messages = get_flashed_messages(with_categories=true) %} diff --git a/app/templates/base/layout.html b/app/templates/base/layout.html index 89ad385..fe83440 100644 --- a/app/templates/base/layout.html +++ b/app/templates/base/layout.html @@ -47,7 +47,7 @@ </span> <span class="navbar-item"> - <a class="button is-white is-outlined" href="/workout/record"> + <a class="button is-white is-outlined" href="/workout/select"> <span class="icon"> <i class="fa fa-pencil"></i> </span> diff --git a/app/templates/home.html b/app/templates/home.html index 9f8dfe9..c9aa90d 100644 --- a/app/templates/home.html +++ b/app/templates/home.html @@ -79,7 +79,7 @@ </p> </section> <footer class="modal-card-foot"> - <button class="button is-danger">Confirm</button> + <a href="/api/workout/delete?id={{ workout.id }}" class="button is-danger">Confirm</a> <button class="button">Cancel</button> </footer> </div> diff --git a/app/templates/workout/record.html b/app/templates/workout/record.html index 1a544fc..94fe611 100644 --- a/app/templates/workout/record.html +++ b/app/templates/workout/record.html @@ -1,37 +1,48 @@ -{% extends 'base/layout.html' %} +{% extends 'base/form.html' %} -{% block content %} +{% block title %}Record {{ workout.name }}{% endblock %} -<div class="continer"> - <div class="columns is-centered"> - <div class="column"> - <h1 class="title is-2">Leg Day</h1> - <div class="box"> - <div class="tabs is-fullwidth"> - <ul> - <li> - <a> - <span class="icon"><i class="fas fa-angle-left" aria-hidden="true"></i></span> - <span>Left</span> - </a> - </li> - <li> - <a> - <span class="icon"><i class="fas fa-angle-up" aria-hidden="true"></i></span> - <span>Up</span> - </a> - </li> - <li> - <a> - <span>Right</span> - <span class="icon"><i class="fas fa-angle-right" aria-hidden="true"></i></span> - </a> - </li> - </ul> - </div> - </div> - </div> +{% block form %} +{% for exercise in workout.exercises %} +<div> + <h1 id="{{ exercise.name }}" class="title is-4 has-text-black">{{ exercise.name }}</h1> + <table class="table is-fullwidth is-hoverable"> + <thead> + <th>Set</th> + <th>lbs</th> + <th>Reps</th> + <th>Done</th> + </thead> + <tbody> + {% for i in range(exercise.sets) %} + <tr> + <th>{{ i + 1 }}</th> + <td><input class="input" type="number"></td> + <td><input class="input" type="number"></td> + <td> + <a class="button" onClick="onClickSetCheck(this)"> + <span class="icon is-small"> + <i class="fa fa-check"></i> + </span> + </a> + </td> + </tr> + {% endfor %} + </tbody> + </table> + <div class="buttons is-centered"> + <a class="button is-primary" onClick="onClickAddSet(this)"> + <span class="icon is-small"> + <i class="fa fa-plus"></i> + </span> + <span>Add Set</span> + </a> + <a class="button is-danger">Skip</a> </div> + <hr> </div> +{% endfor %} + +<script async type="text/javascript" src="/static/js/record.js"></script> {% endblock %} diff --git a/app/templates/workout/select.html b/app/templates/workout/select.html new file mode 100644 index 0000000..c01a4f8 --- /dev/null +++ b/app/templates/workout/select.html @@ -0,0 +1,23 @@ +{% extends 'base/layout.html' %} + +{% block content %} +<div class="continer"> + <div class="columns is-centered"> + {% for workout in current_user.workouts %} + <div class="column"> + <div class="card"> + <header class="card-header"> + <p class="card-header-title"> {{ workout.name }}</p> + </header> + <div class="card-content"> + <div class="content"> + <a class="button" href="/workout/record?id={{ workout.id }}">Start</a> + </div> + </div> + </div> + </div> + {% endfor %} + </div> +</div> + +{% endblock %} |
