summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/routes/__init__.py4
-rw-r--r--app/routes/api.py17
-rw-r--r--app/routes/basic.py12
-rw-r--r--app/routes/user.py53
-rw-r--r--app/routes/workout.py (renamed from app/routes.py)73
-rw-r--r--app/static/js/record.js74
-rw-r--r--app/templates/base/form.html2
-rw-r--r--app/templates/base/layout.html2
-rw-r--r--app/templates/home.html2
-rw-r--r--app/templates/workout/record.html73
-rw-r--r--app/templates/workout/select.html23
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 %}