-
Notifications
You must be signed in to change notification settings - Fork 0
Improve student activity registration system #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request migrates the student activity registration system from in-memory storage to persistent file-based storage and adds participant management capabilities. The changes enable administrators to view and remove participants from activities through an enhanced UI with real-time updates.
Key Changes:
- Implemented persistent storage using
activities.jsonwith thread-safe read/write operations - Added DELETE endpoint for unregistering participants with proper validation
- Enhanced frontend to display participant lists with delete functionality and automatic list refresh
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/app.py |
Replaced in-memory storage with file-based persistence, added thread-safe load/save functions, implemented unregister endpoint with duplicate signup validation |
src/activities.json |
New persistent data file containing all activity information and participant lists |
src/static/app.js |
Added participant list rendering with delete icons and event handlers, implemented automatic refresh after signup/removal |
src/static/styles.css |
Added styling for participant sections, delete buttons, and empty state display |
tests/test_app.py |
New test suite covering activity listing, signup, and unregister functionality |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def load_activities(): | ||
| with _activities_lock: | ||
| with open(DATA_FILE, "r", encoding="utf-8") as f: | ||
| return json.load(f) |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The load_activities() function should handle the case where the data file doesn't exist or contains invalid JSON. Without error handling, the application will crash on startup if activities.json is missing or corrupted. Consider adding a try-except block to return default data or create the file if it doesn't exist.
| setTimeout(() => { | ||
| activityCard.querySelectorAll('.delete-participant').forEach((icon) => { | ||
| icon.addEventListener('click', async (e) => { | ||
| const activity = icon.getAttribute('data-activity'); | ||
| const email = icon.getAttribute('data-email'); | ||
| if (!confirm(`Remove ${email} from ${activity}?`)) return; | ||
| try { | ||
| const response = await fetch(`/activities/${encodeURIComponent(activity)}/unregister?email=${encodeURIComponent(email)}`, { | ||
| method: 'DELETE', | ||
| }); | ||
| const result = await response.json(); | ||
| if (response.ok) { | ||
| fetchActivities(); | ||
| } else { | ||
| alert(result.detail || 'Failed to remove participant.'); | ||
| } | ||
| } catch (err) { | ||
| alert('Failed to remove participant.'); | ||
| } | ||
| }); | ||
| }); | ||
| }, 0); |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using setTimeout with 0ms delay is unnecessary here since the elements are already in the DOM after innerHTML assignment. The event listeners can be attached immediately without the setTimeout wrapper, improving code clarity and reducing potential timing issues.
| setTimeout(() => { | |
| activityCard.querySelectorAll('.delete-participant').forEach((icon) => { | |
| icon.addEventListener('click', async (e) => { | |
| const activity = icon.getAttribute('data-activity'); | |
| const email = icon.getAttribute('data-email'); | |
| if (!confirm(`Remove ${email} from ${activity}?`)) return; | |
| try { | |
| const response = await fetch(`/activities/${encodeURIComponent(activity)}/unregister?email=${encodeURIComponent(email)}`, { | |
| method: 'DELETE', | |
| }); | |
| const result = await response.json(); | |
| if (response.ok) { | |
| fetchActivities(); | |
| } else { | |
| alert(result.detail || 'Failed to remove participant.'); | |
| } | |
| } catch (err) { | |
| alert('Failed to remove participant.'); | |
| } | |
| }); | |
| }); | |
| }, 0); | |
| activityCard.querySelectorAll('.delete-participant').forEach((icon) => { | |
| icon.addEventListener('click', async (e) => { | |
| const activity = icon.getAttribute('data-activity'); | |
| const email = icon.getAttribute('data-email'); | |
| if (!confirm(`Remove ${email} from ${activity}?`)) return; | |
| try { | |
| const response = await fetch(`/activities/${encodeURIComponent(activity)}/unregister?email=${encodeURIComponent(email)}`, { | |
| method: 'DELETE', | |
| }); | |
| const result = await response.json(); | |
| if (response.ok) { | |
| fetchActivities(); | |
| } else { | |
| alert(result.detail || 'Failed to remove participant.'); | |
| } | |
| } catch (err) { | |
| alert('Failed to remove participant.'); | |
| } | |
| }); | |
| }); |
| if email in activity["participants"]: | ||
| raise HTTPException(status_code=400, detail="Student already signed up for this activity") |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The duplicate signup validation logic added in the signup endpoint lacks test coverage. Consider adding a test case that attempts to sign up the same email twice and verifies that a 400 error is returned with the appropriate error message.
| # Add student | ||
| if email in activity["participants"]: | ||
| raise HTTPException(status_code=400, detail="Student already signed up for this activity") | ||
| activity["participants"].append(email) |
Copilot
AI
Dec 1, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The signup endpoint doesn't validate whether the activity has reached max_participants. Participants can be added beyond the maximum capacity, making the 'spots left' display in the UI inaccurate. Add a check to compare len(activity['participants']) against activity['max_participants'] before appending.
This pull request introduces persistent storage for extracurricular activities, adds participant management features, and enhances both the frontend and backend to support viewing and removing activity participants. It also includes new styling for participant lists and adds automated tests to ensure correct behavior.
Backend Improvements:
activities.jsonfile, with thread-safe load and save functions for reading and writing activities. (src/app.py,src/activities.json) [1] [2]/activities/{activity_name}/unregisterto allow unregistering a participant from an activity, updating the persistent store accordingly. (src/app.py)Frontend Enhancements:
src/static/app.js)src/static/app.js)Styling Updates:
src/static/styles.css)Testing:
tests/test_app.py)