Conversation
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
This is a great start, but changes are needed because several critical bugs prevent the application's core features from working correctly. Please address the following blockers:
- Joining Rooms & Message History: The server crashes when a user joins a room due to an undefined
userNamevariable inserver/src/services/room.service.js. Additionally, the message history isn't being loaded because the query inserver/src/socket/events.jsneeds toincludetheMessagemodel to fetch past messages. - Sending Messages: Message creation fails in
server/src/socket/events.js. The code usessocket.userId, which is never assigned, and passes an incorrect property (authorinstead of the expectedauthorName) to the service. - Missing Timestamps: A key requirement is not fully met. The client UI in
client/main.jsrenders the author and text but is missing the message's timestamp.
Once these issues are resolved, the application should be fully functional. You're on the right track!
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
client/main.js
Outdated
| authorEl.textContent = message.authorName; | ||
| textEl.textContent = message.text; |
There was a problem hiding this comment.
The task requires all messages to display an author, time, and text. Currently, only the author and text are being rendered. You should also display the message's timestamp (e.g., from message.createdAt).
client/main.js
Outdated
|
|
||
| socket.emit('message_send', { | ||
| text, | ||
| roomId: state.activeRoom.id, |
There was a problem hiding this comment.
It's good that you've implemented the sendMessageHandler. However, there's a potential issue here. If a user hasn't joined a room yet, state.activeRoom will be null, and trying to access state.activeRoom.id will cause a runtime error. It's best to add a check to ensure state.activeRoom exists before sending a message.
client/main.js
Outdated
|
|
||
| socket.on('message_new', message => { | ||
| state.messages.push(message); | ||
| renderMessages(); |
There was a problem hiding this comment.
Calling renderMessages() on every new message clears the entire chat and then re-renders all messages from scratch. This can become slow and inefficient if a room has many messages. A better approach would be to create a new function that just renders a single message and appends it to the messageList.
server/src/socket/events.js
Outdated
|
|
||
| socket.join(roomId); | ||
|
|
||
| socket.emit('message_history', room.messages); |
There was a problem hiding this comment.
According to the task requirements, a new user joining a room should see all previous messages. However, room.messages will likely be undefined here because the roomService.joinRoom function doesn't load the associated messages. You'll need to update the query in your service to include the Message model to fetch the message history.
server/src/socket/events.js
Outdated
|
|
||
| const message = await messageService.createMessage({ | ||
| text, | ||
| author: socket.userName, |
There was a problem hiding this comment.
The messageService.createMessage function expects the author's name under the property authorName, but here you're passing it as author. This mismatch will prevent the author's name from being saved correctly. Please ensure the property names match what the service layer expects.
server/src/socket/events.js
Outdated
| const message = await messageService.createMessage({ | ||
| text, | ||
| author: socket.userName, | ||
| userId: socket.userId, |
There was a problem hiding this comment.
The socket.userId property is used here, but it's never assigned a value anywhere in the code. When a user joins, you should find or create a user record in the database and then store their ID on the socket object for later use, like when creating messages.
server/src/services/room.service.js
Outdated
| } | ||
|
|
||
| await Room.update({ name: newName }, { where: { id }}); | ||
| const room = Room.findByPk(id) |
There was a problem hiding this comment.
Room.findByPk(id) is an asynchronous operation and returns a Promise. You need to use await here to get the actual room object. Without await, the room variable will be a Promise, and the if (!room) check on the next line will not work as intended.
server/src/services/room.service.js
Outdated
| }; | ||
|
|
||
| const joinRoom = async ({ roomId }) => { | ||
| if (!roomId || !userName) { |
There was a problem hiding this comment.
The variable userName is used here but it is not defined within the function's scope. The function only receives roomId from its parameters. This will cause a ReferenceError when the function is called.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
Good work on the overall structure of the application. However, several critical bugs are preventing the core features—joining rooms, sending messages, and viewing message history—from working correctly. Changes are needed to address these blockers.
On the server-side:
- In
server/src/socket/events.js, the call touserService.findOrCreateUserisasyncbut is not being awaited. This results insocket.userIdbeingundefined. - In the same file, the call to
messageService.createMessageis missing the requiredauthorNameproperty, which will cause message creation to fail. - In
server/src/services/room.service.js, theMessageandUsermodels are used in a query but have not been imported, which will crash the server when a user tries to join a room.
On the client-side in client/main.js:
- The
renderOneMessagefunction uses a variablemessageBlockthat is never declared. - The timestamp element (
dateEl) is created but is never appended to the message block, so it doesn't appear in the UI.
Addressing these issues should make the application fully functional. You're very close!
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Important
Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.
Tip
If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.
Caution
Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.
Footnotes
| const dateEl = document.createElement('span'); | ||
| authorEl.textContent = message.authorName; | ||
| textEl.textContent = message.text; | ||
| messageBlock.className = 'message'; |
There was a problem hiding this comment.
The variable messageBlock is used here and in the following lines, but it has not been declared anywhere in this function's scope. You need to create this element, for example: const messageBlock = document.createElement('div');.
client/main.js
Outdated
| dateEl.textContent = new Date(message.createdAt.toLocaleTimeString(uk-UA, { | ||
| hour: '2-digit', | ||
| minute: '2-digit', | ||
| })); |
There was a problem hiding this comment.
The logic for formatting the date is incorrect. message.createdAt should be a date string that new Date() can parse. toLocaleTimeString() returns a formatted time string (e.g., "10:30:55"). Wrapping this result in new Date() will likely lead to an "Invalid Date" error. The correct approach is to parse the original date first and then format it: new Date(message.createdAt).toLocaleTimeString(...).
| messageBlock.appendChild(authorEl); | ||
| messageBlock.appendChild(textEl); |
There was a problem hiding this comment.
The dateEl element containing the message timestamp is created but is never appended to the messageBlock. This means the timestamp will not be displayed in the chat, which is a core requirement. You need to append it, similar to how authorEl and textEl are appended.
| model: Message, | ||
| include: [User], |
There was a problem hiding this comment.
The Message and User models are used here to fetch the message history, but they have not been imported into this file. This will cause a ReferenceError when this function is executed. You need to import them at the top of the file, similar to how the Room model is imported.
server/src/socket/events.js
Outdated
|
|
||
| socket.on('room_join', async ({ roomId, userName }) => { | ||
| try { | ||
| const user = userService.findOrCreateUser(userName); |
There was a problem hiding this comment.
The findOrCreateUser function is async, but it's not being awaited here. This means user will be a promise, not the user object. As a result, socket.userId and socket.userName will be undefined on the following lines, causing issues later when sending messages.
| const message = await messageService.createMessage({ | ||
| text, | ||
| // authorName: socket.userName, | ||
| userId: socket.userId, | ||
| roomId: socket.roomId, | ||
| }) |
There was a problem hiding this comment.
The call to messageService.createMessage is missing the authorName property. According to message.service.js, this field is required and the service will throw an error without it. You should pass socket.userName here.
mateacademy-ai-mentor
left a comment
There was a problem hiding this comment.
Review Summary
Fantastic work addressing all the previous issues! The application is now fully functional, and it's great to see all the core features working correctly. I'm approving your submission to keep you moving forward, but there are a couple of important points to review for your next steps.
The main issue is a build failure caused by an incorrect path in your package.json format script. To fix this, you'll need to update it to point to your client and server/src directories like this:
"format": "prettier --ignore-path .prettierignore --write './client/**/*.js' './server/src/**/*.js'"I also noticed two small areas for improvement:
- In
client/main.js, when sending a message, you can removeuserIdandroomIdfrom the payload, as the server already has this information. - In
server/src/socket/events.js, uncommenting the line that sends the room list on connection will improve the initial experience for new users.
Excellent progress overall, keep up the great work!
✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨
Footnotes
client/main.js
Outdated
| userId: socket.userId, | ||
| roomId: socket.roomId, |
There was a problem hiding this comment.
When sending a message, you're trying to access socket.userId and socket.roomId. These properties are set on the server-side socket object for a specific connection, but they don't exist on the client-side socket object. Here, they will resolve to undefined.
Fortunately, your server-side code for the message_send event only uses the text from this payload and gets the user and room info from its own socket instance, which is why this still works. For correctness, you should only send the data the server actually needs from the client, which in this case is just the text.
server/src/socket/events.js
Outdated
| io.on('connection', async (socket) => { | ||
| console.log('SOCKET CONNECTED', socket.id); | ||
|
|
||
| // socket.emit('room_list', await roomService.getAllRooms()); |
There was a problem hiding this comment.
When a new user connects, they don't receive the list of existing rooms until another user creates, renames, or deletes a room. Uncommenting this line will ensure that every new connection immediately receives the current list of rooms, improving the user experience.
Chat (with Node.js)