Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ bin
include
lib
.Python
tests/
.envrc
__pycache__
__pycache__
.idea/
.coverage
44 changes: 28 additions & 16 deletions clubs.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
{"clubs":[
{
"name":"Simply Lift",
"email":"john@simplylift.co",
"points":"13"
},
{
"name":"Iron Temple",
"email": "admin@irontemple.com",
"points":"4"
},
{ "name":"She Lifts",
"email": "kate@shelifts.co.uk",
"points":"12"
}
]}
{
"clubs": [
{
"name": "Simply Lift",
"email": "john@simplylift.co",
"password": "pbkdf2:sha256:150000$eHVGmFVY$00afed3d5a39621cc5aad05d069b8d8643c9e3e47435471f40861e608e825711",
"points": "13"
},
{
"name": "Power Lift",
"email": "admin@powerlift.com",
"password": "pbkdf2:sha256:150000$YEgAXbf8$09b68fdd4ab198aaf541a4b3a3b680449fff602e43bbfb1e602e970e9acf7b4c",
"points": "5"
},
{
"name": "She Lifts",
"email": "kate@shelifts.co.uk",
"password": "pbkdf2:sha256:150000$g7r5qSMn$fecca97e2fcca7b093a4ca60789c4ebc0b6f4c0331aaaeee1ffa9f03a3404ad5",
"points": "12"
},
{
"name": "Iron Temple",
"email": "admin@irontemple.com",
"password": "pbkdf2:sha256:150000$G0hKG0dK$434a98095c828d2735c63724fe9ae142a88d4aaba9489733c7fd614db655237a",
"points": "4"
}
]
}
22 changes: 16 additions & 6 deletions competitions.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
{
"competitions": [
{
"name": "Spring Festival",
"date": "2020-03-27 10:00:00",
"numberOfPlaces": "25"
},
{
"name": "Fall Classic",
"date": "2020-10-22 13:30:00",
"numberOfPlaces": "13"
"number_of_places": "13"
},
{
"name": "Winter Power",
"date": "2026-06-26 12:16:00",
"number_of_places": "4"
},
{
"name": "Summer Stronger",
"date": "2026-05-30 18:23:40",
"number_of_places": "0"
},
{
"name": "Spring Festival",
"date": "2026-07-27 10:00:00",
"number_of_places": "25"
}
]
}
263 changes: 237 additions & 26 deletions server.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,265 @@
import json
from flask import Flask,render_template,request,redirect,flash,url_for

from datetime import datetime
from flask import Flask, render_template, request, redirect, flash, url_for
from werkzeug.security import generate_password_hash, check_password_hash

def loadClubs():

def load_clubs():
with open('clubs.json') as c:
listOfClubs = json.load(c)['clubs']
return listOfClubs
list_of_clubs = json.load(c)['clubs']
return list_of_clubs


def loadCompetitions():
def load_competitions():
with open('competitions.json') as comps:
listOfCompetitions = json.load(comps)['competitions']
return listOfCompetitions

list_of_competitions = json.load(comps)['competitions']
return list_of_competitions

app = Flask(__name__)
app.secret_key = 'something_special'

competitions = loadCompetitions()
clubs = loadClubs()
competitions = load_competitions()
clubs = load_clubs()

CLUB_POINTS = 15

def update_club_booked_places(club, places, competition_name):
clubs.remove(club)

club.setdefault("booked_places", {})
current = int(club["booked_places"].get(competition_name, 0))
club["booked_places"][competition_name] = str(current + places)

club["points"] = str(int(club["points"]) - places)

clubs.append(club)
save_clubs()

def save_clubs():
with open('clubs.json', 'w') as c:
list_of_clubs = {"clubs": clubs}
json.dump(list_of_clubs, c, indent=4)

def update_competition_available_places(competition, places):
competitions.remove(competition)

competition['number_of_places'] = str(int(competition['number_of_places']) - places)

competitions.append(competition)
save_competitions()

def save_competitions():
with open('competitions.json', 'w') as comps:
list_of_competitions = {"competitions": competitions}
json.dump(list_of_competitions, comps, indent=4)

def add_club(name, email, password, points):
clubs.append({"name": name, "email": email, "password": password, "points": points})
save_clubs()

def update_club_password(club, password):
club["password"] = password
save_clubs()
return club

@app.route('/')
def index():
return render_template('index.html')

@app.route('/showSummary',methods=['POST'])
def showSummary():
club = [club for club in clubs if club['email'] == request.form['email']][0]
return render_template('welcome.html',club=club,competitions=competitions)
@app.route('/signUp')
def sign_up():
return render_template('sign_up.html')

@app.route('/profile/<club>', methods=['GET'])
def profile(club):
the_club = next((c for c in clubs if c['name'] == club), None)

if the_club is None:
flash("Sorry, that club was not found.")
return render_template(template_name_or_list="index.html", error="Club not found"), 404

return render_template(template_name_or_list='profile.html', club=the_club)

@app.route('/profile', methods=['POST'])
def profile_post():
club_name = request.form['name']
club_email = request.form['email']
club_password = request.form['password']
club_password_confirmation = request.form['confirm_password']

club_exists = next((c for c in clubs if c['email'] == club_email or c['name'] == club_name), None)
if club_exists is None:
if club_password != club_password_confirmation:
flash('Sorry, passwords do not match')
return redirect(url_for('sign_up'))

hashed_password = generate_password_hash(club_password)
add_club(club_name, club_email, hashed_password, str(CLUB_POINTS))

the_club = next((c for c in clubs if c['email'] == club_email), None)

if the_club is None:
flash("Sorry, something went wrong. Please try again.")
return render_template(template_name_or_list='sign_up.html')

flash("Great! You have successfully signed up.")
return render_template(template_name_or_list='profile.html', club=the_club)

else:
flash("Sorry, the club already exists.")
return render_template(template_name_or_list='sign_up.html')

@app.route('/changePassword/<club>', methods=['GET', 'POST'])
def change_password(club):
if request.method == 'GET':
the_club = next((c for c in clubs if c['name'] == club), None)

if the_club is None:
flash("Sorry, that club was not found.")
return render_template(template_name_or_list="index.html", error="Email not found"), 404

return render_template(template_name_or_list='change_password.html', club=the_club)
else:
club_password = request.form['password']
club_password_confirmation = request.form['confirm_password']

if club_password != club_password_confirmation:
flash('Sorry, passwords do not match')
return redirect(url_for('change_password'))

the_club = next((c for c in clubs if c['name'] == club), None)
hashed_password = generate_password_hash(club_password)

if check_password_hash(the_club['password'], club_password):
flash('Sorry, you have to type a new different password.')
return render_template(template_name_or_list='change_password.html', club=the_club)

the_club = update_club_password(the_club, hashed_password)

if the_club:
flash("Great! You have successfully changed your password.")
return render_template(template_name_or_list='profile.html', club=the_club)

flash("Sorry, something went wrong. Please try again.")
return render_template(template_name_or_list='index.html')


@app.route('/showSummary/<club>', methods=['GET'])
def show_summary(club):
the_club = next((c for c in clubs if c['name'] == club), None)
return render_template(template_name_or_list='welcome.html',
club=the_club,
competitions=competitions)

@app.route('/showSummary', methods=['POST'])
def show_summary_post():
the_club = next((c for c in clubs if c['email'] == request.form['email']), None)

if the_club is None:
flash("Sorry, that email was not found.")
return render_template(template_name_or_list="index.html", error="Email not found"), 404

if not check_password_hash(the_club['password'], request.form['password']):
flash("Sorry, the password is incorrect.")
return render_template(template_name_or_list="index.html",)

return render_template(template_name_or_list='welcome.html',
club=the_club,
competitions=competitions)

@app.route('/book/<competition>/<club>')
def book(competition,club):
foundClub = [c for c in clubs if c['name'] == club][0]
foundCompetition = [c for c in competitions if c['name'] == competition][0]
if foundClub and foundCompetition:
return render_template('booking.html',club=foundClub,competition=foundCompetition)
def book(competition, club):
found_club = [c for c in clubs if c['name'] == club][0]
found_competition = [c for c in competitions if c['name'] == competition][0]

now = datetime.now()

competition_date = datetime.strptime(found_competition['date'], '%Y-%m-%d %H:%M:%S')

error_message = ""
error_tag = ""

the_competition = next((a_competition for a_competition in competitions
if a_competition['name'] == competition), None)
competition_places = int(the_competition['number_of_places'])

if now > competition_date:
error_message = "Sorry, this competition is outdated. Booking not possible."
error_tag = "Outdated"

elif competition_places == 0:
error_message = "Sorry, this competition is sold out. Booking not possible."
error_tag = "Sold out"

if error_message and error_tag:
flash(error_message)

the_club = next((a_club for a_club in clubs if a_club['name'] == club), None)

return render_template(template_name_or_list='welcome.html',
club=the_club,
competitions=competitions,
error=error_tag), 403

if found_club and found_competition:
return render_template(template_name_or_list='booking.html',
club=found_club,
competition=found_competition)
else:
flash("Something went wrong-please try again")
return render_template('welcome.html', club=club, competitions=competitions)
flash("Sorry, something went wrong. Please try again.")
return render_template(template_name_or_list='welcome.html',
club=club,
competitions=competitions)


@app.route('/purchasePlaces',methods=['POST'])
def purchasePlaces():
def purchase_places():
competition = [c for c in competitions if c['name'] == request.form['competition']][0]
club = [c for c in clubs if c['name'] == request.form['club']][0]
placesRequired = int(request.form['places'])
competition['numberOfPlaces'] = int(competition['numberOfPlaces'])-placesRequired
flash('Great-booking complete!')
return render_template('welcome.html', club=club, competitions=competitions)
places_required = int(request.form['places'])

cumulative_places = places_required + int(club["booked_places"][competition["name"]]) \
if "booked_places" in club else places_required

error_message = ""
error_tag = ""

if places_required < 0:
error_message = "Sorry, you should type a positive number."
error_tag = "Negative number"

elif cumulative_places > 12:
error_message = "Sorry, you are not allow to purchase more than 12 places for this competition."
error_tag = "Over 12 places"

elif places_required > int(competition['number_of_places']):
error_message = "Sorry, there are not enough places available for this competition."
error_tag = "Not enough places"

elif places_required > int(club['points']):
error_message = "Sorry, you do not have enough points to purchase."
error_tag = "Not enough points"

if error_message and error_tag:
flash(error_message)
return render_template(template_name_or_list='welcome.html',
club=club,
competitions=competitions,
error=error_tag), 403

update_club_booked_places(club=club,
places=places_required,
competition_name=competition["name"])

update_competition_available_places(competition=competition, places=places_required)

flash(f"Great! Booking of {places_required} places for "
f"{competition['name']} competition complete!")

return render_template(template_name_or_list='welcome.html',
club=club,
competitions=competitions)


# TODO: Add route for points display
Expand Down
2 changes: 1 addition & 1 deletion templates/booking.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
</head>
<body>
<h2>{{competition['name']}}</h2>
Places available: {{competition['numberOfPlaces']}}
Places available: {{competition['number_of_places']}}
<form action="/purchasePlaces" method="post">
<input type="hidden" name="club" value="{{club['name']}}">
<input type="hidden" name="competition" value="{{competition['name']}}">
Expand Down
Loading