Skip to content

Commit 9da945c

Browse files
authored
Merge pull request #31 from NextStepFinalProject/NXD-30
Nxd 30 - Emphasize the selection of chat recipient
2 parents 9681ffe + 8c9e163 commit 9da945c

File tree

4 files changed

+50
-23
lines changed

4 files changed

+50
-23
lines changed

nextstep-backend/src/services/socket_service.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,13 @@ const initSocket = async (socketListener: Server) => {
2828
await new messageModel(messageToInsert).validate();
2929
const insertedMessage = await messageModel.create(messageToInsert);
3030

31-
// Emit mesage
32-
socketListener.to(roomId).emit(config.socketMethods.messageFromServer, { roomId, message: insertedMessage });
31+
// Emit message with user info
32+
const messageWithUser = {
33+
...insertedMessage.toObject(),
34+
email: user.email,
35+
username: user.username,
36+
};
37+
socketListener.to(roomId).emit(config.socketMethods.messageFromServer, { roomId, message: messageWithUser });
3338
});
3439

3540
// Online users

nextstep-frontend/src/components/DividedList.tsx

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { useState } from 'react';
21
import {
32
Avatar,
43
Box,
@@ -11,19 +10,18 @@ import {
1110

1211
interface User {
1312
id: string;
13+
username?: string;
1414
email: string;
1515
}
1616

17+
interface DividedListProps {
18+
onlineUsers: { id: string, username?: string, email: string }[];
19+
onUserClick: (user: { id: string, username?: string, email: string }) => void;
20+
disabled?: boolean;
21+
selectedUserId?: string | null;
22+
}
1723

18-
const DividedList: React.FC<any> = ({ onlineUsers, onUserClick, disabled = false }) => {
19-
const [selectedUserId, setSelectedUserId] = useState<string | null>(null);
20-
21-
const handleUserClick = (user: User) => {
22-
if (disabled) return;
23-
setSelectedUserId(user.id);
24-
onUserClick(user);
25-
};
26-
24+
const DividedList: React.FC<DividedListProps> = ({ onlineUsers, onUserClick, disabled = false, selectedUserId }) => {
2725
return (
2826
<Box sx={{ display: 'flex', flexWrap: 'wrap', justifyContent: 'center', gap: 4 }}>
2927
<List
@@ -43,16 +41,17 @@ const DividedList: React.FC<any> = ({ onlineUsers, onUserClick, disabled = false
4341
<div key={user.id}>
4442
{index !== 0 && <Divider />}
4543
<ListItemButton
46-
onClick={() => handleUserClick(user)}
44+
className={`divided-list-item${selectedUserId === user.id ? ' selected' : ''}`}
45+
onClick={() => !disabled && onUserClick(user)}
4746
disabled={disabled}
4847
sx={{
4948
py: 1.5,
5049
px: 2,
51-
backgroundColor: user.id === selectedUserId ? 'primary.main' : 'transparent',
52-
color: user.id === selectedUserId ? 'primary.contrastText' : 'text.primary',
50+
backgroundColor: selectedUserId === user.id ? 'primary.main' : 'transparent',
51+
color: selectedUserId === user.id ? 'primary.contrastText' : 'text.primary',
5352
transition: 'all 0.3s ease',
5453
'&:hover': {
55-
backgroundColor: user.id === selectedUserId ? 'primary.dark' : 'action.hover',
54+
backgroundColor: selectedUserId === user.id ? 'primary.dark' : 'action.hover',
5655
transform: 'translateX(4px)',
5756
},
5857
'&.Mui-disabled': {
@@ -75,10 +74,10 @@ const DividedList: React.FC<any> = ({ onlineUsers, onUserClick, disabled = false
7574
/>
7675
</ListItemAvatar>
7776
<ListItemText
78-
primary={user.email}
77+
primary={`${user.username} (${user.email})`}
7978
primaryTypographyProps={{
8079
fontSize: '0.875rem',
81-
fontWeight: user.id === selectedUserId ? 600 : 400,
80+
fontWeight: selectedUserId === user.id ? 600 : 400,
8281
}}
8382
sx={{
8483
transition: 'all 0.3s ease',

nextstep-frontend/src/pages/Chat.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,9 @@
9595

9696
.online-users {
9797
margin-top: 10px;
98+
}
99+
100+
.divided-list-item.selected {
101+
font-weight: bold;
102+
border-radius: 20px;
98103
}

nextstep-frontend/src/pages/Chat.tsx

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const Chat: React.FC = () => {
2525
const [isLoading, setIsLoading] = useState(true);
2626
const [error, setError] = useState<string | null>(null);
2727
const [isConnected, setIsConnected] = useState(false);
28+
const [selectedUserId, setSelectedUserId] = useState<string | null>(null);
2829

2930
const usersMetadataCacheRef = useRef(new Set<LoginResponse>());
3031
const socketRef = useRef<Socket | null>(null);
@@ -138,13 +139,13 @@ const Chat: React.FC = () => {
138139

139140
const onUserClick = async (user: LoginResponse) => {
140141
if (!userAuthRef.current) return;
141-
142+
setSelectedUserId(user.id!);
142143
try {
143144
setIsLoading(true);
144145
const response = await axios.get<Room>(`${config.app.backend_url()}/room/user/${user.id}`, {
145146
headers: { Authorization: `Bearer ${userAuthRef.current.accessToken}` }
146147
});
147-
148+
148149
setRoom(response.data);
149150
socketRef.current?.emit(config.socketMethods.enterRoom, response.data._id);
150151
} catch (err) {
@@ -160,6 +161,17 @@ const Chat: React.FC = () => {
160161
}
161162
}, [room.messages]);
162163

164+
// Type guard for users with valid id and email
165+
function isValidUser(user: LoginResponse): user is LoginResponse & { id: string; email: string } {
166+
return Boolean(user.id && user.email);
167+
}
168+
169+
// Helper to get display name by userId
170+
const getUserDisplayName = (userId: string) => {
171+
const user = onlineUsers.find(u => u.id === userId);
172+
return user?.username || user?.email || 'Unknown User';
173+
};
174+
163175
if (isLoading) {
164176
return (
165177
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
@@ -339,7 +351,7 @@ const Chat: React.FC = () => {
339351
}}
340352
className="message-user"
341353
>
342-
{Array.from(usersMetadataCacheRef.current).find(u => u.userId === m?.userId)?.email}
354+
{getUserDisplayName(m?.userId)}
343355
</Typography>
344356
<Typography
345357
variant="caption"
@@ -439,9 +451,15 @@ const Chat: React.FC = () => {
439451
</Box>
440452
</Box>
441453
<DividedList
442-
onlineUsers={onlineUsers.map(user => ({ id: user.id, email: user.email }))}
443-
onUserClick={onUserClick}
454+
onlineUsers={onlineUsers.filter(isValidUser).map(user => ({ id: user.id, username: user.username, email: user.email }))}
455+
onUserClick={(user) => {
456+
const fullUser = onlineUsers.find(u => u.id === user.id);
457+
if (fullUser) {
458+
onUserClick(fullUser);
459+
}
460+
}}
444461
disabled={!isConnected}
462+
selectedUserId={selectedUserId}
445463
/>
446464
</Paper>
447465
</Box>

0 commit comments

Comments
 (0)