Add acheivement badges to monthly calendar view
This commit is contained in:
@@ -36,6 +36,7 @@ def _fetch_workout_data(db_executor, person_id, start_date, end_date, include_de
|
|||||||
"""Fetches workout data for a person within a date range."""
|
"""Fetches workout data for a person within a date range."""
|
||||||
if include_details:
|
if include_details:
|
||||||
query = """
|
query = """
|
||||||
|
WITH workout_stats AS (
|
||||||
SELECT
|
SELECT
|
||||||
w.workout_id,
|
w.workout_id,
|
||||||
w.start_date,
|
w.start_date,
|
||||||
@@ -43,18 +44,36 @@ def _fetch_workout_data(db_executor, person_id, start_date, end_date, include_de
|
|||||||
t.repetitions,
|
t.repetitions,
|
||||||
t.weight,
|
t.weight,
|
||||||
e.name AS exercise_name,
|
e.name AS exercise_name,
|
||||||
p.name AS person_name
|
p.name AS person_name,
|
||||||
|
-- Max weight ever for this exercise before this set
|
||||||
|
MAX(t.weight) OVER (
|
||||||
|
PARTITION BY p.person_id, e.exercise_id
|
||||||
|
ORDER BY w.start_date, t.topset_id
|
||||||
|
ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
|
||||||
|
) as prev_max_weight,
|
||||||
|
-- Weight from the last time this exercise was performed
|
||||||
|
LAG(t.weight) OVER (
|
||||||
|
PARTITION BY p.person_id, e.exercise_id
|
||||||
|
ORDER BY w.start_date, t.topset_id
|
||||||
|
) as prev_session_weight,
|
||||||
|
-- Reps from the last time this exercise was performed
|
||||||
|
LAG(t.repetitions) OVER (
|
||||||
|
PARTITION BY p.person_id, e.exercise_id
|
||||||
|
ORDER BY w.start_date, t.topset_id
|
||||||
|
) as prev_session_reps
|
||||||
FROM
|
FROM
|
||||||
person p
|
person p
|
||||||
LEFT JOIN workout w ON p.person_id = w.person_id AND w.start_date BETWEEN %s AND %s
|
LEFT JOIN workout w ON p.person_id = w.person_id
|
||||||
LEFT JOIN topset t ON w.workout_id = t.workout_id
|
LEFT JOIN topset t ON w.workout_id = t.workout_id
|
||||||
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
|
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
|
||||||
WHERE
|
WHERE
|
||||||
p.person_id = %s
|
p.person_id = %s
|
||||||
ORDER BY
|
)
|
||||||
w.start_date,
|
SELECT * FROM workout_stats
|
||||||
t.topset_id;
|
WHERE start_date BETWEEN %s AND %s
|
||||||
|
ORDER BY start_date, topset_id;
|
||||||
"""
|
"""
|
||||||
|
return db_executor(query, [person_id, start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d')])
|
||||||
else:
|
else:
|
||||||
query = """
|
query = """
|
||||||
SELECT
|
SELECT
|
||||||
@@ -69,7 +88,6 @@ def _fetch_workout_data(db_executor, person_id, start_date, end_date, include_de
|
|||||||
ORDER BY
|
ORDER BY
|
||||||
w.start_date;
|
w.start_date;
|
||||||
"""
|
"""
|
||||||
# Ensure dates are passed in a format the DB understands (e.g., YYYY-MM-DD strings)
|
|
||||||
return db_executor(query, [start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'), person_id])
|
return db_executor(query, [start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'), person_id])
|
||||||
|
|
||||||
def _group_workouts_by_date(workouts_data):
|
def _group_workouts_by_date(workouts_data):
|
||||||
@@ -97,10 +115,21 @@ def _group_workouts_by_date(workouts_data):
|
|||||||
|
|
||||||
# Add set details if topset_id exists
|
# Add set details if topset_id exists
|
||||||
if row.get('topset_id'):
|
if row.get('topset_id'):
|
||||||
|
weight = row.get('weight') or 0
|
||||||
|
reps = row.get('repetitions') or 0
|
||||||
|
prev_max = row.get('prev_max_weight') or 0
|
||||||
|
prev_weight = row.get('prev_session_weight') or 0
|
||||||
|
prev_reps = row.get('prev_session_reps') or 0
|
||||||
|
|
||||||
|
is_pr = weight > prev_max and prev_max > 0
|
||||||
|
is_improvement = (weight > prev_weight) or (weight == prev_weight and reps > prev_reps) if prev_weight > 0 else False
|
||||||
|
|
||||||
workouts_by_date[workout_date][workout_id]['sets'].append({
|
workouts_by_date[workout_date][workout_id]['sets'].append({
|
||||||
'repetitions': row.get('repetitions'),
|
'repetitions': reps,
|
||||||
'weight': row.get('weight'),
|
'weight': weight,
|
||||||
'exercise_name': row.get('exercise_name')
|
'exercise_name': row.get('exercise_name'),
|
||||||
|
'is_pr': is_pr,
|
||||||
|
'is_improvement': is_improvement
|
||||||
})
|
})
|
||||||
|
|
||||||
# Convert nested defaultdict to regular dict
|
# Convert nested defaultdict to regular dict
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -133,8 +133,15 @@
|
|||||||
{% for set in workout.sets %}
|
{% for set in workout.sets %}
|
||||||
<button
|
<button
|
||||||
class="flex flex-col xl:flex-row items-start lg:items-center flex-shrink-0 px-0 sm:px-0.5 md:px-0.5 lg:px-0.5 text-xs">
|
class="flex flex-col xl:flex-row items-start lg:items-center flex-shrink-0 px-0 sm:px-0.5 md:px-0.5 lg:px-0.5 text-xs">
|
||||||
<span class="ml-0 sm:ml-0.5 md:ml-2 lg:ml-2 font-medium leading-none truncate">{{
|
<span
|
||||||
set.exercise_name }}</span>
|
class="ml-0 sm:ml-0.5 md:ml-2 lg:ml-2 font-medium leading-none truncate flex items-center">
|
||||||
|
{{ set.exercise_name }}
|
||||||
|
{% if set.is_pr %}
|
||||||
|
<span class="ml-1 text-yellow-500" title="All-Time PR!">🏆</span>
|
||||||
|
{% elif set.is_improvement %}
|
||||||
|
<span class="ml-1 text-green-500 font-bold" title="Improved from last time">↑</span>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
<span class="ml-0 sm:ml-0.5 md:ml-2 lg:ml-2 font-light leading-none">{{ set.repetitions }} x {{
|
<span class="ml-0 sm:ml-0.5 md:ml-2 lg:ml-2 font-light leading-none">{{ set.repetitions }} x {{
|
||||||
set.weight }}kg</span>
|
set.weight }}kg</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user