Add initial project structure with Docker setup and frontend/backend files

This commit is contained in:
2024-10-17 18:57:05 -04:00
parent 86f36c4754
commit 4cce05f7d6
15 changed files with 606 additions and 0 deletions

9
frontend/Dockerfile Executable file
View File

@@ -0,0 +1,9 @@
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV SECRET_KEY=super-secret
ENV API_URL=http://backend:5000
EXPOSE 8000
CMD ["python", "app.py"]

101
frontend/app.py Executable file
View File

@@ -0,0 +1,101 @@
import os
from flask import Flask, render_template, redirect, url_for, request, session, jsonify
import requests
app = Flask(__name__)
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'super-secret')
API_URL = os.environ.get('API_URL', 'http://localhost:5000')
@app.route('/')
def index():
if 'access_token' in session:
return redirect(url_for('dashboard'))
return render_template('index.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
data = {
'name': request.form['name'],
'email': request.form['email'],
'age': request.form['age'],
'location': request.form['location'],
'gender': request.form['gender'],
'password': request.form['password']
}
response = requests.post(f"{API_URL}/users", json=data)
if response.status_code == 201:
return redirect(url_for('login'))
else:
return render_template('register.html', error=response.json().get('message', 'Error during registration'))
return render_template('register.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
response = requests.post(f"{API_URL}/auth", json={'email': email, 'password': password})
if response.status_code == 200:
session['access_token'] = response.json()['access_token']
# Save the user ID from the access token or fetch it from the API
session['user_id'] = email # Or any unique identifier like user ID
return redirect(url_for('dashboard'))
else:
return render_template('login.html', error=response.json().get('message', 'Invalid credentials'))
return render_template('login.html')
@app.route('/dashboard')
def dashboard():
if 'access_token' not in session:
return redirect(url_for('login'))
# Fetch the current user's details
headers = {'Authorization': f'Bearer {session["access_token"]}'}
user_response = requests.get(f"{API_URL}/users/me", headers=headers) # Adjust the API URL as necessary
user = user_response.json() if user_response.status_code == 200 else None
# Handle search filters
location = request.args.get('location', '')
age = request.args.get('age', '')
gender = request.args.get('gender', 'Any')
filters = {}
if location:
filters['location'] = location
if age:
filters['age'] = age
if gender and gender != "Any":
filters['gender'] = gender
# Fetch users based on filters
response = requests.get(f"{API_URL}/users", params=filters, headers=headers)
users = response.json() if response.status_code == 200 else []
# Fetch messages for the current user
messages_response = requests.get(f"{API_URL}/messages", headers=headers)
messages = messages_response.json() if messages_response.status_code == 200 else []
return render_template('dashboard.html', user=user, users=users, messages=messages)
@app.route('/messages', methods=['POST'])
def send_message():
if 'access_token' not in session:
return redirect(url_for('login'))
data = {
'receiver_id': request.form['receiver_id'],
'content': request.form['message_content']
}
headers = {'Authorization': f'Bearer {session["access_token"]}', 'Content-Type': 'application/json'}
response = requests.post(f"{API_URL}/messages", headers=headers, json=data)
if response.status_code == 201:
return redirect(url_for('dashboard'))
else:
return jsonify({'message': 'Error sending message'}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=True)

4
frontend/requirements.txt Executable file
View File

@@ -0,0 +1,4 @@
Flask==2.2.5
requests==2.31.0
Werkzeug==2.3.0
Flask-JWT-Extended==4.4.4

View File

@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>Welcome, {{ user.name }}</h1>
<a href="{{ url_for('logout') }}">Logout</a>
<h2>Search Users</h2>
<form method="GET">
<input type="text" name="location" placeholder="Location">
<input type="number" name="age" placeholder="Age">
<select name="gender">
<option value="Any">Any</option>
<option value="Male">Male</option>
<option value="Female">Female</option>
</select>
<button type="submit">Search</button>
</form>
<h2>Users</h2>
<ul>
{% for user in users %}
<li>{{ user.name }} - {{ user.age }} years old - {{ user.location }} - {{ user.gender }}</li>
{% else %}
<li>No users found.</li>
{% endfor %}
</ul>
<h2>Messages</h2>
<form method="POST" action="{{ url_for('send_message') }}">
<input type="hidden" name="receiver_id" value="{{ user.id }}">
<textarea name="message_content" placeholder="Type your message here..."></textarea>
<button type="submit">Send Message</button>
</form>
<ul>
{% for message in messages %}
<li>{{ message.content }}</li>
{% else %}
<li>No messages found.</li>
{% endfor %}
</ul>
</div>
</body>
</html>

13
frontend/templates/eula.html Executable file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>End User License Agreement</title>
</head>
<body>
<h1>End User License Agreement (EULA)</h1>
<p>[Insert your EULA text here]</p>
<a href="{{ url_for('register') }}">Back to Registration</a>
</body>
</html>

18
frontend/templates/index.html Executable file
View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>Welcome to the Workout Buddy</h1>
<div>
<a href="{{ url_for('login') }}">Login</a>
<a href="{{ url_for('register') }}">Register</a>
</div>
</div>
</body>
</html>

26
frontend/templates/login.html Executable file
View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>Login</h1>
<form method="POST">
<label for="email">Email:</label>
<input type="email" name="email" required>
<label for="password">Password:</label>
<input type="password" name="password" required>
<button type="submit">Login</button>
</form>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
</div>
</body>
</html>

View File

@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>Register</h1>
<form method="POST">
<div class="form-group">
<label for="name">Name:</label>
<input type="text" name="name" required>
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="email" name="email" required>
</div>
<div class="form-group">
<label for="age">Age:</label>
<input type="number" name="age" min="18" required>
</div>
<div class="form-group">
<label for="location">Location:</label>
<input type="text" name="location" required>
</div>
<div class="form-group">
<label for="gender">Gender:</label>
<select name="gender" required>
<option value="Male">Male</option>
<option value="Female">Female</option>
<option value="Prefer Not to Say">Prefer Not to Say</option>
</select>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" name="password" required>
</div>
<p>By registering, you agree to our <a href="/eula" target="_blank">End User License Agreement (EULA)</a>.</p>
<button type="submit">Register</button>
</form>
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
</div>
</body>
</html>

View File

@@ -0,0 +1,40 @@
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4; /* Light background color for better visibility */
}
.container {
max-width: 400px; /* Limit the width of the form container */
margin: 50px auto; /* Center the form horizontally and add vertical margin */
padding: 20px;
background-color: white; /* White background for the form */
border-radius: 8px; /* Rounded corners for the form */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
}
h1 {
text-align: center; /* Center the heading */
}
.form-group {
margin-bottom: 500px; /* Increase space between form groups */
}
button {
width: 100%; /* Make the button full-width */
padding: 10px; /* Add padding to the button */
background-color: #28a745; /* Green background color */
color: white; /* White text color */
border: none; /* Remove default border */
border-radius: 5px; /* Rounded corners for the button */
cursor: pointer; /* Change cursor to pointer on hover */
}
button:hover {
background-color: #218838; /* Darker green on hover */
}
.error {
color: red; /* Red color for error messages */
text-align: center; /* Center error messages */
}

40
frontend/templates/styles.css Executable file
View File

@@ -0,0 +1,40 @@
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4; /* Light background color for better visibility */
}
.container {
max-width: 400px; /* Limit the width of the form container */
margin: 50px auto; /* Center the form horizontally and add vertical margin */
padding: 20px;
background-color: white; /* White background for the form */
border-radius: 8px; /* Rounded corners for the form */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
}
h1 {
text-align: center; /* Center the heading */
}
.form-group {
margin-bottom: 500px; /* Increase space between form groups */
}
button {
width: 100%; /* Make the button full-width */
padding: 10px; /* Add padding to the button */
background-color: #28a745; /* Green background color */
color: white; /* White text color */
border: none; /* Remove default border */
border-radius: 5px; /* Rounded corners for the button */
cursor: pointer; /* Change cursor to pointer on hover */
}
button:hover {
background-color: #218838; /* Darker green on hover */
}
.error {
color: red; /* Red color for error messages */
text-align: center; /* Center error messages */
}