From 95a0b1dde395d79ad7c05607e5ec4ab519f8076d Mon Sep 17 00:00:00 2001 From: sstent Date: Thu, 18 Dec 2025 09:22:56 -0800 Subject: [PATCH] first commit --- CentralDB | 1 + DB_API_SPEC.json | 1 + GarminSync | 1 + GarminSync_API_SPEC.json | 1 + LLMCoach | 1 + ReportGenerator | 1 + Report_API_SPEC.json | 0 WebUI | 1 + docker-compose.dev.yml | 39 ++++++++++++++++++++++++ docker-compose.yml | 65 ++++++++++++++++++++++++++++++++++++++++ 10 files changed, 111 insertions(+) create mode 160000 CentralDB create mode 100644 DB_API_SPEC.json create mode 160000 GarminSync create mode 100644 GarminSync_API_SPEC.json create mode 160000 LLMCoach create mode 160000 ReportGenerator create mode 100644 Report_API_SPEC.json create mode 160000 WebUI create mode 100644 docker-compose.dev.yml create mode 100644 docker-compose.yml diff --git a/CentralDB b/CentralDB new file mode 160000 index 0000000..97b7486 --- /dev/null +++ b/CentralDB @@ -0,0 +1 @@ +Subproject commit 97b74861b8d8c65dc9f67ffe8752a67eabf69d7d diff --git a/DB_API_SPEC.json b/DB_API_SPEC.json new file mode 100644 index 0000000..ebf7435 --- /dev/null +++ b/DB_API_SPEC.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"FitTrack CentralDB API","description":"The API for the FitTrack CentralDB service.","version":"1.0.0"},"paths":{"/activities/{user_id}":{"post":{"summary":"Upload Activity","operationId":"upload_activity_activities__user_id__post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","description":"The ID of the user uploading the activity","title":"User Id"},"description":"The ID of the user uploading the activity"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_activity_activities__user_id__post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/activities":{"get":{"summary":"Get All Activities","operationId":"get_all_activities_activities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/Activity"},"type":"array","title":"Response Get All Activities Activities Get"}}}}}}},"/activities/{activity_id}":{"get":{"summary":"Get Activity By Id","operationId":"get_activity_by_id_activities__activity_id__get","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Activity"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/activities/{activity_id}/file":{"get":{"summary":"Download Activity File","operationId":"download_activity_file_activities__activity_id__file_get","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/activities/{activity_id}/analysis":{"post":{"summary":"Create Analysis Artifact","operationId":"create_analysis_artifact_activities__activity_id__analysis_post","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisArtifactCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisArtifact"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Analysis Artifact","operationId":"get_analysis_artifact_activities__activity_id__analysis_get","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AnalysisArtifact"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/activities/{activity_id}/analysis/artifacts":{"get":{"summary":"List Analysis Artifacts And Charts","operationId":"list_analysis_artifacts_and_charts_activities__activity_id__analysis_artifacts_get","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CombinedArtifactMetadata"},"title":"Response List Analysis Artifacts And Charts Activities Activity Id Analysis Artifacts Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/activities/{activity_id}/analysis/charts":{"post":{"summary":"Upload Chart","operationId":"upload_chart_activities__activity_id__analysis_charts_post","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}},{"name":"chart_create","in":"query","required":true,"schema":{"title":"Chart Create"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_chart_activities__activity_id__analysis_charts_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Chart"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/activities/{activity_id}/analysis/charts/{chart_type}":{"get":{"summary":"Retrieve Chart","operationId":"retrieve_chart_activities__activity_id__analysis_charts__chart_type__get","parameters":[{"name":"activity_id","in":"path","required":true,"schema":{"type":"integer","title":"Activity Id"}},{"name":"chart_type","in":"path","required":true,"schema":{"type":"string","title":"Chart Type"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/coaching/sessions":{"get":{"summary":"Get All Coaching Sessions","operationId":"get_all_coaching_sessions_coaching_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CoachingSession"},"type":"array","title":"Response Get All Coaching Sessions Coaching Sessions Get"}}}}}},"post":{"summary":"Create Coaching Session","operationId":"create_coaching_session_coaching_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingSessionCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingSession"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users":{"post":{"summary":"Create User","operationId":"create_user_users_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Read Users","operationId":"read_users_users_get","parameters":[{"name":"skip","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Skip"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/User"},"title":"Response Read Users Users Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/{user_id}":{"get":{"summary":"Read User","operationId":"read_user_users__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Update User","operationId":"update_user_users__user_id__put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/User"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete User","operationId":"delete_user_users__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health_metrics":{"post":{"summary":"Create Health Metric","operationId":"create_health_metric_health_metrics_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthMetricCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthMetric"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health_metrics/{metric_id}":{"get":{"summary":"Read Health Metric","operationId":"read_health_metric_health_metrics__metric_id__get","parameters":[{"name":"metric_id","in":"path","required":true,"schema":{"type":"integer","title":"Metric Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthMetric"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Update Health Metric","operationId":"update_health_metric_health_metrics__metric_id__put","parameters":[{"name":"metric_id","in":"path","required":true,"schema":{"type":"integer","title":"Metric Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthMetricUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthMetric"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Health Metric","operationId":"delete_health_metric_health_metrics__metric_id__delete","parameters":[{"name":"metric_id","in":"path","required":true,"schema":{"type":"integer","title":"Metric Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/{user_id}/health_metrics":{"get":{"summary":"Read Health Metrics By User","operationId":"read_health_metrics_by_user_users__user_id__health_metrics_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/HealthMetric"},"title":"Response Read Health Metrics By User Users User Id Health Metrics Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/workout_plans":{"post":{"summary":"Create Workout Plan","operationId":"create_workout_plan_workout_plans_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutPlanCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutPlan"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/workout_plans/{plan_id}":{"get":{"summary":"Read Workout Plan","operationId":"read_workout_plan_workout_plans__plan_id__get","parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"integer","title":"Plan Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutPlan"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Update Workout Plan","operationId":"update_workout_plan_workout_plans__plan_id__put","parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"integer","title":"Plan Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutPlanUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutPlan"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"summary":"Delete Workout Plan","operationId":"delete_workout_plan_workout_plans__plan_id__delete","parameters":[{"name":"plan_id","in":"path","required":true,"schema":{"type":"integer","title":"Plan Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/users/{user_id}/workout_plans":{"get":{"summary":"Read Workout Plans By User","operationId":"read_workout_plans_by_user_users__user_id__workout_plans_get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WorkoutPlan"},"title":"Response Read Workout Plans By User Users User Id Workout Plans Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens/":{"post":{"tags":["tokens"],"summary":"Create Token Api","operationId":"create_token_api_tokens__post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tokens/{user_id}":{"get":{"tags":["tokens"],"summary":"Get Token Api","operationId":"get_token_api_tokens__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["tokens"],"summary":"Update Token Api","operationId":"update_token_api_tokens__user_id__put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Token"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["tokens"],"summary":"Delete Token Api","operationId":"delete_token_api_tokens__user_id__delete","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/garmin_credentials/{user_id}":{"post":{"summary":"Create Garmin Credentials","operationId":"create_garmin_credentials_garmin_credentials__user_id__post","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminCredentialsCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminCredentials"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"summary":"Get Garmin Credentials","operationId":"get_garmin_credentials_garmin_credentials__user_id__get","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminCredentials"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"summary":"Update Garmin Credentials","operationId":"update_garmin_credentials_garmin_credentials__user_id__put","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"integer","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminCredentialsUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminCredentials"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/":{"get":{"tags":["Root"],"summary":"Read Root","operationId":"read_root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"Activity":{"properties":{"user_id":{"type":"integer","title":"User Id"},"file_path":{"type":"string","title":"File Path"},"activity_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Activity Metadata"},"id":{"type":"integer","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["user_id","file_path","id","created_at"],"title":"Activity"},"AnalysisArtifact":{"properties":{"id":{"type":"integer","title":"Id"},"activity_id":{"type":"integer","title":"Activity Id"},"data":{"title":"Data"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","activity_id","data","created_at"],"title":"AnalysisArtifact"},"AnalysisArtifactCreate":{"properties":{"data":{"title":"Data"}},"type":"object","required":["data"],"title":"AnalysisArtifactCreate"},"AnalysisArtifactMetadata":{"properties":{"id":{"type":"integer","title":"Id"},"type":{"type":"string","title":"Type","default":"analysis_artifact"},"activity_id":{"type":"integer","title":"Activity Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","activity_id","created_at"],"title":"AnalysisArtifactMetadata"},"Body_upload_activity_activities__user_id__post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_activity_activities__user_id__post"},"Body_upload_chart_activities__activity_id__analysis_charts_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_chart_activities__activity_id__analysis_charts_post"},"Chart":{"properties":{"id":{"type":"integer","title":"Id"},"activity_id":{"type":"integer","title":"Activity Id"},"chart_type":{"type":"string","title":"Chart Type"},"file_path":{"type":"string","title":"File Path"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","activity_id","chart_type","file_path","created_at"],"title":"Chart"},"ChartMetadata":{"properties":{"id":{"type":"integer","title":"Id"},"type":{"type":"string","title":"Type","default":"chart"},"activity_id":{"type":"integer","title":"Activity Id"},"chart_type":{"type":"string","title":"Chart Type"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","activity_id","chart_type","created_at"],"title":"ChartMetadata"},"CoachingSession":{"properties":{"conversation":{"additionalProperties":true,"type":"object","title":"Conversation"},"id":{"type":"integer","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["conversation","id","created_at"],"title":"CoachingSession"},"CoachingSessionCreate":{"properties":{"conversation":{"additionalProperties":true,"type":"object","title":"Conversation"}},"type":"object","required":["conversation"],"title":"CoachingSessionCreate"},"CombinedArtifactMetadata":{"anyOf":[{"$ref":"#/components/schemas/AnalysisArtifactMetadata"},{"$ref":"#/components/schemas/ChartMetadata"}],"title":"CombinedArtifactMetadata"},"GarminCredentials":{"properties":{"user_id":{"type":"integer","title":"User Id"},"garmin_username":{"type":"string","title":"Garmin Username"},"garmin_password_plaintext":{"type":"string","title":"Garmin Password Plaintext"}},"type":"object","required":["user_id","garmin_username","garmin_password_plaintext"],"title":"GarminCredentials"},"GarminCredentialsCreate":{"properties":{"garmin_username":{"type":"string","title":"Garmin Username"},"garmin_password_plaintext":{"type":"string","title":"Garmin Password Plaintext"}},"type":"object","required":["garmin_username","garmin_password_plaintext"],"title":"GarminCredentialsCreate"},"GarminCredentialsUpdate":{"properties":{"garmin_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Garmin Username"},"garmin_password_plaintext":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Garmin Password Plaintext"}},"type":"object","title":"GarminCredentialsUpdate"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthMetric":{"properties":{"user_id":{"type":"integer","title":"User Id"},"metric_type":{"type":"string","title":"Metric Type"},"value":{"type":"number","title":"Value"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"},"id":{"type":"integer","title":"Id"}},"type":"object","required":["user_id","metric_type","value","id"],"title":"HealthMetric"},"HealthMetricCreate":{"properties":{"user_id":{"type":"integer","title":"User Id"},"metric_type":{"type":"string","title":"Metric Type"},"value":{"type":"number","title":"Value"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"}},"type":"object","required":["user_id","metric_type","value"],"title":"HealthMetricCreate"},"HealthMetricUpdate":{"properties":{"metric_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Metric Type"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp"}},"type":"object","title":"HealthMetricUpdate"},"Token":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"user_id":{"type":"string","title":"User Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["access_token","refresh_token","expires_at","user_id","created_at"],"title":"Token"},"TokenCreate":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"user_id":{"type":"string","title":"User Id"}},"type":"object","required":["access_token","refresh_token","expires_at","user_id"],"title":"TokenCreate"},"TokenUpdate":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["access_token","refresh_token","expires_at"],"title":"TokenUpdate"},"User":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"preferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preferences"},"id":{"type":"integer","title":"Id"}},"type":"object","required":["name","email","id"],"title":"User"},"UserCreate":{"properties":{"name":{"type":"string","title":"Name"},"email":{"type":"string","format":"email","title":"Email"},"preferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preferences"}},"type":"object","required":["name","email"],"title":"UserCreate"},"UserUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"preferences":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Preferences"}},"type":"object","title":"UserUpdate"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WorkoutPlan":{"properties":{"user_id":{"type":"integer","title":"User Id"},"plan_details":{"additionalProperties":true,"type":"object","title":"Plan Details"},"id":{"type":"integer","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["user_id","plan_details","id","created_at"],"title":"WorkoutPlan"},"WorkoutPlanCreate":{"properties":{"user_id":{"type":"integer","title":"User Id"},"plan_details":{"additionalProperties":true,"type":"object","title":"Plan Details"}},"type":"object","required":["user_id","plan_details"],"title":"WorkoutPlanCreate"},"WorkoutPlanUpdate":{"properties":{"plan_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Plan Details"}},"type":"object","title":"WorkoutPlanUpdate"}}}} \ No newline at end of file diff --git a/GarminSync b/GarminSync new file mode 160000 index 0000000..b0aa585 --- /dev/null +++ b/GarminSync @@ -0,0 +1 @@ +Subproject commit b0aa585372412e8fba0ccf4caa92352a8781ab99 diff --git a/GarminSync_API_SPEC.json b/GarminSync_API_SPEC.json new file mode 100644 index 0000000..962b070 --- /dev/null +++ b/GarminSync_API_SPEC.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"GarminSync Backend","version":"0.1.0"},"paths":{"/api/sync/garmin/activities":{"post":{"tags":["Garmin Sync"],"summary":"Trigger Garmin Activity Sync","description":"Trigger Garmin Connect Activity Synchronization","operationId":"trigger_garmin_activity_sync_api_sync_garmin_activities_post","parameters":[{"name":"max_activities_to_sync","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":10,"title":"Max Activities To Sync"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivitySyncRequest"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sync/garmin/workouts":{"post":{"tags":["Garmin Sync"],"summary":"Upload Garmin Workout","description":"Upload a workout to Garmin Connect","operationId":"upload_garmin_workout_api_sync_garmin_workouts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkoutUploadRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/sync/garmin/health":{"post":{"tags":["Garmin Sync"],"summary":"Trigger Garmin Health Sync","description":"Trigger Garmin Connect Health Metrics Synchronization","operationId":"trigger_garmin_health_sync_api_sync_garmin_health_post","responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/sync/garmin/sync/status":{"get":{"tags":["Garmin Sync"],"summary":"Get Garmin Sync Status","description":"Retrieve the current status of the single active synchronization job.","operationId":"get_garmin_sync_status_api_sync_garmin_sync_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncJob"}}}}}}},"/api/garmin/login":{"post":{"tags":["Garmin Auth"],"summary":"Garmin Login","description":"Authenticate with Garmin Connect using username and password.\nStores Garmin credentials and authentication tokens in the CentralDB.","operationId":"garmin_login_api_garmin_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminLoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GarminLoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/logout":{"post":{"summary":"Logout","operationId":"logout_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/":{"get":{"summary":"Root","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/background-test":{"post":{"summary":"Run Background Test","operationId":"run_background_test_background_test_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"ActivitySyncRequest":{"properties":{"force_resync":{"type":"boolean","title":"Force Resync","description":"If true, re-download activities even if they exist. Defaults to false.","default":false},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date","description":"Optional start date (YYYY-MM-DD) to sync activities from. If not provided, syncs recent activities."},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date","description":"Optional end date (YYYY-MM-DD) to sync activities up to."}},"type":"object","title":"ActivitySyncRequest"},"GarminLoginRequest":{"properties":{"username":{"type":"string","title":"Username"},"password":{"type":"string","title":"Password"}},"type":"object","required":["username","password"],"title":"GarminLoginRequest"},"GarminLoginResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"GarminLoginResponse"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"SyncJob":{"properties":{"status":{"type":"string","enum":["pending","in_progress","completed","failed"],"title":"Status","default":"pending"},"progress":{"type":"number","title":"Progress","default":0.0},"start_time":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Time"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"job_type":{"anyOf":[{"type":"string","enum":["activities","health","workouts"]},{"type":"null"}],"title":"Job Type"}},"type":"object","title":"SyncJob"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WorkoutUploadRequest":{"properties":{"workout_id":{"type":"integer","title":"Workout Id","description":"The ID of the workout to upload from CentralDB."}},"type":"object","required":["workout_id"],"title":"WorkoutUploadRequest"}}}} \ No newline at end of file diff --git a/LLMCoach b/LLMCoach new file mode 160000 index 0000000..c861dbe --- /dev/null +++ b/LLMCoach @@ -0,0 +1 @@ +Subproject commit c861dbe1ffe8727a9ba8083fe2d8db9d57f49b7e diff --git a/ReportGenerator b/ReportGenerator new file mode 160000 index 0000000..cbe5c83 --- /dev/null +++ b/ReportGenerator @@ -0,0 +1 @@ +Subproject commit cbe5c83300907f02bb45f9b0942566ae01e54d8a diff --git a/Report_API_SPEC.json b/Report_API_SPEC.json new file mode 100644 index 0000000..e69de29 diff --git a/WebUI b/WebUI new file mode 160000 index 0000000..b76a30f --- /dev/null +++ b/WebUI @@ -0,0 +1 @@ +Subproject commit b76a30f5691e012c961fe16f33ff44b247cbab39 diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..33e98d4 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,39 @@ +version: '3.8' + +services: + backend: + build: + context: ./backend + dockerfile: Dockerfile + ports: + - "8001:8001" + volumes: + - ./backend:/app + environment: + - API_PORT=8001 + - CENTRAL_DB_URL=http://central_db:8000 + command: uvicorn src.main:app --host 0.0.0.0 --port 8001 --reload + depends_on: + - central_db + networks: + - fittrack-network + + central_db: + build: + context: ../FitTrack_CentralDB + dockerfile: Dockerfile + ports: + - "8000:8000" + environment: + - GARMIN_CREDENTIALS_ENCRYPTION_KEY=_dbk9p2Rs2p6fx9fHD6x9wy_vr_t723JGhgzALIoE8E= + volumes: + - central_db_data:/app/data # Add this line to persist data + networks: + - fittrack-network + +volumes: + central_db_data: # Define the named volume + +networks: + fittrack-network: + driver: bridge \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..d106712 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,65 @@ +version: '3.8' + +services: + garminsync: + build: + context: ./GarminSync/backend + dockerfile: Dockerfile + ports: + - "8001:8001" + volumes: + - ./GarminSync/backend:/app + environment: + - API_PORT=8001 + - CENTRAL_DB_URL=http://central_db:8000 + command: uvicorn src.main:app --host 0.0.0.0 --port 8001 --reload + depends_on: + - central_db + networks: + - fittrack-network + + reportgenerator: + build: + context: ./ReportGenerator + dockerfile: Dockerfile + ports: + - "8002:8002" + environment: + - API_PORT=8001 + - CENTRAL_DB_URL=http://central_db:8000 + command: uvicorn src.main:app --host 0.0.0.0 --port 8002 --reload + depends_on: + - central_db + networks: + - fittrack-network + + webui: + build: + context: WebUI/frontend + dockerfile: Dockerfile + ports: + - "3000:80" + depends_on: + - central_db + networks: + - fittrack-network + + central_db: + build: + context: ./CentralDB + dockerfile: Dockerfile + ports: + - "8000:8000" + environment: + - GARMIN_CREDENTIALS_ENCRYPTION_KEY=_dbk9p2Rs2p6fx9fHD6x9wy_vr_t723JGhgzALIoE8E= + volumes: + - central_db_data:/app/data # Add this line to persist data + networks: + - fittrack-network + +volumes: + central_db_data: # Define the named volume + +networks: + fittrack-network: + driver: bridge \ No newline at end of file