diff --git a/api/backend/Health_Analyst_Blueprint/average_duration b/api/backend/Health_Analyst_Blueprint/average_duration new file mode 100644 index 0000000000..8b7fe7d147 --- /dev/null +++ b/api/backend/Health_Analyst_Blueprint/average_duration @@ -0,0 +1,48 @@ +from flask import Blueprint, jsonify, request +from backend.db_connection import db +from mysql.connector import Error +from flask import current_app + +# Create a Blueprint for average duration route +average_duration = Blueprint("average_duration", __name__) + +@average_duration.route("/client_workout_log/avg_duration", methods=["GET"]) +def get_average_workout_duration(): + # Get query parameters for filtering + try: + year = request.args.get("year") + week = request.args.get("week") + + # Prepare the Base query + query = """ + SELECT + c.client_id, + YEAR(cwl.date) AS year, + WEEK(cwl.date, 1) AS week, + AVG(cwl.duration_minutes) AS avg_duration + FROM Client c + JOIN Client_Workout_Log cwl ON c.client_id = cwl.client_id + WHERE cwl.completion_status = 'completed' + """ + params = [] + if year: + query += " AND YEAR(cwl.date) = %s" + params.append(year) + if week: + query += " AND WEEK(cwl.date, 1) = %s" + params.append(week) + query += """ + GROUP BY c.client_id, YEAR(cwl.date), WEEK(cwl.date, 1) + ORDER BY c.client_id, year, week; + """ + + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query, params) + duration = cursor.fetchall() + cursor.close() + + current_app.logger.info(f'Successfully retrieved {len(ngos)} NGOs') + return jsonify(duration), 200 + except Error as e: + current_app.logger.error(f'Database error in get_average_workout_duration: {str(e)}') + return jsonify({"error": str(e)}), 500 diff --git a/api/backend/Health_Analyst_Blueprint/client_info b/api/backend/Health_Analyst_Blueprint/client_info new file mode 100644 index 0000000000..ab7c571aa6 --- /dev/null +++ b/api/backend/Health_Analyst_Blueprint/client_info @@ -0,0 +1,68 @@ +from flask import Blueprint, jsonify, request +from backend.db_connection import db +from mysql.connector import Error +from flask import current_app + + +client_info = Blueprint('client_info', __name__) +@client_info.route("/client/", methods=["GET"]) +def get_client_info(client_id): + try: + query = """ + SELECT + c.client_id, + c.first_name, + c.last_name, + c.date_of_birth, + c.Goals, + c.fitness_level, + c.Age, + c.join_date + FROM Client c; + """ + + cursor = db.get_db().cursor() + cursor.execute(query) + clients = cursor.fetchall() + cursor.close() + return jsonify(clients), 200 + except Error as e: + return jsonify({"error": str(e)}), 500 + + +@client_info.route("/client/", methods=["PUT"]) +def update_client_info(client_id): + try: + data = request.getjson() + + fields = [ + 'first_name', + 'last_name', + 'date_of_birth', + 'Goals', + 'fitness_level', + 'Age', + 'join_date' + ] + updates = [] + params = [] + + for f in fields: + if f in data: + updates.append(f"{f} = %s") + params.append(date[f]) + if not updates: + return jsonify({"error": "No valid fields provided."}), 400 + params.append(client_id) + + query = f""" + UPDATE Client + SET {", ".join(updates)} + WHERE client_id = %s + """ + cursor = db.get_db().cursor() + cursor.execute(query, params) + cursor.close() + return jsonify({"message: Client demographic information updated"}), 200 + except Error as e: + return jsonify({"error": str(e)}), 500 \ No newline at end of file diff --git a/api/backend/Health_Analyst_Blueprint/health_metrics b/api/backend/Health_Analyst_Blueprint/health_metrics new file mode 100644 index 0000000000..ced261f6ff --- /dev/null +++ b/api/backend/Health_Analyst_Blueprint/health_metrics @@ -0,0 +1,114 @@ +from flask import Blueprint, jsonify, request +from backend.db_connection import db +from mysql.connector import Error +from flask import current_app + + +health_metrics = Blueprint('health_metrics', __name__) +@health_metrics.route("/health_metrics", methods=["GET"]) +def get_most_recent_health_metrics(): + try: + query = """ + SELECT + hm.client_id, + hm.record_date, + hm.weight_kg, + hm.body_fat_percentage, + hm.heart_rate + FROM Health_Metrics hm + WHERE hm.record_date = ( + SELECT MAX(record_date) + FROM Health_Metrics + WHERE client_id = hm.client_id + ); + """ + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query) + metrics = cursor.fetchall() + cursor.close() + + current_app.logger.info(f'Successfully retrieved {len(metrics)} health metric records') + return jsonify(metrics), 200 + except Error as e: + current_app.logger.error(f'Database error in get_most_recent_health_metric: {str(e)}') + return jsonify({"error": str(e)}), 500 + + +@health_metrics.route("/health_metrics", methods=["POST"]) +def add_health_metric(): + try: + data = request.get_json() + required_fields = [ + 'client_id', + 'record_date', + 'weight_kg', + 'body_fat_percentage', + 'heart-rate' + ] + + for field in allowed_fields: + if field not in data: + return jsonify({"error": f"Missing required field: {field}"}) + + query = """ + INSERT INTO Health_Metrics + (client_id, record_date, weight_kg, body_fat_percentage, heart_rate) + VALUES (%s, %s, %s, %s, %s); + """ + params = ( + data['client_id'], + data['record_date'], + data['weight_kg'], + data['body_fat_percentage'], + data['heart_rate'] + ) + + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query, params) + cursor.close() + + current_app.logger.info("New metric successfully created") + return jsonify({"message: Health metric record added successfully"}), 201 + except Error as e: + current_app.logger.error(f'Database error in add_health_metric: {str(e)}') + return jsonify({"error": str(e)}), 500 + + +@health_metrics.route("/health_metrics", methods=["PUT"]) +def update_health_metric(metric_id): + try: + data = request.get_json() + + fields = [ + 'record_date', + 'weight_kg', + 'body_fat_percentage', + 'heart_rate' + ] + + updates = [] + params = [] + + for f in fields: + if f in data: + updates.append(f"{f} = %s") + params.append(data[f]) + if not updates: + return jsonify({"error": "No valid fields provided"}, 400) + params.append(metric_id) + + query = f""" + UPDATE Health_Metrics + SET{", ".join(updates)} + WHERE metric_id = %s; + """ + + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query, params) + cursor.close() + + current_app.logger.info("Health metric successfully updated") + return jsonify({"message: Health metric record updated successfully"}), 200 + except Error as e: + current_app.logger.error(f'Database error in update_health_metric: {str(e)}') + return jsonify({"error": str(e)}), 500 diff --git a/api/backend/Health_Analyst_Blueprint/health_progression b/api/backend/Health_Analyst_Blueprint/health_progression new file mode 100644 index 0000000000..4d7c740a25 --- /dev/null +++ b/api/backend/Health_Analyst_Blueprint/health_progression @@ -0,0 +1,31 @@ +from flask import Blueprint, jsonify, request +from backend.db_connection import db +from mysql.connector import Error +from flask import current_app + + +health_progression = Blueprint('health_progression', __name__) +@health_progression.route("/health_metric//month", methods=["GET"]) +def get_health_progression(): + try: + query = """ + SELECT + client_id, + MONTH(hm.record_date) AS month, + AVG(weight_kg), + AVG(body_fat_percentage) + FROM Health_Metrics hm + GROUP BY client_id, MONTH(hm.record_date) + ORDER BY client_id, month; + """ + + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query) + progression = cursor.fetchall() + cursor.close() + + current_app.logger.info(f'Successfully retrieved {len(progression)} health metric records') + return jsonify(progression), 200 + except Error as e: + current_app.logger.error(f'Database error in get_health_progression: {str(e)}') + return jsonify({"error": str(e)}), 500 \ No newline at end of file diff --git a/api/backend/Health_Analyst_Blueprint/program_completion_rate b/api/backend/Health_Analyst_Blueprint/program_completion_rate new file mode 100644 index 0000000000..3e4b68a56b --- /dev/null +++ b/api/backend/Health_Analyst_Blueprint/program_completion_rate @@ -0,0 +1,36 @@ +from flask import Blueprint, jsonify, request +from backend.db_connection import db +from mysql.connector import Error +from flask import current_app + + +analytics = Blueprint('analytics', __name__) +@analytics.route("/client_specific_workout_program//completion_rate", methods=["GET"]) +def get_program_completion_rate(): + try: + query = """ + SELECT + cswp.program_id, + cswp.name AS program_name, + COUNT(cwl.log_id) AS total_workouts, + SUM(cwl.completion_status = 'completed') AS completed_workouts, + ROUND( + SUM(cwl.completion_status = 'completed') / COUNT(cwl.log_id), + 3 + ) AS completion_rate + FROM Client_Specific_Workout_Program cswp JOIN Client_Workout_Log cwl + ON cswp.workout_id = cwl.workout_id + AND cswp.client_id = cwl.client_id + GROUP BY cswp.program_id, cswp.name + ORDER BY completion_rate DESC; + """ + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query) + completion = cursor.fetchall() + cursor.close() + + current_app.logger.info(f'Successfully retrieved program completion rate') + return jsonify(completion), 200 + except Error as e: + current_app.logger.error(f'Database error in get_program_completion_rate: {str(e)}') + return jsonify({"error": str(e)}), 500 diff --git a/api/backend/Health_Analyst_Blueprint/workout_program_frequency b/api/backend/Health_Analyst_Blueprint/workout_program_frequency new file mode 100644 index 0000000000..233965c188 --- /dev/null +++ b/api/backend/Health_Analyst_Blueprint/workout_program_frequency @@ -0,0 +1,31 @@ +from flask import Blueprint, jsonify, request +from backend.db_connection import db +from mysql.connector import Error +from flask import current_app + + +frequency = Blueprint('frequency', __name__) +@frequency.route("/workout_session_template/used", methods=["GET"]) +def get_program_frequency(): + try: + query = """ + SELECT + cwl.workout_id, + wst.name, + COUNT(*) AS used + FROM Client_Workout_Log cwl JOIN Workout_Session_Template wst + ON cwl.workout_id = wst.workout_id + GROUP BY cwl.workout_id, wst.name + ORDER BY used DESC; + """ + + current_app.logger.debug(f'Executing query: {query}') + cursor.execute(query) + count = cursor.fetchall() + cursor.close() + + current_app.logger.info(f'Successfully retried workout program frequency') + return jsonify(count), 200 + except Error as e: + current_app.logger.error(f'Database error in get_program_frequecy: {str(e)}') + return jsonify({"error": str(e)}), 500 diff --git a/app/src/pages/03_Average_Duration b/app/src/pages/03_Average_Duration new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/04_Client_info b/app/src/pages/04_Client_info new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/05_Health_Metrics b/app/src/pages/05_Health_Metrics new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/06_Progression b/app/src/pages/06_Progression new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/07_Program_Completion b/app/src/pages/07_Program_Completion new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/08_Program_Frequency b/app/src/pages/08_Program_Frequency new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/src/pages/Analyst_Home b/app/src/pages/Analyst_Home new file mode 100644 index 0000000000..e69de29bb2