Browse Source

initial commit

master
Madiwka3 1 year ago
commit
b877ccd545
17 changed files with 579 additions and 0 deletions
  1. +3
    -0
      .vscode/settings.json
  2. +3
    -0
      app/.vscode/settings.json
  3. +13
    -0
      app/Dockerfile
  4. BIN
      app/__pycache__/main.cpython-39.pyc
  5. +260
    -0
      app/app.py
  6. +6
    -0
      app/requirements.txt
  7. +1
    -0
      app/tempCodeRunnerFile.py
  8. +73
    -0
      app/templates/base.html
  9. +18
    -0
      app/templates/caregiver_dashboard.html
  10. +26
    -0
      app/templates/create_job.html
  11. +30
    -0
      app/templates/family_dashboard.html
  12. +20
    -0
      app/templates/login.html
  13. +41
    -0
      app/templates/register.html
  14. +26
    -0
      app/templates/update.html
  15. +26
    -0
      app/templates/update_job.html
  16. +19
    -0
      docker-compose.yml
  17. +14
    -0
      vercel.json

+ 3
- 0
.vscode/settings.json View File

@@ -0,0 +1,3 @@
{
"workbench.colorTheme": "Atom One Dark"
}

+ 3
- 0
app/.vscode/settings.json View File

@@ -0,0 +1,3 @@
{
"workbench.colorTheme": "Copilot Theme"
}

+ 13
- 0
app/Dockerfile View File

@@ -0,0 +1,13 @@
FROM python:3.11-slim

WORKDIR /app
COPY ./requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
ENV PYTHONPATH "${PYTHONPATH}:/app/"
COPY . .



EXPOSE 5000
CMD [ "flask", "run", "--host=0.0.0.0", "--port=5000"]


BIN
app/__pycache__/main.cpython-39.pyc View File


+ 260
- 0
app/app.py View File

@@ -0,0 +1,260 @@
from flask import Flask, render_template, request, redirect, url_for, jsonify, flash, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required
from datetime import datetime, timedelta
from sqlalchemy import MetaData, create_engine
from sqlalchemy.ext.automap import automap_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base


app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqlconnector://root:12345@localhost/assignment'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = 'jwt_secret_key'
app.config['JWT_ACCESS_TOKEN_EXPIRES'] = timedelta(days=1)
app.config['SECRET_KEY'] = 'secret_key'
jwt = JWTManager(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'

db = SQLAlchemy(app)

class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
email = db.Column(db.String(255), nullable=False)
given_name = db.Column(db.String(255), nullable=False)
surname = db.Column(db.String(255), nullable=False)
city = db.Column(db.String(255))
phone_number = db.Column(db.String(20))
profile_description = db.Column(db.Text)
password = db.Column(db.String(255), nullable=False)
role = db.Column(db.String(20), nullable = False)

class Caregiver(db.Model):
caregiver_user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'), primary_key=True)
photo = db.Column(db.LargeBinary)
gender = db.Column(db.String(20))
caregiving_type = db.Column(db.String(255))
hourly_rate = db.Column(db.Integer)
user = db.relationship('User', backref='caregiver', uselist=False)

class Member(db.Model):
member_user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'), primary_key=True)
house_rules = db.Column(db.Text)
user = db.relationship('User', backref='member', uselist=False)

class Address(db.Model):
member_user_id = db.Column(db.Integer, db.ForeignKey('member.member_user_id'), primary_key=True)
house_number = db.Column(db.Integer)
street = db.Column(db.String(255))
town = db.Column(db.String(255))
member = db.relationship('Member', backref='address', uselist=False)

class Job(db.Model):
job_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
member_user_id = db.Column(db.Integer, db.ForeignKey('member.member_user_id'))
required_caregiving_type = db.Column(db.String(255))
other_requirements = db.Column(db.Text)
date_posted = db.Column(db.Date)
member = db.relationship('Member', backref='jobs')

class JobApplication(db.Model):
caregiver_user_id = db.Column(db.Integer, db.ForeignKey('caregiver.caregiver_user_id'), primary_key=True)
job_id = db.Column(db.Integer, db.ForeignKey('job.job_id'), primary_key=True)
date_applied = db.Column(db.Date)

class Appointment(db.Model):
appointment_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
caregiver_user_id = db.Column(db.Integer, db.ForeignKey('caregiver.caregiver_user_id'))
member_user_id = db.Column(db.Integer, db.ForeignKey('member.member_user_id'))
appointment_date = db.Column(db.Date)
appointment_time = db.Column(db.Time)
work_hours = db.Column(db.String(50))
status = db.Column(db.String(50))



login_manager = LoginManager(app)
login_manager.login_view = 'login'

@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))

headers = {'Content-Type': 'application/json'}

@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))

@app.route('/', methods=['GET'])
def login_page():
return render_template('login.html')

@app.route('/', methods=['POST'])
def login_user():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']

user = User.query.filter_by(email=email).first()

if user and user.password == password:
session['user_id'] = user.user_id
session['role'] = user.role
access_token = create_access_token(identity=user.user_id)

if user.role == 'caregiver':
return redirect(url_for('caregiver_dashboard'))
elif user.role == 'family':
return redirect(url_for('family_dashboard'))

else:
return jsonify({'status': 'error', 'message': 'Invalid email or password'}), 401

@app.route('/caregiver_dashboard')
def caregiver_dashboard():
if 'user_id' in session and session.get('role') == 'caregiver':
user_id = session.get('user_id')
user = User.query.get(user_id)
return render_template('caregiver_dashboard.html', user=user)
else:
return redirect(url_for('login_page'))

@app.route('/family_dashboard')
def family_dashboard():
if 'user_id' in session and session.get('role') == 'family':
user_id = session.get('user_id')
user = User.query.get(user_id)
jobs = Job.query.filter_by(member_user_id=user_id).all()
return render_template('family_dashboard.html', user=user, jobs=jobs)
else:
return redirect(url_for('login_page'))

@app.route('/protected', methods=['GET'])
@login_required
def protected():
current_user = get_jwt_identity()
return jsonify(logged_in_as=current_user), 200


@app.route('/register', methods=['GET'])
def registration_page():
return render_template('register.html')


@app.route('/register', methods=['POST'])
def register():
username = request.form.get('username', None)
password = request.form.get('password', None)
given_name = request.form.get('name', None)
surname = request.form.get('surname', None)
city = request.form.get('city', None)
phone_number = request.form.get('phone_number', None)
profile_description = request.form.get('profile_description', None)
role = request.form.get('role', None)

if not username or not password or not given_name or not surname or not city or not phone_number or not profile_description or not role:
return jsonify({'message': 'All fields are required'}), 400

existing_user = User.query.filter_by(email=username).first()

if existing_user:
return jsonify({'message': 'User already exists'}), 409

new_user = User(email=username, password=password, given_name=given_name, surname=surname, city=city, phone_number=phone_number, profile_description=profile_description, role=role)

db.session.add(new_user)
db.session.commit()

return redirect(url_for('login_page'))

@app.route('/update/<int:user_id>', methods=['GET', 'POST'])
def update_user(user_id):
user = User.query.get(user_id)

if request.method == 'POST':
user.email = request.form['email']
user.given_name = request.form['given_name']
user.surname = request.form['surname']
user.city = request.form['city']
user.phone_number = request.form['phone_number']
user.profile_description = request.form['profile_description']

db.session.commit()

if user.role == 'caregiver':
return redirect(url_for('caregiver_dashboard'))
elif user.role == 'family':
return redirect(url_for('family_dashboard'))

return render_template('update.html', user=user)


@app.route('/create_job', methods=['GET', 'POST'])
def create_job():
if request.method == 'POST':
user_id = session.get('user_id')
member = User.query.get(user_id)

new_job = Job(
member_user_id=user_id,
required_caregiving_type=request.form['required_caregiving_type'],
other_requirements=request.form['other_requirements'],
date_posted=datetime.now().date()
)

db.session.add(new_job)
db.session.commit()

flash("Job created successfully", "success")
return redirect(url_for('family_dashboard'))

return render_template('create_job.html')

@app.route('/update_job/<int:job_id>', methods=['GET', 'POST'])
def update_job(job_id):
job = Job.query.get(job_id)

if not job:
flash("Job not found", "error")
return redirect(url_for('family_dashboard'))

if request.method == 'POST':
job.required_caregiving_type = request.form['required_caregiving_type']
job.other_requirements = request.form['other_requirements']
job.date_posted = datetime.now().date()

db.session.commit()

flash("Job updated successfully", "success")
return redirect(url_for('family_dashboard'))

return render_template('update_job.html', job=job)

@app.route('/delete_job/<int:job_id>', methods=['GET'])
def delete_job(job_id):
job = Job.query.get(job_id)

if not job:
flash("Job not found", "error")
return redirect(url_for('family_dashboard'))

db.session.delete(job)
db.session.commit()

flash("Job deleted successfully", "success")
return redirect(url_for('family_dashboard'))


@app.route('/logout')
def logout_user():
session.pop('user_id', None)
return redirect(url_for('login_page'))

if __name__ == '__main__':
app.run(debug=True)

+ 6
- 0
app/requirements.txt View File

@@ -0,0 +1,6 @@
Flask==2.0.1
Flask-SQLAlchemy==2.5.1
Werkzeug==2.0.1
Flask-JWT-Extended==4.2.3
Flask-Login==0.5.0
SQLAlchemy==1.4.25

+ 1
- 0
app/tempCodeRunnerFile.py View File

@@ -0,0 +1 @@
/

+ 73
- 0
app/templates/base.html View File

@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ page_title }}</title>
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
}

main {
max-width: 300px;
padding: 20px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

label {
display: block;
margin-bottom: 8px;
color: #555;
}

input {
width: 100%;
padding: 8px;
margin-bottom: 16px;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 4px;
}

button {
background-color: #4caf50;
color: #fff;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
display: block;
width: 100%;
}

button:hover {
background-color: #45a049;
}

p {
color: red;
text-align: center;
}
</style>
</head>

<body>

<main>
{% block content %}{% endblock %}
</main>

</body>

</html>

+ 18
- 0
app/templates/caregiver_dashboard.html 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>User List</title>
</head>
<body>
<h2>Caregiver dashboard</h2>
<ul>
<li>
{{ user.given_name }} {{ user.surname }}
<a href="{{ url_for('update_user', user_id=user.user_id) }}">Update</a>
</li>
</ul>
<a href="{{ url_for('logout_user') }}">Logout</a>
</body>
</html>

+ 26
- 0
app/templates/create_job.html View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">

<head>
<!-- Head content -->
</head>

<body>
<h2>Create Job</h2>

{% if message %}
<p>{{ message }}</p>
{% endif %}

<form action="{{ url_for('create_job') }}" method="post">
<label for="required_caregiving_type">Required Caregiving Type:</label>
<input type="text" id="required_caregiving_type" name="required_caregiving_type" required>

<label for="other_requirements">Other Requirements:</label>
<textarea id="other_requirements" name="other_requirements" required></textarea>

<button type="submit">Create Job</button>
</form>
</body>

</html>

+ 30
- 0
app/templates/family_dashboard.html View File

@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>User List</title>
</head>
<body>
<h2>Family member dashboard</h2>
<ul>
<li>
{{ user.given_name }} {{ user.surname }}
<a href="{{ url_for('update_user', user_id=user.user_id) }}">Update</a>
</li>
</ul>
<h3>Jobs:</h3>
<ul>
{% for job in jobs %}
<li>
{{ job.required_caregiving_type }} - {{ job.other_requirements }}
<a href="{{ url_for('update_job', job_id=job.job_id) }}">Update</a>
<a href="{{ url_for('delete_job', job_id=job.job_id) }}" onclick="return confirm('Are you sure you want to delete this job?')">Delete</a>
</li>
{% endfor %}
</ul>
<a href="{{ url_for('create_job') }}">Create New Job</a>
<br>
<a href="{{ url_for('logout_user') }}">Logout</a>
</body>
</html>

+ 20
- 0
app/templates/login.html View File

@@ -0,0 +1,20 @@
{% extends 'base.html' %}

{% block title %}Login{% endblock %}

{% block content %}
{% if message %}
<p>{{ message }}</p>
{% endif %}

<form action="/" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>

<label for="password">Password:</label>
<input type="password" id="password" name="password" required>

<button type="submit">Login</button>
</form>
<p><a href="{{ url_for('registration_page') }}">Register here</a></p>
{% endblock %}

+ 41
- 0
app/templates/register.html View File

@@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Registration</title>
</head>
<body>
<h1>Registration</h1>
<form method="post" action="/register">
<label for="username">Username (Email):</label>
<input type="text" id="username" name="username" required>

<label for="password">Password:</label>
<input type="password" id="password" name="password" required>

<label for="name">Given Name:</label>
<input type="text" id="name" name="name" required>

<label for="surname">Surname:</label>
<input type="text" id="surname" name="surname" required>

<label for="city">City:</label>
<input type="text" id="city" name="city" required>

<label for="phone_number">Phone Number:</label>
<input type="text" id="phone_number" name="phone_number" required>

<label for="profile_description">Profile Description:</label>
<textarea id="profile_description" name="profile_description" rows="4" required></textarea>

<label for="role">Role:</label>
<select id="role" name="role" required>
<option value="family">Family</option>
<option value="caregiver">Caregiver</option>
</select>

<button type="submit">Register</button>
</form>
</body>
</html>

+ 26
- 0
app/templates/update.html 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>Update User</title>
</head>
<body>
<h1>Update User</h1>
<form method="post" action="{{ url_for('update_user', user_id=user.user_id) }}">
<label>Email:</label>
<input type="email" name="email" value="{{ user.email }}" required><br>
<label>Given Name:</label>
<input type="text" name="given_name" value="{{ user.given_name }}" required><br>
<label>Surname:</label>
<input type="text" name="surname" value="{{ user.surname }}" required><br>
<label>City:</label>
<input type="text" name="city" value="{{ user.city }}"><br>
<label>Phone Number:</label>
<input type="text" name="phone_number" value="{{ user.phone_number }}"><br>
<label>Profile Description:</label>
<textarea name="profile_description">{{ user.profile_description }}</textarea><br>
<input type="submit" value="Update">
</form>
</body>
</html>

+ 26
- 0
app/templates/update_job.html View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">

<head>
<!-- Head content -->
</head>

<body>
<h2>Update Job</h2>

{% if message %}
<p>{{ message }}</p>
{% endif %}

<form action="{{ url_for('update_job', job_id=job.job_id) }}" method="post">
<label for="required_caregiving_type">Required Caregiving Type:</label>
<input type="text" id="required_caregiving_type" name="required_caregiving_type" value="{{ job.required_caregiving_type }}" required>

<label for="other_requirements">Other Requirements:</label>
<textarea id="other_requirements" name="other_requirements" required>{{ job.other_requirements }}</textarea>

<button type="submit">Update Job</button>
</form>
</body>

</html>

+ 19
- 0
docker-compose.yml View File

@@ -0,0 +1,19 @@
version: "3"

services:
app:
build: app
restart: always
links:
- "db"
ports:
- "5000:5000"
environment:
- FLASK_ENV= production
db:
image: mysql:8.0
ports:
- "32000:3306"
restart: always
environment:
MYSQL_ROOT_PASSWORD: 12345

+ 14
- 0
vercel.json View File

@@ -0,0 +1,14 @@
{
"builds": [
{
"src": "api/app.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "api/app.py"
}
]
}

Loading…
Cancel
Save