Load dashboard displays using htmx
This commit is contained in:
@@ -24,89 +24,118 @@ def health():
|
||||
@main.route('/dashboard', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def dashboard():
|
||||
"""Render the dashboard with readings, stats, and calendar views."""
|
||||
"""Render the dashboard shell and default list view."""
|
||||
user_tz = timezone(current_user.profile.timezone or 'UTC')
|
||||
|
||||
# Get date range for readings
|
||||
# Get date range for filters
|
||||
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'))
|
||||
end_date = request.form.get('end_date') or (last_reading and last_reading.strftime('%Y-%m-%d'))
|
||||
start_date = request.form.get('start_date') or request.args.get('start_date') or (first_reading and first_reading.strftime('%Y-%m-%d'))
|
||||
end_date = request.form.get('end_date') or request.args.get('end_date') or (last_reading and last_reading.strftime('%Y-%m-%d'))
|
||||
|
||||
# Pagination for list view
|
||||
page = request.args.get('page', 1, type=int)
|
||||
|
||||
# Weekly View Navigation Offset
|
||||
week_offset = request.args.get('week_offset', 0, type=int)
|
||||
|
||||
# Monthly View Navigation Offset
|
||||
month_offset = request.args.get('month_offset', 0, type=int)
|
||||
|
||||
# Fetch paginated readings for the list view
|
||||
paginated = fetch_readings_paginated(current_user.id, start_date, end_date, user_tz, page, PAGE_SIZE)
|
||||
|
||||
# For calendar/graph/badges, fetch only current month + week readings (much smaller set)
|
||||
now = datetime.now(user_tz)
|
||||
|
||||
# Calculate target week date for weekly view
|
||||
target_week_date = now + timedelta(weeks=week_offset)
|
||||
# Ensure we fetch enough data back to cover the week_offset
|
||||
month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
month_start_utc = month_start.astimezone(utc)
|
||||
target_week_start = target_week_date - timedelta(days=target_week_date.weekday())
|
||||
target_week_start_utc = target_week_start.replace(hour=0, minute=0, second=0, microsecond=0).astimezone(utc)
|
||||
|
||||
# Calculate target month date for monthly view
|
||||
target_month_year = now.year + (now.month + month_offset - 1) // 12
|
||||
target_month_month = (now.month + month_offset - 1) % 12 + 1
|
||||
target_month_date = now.replace(year=target_month_year, month=target_month_month, day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
target_month_start_utc = target_month_date.astimezone(utc)
|
||||
|
||||
# Fetch from the earliest of the current month OR the requested target week/month
|
||||
fetch_start_utc = min(month_start_utc, target_week_start_utc, target_month_start_utc)
|
||||
calendar_readings = fetch_readings_for_range(current_user.id, fetch_start_utc)
|
||||
|
||||
# Annotate all readings with relative and localized timestamps
|
||||
annotate_readings(paginated.items, user_tz)
|
||||
annotate_readings(calendar_readings, user_tz)
|
||||
|
||||
# Build shared lookup for calendar views (single pass)
|
||||
readings_by_day = build_readings_by_day(calendar_readings, user_tz)
|
||||
|
||||
# Generate calendar views from the shared lookup
|
||||
week_view = generate_weekly_calendar(readings_by_day, target_week_date, user_tz)
|
||||
month_view = generate_monthly_calendar(readings_by_day, target_month_date, user_tz)
|
||||
|
||||
# Calculate weekly averages via SQL (much faster than Python)
|
||||
# Calculate weekly averages via SQL
|
||||
systolic_avg, diastolic_avg, heart_rate_avg = calculate_weekly_summary_sql(current_user.id)
|
||||
|
||||
# Badges from the paginated readings (or full set if needed)
|
||||
badges = calculate_progress_badges(paginated.items)
|
||||
|
||||
# Prepare graph data from calendar readings (current month)
|
||||
graph_data = prepare_graph_data(calendar_readings)
|
||||
# Badges need paginated or all readings. We'll fetch all readings for badges
|
||||
# Note: To avoid huge queries, we might want a specific badge query in the future.
|
||||
# For now, let's fetch current month readings + previous as a rough approximation or keep behavior.
|
||||
# A generic query for badges:
|
||||
all_readings = Reading.query.filter_by(user_id=current_user.id).order_by(Reading.timestamp.desc()).all()
|
||||
badges = calculate_progress_badges(all_readings)
|
||||
|
||||
# We will default to showing the list view on initial load
|
||||
page = request.args.get('page', 1, type=int)
|
||||
paginated = fetch_readings_paginated(current_user.id, start_date, end_date, user_tz, page, PAGE_SIZE)
|
||||
annotate_readings(paginated.items, user_tz)
|
||||
|
||||
return render_template(
|
||||
'dashboard.html',
|
||||
readings=paginated.items,
|
||||
pagination=paginated,
|
||||
profile=current_user.profile,
|
||||
badges=badges,
|
||||
systolic_avg=systolic_avg,
|
||||
diastolic_avg=diastolic_avg,
|
||||
heart_rate_avg=heart_rate_avg,
|
||||
delete_form=DeleteForm(),
|
||||
start_date=start_date,
|
||||
end_date=end_date,
|
||||
month=month_view,
|
||||
week=week_view,
|
||||
date=date,
|
||||
target_month_date=target_month_date,
|
||||
week_offset=week_offset,
|
||||
month_offset=month_offset,
|
||||
active_view=request.args.get('activeView', 'list'),
|
||||
**graph_data
|
||||
delete_form=DeleteForm(),
|
||||
active_view='list',
|
||||
# default view context
|
||||
readings=paginated.items,
|
||||
pagination=paginated
|
||||
)
|
||||
|
||||
@main.route('/dashboard/list', methods=['GET'])
|
||||
@login_required
|
||||
def dashboard_list():
|
||||
user_tz = timezone(current_user.profile.timezone or 'UTC')
|
||||
first_reading, last_reading = get_reading_date_range(current_user.id, user_tz)
|
||||
start_date = request.args.get('start_date') or (first_reading and first_reading.strftime('%Y-%m-%d'))
|
||||
end_date = request.args.get('end_date') or (last_reading and last_reading.strftime('%Y-%m-%d'))
|
||||
page = request.args.get('page', 1, type=int)
|
||||
|
||||
paginated = fetch_readings_paginated(current_user.id, start_date, end_date, user_tz, page, PAGE_SIZE)
|
||||
annotate_readings(paginated.items, user_tz)
|
||||
|
||||
return render_template('partials/dashboard_list.html', readings=paginated.items, pagination=paginated)
|
||||
|
||||
@main.route('/dashboard/weekly', methods=['GET'])
|
||||
@login_required
|
||||
def dashboard_weekly():
|
||||
user_tz = timezone(current_user.profile.timezone or 'UTC')
|
||||
week_offset = request.args.get('week_offset', 0, type=int)
|
||||
now = datetime.now(user_tz)
|
||||
|
||||
target_week_date = now + timedelta(weeks=week_offset)
|
||||
target_week_start = target_week_date - timedelta(days=target_week_date.weekday())
|
||||
target_week_start_utc = target_week_start.replace(hour=0, minute=0, second=0, microsecond=0).astimezone(utc)
|
||||
target_week_end_utc = (target_week_start + timedelta(days=7)).replace(hour=0, minute=0, second=0, microsecond=0).astimezone(utc)
|
||||
|
||||
calendar_readings = fetch_readings_for_range(current_user.id, target_week_start_utc, target_week_end_utc)
|
||||
annotate_readings(calendar_readings, user_tz)
|
||||
readings_by_day = build_readings_by_day(calendar_readings, user_tz)
|
||||
week_view = generate_weekly_calendar(readings_by_day, target_week_date, user_tz)
|
||||
|
||||
return render_template('partials/dashboard_weekly.html', week=week_view, week_offset=week_offset)
|
||||
|
||||
@main.route('/dashboard/monthly', methods=['GET'])
|
||||
@login_required
|
||||
def dashboard_monthly():
|
||||
user_tz = timezone(current_user.profile.timezone or 'UTC')
|
||||
month_offset = request.args.get('month_offset', 0, type=int)
|
||||
now = datetime.now(user_tz)
|
||||
|
||||
target_month_year = now.year + (now.month + month_offset - 1) // 12
|
||||
target_month_month = (now.month + month_offset - 1) % 12 + 1
|
||||
target_month_date = now.replace(year=target_month_year, month=target_month_month, day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
first_day = target_month_date
|
||||
start_date = first_day - timedelta(days=(first_day.weekday() + 1) % 7)
|
||||
end_date = start_date + timedelta(days=42)
|
||||
|
||||
start_utc = start_date.replace(hour=0, minute=0, second=0, microsecond=0).astimezone(utc)
|
||||
end_utc = end_date.replace(hour=0, minute=0, second=0, microsecond=0).astimezone(utc)
|
||||
|
||||
calendar_readings = fetch_readings_for_range(current_user.id, start_utc, end_utc)
|
||||
annotate_readings(calendar_readings, user_tz)
|
||||
readings_by_day = build_readings_by_day(calendar_readings, user_tz)
|
||||
month_view = generate_monthly_calendar(readings_by_day, target_month_date, user_tz)
|
||||
|
||||
return render_template('partials/dashboard_monthly.html', month=month_view, target_month_date=target_month_date, month_offset=month_offset)
|
||||
|
||||
@main.route('/dashboard/graph', methods=['GET'])
|
||||
@login_required
|
||||
def dashboard_graph():
|
||||
user_tz = timezone(current_user.profile.timezone or 'UTC')
|
||||
now = datetime.now(user_tz)
|
||||
month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
||||
month_start_utc = month_start.astimezone(utc)
|
||||
|
||||
calendar_readings = fetch_readings_for_range(current_user.id, month_start_utc)
|
||||
annotate_readings(calendar_readings, user_tz)
|
||||
|
||||
graph_data = prepare_graph_data(calendar_readings)
|
||||
|
||||
return render_template('partials/dashboard_graph.html', **graph_data)
|
||||
|
||||
def get_reading_date_range(user_id, user_tz):
|
||||
"""Fetch the earliest and latest reading timestamps for a user."""
|
||||
result = db.session.query(
|
||||
|
||||
Reference in New Issue
Block a user