Improve monthly calendar view

This commit is contained in:
Peter Stockings
2026-02-02 21:45:22 +11:00
parent 2b330e4743
commit f53bf3d106
3 changed files with 100 additions and 41 deletions

View File

@@ -148,12 +148,38 @@ def _process_workouts_for_month_view(grouped_workouts, start_date, end_date, sel
day_workouts_dict = grouped_workouts.get(current_date, {})
day_workouts_list = list(day_workouts_dict.values()) # Convert workout dicts to list
total_sets = 0
has_pr = False
has_improvement = False
pr_count = 0
improvement_count = 0
unique_exercise_names = []
for workout in day_workouts_list:
total_sets += len(workout.get('sets', []))
for s in workout.get('sets', []):
if s.get('is_pr'):
has_pr = True
pr_count += 1
if s.get('is_improvement'):
has_improvement = True
improvement_count += 1
name = s.get('exercise_name')
if name and name not in unique_exercise_names:
unique_exercise_names.append(name)
days_data.append({
'date_obj': current_date, # Pass the date object for easier template logic
'day': current_date.day,
'is_today': current_date == today, # Correct comparison: date object == date object
'is_in_current_month': current_date.month == selected_date.month,
'has_workouts': len(day_workouts_list) > 0,
'workout_count': len(day_workouts_list),
'total_sets': total_sets,
'has_pr': has_pr,
'has_improvement': has_improvement,
'pr_count': pr_count,
'improvement_count': improvement_count,
'exercise_names': unique_exercise_names[:3], # Limit to first 3 for summary
'workouts': day_workouts_list
})
current_date += timedelta(days=1)

File diff suppressed because one or more lines are too long

View File

@@ -85,69 +85,102 @@
</div>
{% if view == 'month' %}
<div class="flex flex-col px-2 py-2 -mb-px">
<div class="grid grid-cols-7 pl-2 pr-2">
<div class="flex flex-col px-1 sm:px-2 py-2 -mb-px">
<div class="grid grid-cols-7">
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Sunday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Sun</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">S</span>
</div>
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Monday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Mon</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">M</span>
</div>
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Tuesday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Tue</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">T</span>
</div>
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Wednesday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Wed</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">W</span>
</div>
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Thursday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Thu</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">T</span>
</div>
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Friday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Fri</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">F</span>
</div>
<div class="p-2 h-10 text-center font-bold">
<div class="p-1 h-8 text-center font-bold text-xs">
<span class="xl:block lg:block md:block sm:block hidden">Saturday</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">Sat</span>
<span class="xl:hidden lg:hidden md:hidden sm:hidden block">S</span>
</div>
</div>
<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 w-full border-t border-l">
{% for day in days %}
<div
class="{% if day.is_today %}rounded-md border-4 border-green-50{% endif %} border flex flex-col h-36 sm:h-40 md:h-30 lg:h-30 mx-auto mx-auto overflow-hidden w-full pt-2 pl-1 cursor-pointer {% if day.is_in_current_month %}bg-gray-100{% endif %}">
<div class="top h-5 w-full">
<span class="text-gray-500 font-semibold">{{ day.day }}</span>
</div>
{% for workout in day.workouts %}
<div class="bottom flex-grow py-1 w-full"
hx-get="{{ url_for('workout.show_workout', person_id=person_id, workout_id=workout.workout_id) }}"
hx-push-url="true" hx-target="#container">
{% for set in workout.sets %}
<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">
<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 %}
class="{% if day.is_today %}ring-2 ring-green-100 ring-inset{% endif %} border-b border-r flex flex-col h-20 sm:h-40 md:h-30 lg:h-30 mx-auto overflow-hidden w-full pt-1 px-1 cursor-pointer relative {% if not day.is_in_current_month %}opacity-40{% else %}bg-gray-50/50{% endif %}">
<div class="flex justify-between items-start mb-0.5">
<span class="text-gray-400 font-medium text-[9px] sm:text-xs leading-none">{{ day.day }}</span>
{% if day.has_workouts and (day.pr_count > 0 or day.improvement_count > 0) %}
<div
class="flex items-center bg-white/80 border border-gray-100 rounded-full px-1 shadow-sm h-3.5 sm:h-4">
{% if day.pr_count > 0 %}
<span class="text-[8px] sm:text-[9px] font-bold text-yellow-600 flex items-center">
🏆<span class="ml-0.5">{{ day.pr_count }}</span>
</span>
<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>
</button>
{% endif %}
{% if day.pr_count > 0 and day.improvement_count > 0 %}
<span class="mx-0.5 text-gray-300 text-[8px]">|</span>
{% endif %}
{% if day.improvement_count > 0 %}
<span class="text-[8px] sm:text-[9px] font-bold text-green-600 flex items-center">
<span class="ml-0.5">{{ day.improvement_count }}</span>
</span>
{% endif %}
</div>
{% endif %}
</div>
{% if day.has_workouts %}
<!-- Mobile Summary -->
<div
class="sm:hidden flex flex-col flex-grow text-[8px] text-gray-500 font-medium leading-tight overflow-hidden pb-1 space-y-0.5">
{% for name in day.exercise_names %}
<div class="truncate pl-0.5 border-l border-blue-200">{{ name }}</div>
{% endfor %}
</div>
{% endfor %}
<!-- Desktop Detailed List -->
<div class="hidden sm:block flex-1 overflow-hidden">
{% for workout in day.workouts %}
<div class="py-1 w-full"
hx-get="{{ url_for('workout.show_workout', person_id=person_id, workout_id=workout.workout_id) }}"
hx-push-url="true" hx-target="#container">
{% for set in workout.sets %}
<div class="flex flex-col w-full px-0.5 text-[9px] lg:text-[10px] leading-tight mb-1">
<span class="truncate flex items-center min-w-0">
<span class="truncate">{{ set.exercise_name }}</span>
</span>
<span class="font-light text-gray-400 text-[8px] lg:text-[9px] flex items-center">
<span>{{ set.repetitions }} x {{ set.weight }}kg</span>
{% if set.is_pr %}
<span class="ml-1 text-yellow-500 shrink-0 text-[8px]">🏆</span>
{% elif set.is_improvement %}
<span class="ml-1 text-green-500 font-bold shrink-0 text-[8px]"></span>
{% endif %}
</span>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endfor %}