Add progress badge denoting current streak length, and refactor dashboard route

This commit is contained in:
Peter Stockings
2024-12-26 16:15:36 +11:00
parent 97a8e54e11
commit cec37fe1f7

View File

@@ -58,84 +58,105 @@ def landing():
@main.route('/dashboard', methods=['GET', 'POST'])
@login_required
def dashboard():
# Initialize start_date and end_date
start_date = None
end_date = None
# Retrieve the first and last timestamps in a single query
first_last_readings = (
db.session.query(
func.min(Reading.timestamp).label('first'),
func.max(Reading.timestamp).label('last')
# Helper function to get first and last reading timestamps
def get_reading_date_range(user_id):
result = (
db.session.query(
func.min(Reading.timestamp).label('first'),
func.max(Reading.timestamp).label('last')
)
.filter(Reading.user_id == user_id)
.first()
)
.filter(Reading.user_id == current_user.id)
.first()
)
return result.first, result.last
# Extract the first and last timestamps
first_reading_timestamp = first_last_readings.first
last_reading_timestamp = first_last_readings.last
# Helper function to calculate weekly summary averages
def calculate_weekly_summary(readings):
one_week_ago = datetime.now() - timedelta(days=7)
weekly_readings = [r for r in readings if r.timestamp >= one_week_ago]
if weekly_readings:
systolic_avg = round(sum(r.systolic for r in weekly_readings) / len(weekly_readings), 1)
diastolic_avg = round(sum(r.diastolic for r in weekly_readings) / len(weekly_readings), 1)
heart_rate_avg = round(sum(r.heart_rate for r in weekly_readings) / len(weekly_readings), 1)
else:
systolic_avg = diastolic_avg = heart_rate_avg = 0
return systolic_avg, diastolic_avg, heart_rate_avg
# Default to first and last reading dates if not provided
if not start_date and first_reading_timestamp:
start_date = first_reading_timestamp.strftime('%Y-%m-%d')
if not end_date and last_reading_timestamp:
end_date = last_reading_timestamp.strftime('%Y-%m-%d')
# Helper function to calculate progress badges
def calculate_progress_badges(readings, weekly_readings):
badges = []
# General badges
if len(readings) >= 10:
badges.append("10 Readings Logged")
if len(readings) >= 100:
badges.append("100 Readings Milestone")
if len(weekly_readings) >= 7:
badges.append("Logged Readings for 7 Days")
# Streak badge
if readings:
streak_count = 1 # Start streak count with today's reading
today = datetime.now().date()
# Default to all readings
# Sort readings by timestamp in ascending order
sorted_readings = sorted(readings, key=lambda r: r.timestamp)
for i in range(len(sorted_readings) - 1, 0, -1):
current_day = sorted_readings[i].timestamp.date()
previous_day = sorted_readings[i - 1].timestamp.date()
# Check if days are consecutive
if (current_day - previous_day).days == 1:
streak_count += 1
elif (current_day - previous_day).days > 1:
break # Streak is broken
# Add streak badge if the streak is greater than 1
if streak_count > 1 and sorted_readings[-1].timestamp.date() == today:
badges.append(f"Current Streak: {streak_count} Days")
return badges
# Get the first and last reading timestamps
first_reading_timestamp, last_reading_timestamp = get_reading_date_range(current_user.id)
# Set default start and end dates
start_date = first_reading_timestamp.strftime('%Y-%m-%d') if first_reading_timestamp else None
end_date = last_reading_timestamp.strftime('%Y-%m-%d') if last_reading_timestamp else None
# Handle filtering for POST request
readings_query = Reading.query.filter_by(user_id=current_user.id)
# Handle filtering if it's a POST request
if request.method == 'POST':
start_date = request.form.get('start_date')
end_date = request.form.get('end_date')
start_date = request.form.get('start_date') or start_date
end_date = request.form.get('end_date') or end_date
if start_date and end_date:
start_date_obj = datetime.strptime(start_date, '%Y-%m-%d')
end_date_obj = datetime.strptime(end_date, '%Y-%m-%d')
readings_query = readings_query.filter(
Reading.timestamp >= start_date_obj,
Reading.timestamp <= end_date_obj
Reading.timestamp >= datetime.strptime(start_date, '%Y-%m-%d'),
Reading.timestamp <= datetime.strptime(end_date, '%Y-%m-%d')
)
# Format start_date and end_date for the template
start_date = start_date_obj.strftime('%Y-%m-%d')
end_date = end_date_obj.strftime('%Y-%m-%d')
# Fetch and order readings
# Fetch readings
readings = readings_query.order_by(Reading.timestamp.desc()).all()
# Add human-readable relative timestamps to readings
# Add relative timestamps to readings
now = datetime.utcnow()
for reading in readings:
reading.relative_timestamp = humanize.naturaltime(now - reading.timestamp)
# Calculate weekly summary and progress badges
systolic_avg, diastolic_avg, heart_rate_avg = calculate_weekly_summary(readings)
weekly_readings = [r for r in readings if r.timestamp >= (datetime.now() - timedelta(days=7))]
badges = calculate_progress_badges(readings, weekly_readings)
# Weekly summary (last 7 days)
one_week_ago = datetime.now() - timedelta(days=7)
weekly_readings = [r for r in readings if r.timestamp >= one_week_ago]
systolic_avg = round(sum(r.systolic for r in weekly_readings) / len(weekly_readings), 1) if weekly_readings else 0
diastolic_avg = round(sum(r.diastolic for r in weekly_readings) / len(weekly_readings), 1) if weekly_readings else 0
heart_rate_avg = round(sum(r.heart_rate for r in weekly_readings) / len(weekly_readings), 1) if weekly_readings else 0
# Progress badges
badges = []
if len(readings) >= 10:
badges.append("10 Readings Logged")
if len(readings) >= 100:
badges.append("100 Readings Milestone")
if len(weekly_readings) >= 7:
badges.append("Logged Readings for 7 Days")
# Prepare data for the graphs
# Prepare graph data
timestamps = [reading.timestamp.strftime('%b %d') for reading in readings]
systolic = [reading.systolic for reading in readings]
diastolic = [reading.diastolic for reading in readings]
heart_rate = [reading.heart_rate for reading in readings]
# Pass the delete form to the template
delete_form = DeleteForm()
# Render template
return render_template(
'dashboard.html',
readings=readings,
@@ -144,7 +165,7 @@ def dashboard():
systolic_avg=systolic_avg,
diastolic_avg=diastolic_avg,
heart_rate_avg=heart_rate_avg,
delete_form=delete_form,
delete_form=DeleteForm(),
timestamps=timestamps,
systolic=systolic,
diastolic=diastolic,