Add acheivement badges to monthly calendar view

This commit is contained in:
Peter Stockings
2026-02-02 20:54:28 +11:00
parent bc2a350e90
commit 2b330e4743
3 changed files with 62 additions and 26 deletions

View File

@@ -36,25 +36,44 @@ def _fetch_workout_data(db_executor, person_id, start_date, end_date, include_de
"""Fetches workout data for a person within a date range."""
if include_details:
query = """
SELECT
w.workout_id,
w.start_date,
t.topset_id,
t.repetitions,
t.weight,
e.name AS exercise_name,
p.name AS person_name
FROM
person p
LEFT JOIN workout w ON p.person_id = w.person_id AND w.start_date BETWEEN %s AND %s
LEFT JOIN topset t ON w.workout_id = t.workout_id
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
WHERE
p.person_id = %s
ORDER BY
w.start_date,
t.topset_id;
WITH workout_stats AS (
SELECT
w.workout_id,
w.start_date,
t.topset_id,
t.repetitions,
t.weight,
e.name AS exercise_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
person p
LEFT JOIN workout w ON p.person_id = w.person_id
LEFT JOIN topset t ON w.workout_id = t.workout_id
LEFT JOIN exercise e ON t.exercise_id = e.exercise_id
WHERE
p.person_id = %s
)
SELECT * FROM workout_stats
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:
query = """
SELECT
@@ -69,8 +88,7 @@ def _fetch_workout_data(db_executor, person_id, start_date, end_date, include_de
ORDER BY
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):
"""Groups workout data by date and workout ID."""
@@ -97,10 +115,21 @@ def _group_workouts_by_date(workouts_data):
# Add set details if topset_id exists
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({
'repetitions': row.get('repetitions'),
'weight': row.get('weight'),
'exercise_name': row.get('exercise_name')
'repetitions': reps,
'weight': weight,
'exercise_name': row.get('exercise_name'),
'is_pr': is_pr,
'is_improvement': is_improvement
})
# Convert nested defaultdict to regular dict