From 2182f14c00b24d76b2087608f50b29573db4a783 Mon Sep 17 00:00:00 2001 From: dotanp <3824200+dotanp@users.noreply.github.com> Date: Fri, 26 Jun 2026 09:43:00 +0000 Subject: [PATCH 1/4] Add extracurricular activities and signup validation to API --- src/app.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/app.py b/src/app.py index 4ebb1d9..d720c4a 100644 --- a/src/app.py +++ b/src/app.py @@ -38,6 +38,42 @@ "schedule": "Mondays, Wednesdays, Fridays, 2:00 PM - 3:00 PM", "max_participants": 30, "participants": ["john@mergington.edu", "olivia@mergington.edu"] + }, + "Basketball Team": { + "description": "Competitive basketball team for interscholastic play", + "schedule": "Mondays and Wednesdays, 4:00 PM - 5:30 PM", + "max_participants": 15, + "participants": ["alex@mergington.edu"] + }, + "Tennis Club": { + "description": "Learn tennis skills and compete in matches", + "schedule": "Tuesdays and Thursdays, 3:30 PM - 5:00 PM", + "max_participants": 16, + "participants": ["ava@mergington.edu"] + }, + "Art Studio": { + "description": "Explore painting, drawing, and mixed media techniques", + "schedule": "Wednesdays, 3:30 PM - 5:00 PM", + "max_participants": 18, + "participants": ["isabella@mergington.edu", "lucas@mergington.edu"] + }, + "Drama Club": { + "description": "Perform in theatrical productions and develop acting skills", + "schedule": "Thursdays, 4:00 PM - 5:30 PM", + "max_participants": 25, + "participants": ["noah@mergington.edu"] + }, + "Debate Team": { + "description": "Engage in competitive debate and public speaking", + "schedule": "Mondays and Fridays, 3:30 PM - 4:30 PM", + "max_participants": 14, + "participants": ["mia@mergington.edu", "ethan@mergington.edu"] + }, + "Science Club": { + "description": "Conduct experiments and explore advanced scientific concepts", + "schedule": "Tuesdays, 3:30 PM - 5:00 PM", + "max_participants": 20, + "participants": ["charlotte@mergington.edu"] } } @@ -61,7 +97,9 @@ def signup_for_activity(activity_name: str, email: str): # Get the specific activity activity = activities[activity_name] - + # Validate student is not already signed up + if email in activity["participants"]: + raise HTTPException(status_code=400, detail="Student already signed up for this activity") # Add student activity["participants"].append(email) return {"message": f"Signed up {email} for {activity_name}"} From 94fe9c8b3a699e2d8ca60b049197379da944db70 Mon Sep 17 00:00:00 2001 From: dotanp <3824200+dotanp@users.noreply.github.com> Date: Fri, 26 Jun 2026 16:03:41 +0000 Subject: [PATCH 2/4] Implement participant unregistration feature and enhance UI for activities --- src/app.py | 17 ++++++++ src/static/app.js | 91 ++++++++++++++++++++++++++++++++++++++++++- src/static/index.html | 4 +- src/static/styles.css | 89 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 4 deletions(-) diff --git a/src/app.py b/src/app.py index d720c4a..afa7609 100644 --- a/src/app.py +++ b/src/app.py @@ -103,3 +103,20 @@ def signup_for_activity(activity_name: str, email: str): # Add student activity["participants"].append(email) return {"message": f"Signed up {email} for {activity_name}"} + + +@app.delete("/activities/{activity_name}/participants/{email}") +def unregister_from_activity(activity_name: str, email: str): + """Unregister a student from an activity""" + # Validate activity exists + if activity_name not in activities: + raise HTTPException(status_code=404, detail="Activity not found") + + activity = activities[activity_name] + + # Validate student is currently signed up + if email not in activity["participants"]: + raise HTTPException(status_code=404, detail="Student is not signed up for this activity") + + activity["participants"].remove(email) + return {"message": f"Unregistered {email} from {activity_name}"} diff --git a/src/static/app.js b/src/static/app.js index dcc1e38..2ef542f 100644 --- a/src/static/app.js +++ b/src/static/app.js @@ -4,27 +4,71 @@ document.addEventListener("DOMContentLoaded", () => { const signupForm = document.getElementById("signup-form"); const messageDiv = document.getElementById("message"); + function escapeHtml(value) { + return String(value) + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); + } + // Function to fetch activities from API async function fetchActivities() { try { - const response = await fetch("/activities"); + const response = await fetch("/activities", { cache: "no-store" }); const activities = await response.json(); // Clear loading message activitiesList.innerHTML = ""; + activitySelect.innerHTML = ''; // Populate activities list Object.entries(activities).forEach(([name, details]) => { const activityCard = document.createElement("div"); activityCard.className = "activity-card"; - const spotsLeft = details.max_participants - details.participants.length; + const participants = Array.isArray(details.participants) ? details.participants : []; + const maxParticipants = details.max_participants || 0; + const spotsLeft = maxParticipants - participants.length; + const encodedActivity = encodeURIComponent(name); + const participantItems = participants.length + ? participants + .map((participant) => { + const encodedParticipant = encodeURIComponent(participant); + const safeParticipant = escapeHtml(participant); + + return ` +
${details.description}
Schedule: ${details.schedule}
Availability: ${spotsLeft} spots left
+Participants
+ +© 2023 Mergington High School
- +