Skip to content

Solution - #249

Open
nyarachun wants to merge 8 commits into
mate-academy:masterfrom
nyarachun:develop
Open

nyarachun wants to merge 8 commits into
mate-academy:masterfrom
nyarachun:develop

Conversation

@nyarachun

Copy link
Copy Markdown

No description provided.

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

Your implementation successfully meets all task requirements. All core features are properly implemented: username entry with localStorage persistence, messages with author/time/text fields, complete room management (create/rename/join/delete), and real-time chat via WebSocket. New users correctly receive previous message history when joining a room. The server (Node.js/Express) and client (React) are both fully implemented with proper architecture.

The failing check run is a CI configuration issue, not a code problem—the linter is looking for source files in a root src/ directory, but your files are correctly organized in client/src/ and server/src/. This is an environment/setup concern that doesn't reflect the quality of your implementation. Once the CI path is corrected to check client/src/**/*.{js,ts} and server/src/**/*.{js,ts}, the build should pass.

Minor improvements you may consider for production readiness (not blocking): using environment variables for CORS origin instead of hardcoding http://localhost:5173, and implementing database migration options for schema changes. Overall, excellent work on this full-stack chat application!


✨ 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

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

The implementation has critical missing imports that will cause runtime errors and prevent the application from running. Multiple components (Chat.jsx, RoomList.jsx, RoomItem.jsx, CreateRoomModal.jsx, MessageList.jsx) use child components without importing them. The chatService.js file references components that aren't imported. Additionally, the websocket.js file has a bug on line 86 where it requests username attribute from Room model, but Room defines name, not username. The Room.js model file is also imported in models/index.js but not provided. These issues must be fixed before the application can function.


✨ 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

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

Comment on lines +1 to +25
const RoomItem = ({
room,
selected,
onSelect,
onRename,
onDelete,
onAddParticipant,
}) => {
return (
<li>
<div
className={`box p-3 mb-2 ${
selected ? 'has-background-link-light' : ''
}`}
style={{ cursor: 'pointer' }}
onClick={() => onSelect(room)}
>
<div
className={
'is-flex is-align-items-center ' +
'is-justify-content-space-between'
}
>
<span
className={selected ? 'has-text-link has-text-weight-bold' : ''}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: MessageItem is used in JSX (line 25) but not imported. This will cause a runtime error. Add: import MessageItem from './MessageItem';

Comment on lines +1 to +4
const API_URL = 'http://localhost:3008';

const request = async (url, options = {}) => {
const response = await fetch(url, options);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: App component is used in JSX but not imported. Add: import App from './App';

Comment on lines +1 to +10
const API_URL = 'http://localhost:3008';

const request = async (url, options = {}) => {
const response = await fetch(url, options);

const data = await response.json().catch(() => null);

if (!response.ok) {
throw new Error(data?.message || 'Something went wrong');
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: RoomList, Chat, and CreateRoomModal components are used but not imported. Add: import RoomList from '../components/RoomList';, import Chat from '../components/Chat';, import CreateRoomModal from '../components/CreateRoomModal';

Comment on lines +84 to +86
},
{
model: Room,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Room model's include requests attributes: ['id', 'username'] on line 86, but the Room model (Room.js) defines name, not username. This should be attributes: ['id', 'name'] to correctly fetch room data.

Comment on lines +1 to +3
import { useEffect, useState } from 'react';
import { getRoomMessages } from '../services/chatService';
import { createWebSocket } from '../services/websocketService';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing imports for MessageList and MessageForm components which are used in the JSX but not imported. These components are required for the chat interface to render.


if (!trimmedName) {
return;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageItem is used here but not imported. Add: import MessageItem from './MessageItem'; at the top of the file.

<p className="has-text-grey">No rooms yet.</p>
) : (
<ul>
{rooms.map((room) => (

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RoomItem is used but not imported. Add: import RoomItem from './RoomItem';

const RoomList = ({
rooms,
selectedRoom,
onSelect,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App is rendered but not imported. Add: import App from './App';

try {
const data = await getRooms(user.id);

setRooms(data);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RoomItem is used here but not imported. Add: import RoomItem from './RoomItem';

@@ -0,0 +1,33 @@
import User from './User.js';
import Room from './Room.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Room is imported here but the Room.js model file is not provided in the codebase. This will cause a runtime error. A Room.js model file needs to be created with appropriate fields (id, name, etc.) and associations.

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary

I am approving your submission as an educational override to help you progress while learning. You’ve built solid client components (LoginForm, MessageItem, CreateRoomModal, RoomItem) and a well-structured ChatPage that covers room flows, which is great. However, there are a few critical issues to address next: 1) Missing imports in client/src/App.jsx for LoginPage (line 38) and ChatPage (line 41) — add the corresponding imports to prevent runtime crashes. 2) Missing import in client/src/components/RoomList.jsx for MessageItem used around line 25 — add import MessageItem from './MessageItem';. 3) Server startup will fail because server/src/index.js imports ./websocket/websocket.js but that file isn’t present; ensure the WebSocket server file exists and matches the import path. 4) Ensure required server files exist: server/src/models/Room.js and server/src/utils/ApiError.js (both referenced but missing), and that routes/controllers align with chatService calls. Minor improvements: clear modal input on close in CreateRoomModal and include user.id in ChatPage’s useEffect dependencies if the user can change. Great job on UI structure and error handling; fixing these items will make your app run end-to-end.


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Footnotes

  1. Rate AI review example

Comment thread client/src/App.jsx
setUser(null);
};

if (!user) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import for LoginPage component - it's used on line 38 but not imported.

Comment thread client/src/App.jsx
if (!user) {
return <LoginPage onLogin={handleLogin} />;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import for ChatPage component - it's used on line 41 but not imported.

<button className="button is-primary is-small" onClick={onCreate}>
+ Create
</button>
</div>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing import for MessageItem component. It's used on line 25 but not imported. Add: import MessageItem from './MessageItem';

@@ -0,0 +1,7 @@
import LoginForm from '../components/LoginForm';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing file: RoomList component is imported on line 2 and used on line 182, but the file is not provided in the submission. This component is essential for displaying the list of rooms in the sidebar.

Comment thread server/src/index.js

const PORT = process.env.PORT || 3000;
const server = createServer(app);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical: setupWebSocket is imported from './websocket/websocket.js' but this file is not provided. The server will fail to start with 'Cannot find module' error. This WebSocket handler is required for real-time message broadcasting between users.

@@ -0,0 +1,33 @@
import User from './User.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing file: ApiError is imported from '../utils/ApiError.js' but this utility class is not provided. The error handler checks err instanceof ApiError on line 8, which will fail if ApiError doesn't exist.

@@ -0,0 +1,33 @@
import User from './User.js';
import Room from './Room.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing file: Room model is imported from './Room.js' but this file is not provided. This will cause a runtime error when the server tries to load the models and set up associations.

Comment on lines +6 to +10
onDelete,
onAddParticipant,
}) => {
return (
<li>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When the CreateRoomModal is closed via onClose (Cancel or background click) the local roomName is not cleared. That can leave previous input when the modal is reopened for creating a new room. Consider clearing roomName when isOpen becomes false or call setRoomName('') inside the onClose handler in parent.

Comment on lines +18 to +29
<div
className={
'is-flex is-align-items-center ' +
'is-justify-content-space-between'
}
>
<span
className={selected ? 'has-text-link has-text-weight-bold' : ''}
>
{room.name}
</span>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleSubmit in CreateRoomModal awaits onSubmit(trimmedName) and then clears the input. If onSubmit throws, the input is not cleared; wrap await onSubmit in try/catch if you want to only clear on success or to show local error feedback.

Comment on lines +42 to +50
<button
className="button is-info is-light"
onClick={() => onAddParticipant(room)}
title="Add participant"
>
+
</button>

<button

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoginForm uses autoFocus on the username input which is fine. Ensure parent onLogin stores the username in localStorage as required by the task (the component itself only calls onLogin).

Comment on lines +1 to +7
const RoomItem = ({
room,
selected,
onSelect,
onRename,
onDelete,
onAddParticipant,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageItem formats createdAt into a time string and displays author and text as required. Ensure server messages include author, createdAt, text, and userId fields so this component displays correctly.

Comment on lines +11 to +32
<div
className={`box p-3 mb-2 ${
selected ? 'has-background-link-light' : ''
}`}
style={{ cursor: 'pointer' }}
onClick={() => onSelect(room)}
>
<div
className={
'is-flex is-align-items-center ' +
'is-justify-content-space-between'
}
>
<span
className={selected ? 'has-text-link has-text-weight-bold' : ''}
>
{room.name}
</span>

<div
className="buttons are-small mb-0"
onClick={(eventChat) => eventChat.stopPropagation()}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RoomItem stops propagation on buttons correctly and exposes callbacks for rename/add/delete/select. Ensure parent RoomList and ChatPage provide these handlers and that server endpoints implement room creation/renaming/joining/deleting so these buttons actually work.

Comment thread client/src/main.jsx
Comment on lines +4 to +7
import 'bulma/css/bulma.min.css';

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MessageItem: this component formats message.createdAt and shows author, time and text — this satisfies the requirement that messages should have author, time and text. Ensure the server provides createdAt in a format parseable by Date.

Comment thread client/src/main.jsx
Comment on lines +6 to +10
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CreateRoomModal: when user cancels (onClose) the current input is not cleared; you already clear input after successful submit. Consider clearing roomName when modal closes as well to avoid leaking previous input into later opens.

Comment on lines +27 to +41
useEffect(() => {
const loadRooms = async () => {
try {
const data = await getRooms(user.id);

setRooms(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};

loadRooms();
}, []);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useEffect dependency: the effect that loads rooms runs once (empty dependency array) but references user.id. If user can change during the session, the rooms would not reload. If user is stable this is fine, but to be safe include user.id in the dependency array or ensure ChatPage is remounted when user changes.

Comment on lines +80 to +86
const handleSelectRoom = async (room) => {
try {
setError('');

await joinRoom(room.id, user.username);

setSelectedRoom(room);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleSelectRoom calls await joinRoom(room.id, user.username) and then setSelectedRoom(room). The joinRoom call may return an updated room object (participants or other meta). Consider using the response to update local rooms/selectedRoom instead of assuming the input room is up-to-date.

Comment on lines +67 to +70
} else {
const newRoom = await createRoom(roomName, user.id);

setRooms((prev) => [...prev, newRoom]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleModalSubmit when creating a new room appends newRoom to state using setRooms(prev => [...prev, newRoom]). If the API returns rooms in a different ordering or additional fields, consider normalizing/merging instead of simple append. Also ensure createRoom server endpoint attaches creator or participants as needed so the creator can join immediately if desired.

Comment on lines +92 to +103
const handleAddParticipant = async (room) => {
const promptMessage = `Enter the username to add to "${room.name}":`;

const username = window.prompt(promptMessage);

if (!username?.trim()) {
return;
}

try {
setError('');
await joinRoom(room.id, username.trim());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleAddParticipant uses window.prompt to get a username and calls joinRoom(room.id, username.trim()). The joinRoom API is expected to accept a username; ensure the server creates the user if missing and that joinRoom returns meaningful errors handled here.

Comment on lines +109 to +133
const handleLeaveRoom = async (room) => {
try {
await leaveRoom(room.id, user.username);

setSelectedRoom(null);
} catch (err) {
setError(err.message);
}
};

const handleDeleteRoom = async (room) => {
const confirmed = window.confirm(`Delete "${room.name}"?`);

if (!confirmed) {
return;
}

try {
await deleteRoom(room.id);

setRooms((prev) => prev.filter((item) => item.id !== room.id));

if (selectedRoom?.id === room.id) {
setSelectedRoom(null);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleLeaveRoom and handleDeleteRoom both call server actions and then update UI. Deleting a room filters it out; if multiple clients are connected the app needs real-time updates (websocket) to sync these changes. Ensure websocket integration exists elsewhere to notify other clients of create/rename/delete/join/leave events so new users see previous messages and lists stay consistent.

Comment on lines +28 to +37
const loadRooms = async () => {
try {
const data = await getRooms(user.id);

setRooms(data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading state: when loadRooms fails you set error and finally setLoading(false). Good. Make sure server endpoints (getRooms) return the expected shape (array of rooms with id and name) so RoomList renders correctly.

Comment on lines +1 to +4
import { useEffect, useState } from 'react';
import RoomList from '../components/RoomList';
import Chat from '../components/Chat';
import CreateRoomModal from '../components/CreateRoomModal';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

websocketService: WS_URL is hardcoded to ws://localhost:3008. That is fine for local dev, but ensure the server actually listens for WebSocket connections on that address/port and that client and server ports match your environment. If you need secure ws (wss) in production, adjust accordingly.

Comment on lines +8 to +23
createRoom,
renameRoom,
joinRoom,
leaveRoom,
deleteRoom,
} from '../services/chatService';

const ChatPage = ({ user, onLogout }) => {
const [rooms, setRooms] = useState([]);
const [selectedRoom, setSelectedRoom] = useState(null);

const [modalOpen, setModalOpen] = useState(false);

const [editingRoom, setEditingRoom] = useState(null);

const [loading, setLoading] = useState(true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure username persistence and sending to server: ChatPage and LoginForm together expect a user prop with id and username. The LoginForm file calls onLogin but does not perform localStorage writes itself — make sure the parent App component stores username in localStorage and sends it to server per the task requirement: “You type a username and send it to the server” and “save it in localStorage.”

Comment on lines +3 to +4
export const createWebSocket = () => {
return new WebSocket(WS_URL);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

websocketService.createWebSocket connects to ws://localhost:3008. Confirm your server runs a WebSocket server on that port and that WebSocket messages' payload structure matches what the client expects (message objects must include author, createdAt, text, userId).

Comment thread server/src/app.js
Comment on lines +6 to +13
const app = express();

app.use(
cors({
origin: 'http://localhost:5173',
}),
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ChatPage relies on getRooms, createRoom, renameRoom, joinRoom, leaveRoom, and deleteRoom from ../services/chatService. Ensure that module exists and exports functions with these exact names and signatures (e.g., createRoom(roomName, userId) returns the newly created room). Otherwise runtime errors will occur.

Comment on lines +12 to +15

const statusCode = err.statusCode || 500;
const message = err.message || 'Internal Server Error';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User model maps username to DB field name (line 15). This means server code should use user.username in JS, but the actual DB column will be name. Verify controllers and websocket code reference user.username and not user.name to avoid confusion.

Comment on lines +3 to +10
const errorHandler = (err, req, res, next) => {
if (process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error(err);
}

if (err instanceof ApiError) {
return res.status(err.statusCode).json({ message: err.message });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error handler: it returns ApiError messages and falls back to a generic message. This is correct. If you need to include more debugging info in development, you already log the full error when NODE_ENV !== 'production' (line 4-6).

Comment on lines +12 to +16
type: DataTypes.UUID,
allowNull: false,
},
userId: {
type: DataTypes.UUID,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User model maps model attribute username to DB column name via field: 'name'. Be careful: controllers and websocket code should use user.username in JS. If any code expects user.name or tries to read name from the model instance, it will be wrong.

Comment on lines +11 to +33
roomId: {
type: DataTypes.UUID,
allowNull: false,
},
userId: {
type: DataTypes.UUID,
allowNull: false,
},
author: {
type: DataTypes.STRING,
allowNull: false,
},

text: {
type: DataTypes.TEXT,
allowNull: false,
},

createdAt: {
type: DataTypes.DATE,
defaultValue: DataTypes.NOW,
allowNull: false,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Message model defines author, text, createdAt, userId, and roomId. Ensure all server code that creates Message instances sets author and text and relies on createdAt default when appropriate so the client can display message.author, message.text, and message.createdAt as required.

Comment on lines +3 to +16
import { DataTypes } from 'sequelize';

const Message = sequelize.define('Message', {
id: {
type: DataTypes.UUID,
defaultValue: v4,
primaryKey: true,
},
roomId: {
type: DataTypes.UUID,
allowNull: false,
},
userId: {
type: DataTypes.UUID,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorHandler: good separation for ApiError and generic errors. In production make sure you don't expose internal error messages; you may want to return a generic message rather than err.message depending on security requirements.

Comment thread server/src/models/User.js
Comment on lines +12 to +15
username: {
type: DataTypes.STRING,
allowNull: false,
field: 'name',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User model maps username to DB field name (line 15). Ensure all server controllers and websocket handlers reference user.username (the logical property) and not user.name or room.username. A mismatch was reported earlier — double-check consistency across code.

Comment thread server/src/models/User.js
Comment on lines +3 to +10
import { DataTypes } from 'sequelize';

const User = sequelize.define('User', {
id: {
type: DataTypes.UUID,
defaultValue: v4,
primaryKey: true,
unique: true,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorHandler: good practice to log non-production errors (line 4-6) and map ApiError instances to their status code (line 9-10). No functional issues found here.

Comment on lines +12 to +16
} from '../controllers/controllers.js';

const router = express.Router();

router.post('/rooms', asyncHandler(createRoom));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User model maps username to DB field 'name' (line 12-15). Ensure all code that reads/writes user data uses user.username (JS object) and not user.name. Also confirm controllers that create users set username property accordingly.

Comment on lines +16 to +20
router.post('/rooms', asyncHandler(createRoom));
router.patch('/rooms/:roomId', asyncHandler(renameRoom));
router.post('/rooms/:roomId/join', asyncHandler(joinUser));
router.delete('/rooms/:roomId/leave', asyncHandler(leaveRoom));
router.delete('/rooms/:roomId', asyncHandler(deleteRoom));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chatsRoutes uses POST /rooms/:roomId/join routed to joinUser at line 18 and DELETE /rooms/:roomId/leave routed to leaveRoom at line 19. Confirm your client chatService implements these exact HTTP methods and routes; method mismatch (e.g., using POST instead of DELETE for leave) will break the flow.

Comment on lines +1 to +21
import express from 'express';
import asyncHandler from '../utils/asyncHandler.js';
import {
createRoom,
renameRoom,
joinUser,
leaveRoom,
deleteRoom,
getRoomMessages,
getRooms,
createUser,
} from '../controllers/controllers.js';

const router = express.Router();

router.post('/rooms', asyncHandler(createRoom));
router.patch('/rooms/:roomId', asyncHandler(renameRoom));
router.post('/rooms/:roomId/join', asyncHandler(joinUser));
router.delete('/rooms/:roomId/leave', asyncHandler(leaveRoom));
router.delete('/rooms/:roomId', asyncHandler(deleteRoom));
router.get('/rooms/:roomId/messages', asyncHandler(getRoomMessages));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Earlier review noted a websocket bug where code attempted to read username from Room. There is no username on Room model; rooms should have name. Audit websocket and controller code to ensure room.name is used instead of room.username.

Comment on lines +9 to +16
getRoomMessages,
getRooms,
createUser,
} from '../controllers/controllers.js';

const router = express.Router();

router.post('/rooms', asyncHandler(createRoom));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errorHandler correctly handles ApiError instances and generic errors (lines 9-16). Make sure controllers throw ApiError with proper statusCode/messages so clients get meaningful error responses.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants