feat(chat): add country flags and competitor numbers with normalized data architecture

Implemented display of country flags and competitor numbers in event chat messages:
- Country flags displayed as emoji (🇸🇪, 🇵🇱, etc.) with proper emoji font support
- Competitor numbers shown in #123 format next to usernames
- Normalized data architecture with user and participant caches on frontend
- User data (username, avatar, country) and participant data (competitorNumber) cached separately
- Messages store only core data (id, content, userId, createdAt)
- Prevents data inconsistency when users update profile information
- Fixed duplicate message keys React warning with deduplication logic
- Backend sends nested user/participant objects for cache population
- Auto-updates across all messages when user changes avatar or country

Backend changes:
- Socket.IO event_message and message_history include nested user/participant data
- API /events/:slug/messages endpoint restructured with same nested format
- Batch lookup of competitor numbers for efficiency

Frontend changes:
- useEventChat hook maintains userCache and participantCache
- ChatMessage component accepts separate user/participant props
- ChatMessageList performs cache lookups during render
- Emoji font family support for cross-platform flag rendering
This commit is contained in:
Radosław Gierwiało
2025-11-29 19:49:06 +01:00
parent 671b16cb82
commit 4e9557bd29
6 changed files with 269 additions and 17 deletions

View File

@@ -38,6 +38,8 @@ const EventChatPage = () => {
isConnected,
loadingOlder,
hasMore,
userCache,
participantCache,
sendMessage: handleSendMessage,
loadOlderMessages
} = useEventChat(slug, user?.id, event, messagesContainerRef);
@@ -478,6 +480,8 @@ const EventChatPage = () => {
<div className="flex-1 flex flex-col">
<ChatMessageList
messages={messages}
userCache={userCache}
participantCache={participantCache}
currentUserId={user.id}
messagesEndRef={messagesEndRef}
messagesContainerRef={messagesContainerRef}