From c4240f05bbb274bbeef1b6e7cc5f214927291b38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Gierwia=C5=82o?= Date: Fri, 14 Nov 2025 15:35:39 +0100 Subject: [PATCH] feat: add Socket.IO heats_updated broadcast event - Export getIO function from socket module - Broadcast heats_updated event when user updates their heats - Event includes userId, username, and updated heats array - Non-blocking broadcast (won't fail request if socket fails) --- backend/src/routes/events.js | 23 +++++++++++++++++++++++ backend/src/socket/index.js | 14 ++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/backend/src/routes/events.js b/backend/src/routes/events.js index 219ce47..c326fcb 100644 --- a/backend/src/routes/events.js +++ b/backend/src/routes/events.js @@ -1,6 +1,7 @@ const express = require('express'); const { prisma } = require('../utils/db'); const { authenticate } = require('../middleware/auth'); +const { getIO } = require('../socket'); const router = express.Router(); @@ -566,6 +567,28 @@ router.post('/:slug/heats', authenticate, async (req, res, next) => { return userHeats; }); + // Broadcast heats update to all users in event room + try { + const io = getIO(); + const roomName = `event_${event.id}`; + io.to(roomName).emit('heats_updated', { + userId: req.user.id, + username: req.user.username, + heats: result.map(heat => ({ + id: heat.id, + divisionId: heat.divisionId, + division: heat.division, + competitionTypeId: heat.competitionTypeId, + competitionType: heat.competitionType, + heatNumber: heat.heatNumber, + role: heat.role, + })), + }); + } catch (socketError) { + // Don't fail the request if socket broadcast fails + console.error('Failed to broadcast heats update:', socketError); + } + res.json({ success: true, count: result.length, diff --git a/backend/src/socket/index.js b/backend/src/socket/index.js index 9713dbc..c8f8b6a 100644 --- a/backend/src/socket/index.js +++ b/backend/src/socket/index.js @@ -5,8 +5,18 @@ const { prisma } = require('../utils/db'); // Track active users in each event room const activeUsers = new Map(); // eventId -> Set of { socketId, userId, username, avatar } +// Global Socket.IO instance +let io; + +function getIO() { + if (!io) { + throw new Error('Socket.IO not initialized'); + } + return io; +} + function initializeSocket(httpServer) { - const io = new Server(httpServer, { + io = new Server(httpServer, { cors: { origin: process.env.CORS_ORIGIN || 'http://localhost:8080', credentials: true, @@ -348,4 +358,4 @@ function initializeSocket(httpServer) { return io; } -module.exports = { initializeSocket }; +module.exports = { initializeSocket, getIO };