Make calendar month view default when viewing a persons workout and display workouts for month view (year view remaining)

This commit is contained in:
Peter Stockings
2022-12-03 16:57:35 +11:00
parent 3921b22ed3
commit aed610d8b6
4 changed files with 43 additions and 294 deletions

25
app.py
View File

@@ -1,4 +1,5 @@
from datetime import datetime, date, timedelta from datetime import datetime, date, timedelta
import calendar
import os import os
from flask import Flask, render_template, redirect, request, url_for from flask import Flask, render_template, redirect, request, url_for
import jinja_partials import jinja_partials
@@ -31,7 +32,7 @@ def get_person_list():
return render_template('partials/people_link.html', people=people) return render_template('partials/people_link.html', people=people)
@ app.route("/person/<int:person_id>") @ app.route("/person/<int:person_id>/workout/list", methods=['GET'])
@ validate_person @ validate_person
def get_person(person_id): def get_person(person_id):
person = db.get_person(person_id) person = db.get_person(person_id)
@@ -70,15 +71,31 @@ def get_calendar(person_id):
'date'), '%Y-%m-%d') or date.today() 'date'), '%Y-%m-%d') or date.today()
selected_view = request.args.get('view') or 'month' selected_view = request.args.get('view') or 'month'
if selected_view == 'all':
return redirect(url_for('get_person', person_id=person_id))
next_date = selected_date + (timedelta( next_date = selected_date + (timedelta(
365/12) if selected_view == 'month' else timedelta(365)) 365/12) if selected_view == 'month' else timedelta(365))
previous_date = selected_date + (timedelta( previous_date = selected_date + (timedelta(
-365/12) if selected_view == 'month' else timedelta(-365)) -365/12) if selected_view == 'month' else timedelta(-365))
first_date_of_view = selected_date.replace(
day=1) if selected_view == 'month' else selected_date.replace(month=1, day=1)
last_date_of_view = first_date_of_view + \
(timedelta(365/12) if selected_view == 'month' else timedelta(365))
start = dict([(6, 0), (0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)])
start_date = first_date_of_view - \
timedelta(days=start[first_date_of_view.weekday()])
end = dict([(6, 6), (0, 5), (1, 4), (2, 3), (3, 2), (4, 1), (5, 0)])
end_date = last_date_of_view + \
timedelta(days=end[last_date_of_view.weekday()])
if htmx: if htmx:
return render_template('partials/page/calendar.html', return render_template('partials/page/calendar.html',
person=person, selected_date=selected_date, selected_view=selected_view, next_date=next_date, previous_date=previous_date) person=person, selected_date=selected_date, selected_view=selected_view, next_date=next_date, previous_date=previous_date, start_date=start_date, end_date=end_date)
return render_template('calendar.html', person=person, selected_date=selected_date, selected_view=selected_view, next_date=next_date, previous_date=previous_date) return render_template('calendar.html', person=person, selected_date=selected_date, selected_view=selected_view, next_date=next_date, previous_date=previous_date, start_date=start_date, end_date=end_date)
@ app.route("/person/<int:person_id>/workout", methods=['POST']) @ app.route("/person/<int:person_id>/workout", methods=['POST'])
@@ -282,7 +299,7 @@ def my_utility_processor():
def strftime(date, format="%b %d %Y"): def strftime(date, format="%b %d %Y"):
return date.strftime(format) return date.strftime(format)
return dict(get_list_of_people_and_workout_count=get_list_of_people_and_workout_count, is_selected_page=is_selected_page, get_first_element_from_list_with_matching_attribute=get_first_element_from_list_with_matching_attribute, is_checked=is_checked, strftime=strftime) return dict(get_list_of_people_and_workout_count=get_list_of_people_and_workout_count, is_selected_page=is_selected_page, get_first_element_from_list_with_matching_attribute=get_first_element_from_list_with_matching_attribute, is_checked=is_checked, strftime=strftime, datetime=datetime, timedelta=timedelta)
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -4,6 +4,6 @@
{{ render_partial('partials/page/calendar.html', {{ render_partial('partials/page/calendar.html',
person=person, selected_date=selected_date, selected_view=selected_view, next_date=next_date, person=person, selected_date=selected_date, selected_view=selected_view, next_date=next_date,
previous_date=previous_date) }} previous_date=previous_date, start_date=start_date, end_date=end_date) }}
{% endblock %} {% endblock %}

View File

@@ -35,6 +35,7 @@
hx-vals='{"date": "{{ selected_date }}"}' hx-push-url="true"> hx-vals='{"date": "{{ selected_date }}"}' hx-push-url="true">
<option value="month" {% if selected_view=='month' %}selected{% endif %}>Month</option> <option value="month" {% if selected_view=='month' %}selected{% endif %}>Month</option>
<option value="year" {% if selected_view=='year' %}selected{% endif %}>Year</option> <option value="year" {% if selected_view=='year' %}selected{% endif %}>Year</option>
<option value="all">All</option>
</select> </select>
</div> </div>
</div> </div>
@@ -74,301 +75,32 @@
<div class="grid grid-cols-7 overflow-hidden flex-1 pl-2 pr-2 w-full"> <div class="grid grid-cols-7 overflow-hidden flex-1 pl-2 pr-2 w-full">
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer"> {% for i in range((end_date-start_date).days + 1) %}
{% set date = start_date + timedelta(days=i) %}
{% set workout =
get_first_element_from_list_with_matching_attribute(person['Workouts'],
'StartDate',
date) %}
<div class="{% if date == datetime.today().date() %}rounded-md border-4 border-green-50{% endif %} border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer {% if selected_date.month != date.month %}bg-gray-100{% endif %}"
{% if workout %}
hx-get="{{ url_for('get_workout' ,person_id=person['PersonId'], workout_id=workout['WorkoutId']) }}"
hx-target="#container" hx-push-url="true" {% endif %}>
<div class="top h-5 w-full"> <div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">1</span> <span class="text-gray-500 font-semibold">{{ date.day }}</span>
</div> </div>
<div class="bottom flex-grow h-30 py-1 w-full"> <div class="bottom flex-grow h-30 py-1 w-full">
{% if workout %}
{% for topset in workout['TopSets'] %}
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs"> <button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">Squat</span> <span class="ml-2 font-medium leading-none truncate">{{ topset['ExerciseName'] }}</span>
<span class="ml-2 font-light leading-none">5x50kg</span> <span class="ml-2 font-light leading-none">{{ topset['Repetitions'] }} x {{ topset['Weight']
</button> }}kg</span>
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">DB Seal row</span>
<span class="ml-2 font-light leading-none">12x20kg</span>
</button> </button>
{% endfor %}
{% endif %}
</div> </div>
</div> </div>
{% endfor %}
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">2</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full">
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">Squat</span>
<span class="ml-2 font-light leading-none">5x50kg</span>
</button>
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">DB Seal row</span>
<span class="ml-2 font-light leading-none">12x20kg</span>
</button>
</div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">3</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">4</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">6</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">7</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full">
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">Squat</span>
<span class="ml-2 font-light leading-none">5x50kg</span>
</button>
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">DB Seal row</span>
<span class="ml-2 font-light leading-none">12x20kg</span>
</button>
</div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold text-sm">8</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">9</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">10</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">12</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full">
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">Squat</span>
<span class="ml-2 font-light leading-none">5x50kg</span>
</button>
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">DB Seal row</span>
<span class="ml-2 font-light leading-none">12x20kg</span>
</button>
</div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">13</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div
class="rounded-md border-4 border-green-50 border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">14</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">15</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold text-sm">16</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">16</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full">
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">Squat</span>
<span class="ml-2 font-light leading-none">5x50kg</span>
</button>
<button class="flex items-center flex-shrink-0 h-5 px-1 text-xs">
<span class="ml-2 font-medium leading-none truncate">DB Seal row</span>
<span class="ml-2 font-light leading-none">12x20kg</span>
</button>
</div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">17</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">18</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">19</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">20</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">21</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold text-sm">22</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">23</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">24</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">25</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">26</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">27</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">28</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold text-sm">29</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">30</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">31</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div
class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer bg-gray-100 pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">1</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div
class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer bg-gray-100 pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">2</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div
class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer bg-gray-100 pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">3</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div
class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer bg-gray-100 pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">4</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
<div
class="border flex flex-col h-40 mx-auto mx-auto overflow-hidden w-full pt-2 pl-2 cursor-pointer bg-gray-100 pt-2 pl-2 cursor-pointer">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold text-sm">5</span>
</div>
<div class="bottom flex-grow h-30 py-1 w-full"></div>
</div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,6 @@
{% for p in people %} {% for p in people %}
<li> <li>
<a hx-get="{{ url_for('get_person' ,person_id=p['PersonId']) }}" hx-push-url="true" hx-target="#container" class="text-base text-gray-900 font-normal rounded-lg hover:bg-gray-100 flex items-center p-2 group cursor-pointer {% if <a hx-get="{{ url_for('get_calendar' ,person_id=p['PersonId']) }}" hx-push-url="true" hx-target="#container" class="text-base text-gray-900 font-normal rounded-lg hover:bg-gray-100 flex items-center p-2 group cursor-pointer {% if
p['IsActive']==1 %} bg-gray-200 {% endif %}"> p['IsActive']==1 %} bg-gray-200 {% endif %}">
<svg class="w-6 h-6 text-gray-500 flex-shrink-0 group-hover:text-gray-900 transition duration-75" <svg class="w-6 h-6 text-gray-500 flex-shrink-0 group-hover:text-gray-900 transition duration-75"
fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"> fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">