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:
141
features/calendar.py
Normal file
141
features/calendar.py
Normal 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
|
||||
Reference in New Issue
Block a user