From 4aafd5853bdc2799c761afecb8bd754fd1dd8562 Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Fri, 24 Oct 2025 21:31:57 -0700 Subject: [PATCH] feat: add connected teams tracking and emit list on connection --- .../leagues/$leagueId.draft.$seasonId.tsx | 7 +++ server/socket.ts | 49 ++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/app/routes/leagues/$leagueId.draft.$seasonId.tsx b/app/routes/leagues/$leagueId.draft.$seasonId.tsx index 3f01b5b..3fc45b2 100644 --- a/app/routes/leagues/$leagueId.draft.$seasonId.tsx +++ b/app/routes/leagues/$leagueId.draft.$seasonId.tsx @@ -401,6 +401,11 @@ export default function DraftRoom() { }); }; + const handleConnectedTeamsList = (data: { teamIds: string[] }) => { + console.log("Received connected teams list:", data.teamIds); + setConnectedTeams(new Set(data.teamIds)); + }; + on("pick-made", handlePickMade); on("timer-update", handleTimerUpdate); on("draft-paused", handleDraftPaused); @@ -409,6 +414,7 @@ export default function DraftRoom() { on("autodraft-updated", handleAutodraftUpdated); on("team-connected", handleTeamConnected); on("team-disconnected", handleTeamDisconnected); + on("connected-teams-list", handleConnectedTeamsList); return () => { off("pick-made", handlePickMade); @@ -419,6 +425,7 @@ export default function DraftRoom() { off("autodraft-updated", handleAutodraftUpdated); off("team-connected", handleTeamConnected); off("team-disconnected", handleTeamDisconnected); + off("connected-teams-list", handleConnectedTeamsList); }; }, [on, off, currentPick, userTeam]); diff --git a/server/socket.ts b/server/socket.ts index 05d9418..b826450 100644 --- a/server/socket.ts +++ b/server/socket.ts @@ -25,6 +25,7 @@ interface ServerToClientEvents { }) => void; "team-connected": (data: { teamId: string }) => void; "team-disconnected": (data: { teamId: string }) => void; + "connected-teams-list": (data: { teamIds: string[] }) => void; "draft-paused": () => void; "draft-resumed": () => void; } @@ -42,6 +43,9 @@ declare global { let io: SocketIOServer | null = null; +// Track connected teams per season +const connectedTeams = new Map>(); // seasonId -> Set + /** * Initialize Socket.IO server */ @@ -78,12 +82,28 @@ export function initializeSocketIO(httpServer: HTTPServer): SocketIOServer { currentSeasonId = seasonId; console.log(`Socket ${socket.id} joined draft-${seasonId}`); - // If teamId provided, track connection and emit event + // If teamId provided, track connection and emit events if (teamId) { currentTeamId = teamId; socket.join(`team-${teamId}`); + + // Initialize the season's connected teams set if it doesn't exist + if (!connectedTeams.has(seasonId)) { + connectedTeams.set(seasonId, new Set()); + } + + // Get current connected teams for this season + const seasonConnectedTeams = connectedTeams.get(seasonId)!; + + // Send the list of already-connected teams to this socket + socket.emit("connected-teams-list", { teamIds: Array.from(seasonConnectedTeams) }); + + // Add this team to the connected teams set + seasonConnectedTeams.add(teamId); + + // Broadcast to everyone else that this team connected io!.to(`draft-${seasonId}`).emit("team-connected", { teamId }); - console.log(`Team ${teamId} connected to draft-${seasonId}`); + console.log(`Team ${teamId} connected to draft-${seasonId}. Total connected: ${seasonConnectedTeams.size}`); } }); @@ -95,6 +115,19 @@ export function initializeSocketIO(httpServer: HTTPServer): SocketIOServer { // Emit disconnection event if team was tracked if (currentTeamId) { socket.leave(`team-${currentTeamId}`); + + // Remove team from connected teams tracking + const seasonConnectedTeams = connectedTeams.get(seasonId); + if (seasonConnectedTeams) { + seasonConnectedTeams.delete(currentTeamId); + console.log(`Team ${currentTeamId} removed from tracking. Remaining: ${seasonConnectedTeams.size}`); + + // Clean up empty sets + if (seasonConnectedTeams.size === 0) { + connectedTeams.delete(seasonId); + } + } + io!.to(`draft-${seasonId}`).emit("team-disconnected", { teamId: currentTeamId }); console.log(`Team ${currentTeamId} disconnected from draft-${seasonId}`); } @@ -118,6 +151,18 @@ export function initializeSocketIO(httpServer: HTTPServer): SocketIOServer { // Emit disconnection event if team was tracked if (currentTeamId && currentSeasonId) { + // Remove team from connected teams tracking + const seasonConnectedTeams = connectedTeams.get(currentSeasonId); + if (seasonConnectedTeams) { + seasonConnectedTeams.delete(currentTeamId); + console.log(`Team ${currentTeamId} removed from tracking on disconnect. Remaining: ${seasonConnectedTeams.size}`); + + // Clean up empty sets + if (seasonConnectedTeams.size === 0) { + connectedTeams.delete(currentSeasonId); + } + } + io!.to(`draft-${currentSeasonId}`).emit("team-disconnected", { teamId: currentTeamId }); console.log(`Team ${currentTeamId} disconnected from draft-${currentSeasonId}`); }