diff --git a/nextstep-backend/src/services/socket_service.ts b/nextstep-backend/src/services/socket_service.ts index 3091a2e..0e488c9 100644 --- a/nextstep-backend/src/services/socket_service.ts +++ b/nextstep-backend/src/services/socket_service.ts @@ -28,8 +28,13 @@ const initSocket = async (socketListener: Server) => { await new messageModel(messageToInsert).validate(); const insertedMessage = await messageModel.create(messageToInsert); - // Emit mesage - socketListener.to(roomId).emit(config.socketMethods.messageFromServer, { roomId, message: insertedMessage }); + // Emit message with user info + const messageWithUser = { + ...insertedMessage.toObject(), + email: user.email, + username: user.username, + }; + socketListener.to(roomId).emit(config.socketMethods.messageFromServer, { roomId, message: messageWithUser }); }); // Online users diff --git a/nextstep-frontend/src/components/DividedList.tsx b/nextstep-frontend/src/components/DividedList.tsx index a16e074..2631b8a 100644 --- a/nextstep-frontend/src/components/DividedList.tsx +++ b/nextstep-frontend/src/components/DividedList.tsx @@ -1,4 +1,3 @@ -import { useState } from 'react'; import { Avatar, Box, @@ -11,19 +10,18 @@ import { interface User { id: string; + username?: string; email: string; } +interface DividedListProps { + onlineUsers: { id: string, username?: string, email: string }[]; + onUserClick: (user: { id: string, username?: string, email: string }) => void; + disabled?: boolean; + selectedUserId?: string | null; +} -const DividedList: React.FC = ({ onlineUsers, onUserClick, disabled = false }) => { - const [selectedUserId, setSelectedUserId] = useState(null); - - const handleUserClick = (user: User) => { - if (disabled) return; - setSelectedUserId(user.id); - onUserClick(user); - }; - +const DividedList: React.FC = ({ onlineUsers, onUserClick, disabled = false, selectedUserId }) => { return ( = ({ onlineUsers, onUserClick, disabled = false
{index !== 0 && } handleUserClick(user)} + className={`divided-list-item${selectedUserId === user.id ? ' selected' : ''}`} + onClick={() => !disabled && onUserClick(user)} disabled={disabled} sx={{ py: 1.5, px: 2, - backgroundColor: user.id === selectedUserId ? 'primary.main' : 'transparent', - color: user.id === selectedUserId ? 'primary.contrastText' : 'text.primary', + backgroundColor: selectedUserId === user.id ? 'primary.main' : 'transparent', + color: selectedUserId === user.id ? 'primary.contrastText' : 'text.primary', transition: 'all 0.3s ease', '&:hover': { - backgroundColor: user.id === selectedUserId ? 'primary.dark' : 'action.hover', + backgroundColor: selectedUserId === user.id ? 'primary.dark' : 'action.hover', transform: 'translateX(4px)', }, '&.Mui-disabled': { @@ -75,10 +74,10 @@ const DividedList: React.FC = ({ onlineUsers, onUserClick, disabled = false /> { const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); const [isConnected, setIsConnected] = useState(false); + const [selectedUserId, setSelectedUserId] = useState(null); const usersMetadataCacheRef = useRef(new Set()); const socketRef = useRef(null); @@ -138,13 +139,13 @@ const Chat: React.FC = () => { const onUserClick = async (user: LoginResponse) => { if (!userAuthRef.current) return; - + setSelectedUserId(user.id!); try { setIsLoading(true); const response = await axios.get(`${config.app.backend_url()}/room/user/${user.id}`, { headers: { Authorization: `Bearer ${userAuthRef.current.accessToken}` } }); - + setRoom(response.data); socketRef.current?.emit(config.socketMethods.enterRoom, response.data._id); } catch (err) { @@ -160,6 +161,17 @@ const Chat: React.FC = () => { } }, [room.messages]); + // Type guard for users with valid id and email + function isValidUser(user: LoginResponse): user is LoginResponse & { id: string; email: string } { + return Boolean(user.id && user.email); + } + + // Helper to get display name by userId + const getUserDisplayName = (userId: string) => { + const user = onlineUsers.find(u => u.id === userId); + return user?.username || user?.email || 'Unknown User'; + }; + if (isLoading) { return ( @@ -339,7 +351,7 @@ const Chat: React.FC = () => { }} className="message-user" > - {Array.from(usersMetadataCacheRef.current).find(u => u.userId === m?.userId)?.email} + {getUserDisplayName(m?.userId)} { ({ id: user.id, email: user.email }))} - onUserClick={onUserClick} + onlineUsers={onlineUsers.filter(isValidUser).map(user => ({ id: user.id, username: user.username, email: user.email }))} + onUserClick={(user) => { + const fullUser = onlineUsers.find(u => u.id === user.id); + if (fullUser) { + onUserClick(fullUser); + } + }} disabled={!isConnected} + selectedUserId={selectedUserId} />