Skip to content
Merged
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
79 changes: 59 additions & 20 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,37 @@
app.mount("/static", StaticFiles(directory=os.path.join(Path(__file__).parent,
"static")), name="static")


# Update the Activity class to include participants
class Activity:
def __init__(self, id, name, date, location, description):
self.id = id
self.name = name
self.date = date
self.location = location
self.description = description
self.participants = [] # Add a list to store participants


# In-memory activity database
activities = {
"Chess Club": {
"description": "Learn strategies and compete in chess tournaments",
"schedule": "Fridays, 3:30 PM - 5:00 PM",
"max_participants": 12,
"participants": ["michael@mergington.edu", "daniel@mergington.edu"]
},
"Programming Class": {
"description": "Learn programming fundamentals and build software projects",
"schedule": "Tuesdays and Thursdays, 3:30 PM - 4:30 PM",
"max_participants": 20,
"participants": ["emma@mergington.edu", "sophia@mergington.edu"]
},
"Gym Class": {
"description": "Physical education and sports activities",
"schedule": "Mondays, Wednesdays, Fridays, 2:00 PM - 3:00 PM",
"max_participants": 30,
"participants": ["john@mergington.edu", "olivia@mergington.edu"]
}
}
activities = [
Activity(1, "Hiking at Mountain Trail", "2023-10-15", "Mountain Park",
"A beginner-friendly hiking trip with beautiful views."),
Activity(2, "Community Cleanup", "2023-10-22", "City Beach",
"Help keep our beach clean! Supplies will be provided."),
Activity(3, "Charity Run", "2023-11-05", "Downtown",
"5k run to raise funds for the local animal shelter.")
]


# Add function to add a participant to an activity
def add_participant_to_activity(activity_id, participant_name):
for activity in activities:
if activity.id == int(activity_id):
if participant_name not in activity.participants:
activity.participants.append(participant_name)
return True
return False


@app.get("/")
Expand All @@ -62,6 +72,35 @@ 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 is already signed up")

# Add student
activity["participants"].append(email)
return {"message": f"Signed up {email} for {activity_name}"}


# Add route to handle participant registration
@app.route('/register', methods=['POST'])
Copy link

Copilot AI Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mixing Flask decorators (@app.route) with FastAPI app instance. The existing code uses FastAPI (@app.get, @app.post) but this new route uses Flask syntax, which will not work with FastAPI.

Copilot uses AI. Check for mistakes.

def register():
activity_id = request.form.get('activity_id')
participant_name = request.form.get('participant_name')

if not activity_id or not participant_name:
return redirect(url_for('index', error="Please fill in all fields"))

success = add_participant_to_activity(activity_id, participant_name)

if success:
return redirect(url_for('index', message="Successfully registered for the activity!"))
else:
return redirect(url_for('index', error="Activity not found or registration failed"))


# Update the index route to pass error/success messages
@app.route('/')
def index():
error = request.args.get('error')
message = request.args.get('message')
return render_template('index.html', activities=activities, error=error, message=message)
Comment on lines +85 to +106
Copy link

Copilot AI Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Flask route decorator with FastAPI. This conflicts with the existing FastAPI @app.get('/') decorator and will cause routing conflicts.

Suggested change
@app.route('/register', methods=['POST'])
def register():
activity_id = request.form.get('activity_id')
participant_name = request.form.get('participant_name')
if not activity_id or not participant_name:
return redirect(url_for('index', error="Please fill in all fields"))
success = add_participant_to_activity(activity_id, participant_name)
if success:
return redirect(url_for('index', message="Successfully registered for the activity!"))
else:
return redirect(url_for('index', error="Activity not found or registration failed"))
# Update the index route to pass error/success messages
@app.route('/')
def index():
error = request.args.get('error')
message = request.args.get('message')
return render_template('index.html', activities=activities, error=error, message=message)
@app.post('/register')
async def register(activity_id: str, participant_name: str):
if not activity_id or not participant_name:
return RedirectResponse(url=f"/?error=Please fill in all fields", status_code=303)
success = add_participant_to_activity(activity_id, participant_name)
if success:
return RedirectResponse(url=f"/?message=Successfully registered for the activity!", status_code=303)
else:
return RedirectResponse(url=f"/?error=Activity not found or registration failed", status_code=303)
# Update the index route to pass error/success messages
@app.get('/')
async def index(error: str = None, message: str = None):
return {"activities": activities, "error": error, "message": message}

Copilot uses AI. Check for mistakes.

Comment on lines +85 to +106
Copy link

Copilot AI Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Flask's request object in what should be a FastAPI application. FastAPI uses different request handling patterns and this will cause runtime errors.

Suggested change
@app.route('/register', methods=['POST'])
def register():
activity_id = request.form.get('activity_id')
participant_name = request.form.get('participant_name')
if not activity_id or not participant_name:
return redirect(url_for('index', error="Please fill in all fields"))
success = add_participant_to_activity(activity_id, participant_name)
if success:
return redirect(url_for('index', message="Successfully registered for the activity!"))
else:
return redirect(url_for('index', error="Activity not found or registration failed"))
# Update the index route to pass error/success messages
@app.route('/')
def index():
error = request.args.get('error')
message = request.args.get('message')
return render_template('index.html', activities=activities, error=error, message=message)
@app.post('/register')
async def register(request: Request):
form_data = await request.form()
activity_id = form_data.get('activity_id')
participant_name = form_data.get('participant_name')
if not activity_id or not participant_name:
raise HTTPException(status_code=400, detail="Please fill in all fields")
success = add_participant_to_activity(activity_id, participant_name)
if success:
return {"message": "Successfully registered for the activity!"}
else:
raise HTTPException(status_code=404, detail="Activity not found or registration failed")
# Update the index route to pass error/success messages
@app.get('/')
async def index(error: str = None, message: str = None):
return {"activities": activities, "error": error, "message": message}

Copilot uses AI. Check for mistakes.

41 changes: 41 additions & 0 deletions src/static/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,47 @@ document.addEventListener("DOMContentLoaded", () => {
}
});

// Handle the registration form submission
const registrationForm = document.getElementById("registration-form");
if (registrationForm) {
registrationForm.addEventListener("submit", function (e) {
const activityId = document.getElementById("activity-select").value;
const participantName = document.getElementById("participant-name").value;

if (!activityId || !participantName) {
e.preventDefault();
showMessage("Please fill in all fields", "error");
}
});
}

// Check for URL parameters to show success/error messages
const urlParams = new URLSearchParams(window.location.search);
const errorMessage = urlParams.get("error");
const successMessage = urlParams.get("message");

if (errorMessage) {
showMessage(errorMessage, "error");
}

if (successMessage) {
showMessage(successMessage, "success");
}

// Function to show messages
function showMessage(text, type) {
const messageDiv = document.getElementById("message");
if (messageDiv) {
messageDiv.textContent = text;
messageDiv.className = `message ${type}`;
messageDiv.classList.remove("hidden");

setTimeout(() => {
messageDiv.classList.add("hidden");
}, 5000);
}
}

// Initialize app
fetchActivities();
});
51 changes: 51 additions & 0 deletions src/static/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,57 @@ section h3 {
margin-bottom: 8px;
}

/* Participants section styling */
Copy link

Copilot AI Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The participant styling CSS is duplicated between this file and the index.html template. This creates maintenance issues as changes need to be made in multiple places.

Copilot uses AI. Check for mistakes.

.participants-section {
margin-top: 15px;
border-top: 1px dashed #ddd;
padding-top: 10px;
}

.participants-section h5 {
color: #1a237e;
margin-bottom: 8px;
font-size: 0.95rem;
}

.participants-list {
list-style-type: none;
margin-left: 5px;
}

.participants-list li {
padding: 4px 0;
display: flex;
align-items: center;
}

.participants-list li:before {
content: "•";
color: #3949ab;
font-weight: bold;
display: inline-block;
width: 1em;
margin-right: 5px;
}

.participant-badge {
background-color: #e8eaf6;
border-radius: 15px;
padding: 4px 10px;
font-size: 0.85rem;
color: #3949ab;
display: inline-block;
margin-right: 5px;
border: 1px solid #c5cae9;
}

/* Empty participants message */
.no-participants {
font-style: italic;
color: #757575;
font-size: 0.9rem;
}

.form-group {
margin-bottom: 15px;
}
Expand Down
Loading