Feat : Specator Mode, Team Creation Interface - #55
Open
DefineAditya wants to merge 1 commit into
Open
DefineAditya wants to merge 1 commit into
DefineAditya wants to merge 1 commit into
Conversation
15 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Resolves #44
🚀 Feature/Fix: Spectator Mode, Team Management UX, and Match History Persistence
📝 Summary
This PR introduces three major upgrades to the contest engine: a robust Spectator Mode for live matches, a completely overhauled Team Creation/Registration interface, and critical bug fixes for Match History database persistence.
✨ 1. Spectator Mode Implementation
• Granular Restrictions: Added a new spectatorRestriction field to the ContestMatch schema with support for "none", "all", "admin_creator", and "club_members".
• Dynamic Access Control: Implemented backend logic in getContestListingAction to compute a canSpectate boolean for the frontend. Access
automatically checks user authentication, club roles (e.g., Core Team / Competitive Programming module), and contest creator status.
• Testing: Added comprehensive integration tests (contests-spectator.test.ts) to validate all permutations of spectator access levels.
🛡️ 2. Team Creation & Interface Enhancements
• Private Team Join Codes: Built and fully integrated the ability to create private teams and allow users to seamlessly join them using a unique secure join code.
• Robust Join/Invite Flows: Introduced ContestTeamRequest and ContestRegistrationTeam models to support a fully asynchronous invite and join request system alongside the join code method.
• UI/UX Improvements:
• Team leaders can now immediately see incoming join requests without needing to dive into the "Manage Team" modal.
• Invited users now properly see the "Accept" button for their invites.
• Replaced raw MongoDB Object IDs with easily readable user handles/names in the incoming requests dashboards.
• Security & Edge-Case Fixes:
• Name Collision Bug: Fixed an issue where creating a team with the same name as an existing team (case-insensitive) would forcibly merge the user into the existing team instead of rejecting the creation.
• Leader Abandonment (Ghost Teams): Added cleanup logic so that if a team leader unregisters, leadership is automatically passed to another member. If the team is empty, it is deleted from the database.
• Cross-Team Registration: Added strict backend validation to prevent a user from accepting invites or joining teams if they are already registered for the contest.
💾 3. Contest History & Database Persistence
• Incomplete Match History (Bracket Formats): Fixed a bug where a user's match history would erroneously display their first tournament match (e.g., Round 1) even if they advanced to the finals. The query in getContestListingAction now strictly sorts by actualStartTime: -1 and createdAt: -1 to fetch and render their latest/final placement.
• Forfeit/Tie Persistence: Fixed an issue in reconciliationWorker.ts where forfeits in non-bracket formats resulted in both teams having 0 points, causing the Match History to log the outcome as a "Tie". The worker now dynamically assigns the winner 1 point (if they were at 0) and the forfeiter -1 points, ensuring the history accurately reflects a Victory and Defeat.
• Redis Cache Race Condition: Resolved a scaling issue in non-bracket formats where the contest:${contestId}:rooms cache was aggressively deleted the moment the first room finished. The cleanup worker now safely verifies that totalRooms === endedRooms before wiping the contest cache.
🛠️ Technical Chores
• Resolved strict TypeScript compiler errors related to AppResult discriminated unions and Mongoose query payload schemas.
• Passed all Next.js Turbopack build steps and strict environment variable validations (DEV_AUTH_ENABLED).
──────
Reviewer Notes
Please ensure that the newly created Mongoose schemas (ContestRegistrationTeam.ts, ContestTeamRequest.ts) are properly registered in the database context. All tests pass successfully under pnpm build.