Fitness and Activity Tracker is a web application that helps users set and track their fitness goals. The app integrates with the wger Workout Manager API to provide exercise recommendations, log daily workouts, and visualize progress through charts.
This application is developed using Flask for the backend, SQLite for the database, and SQLAlchemy as the ORM. It includes account management features for secure user authentication and leverages Docker for containerization.
-
Account Management
- Securely store passwords using hashing with salts
- Allow users to register, log in, and update their passwords
-
Workout Tracking
- Log daily workouts and activities
- Set and track fitness goals
- View progress using charts
-
Exercise Recommendations
- Fetch exercise recommendations from the wger Workout Manager API
- Save favorite exercises or routines
-
Health Check
- Verify the app's status through a health check route
- Backend Framework: Flask
- Database: SQLite
- ORM: SQLAlchemy
- External API: wger Workout Manager API
- Containerization: Docker
- Python 3.10+
- Docker (if containerizing the app)
- Clone the repository:
git clone <[email protected]:arnavSingh23/CS411-FinalProject.git>
cd fitness-tracker
- Create a virtual environment and install dependencies:
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
- Set up your environment variables:
- Create a
.env
file in the project root and add the following variables:
- Create a
FLASK_APP=app.py
FLASK_ENV=development
SECRET_KEY=<your-secret-key>
API_KEY=<wger-api-key>
- Initialize the database:
flask db init
flask db migrate
flask db upgrade
- Start the Flask application:
flask run
- Open the app in your browser at
http://127.0.0.1:5000
- Build the Docker image:
docker build -t fitness-tracker .
- Run the Docker container:
docker run -p 5000:5000 --env-file .env fitness-tracker
- Login
- Route:
/login
- Method: POST
- Purpose: Authenticate users by verifying their password against stored hashes
- Request Format:
- Route:
{
"username": "string",
"password": "string"
}
- Response Format:
{
"message": "Login successful",
"token": "jwt-token-string"
}
-
Error Response:
-
Status: 401 Unauthorized
{
"message": "Invalid username or password"
}
- Status: 400 Bad Request
{
"message": "Missing required fields"
}
- Status 500 Interal Server Error
{
"message": "An unexpected error occurred"
}
- Create Account
- Route:
/create-account
- Method: POST
- Purpose: Allow users to register
- Request Format:
- Route:
{
"username": "string",
"password": "string"
}
- Response Format:
{
"message": "Account created successfully"
}
-
Error Response:
-
Status: 400 Bad Request
{
"message": "Username already exists"
}
- Status: 400 Bad Request
{
"message": "Missing required fields"
}
- Status 500 Interal Server Error
{
"message": "An unexpected error occurred"
}
- Update Password
- Route:
/update-password
- Method: POST
- Purpose: Allow users to update their password
- Request Format:
- Route:
{
"username": "string",
"current_password": "string",
"new_password": "string"
}
- Response Format:
{
"message": "Password updated successfully"
}
-
Error Response:
-
Status: 401 Unauthorized
{
"message": "Invalid username or current password"
}
- Status: 400 Bad Request
{
"message": "Missing required fields"
}
- Status 500 Interal Server Error
{
"message": "An unexpected error occurred"
}
-
Route:
/health
- Method: GET
- Purpose: Health check route to verify the app is running
-
Response Format:
{
"status": "OK"
}
- Log Workouts
- Route:
/log-workout
- Method: POST
- Purpose: Log user workouts
- Request Format:
{ "user_id": "integer", "exercise_id": "integer", "repetitions": "integer", "weight": "float", "date": "YYYY-MM-DD", "comment": "string" }
- Response Format:
{ "message": "Workout logged successfully" }
- Route:
- View Workouts
- Route:
/view-workouts
- Method: GET
- Purpose: Retrieve all logged workouts for a user
- Request Format:
{ "user_id": "integer" }
- Response Format:
{ "exercise_id": "integer", "repetitions": "integer", "weight": "float", "date": "YYYY-MM-DD", "comment": "string" }
- Route:
- Health Check
- Route:
/health
- Method: GET
- Purpose: Verify the app is running
- Response Format:
- Route:
{
"status": "OK"
}
- Excercise Recommendandations
Route: /recommendations
Method: GET
Purpose:
Retrieve exercise recommendations from the Wger Workout Manager API based on specified filters for category and equipment.
Parameter | Type | Required | Description |
---|---|---|---|
category |
str |
No | Filter exercises by category ID. |
equipment |
str |
No | Filter exercises by equipment ID. |
curl "http://127.0.0.1:5000/recommendations?category=4&equipment=7"
β
- The API fetches exercise data from the Wger Workout Manager API based on the provided category and equipment filters.
- If the API call is successful, a list of exercises is returned in JSON format.
- If the API call fails, an error message with status code 500 is returned.
- Save Exercise
Route:
/save-exercise
Method:POST
Purpose:
Allow users to save favorite exercises into an in-memory dictionary for future access.
Parameter | Type | Required | Description |
---|---|---|---|
user_id |
int |
Yes | The ID of the user saving the exercise. |
exercise_id |
int |
Yes | The ID of the exercise being saved. |
name |
str |
Yes | The name of the exercise. |
description |
str |
No | A description of the exercise. |
- Request Format:
{
"user_id": 1,
"exercise_id": 101,
"name": "Push-ups",
"description": "An exercise for chest and triceps."
}
- Response Format:
{
"exercise_id": "integer",
"repetitions": "integer",
"weight": "float",
"date": "YYYY-MM-DD",
"comment": "string"
}
- This route allows users to save specific exercises as favorites.
- Users must provide their user_id and details of the exercise to be saved.
- If successful, a confirmation message is returned.
- If an error occurs, a status code with a corresponding error message is returned.
-
Error Response:
-
Status: Status Code 400
{
"message": "Missing required fields in the request."
}
- Status: Status Code 500
{
"message": "An unexpected error occurred."
}