Refactor calendar (month and year view), switching to vertical slice arch. Also in progress of refactoring of stats so they are retreived after inital page load for performance sake

This commit is contained in:
Peter Stockings
2024-04-11 13:45:38 +10:00
parent 76789a4934
commit 63d997a3f1
7 changed files with 302 additions and 133 deletions

141
features/calendar.py Normal file
View File

@@ -0,0 +1,141 @@
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import pandas as pd
class Calendar:
def __init__(self, db_connection_method):
self.execute = db_connection_method
def fetch_workouts_for_person(self, person_id, date, view):
prev_date, next_date = None, None
if view == 'month':
first_day_of_month = date.replace(day=1)
days_to_subtract = (first_day_of_month.weekday() + 1) % 7
start_date = first_day_of_month - timedelta(days=days_to_subtract)
end_date = start_date + timedelta(days=6 * 7 - 1)
prev_date = first_day_of_month - relativedelta(months=1)
next_date = first_day_of_month + relativedelta(months=1)
elif view == 'year':
start_date = date.replace(month=1, day=1)
end_date = date.replace(year=date.year + 1, month=1, day=1) - timedelta(days=1)
prev_date = date - relativedelta(years=1)
next_date = date + relativedelta(years=1)
else:
raise ValueError('Invalid view')
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;
"""
workouts_data = self.execute(query, [start_date, end_date, person_id])
# Assuming person_name is the same for all rows as we filter by person_id
person_name = workouts_data[0]['person_name'] if workouts_data else 'Unknown'
calendar_view = {'prev_date': prev_date, 'next_date': next_date, 'person_id': person_id, 'person_name': person_name, 'view': view, 'date': date}
if view == 'month':
calendar_view['days'] = []
workouts_by_date = {}
for row in workouts_data:
if row['workout_id'] is None:
continue # Skip rows that don't have workout data
workout_date_str = row['start_date'].strftime("%Y-%m-%d")
workout_id = row['workout_id']
if workout_date_str not in workouts_by_date:
workouts_by_date[workout_date_str] = {}
if workout_id not in workouts_by_date[workout_date_str]:
workouts_by_date[workout_date_str][workout_id] = {
'workout_id': workout_id,
'start_date': row['start_date'],
'sets': []
}
workouts_by_date[workout_date_str][workout_id]['sets'].append({
'repetitions': row['repetitions'],
'weight': row['weight'],
'exercise_name': row['exercise_name']
})
for current_date in pd.date_range(start_date, end_date, freq='D'):
date_str = current_date.strftime("%Y-%m-%d")
day_workouts = workouts_by_date.get(date_str, {})
today = datetime.today().date()
calendar_view['days'].append({
'day': current_date.day,
'is_today': current_date == today,
'is_in_current_month': current_date.month == date.month, # Ensure it compares with the selected month
'has_workouts': len(day_workouts) > 0,
'workouts': list(day_workouts.values())
})
elif view == 'year':
calendar_view['months'] = []
workouts_by_date = {}
for row in workouts_data:
if row['start_date'] is None:
continue # Skip rows that don't have workout data
workout_date_str = row['start_date'].strftime("%Y-%m-%d")
if workout_date_str not in workouts_by_date:
workouts_by_date[workout_date_str] = []
workouts_by_date[workout_date_str].append({
'workout_id': row['workout_id'],
'start_date': row['start_date'],
'topset_id': row['topset_id'],
'repetitions': row['repetitions'],
'weight': row['weight'],
'exercise_name': row['exercise_name']
})
for month in range(1, 13):
first_day_of_month = date.replace(month=month, day=1)
days_to_subtract = (first_day_of_month.weekday() + 1) % 7
start_date = first_day_of_month - timedelta(days=days_to_subtract)
end_date = start_date + timedelta(days=6 * 7 - 1)
month_data = {'name': first_day_of_month.strftime('%B'), 'first_day_of_month': first_day_of_month, 'days': []}
current_day = start_date
while current_day <= end_date:
day_workouts = workouts_by_date.get(current_day.strftime('%Y-%m-%d'), [])
has_workouts = len(day_workouts) > 0
first_workout_id = day_workouts[0]['workout_id'] if has_workouts else None
day_data = {
'day': current_day.day,
'is_today': current_day == datetime.today().date(),
'is_in_current_month': current_day.month == month,
'workouts': day_workouts,
'has_workouts': has_workouts,
'first_workout_id': first_workout_id
}
month_data['days'].append(day_data)
current_day += timedelta(days=1)
calendar_view['months'].append(month_data)
return calendar_view