fix(chat): real-time active users list updates

Fixed issue where active users list in event chat did not update in
real-time when new users joined. Users had to refresh the page to see
newly joined participants.

Root Cause:
- getAllDisplayUsers() used checkedInUsers (loaded once from API) as
  base list, with activeUsers (Socket.IO real-time) only for isOnline flag
- When new user joined chat, they appeared in activeUsers but not in
  checkedInUsers, so they were not displayed

Solution:
- Rewrote getAllDisplayUsers() to prioritize activeUsers (real-time data)
- Merges activeUsers (online) with checkedInUsers (offline checked-in users)
- Uses Socket.IO data as source of truth for online users
- Enriches with database data when available (firstName, lastName, etc)
- Sorts online users first, offline second

Changes:
- EventChatPage.jsx: Rewrote getAllDisplayUsers() to merge activeUsers
  with checkedInUsers, prioritizing real-time Socket.IO data
- useEventChat.js: Added debug logging for active_users events
- socket/index.js: Added debug logging for active_users emissions

Testing:
- User A in chat sees User B appear immediately when B joins
- No page refresh required
- Online/offline status updates in real-time
This commit is contained in:
Radosław Gierwiało
2025-12-02 23:38:46 +01:00
parent a8fcb5e6eb
commit dd3176196e
3 changed files with 35 additions and 8 deletions

View File

@@ -246,16 +246,38 @@ const EventChatPage = () => {
// Combine checked-in users with online status
const getAllDisplayUsers = () => {
const activeUserIds = new Set(activeUsers.map(u => u.userId));
// Create map of userId -> user data from activeUsers (real-time socket data)
const activeUsersMap = new Map(activeUsers.map(u => [u.userId, { ...u, isOnline: true }]));
// Merge checked-in users with online status
const allUsers = checkedInUsers.map(user => ({
...user,
isOnline: activeUserIds.has(user.userId),
}));
// Create map of userId -> user data from checkedInUsers (database data)
const checkedInUsersMap = new Map(checkedInUsers.map(u => [u.userId, { ...u, isOnline: false }]));
// Sort: online first, then offline
return allUsers.sort((a, b) => {
// Merge: prioritize activeUsers data (it's real-time), add offline users from checkedInUsers
const mergedMap = new Map();
// Add all active users (online)
activeUsers.forEach(u => {
const checkedInData = checkedInUsersMap.get(u.userId);
mergedMap.set(u.userId, {
userId: u.userId,
username: u.username,
avatar: u.avatar,
// Use additional data from checkedInUsers if available
...checkedInData,
// Override with socket data
isOnline: true,
});
});
// Add offline checked-in users (not in activeUsers)
checkedInUsers.forEach(u => {
if (!mergedMap.has(u.userId)) {
mergedMap.set(u.userId, { ...u, isOnline: false });
}
});
// Convert to array and sort: online first, then offline
return Array.from(mergedMap.values()).sort((a, b) => {
if (a.isOnline === b.isOnline) return 0;
return a.isOnline ? -1 : 1;
});