Skip to content
Closed
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
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
fastapi
uvicorn
pytest
httpx
40 changes: 40 additions & 0 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,42 @@
"schedule": "Mondays, Wednesdays, Fridays, 2:00 PM - 3:00 PM",
"max_participants": 30,
"participants": ["john@mergington.edu", "olivia@mergington.edu"]
},
"Soccer Team": {
"description": "Competitive soccer team training and matches",
"schedule": "Monday, Wednesday, Friday, 4:00 PM - 6:00 PM",
"max_participants": 22,
"participants": ["liam@mergington.edu", "noah@mergington.edu"]
},
"Basketball Club": {
"description": "Pickup games, drills, and intramural tournaments",
"schedule": "Tuesdays and Thursdays, 5:00 PM - 7:00 PM",
"max_participants": 15,
"participants": ["ava@mergington.edu", "isabella@mergington.edu"]
},
"Art Club": {
"description": "Explore drawing, painting, and mixed media projects",
"schedule": "Wednesdays, 3:30 PM - 5:00 PM",
"max_participants": 18,
"participants": ["mia@mergington.edu", "charlotte@mergington.edu"]
},
"Drama Club": {
"description": "Acting workshops, rehearsals, and stage productions",
"schedule": "Thursdays, 4:00 PM - 6:30 PM",
"max_participants": 25,
"participants": ["amelia@mergington.edu", "harper@mergington.edu"]
},
"Debate Team": {
"description": "Practice public speaking, research, and competitive debates",
"schedule": "Mondays and Thursdays, 4:00 PM - 5:30 PM",
"max_participants": 16,
"participants": ["elijah@mergington.edu", "lucas@mergington.edu"]
},
"Math Club": {
"description": "Problem-solving sessions and preparation for math competitions",
"schedule": "Fridays, 3:30 PM - 4:30 PM",
"max_participants": 20,
"participants": ["oliver@mergington.edu", "jack@mergington.edu"]
}
}

Expand All @@ -62,6 +98,10 @@ 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}"}
5 changes: 5 additions & 0 deletions src/static/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ document.addEventListener("DOMContentLoaded", () => {
<p>${details.description}</p>
<p><strong>Schedule:</strong> ${details.schedule}</p>
<p><strong>Availability:</strong> ${spotsLeft} spots left</p>
<p><strong>Participants:</strong></p>
<ul class="participants">
${details.participants.map(participant => `<li>${participant}</li>`).join('')}
</ul>
`;

activitiesList.appendChild(activityCard);
Expand Down Expand Up @@ -62,6 +66,7 @@ document.addEventListener("DOMContentLoaded", () => {
messageDiv.textContent = result.message;
messageDiv.className = "success";
signupForm.reset();
await fetchActivities(); // Fetch updated activities
} else {
messageDiv.textContent = result.detail || "An error occurred";
messageDiv.className = "error";
Expand Down
8 changes: 8 additions & 0 deletions src/static/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ section h3 {
margin-bottom: 8px;
}

.activity-card .participants {
margin-top: 10px;
padding: 10px;
border-top: 1px solid #ddd;
list-style-type: disc;
padding-left: 20px;
}

.form-group {
margin-bottom: 15px;
}
Expand Down
37 changes: 37 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest
from fastapi.testclient import TestClient
from src import app as app_module

client = TestClient(app_module.app)


def test_get_activities():
"""GET /activities should return the activities dictionary."""
response = client.get("/activities")
assert response.status_code == 200
data = response.json()
# Basic sanity checks
assert isinstance(data, dict)
assert "Chess Club" in data
assert isinstance(data["Chess Club"].get("participants"), list)


def test_signup_for_activity():
"""POST signup should add the email to the activity participants."""
activity = "Chess Club"
test_email = "test.user@example.com"

# Ensure clean state before test
participants = app_module.activities[activity]["participants"]
if test_email in participants:
participants.remove(test_email)

try:
response = client.post(f"/activities/{activity}/signup", params={"email": test_email})
assert response.status_code == 200
assert response.json() == {"message": f"Signed up {test_email} for {activity}"}
assert test_email in app_module.activities[activity]["participants"]
finally:
# Cleanup added test email
if test_email in app_module.activities[activity]["participants"]:
app_module.activities[activity]["participants"].remove(test_email)