Add progress badge denoting current streak length, and refactor dashboard route
This commit is contained in:
135
app/routes.py
135
app/routes.py
@@ -58,84 +58,105 @@ def landing():
|
|||||||
@main.route('/dashboard', methods=['GET', 'POST'])
|
@main.route('/dashboard', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def dashboard():
|
def dashboard():
|
||||||
# Initialize start_date and end_date
|
# Helper function to get first and last reading timestamps
|
||||||
start_date = None
|
def get_reading_date_range(user_id):
|
||||||
end_date = None
|
result = (
|
||||||
|
db.session.query(
|
||||||
# Retrieve the first and last timestamps in a single query
|
func.min(Reading.timestamp).label('first'),
|
||||||
first_last_readings = (
|
func.max(Reading.timestamp).label('last')
|
||||||
db.session.query(
|
)
|
||||||
func.min(Reading.timestamp).label('first'),
|
.filter(Reading.user_id == user_id)
|
||||||
func.max(Reading.timestamp).label('last')
|
.first()
|
||||||
)
|
)
|
||||||
.filter(Reading.user_id == current_user.id)
|
return result.first, result.last
|
||||||
.first()
|
|
||||||
)
|
|
||||||
|
|
||||||
# Extract the first and last timestamps
|
# Helper function to calculate weekly summary averages
|
||||||
first_reading_timestamp = first_last_readings.first
|
def calculate_weekly_summary(readings):
|
||||||
last_reading_timestamp = first_last_readings.last
|
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
|
# Helper function to calculate progress badges
|
||||||
if not start_date and first_reading_timestamp:
|
def calculate_progress_badges(readings, weekly_readings):
|
||||||
start_date = first_reading_timestamp.strftime('%Y-%m-%d')
|
badges = []
|
||||||
if not end_date and last_reading_timestamp:
|
|
||||||
end_date = last_reading_timestamp.strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
# Default to all readings
|
# 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()
|
||||||
|
|
||||||
|
# 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)
|
readings_query = Reading.query.filter_by(user_id=current_user.id)
|
||||||
|
|
||||||
# Handle filtering if it's a POST request
|
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
start_date = request.form.get('start_date')
|
start_date = request.form.get('start_date') or start_date
|
||||||
end_date = request.form.get('end_date')
|
end_date = request.form.get('end_date') or end_date
|
||||||
|
|
||||||
if start_date and 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(
|
readings_query = readings_query.filter(
|
||||||
Reading.timestamp >= start_date_obj,
|
Reading.timestamp >= datetime.strptime(start_date, '%Y-%m-%d'),
|
||||||
Reading.timestamp <= end_date_obj
|
Reading.timestamp <= datetime.strptime(end_date, '%Y-%m-%d')
|
||||||
)
|
)
|
||||||
|
|
||||||
# Format start_date and end_date for the template
|
# Fetch readings
|
||||||
start_date = start_date_obj.strftime('%Y-%m-%d')
|
|
||||||
end_date = end_date_obj.strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
# Fetch and order readings
|
|
||||||
readings = readings_query.order_by(Reading.timestamp.desc()).all()
|
readings = readings_query.order_by(Reading.timestamp.desc()).all()
|
||||||
|
|
||||||
# Add human-readable relative timestamps to readings
|
# Add relative timestamps to readings
|
||||||
now = datetime.utcnow()
|
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)
|
||||||
|
|
||||||
|
# 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)
|
# Prepare graph data
|
||||||
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
|
|
||||||
timestamps = [reading.timestamp.strftime('%b %d') for reading in readings]
|
timestamps = [reading.timestamp.strftime('%b %d') for reading in readings]
|
||||||
systolic = [reading.systolic for reading in readings]
|
systolic = [reading.systolic for reading in readings]
|
||||||
diastolic = [reading.diastolic for reading in readings]
|
diastolic = [reading.diastolic for reading in readings]
|
||||||
heart_rate = [reading.heart_rate for reading in readings]
|
heart_rate = [reading.heart_rate for reading in readings]
|
||||||
|
|
||||||
# Pass the delete form to the template
|
# Render template
|
||||||
delete_form = DeleteForm()
|
|
||||||
|
|
||||||
return render_template(
|
return render_template(
|
||||||
'dashboard.html',
|
'dashboard.html',
|
||||||
readings=readings,
|
readings=readings,
|
||||||
@@ -144,7 +165,7 @@ def dashboard():
|
|||||||
systolic_avg=systolic_avg,
|
systolic_avg=systolic_avg,
|
||||||
diastolic_avg=diastolic_avg,
|
diastolic_avg=diastolic_avg,
|
||||||
heart_rate_avg=heart_rate_avg,
|
heart_rate_avg=heart_rate_avg,
|
||||||
delete_form=delete_form,
|
delete_form=DeleteForm(),
|
||||||
timestamps=timestamps,
|
timestamps=timestamps,
|
||||||
systolic=systolic,
|
systolic=systolic,
|
||||||
diastolic=diastolic,
|
diastolic=diastolic,
|
||||||
|
|||||||
Reference in New Issue
Block a user