diff --git a/.gitignore b/.gitignore index 2cba99d87..09821350e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ lib .Python tests/ .envrc -__pycache__ \ No newline at end of file +__pycache__ +venv/ \ No newline at end of file diff --git a/clubs.json b/clubs.json index 1d7ad1ffe..922fe165e 100644 --- a/clubs.json +++ b/clubs.json @@ -1,16 +1,19 @@ -{"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" - } -]} \ No newline at end of file +{ + "clubs": [ + { + "name": "Simply Lift", + "email": "john@simplylift.co", + "points": "6" + }, + { + "name": "Iron Temple", + "email": "admin@irontemple.com", + "points": "1" + }, + { + "name": "She Lifts", + "email": "kate@shelifts.co.uk", + "points": "12" + } + ] +} \ No newline at end of file diff --git a/competitions.json b/competitions.json index 039fc61bd..0f35b3992 100644 --- a/competitions.json +++ b/competitions.json @@ -9,6 +9,11 @@ "name": "Fall Classic", "date": "2020-10-22 13:30:00", "numberOfPlaces": "13" + }, + { + "name": "Summer 2025", + "date": "2025-07-22 13:30:00", + "numberOfPlaces": 0 } ] } \ No newline at end of file diff --git a/server.py b/server.py index 4084baeac..0bd8abdf4 100644 --- a/server.py +++ b/server.py @@ -1,5 +1,6 @@ import json -from flask import Flask,render_template,request,redirect,flash,url_for +from flask import Flask,render_template,request,redirect,flash,url_for,session +from datetime import datetime def loadClubs(): @@ -7,12 +8,19 @@ def loadClubs(): listOfClubs = json.load(c)['clubs'] return listOfClubs - def loadCompetitions(): with open('competitions.json') as comps: listOfCompetitions = json.load(comps)['competitions'] return listOfCompetitions +def saveClubs(clubs_data): + with open('clubs.json', 'w') as c: + json.dump({"clubs": clubs_data}, c, indent=4) + +def saveCompetitions(competitions_data): + with open('competitions.json', 'w') as comps: + json.dump({"competitions": competitions_data}, comps, indent=4) + app = Flask(__name__) app.secret_key = 'something_special' @@ -20,40 +28,126 @@ def loadCompetitions(): competitions = loadCompetitions() clubs = loadClubs() + @app.route('/') def index(): + if 'club_email' in session: + club_email = session['club_email'] + found_clubs = [c for c in clubs if c['email'] == club_email] + if found_clubs: + club = found_clubs[0] + return render_template('welcome.html', club=club, competitions=competitions, + current_date_str=datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + else: + session.pop('club_email', None) + flash("Your club's email was not found. Please log in again.") + return render_template('index.html') 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('/book//') -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] + user_email = request.form['email'] + found_clubs = [club for club in clubs if club['email'] == user_email] + + if found_clubs: + club = found_clubs[0] + session['club_email'] = club['email'] + return render_template('welcome.html',club=club,competitions=competitions, + current_date_str=datetime.now().strftime('%Y-%m-%d %H:%M:%S')) + else: + flash("Sorry, that email was not found.") + session.pop('club_email', None) + return redirect(url_for('index')) + + +@app.route('/book//') +def book(competition_name,club_name): + if 'club_email' not in session: + flash("You need to be logged in to book places.") + return redirect(url_for('index')) + + logged_in_club_email = session['club_email'] + foundClub = [c for c in clubs if c['email'] == logged_in_club_email][0] + + foundCompetition = [c for c in competitions if c['name'] == competition_name][0] + + if foundClub['name'] != club_name: + flash("Attempted to book for a different club. Action blocked.") + return redirect(url_for('index')) + + competition_date = datetime.strptime(foundCompetition['date'], '%Y-%m-%d %H:%M:%S') + if competition_date < datetime.now(): + flash("This competition has already passed. Booking is not allowed.") + return redirect(url_for('index')) + if foundClub and foundCompetition: return render_template('booking.html',club=foundClub,competition=foundCompetition) else: flash("Something went wrong-please try again") - return render_template('welcome.html', club=club, competitions=competitions) + return redirect(url_for('index')) @app.route('/purchasePlaces',methods=['POST']) def purchasePlaces(): + if 'club_email' not in session: + flash("You need to be logged in to purchase places.") + return redirect(url_for('index')) + + logged_in_club_email = session['club_email'] + club = [c for c in clubs if c['email'] == logged_in_club_email][0] + 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) + + if club['name'] != request.form['club']: + flash("Attempted to purchase for a different club. Action blocked.") + return redirect(url_for('index')) + + competition_date = datetime.strptime(competition['date'], '%Y-%m-%d %H:%M:%S') + if competition_date < datetime.now(): + flash("Booking for past competitions is not allowed.") + return redirect(url_for('index')) + + if placesRequired > 12: + flash("You cannot book more than 12 places per competition.") + return redirect(url_for('index')) + + # --- BUG Fix: Prevent overbooking and incorrect point deduction --- + # Check if club has enough points AND if competition has enough places + if int(club['points']) >= placesRequired: + if int(competition['numberOfPlaces']) >= placesRequired: + # ONLY proceed with updates if both conditions are met + competition['numberOfPlaces'] = int(competition['numberOfPlaces']) - placesRequired + club['points'] = str(int(club['points']) - placesRequired) + + saveClubs(clubs) + saveCompetitions(competitions) + + flash('Great-booking complete!') + else: + # Not enough places available in competition + flash(f"Not enough places available in this competition. Only {competition['numberOfPlaces']} places left.") + else: + # Not enough points for the club + flash(f"You do not have enough points to book {placesRequired} places. You currently have {club['points']} points.") + # ------------------------------------------------------------------ + + return redirect(url_for('index')) -# TODO: Add route for points display +@app.route('/pointsDisplay') +def pointsDisplay(): + if 'club_email' not in session: + flash("You need to be logged in to view club points.") + return redirect(url_for('index')) + + sorted_clubs = sorted(clubs, key=lambda c: int(c['points']), reverse=True) + return render_template('points.html', clubs=sorted_clubs) @app.route('/logout') def logout(): - return redirect(url_for('index')) \ No newline at end of file + session.pop('club_email', None) + flash("You have been logged out.") + return redirect(url_for('index')) diff --git a/templates/index.html b/templates/index.html index 926526b7d..2ee8e0e12 100644 --- a/templates/index.html +++ b/templates/index.html @@ -6,6 +6,18 @@

Welcome to the GUDLFT Registration Portal!

+ + {# Add this block to display flashed messages #} + {% with messages = get_flashed_messages()%} + {% if messages %} +
    + {% for message in messages %} +
  • {{message}}
  • + {% endfor %} +
+ {% endif%} + {%endwith%} + Please enter your secretary email to continue:
diff --git a/templates/points.html b/templates/points.html new file mode 100644 index 000000000..cc34d2fb3 --- /dev/null +++ b/templates/points.html @@ -0,0 +1,33 @@ + + + + + Points Display Board | GUDLFT Registration + + +

Club Points Leaderboard

+

Back to Dashboard

+ + {% if clubs %} + + + + + + + + + {% for club_item in clubs %} + + + + + {% endfor %} + +
Club NamePoints
{{ club_item['name'] }}{{ club_item['points'] }}
+ {% else %} +

No clubs found to display points.

+ {% endif %} + + + \ No newline at end of file diff --git a/templates/welcome.html b/templates/welcome.html index ff6b261a2..795f61f55 100644 --- a/templates/welcome.html +++ b/templates/welcome.html @@ -5,7 +5,9 @@ Summary | GUDLFT Registration -

Welcome, {{club['email']}}

Logout +

Welcome, {{club['email']}}

+ Logout | + View All Club Points {% with messages = get_flashed_messages()%} {% if messages %} @@ -23,9 +25,17 @@

Competitions:

{{comp['name']}}
Date: {{comp['date']}}
Number of Places: {{comp['numberOfPlaces']}} - {%if comp['numberOfPlaces']|int >0%} - Book Places - {%endif%} + {# Compare competition date string with current_date_str #} + {% if comp['date'] > current_date_str and comp['numberOfPlaces']|int > 0 %} + {# --- CHANGE THIS LINE --- #} + Book Places + {% else %} + {% if comp['date'] <= current_date_str %} + (Competition passed) + {% else %} + (No places left) + {% endif %} + {% endif %}
{% endfor %}