Fixc weekly graph

This commit is contained in:
Peter Stockings
2024-12-30 23:29:30 +11:00
parent ea0ad126ab
commit 68c8059466
2 changed files with 36 additions and 20 deletions

View File

@@ -25,18 +25,18 @@ def dashboard():
user_tz = timezone(current_user.profile.timezone or 'UTC') user_tz = timezone(current_user.profile.timezone or 'UTC')
# Get date range for readings # Get date range for readings
first_reading, last_reading = get_reading_date_range(current_user.id) first_reading, last_reading = get_reading_date_range(current_user.id, user_tz)
start_date = request.form.get('start_date') or (first_reading and first_reading.strftime('%Y-%m-%d')) start_date = request.form.get('start_date') or (first_reading and first_reading.strftime('%Y-%m-%d'))
end_date = request.form.get('end_date') or (last_reading and last_reading.strftime('%Y-%m-%d')) end_date = request.form.get('end_date') or (last_reading and last_reading.strftime('%Y-%m-%d'))
# Fetch filtered readings # Fetch filtered readings
readings = fetch_readings(current_user.id, start_date, end_date) readings = fetch_readings(current_user.id, start_date, end_date)
now = datetime.utcnow()
# Annotate readings with relative and localized timestamps # Annotate readings with relative and localized timestamps
annotate_readings(readings, now, user_tz) annotate_readings(readings, user_tz)
# Generate calendar view # Generate calendar view
week_view = generate_weekly_calendar(readings, datetime.now(user_tz), user_tz)
month_view = generate_monthly_calendar(readings, datetime.now(user_tz), user_tz) month_view = generate_monthly_calendar(readings, datetime.now(user_tz), user_tz)
# Calculate stats and badges # Calculate stats and badges
@@ -58,18 +58,17 @@ def dashboard():
start_date=start_date, start_date=start_date,
end_date=end_date, end_date=end_date,
month=month_view, month=month_view,
date=date, week = week_view,
timedelta=timedelta,
**graph_data **graph_data
) )
def get_reading_date_range(user_id): def get_reading_date_range(user_id, user_tz):
"""Fetch the earliest and latest reading timestamps for a user.""" """Fetch the earliest and latest reading timestamps for a user."""
result = db.session.query( result = db.session.query(
func.min(Reading.timestamp).label('first'), func.min(Reading.timestamp).label('first'),
func.max(Reading.timestamp).label('last') func.max(Reading.timestamp).label('last')
).filter(Reading.user_id == user_id).first() ).filter(Reading.user_id == user_id).first()
return result.first, result.last return utc.localize(result.first).astimezone(user_tz), utc.localize(result.last).astimezone(user_tz)
def fetch_readings(user_id, start_date, end_date): def fetch_readings(user_id, start_date, end_date):
"""Retrieve readings filtered by date range.""" """Retrieve readings filtered by date range."""
@@ -81,8 +80,9 @@ def fetch_readings(user_id, start_date, end_date):
) )
return query.order_by(Reading.timestamp.desc()).all() return query.order_by(Reading.timestamp.desc()).all()
def annotate_readings(readings, now, user_tz): def annotate_readings(readings, user_tz):
"""Add relative and localized timestamps to readings.""" """Add relative and localized timestamps to readings."""
now = datetime.utcnow()
for reading in readings: for reading in readings:
reading.relative_timestamp = humanize.naturaltime(now - reading.timestamp) reading.relative_timestamp = humanize.naturaltime(now - reading.timestamp)
reading.local_timestamp = utc.localize(reading.timestamp).astimezone(user_tz) reading.local_timestamp = utc.localize(reading.timestamp).astimezone(user_tz)
@@ -116,11 +116,34 @@ def generate_monthly_calendar(readings, selected_date, local_tz):
'day': current_date.day, 'day': current_date.day,
'is_today': current_date == today, 'is_today': current_date == today,
'is_in_current_month': current_date.month == selected_date.month, 'is_in_current_month': current_date.month == selected_date.month,
'readings': readings_by_day.get(current_date, []), 'readings': readings_by_day.get(current_date.date(), []),
} }
for current_date in (start_date + timedelta(days=i) for i in range((end_date - start_date).days + 1)) for current_date in (start_date + timedelta(days=i) for i in range((end_date - start_date).days + 1))
] ]
def generate_weekly_calendar(readings, selected_date, local_tz):
"""Generate a weekly calendar view."""
# Get the start of the week (Monday) and the end of the week (Sunday)
today = datetime.now(local_tz).date()
start_of_week = selected_date - timedelta(days=selected_date.weekday())
end_of_week = start_of_week + timedelta(days=6)
# Group readings by day
readings_by_day = defaultdict(list)
for reading in readings:
local_date = reading.timestamp.astimezone(local_tz).date()
readings_by_day[local_date].append(reading)
# Build the weekly calendar view
return [
{
'date': current_date.strftime('%a, %b %d') ,
'is_today': current_date == today,
'readings': readings_by_day.get(current_date.date(), []),
}
for current_date in (start_of_week + timedelta(days=i) for i in range(7))
]
def prepare_graph_data(readings): def prepare_graph_data(readings):
"""Prepare data for graph rendering.""" """Prepare data for graph rendering."""
return { return {
@@ -174,11 +197,6 @@ def calculate_progress_badges(readings):
if count >= 30: if count >= 30:
badges.append(f"Full Month of Logging: {month}") badges.append(f"Full Month of Logging: {month}")
if streak_count >= 7:
badges.append("Logged Every Day for a Week")
if streak_count >= 30 and previous_date == now:
badges.append("Monthly Streak")
if all(5 <= r.timestamp.hour < 12 for r in sorted_readings[-7:]): if all(5 <= r.timestamp.hour < 12 for r in sorted_readings[-7:]):
badges.append("Morning Riser: Logged Readings Every Morning for a Week") badges.append("Morning Riser: Logged Readings Every Morning for a Week")

View File

@@ -148,13 +148,11 @@
<!-- Weekly View --> <!-- Weekly View -->
<div x-show="activeView === 'weekly'" class="grid grid-cols-7 text-center"> <div x-show="activeView === 'weekly'" class="grid grid-cols-7 text-center">
{% set today = date.today() %} {% for day in week %}
{% for i in range(7) %}
{% set day = today - timedelta(days=today.weekday() - i) %}
<div class="border p-1 md:p-4 bg-gray-50"> <div class="border p-1 md:p-4 bg-gray-50">
<div class="text-sm font-bold text-gray-500">{{ day.strftime('%a, %b %d') }}</div> <div class="text-sm font-bold text-gray-500">{{ day.date }}</div>
{% if day in readings_by_date %} {% if day.readings %}
{% for reading in readings_by_date[day]|sort(attribute="timestamp", reverse = True) %} {% for reading in day.readings %}
<a href="{{ url_for('reading.edit_reading', reading_id=reading.id) }}" <a href="{{ url_for('reading.edit_reading', reading_id=reading.id) }}"
class="block mt-2 p-0 md:p-2 bg-green-100 rounded-lg shadow hover:bg-green-200 transition"> class="block mt-2 p-0 md:p-2 bg-green-100 rounded-lg shadow hover:bg-green-200 transition">
<p class="text-xs font-medium text-green-800"> <p class="text-xs font-medium text-green-800">