Skip to content

Birmingham | 26-SDC-Mar | Chioma Okeke | Sprint 2 | Chat App#84

Open
JanefrancessC wants to merge 6 commits into
CodeYourFuture:mainfrom
JanefrancessC:sprint2-chat-app
Open

Birmingham | 26-SDC-Mar | Chioma Okeke | Sprint 2 | Chat App#84
JanefrancessC wants to merge 6 commits into
CodeYourFuture:mainfrom
JanefrancessC:sprint2-chat-app

Conversation

@JanefrancessC
Copy link
Copy Markdown

@JanefrancessC JanefrancessC commented May 26, 2026

Learners, PR Template

Self checklist

  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • My changes meet the requirements of the task
  • I have tested my changes
  • My changes follow the style guide

Changelist

Backend link
Frontend link

Additional Feature

  • I added the like and dislike buttons, which are incremented on click.

@JanefrancessC JanefrancessC added 📅 Sprint 2 Assigned during Sprint 2 of this module Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. Module-Decomposition The name of the module. labels May 26, 2026
Copy link
Copy Markdown

@cjyuan cjyuan left a comment

Choose a reason for hiding this comment

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

  1. Code works well on normal circumstances. Well done.

  2. Code could use some documentation (comments).

    A useful rule of thumb is to ask yourself whether you could still explain or figure out how the code works few months from now. If the answer is uncertain, consider adding a comment to help future readers understand the intent and reasoning behind it.

  3. The README has this requirement:

    It must also support at least one additional feature.

    In the PR description, can you list the extra features you implemented?

Comment thread chat-app/backend/index.js
Comment on lines +8 to +10
const port = process.env.PORT || 3000;
let nextMessageId = 1;
const messages = [
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Better to declare global constants and variables before const app = express() because lines 5-6 are already logic to setup the server (app).

Comment thread chat-app/backend/index.js
});

app.post("/", (req, res) => {
const { message, user } = req.body;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It's good practice to validate all request inputs.

Note: A more robust implementation

  • Should also handle the case where req.body is null, which would cause const { text, sender } = req.body; to throw.

In this exercise, let's assume the request is always coming from the code in script.js. So no change needed.

Comment thread chat-app/backend/index.js
Comment on lines +59 to +69
!message.trim() ||
!user.trim()
) {
res.status(400).json({ error: `Message and user are required!` });
return;
}

const newMessage = {
id: nextMessageId++,
message,
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.

It's a bit inconsistent that message containing only space characters are not allowed but leading and trailing space characters are acceptable.

Comment thread chat-app/backend/index.js
messages.push(newMessage);
while (callbacksForNewMessages.length > 0) {
const callback = callbacksForNewMessages.pop();
callback([messages[messages.length - 1]]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Wouldn't sending newMessage shorter in syntax?

Comment on lines +79 to +81
state.messages = state.messages.map((msg) =>
msg.id === updatedMessage.id ? updatedMessage : msg,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Note: Not very efficient approach to update one number. (Change is optional, as this is an extra feature).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I didn't give it much thought since it's classwork, but I'll rectify this so I don't have to loop through all the messages to update one message.

Comment on lines +88 to +107
async function dislikeMessage(msgId) {
try {
const response = await fetch(`${serverURL}/${msgId}/dislike`, {
method: "POST",
});

if (!response.ok) {
feedbackEl.innerHTML = `<p>${await response.text()}</p>`;
return;
}
const updatedMessage = await response.json();

state.messages = state.messages.map((msg) =>
msg.id === updatedMessage.id ? updatedMessage : msg,
);
displayMessages();
} catch (error) {
console.error(error.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.

The code in dislikeMessage() and likeMessage() is nearly identical and could be refactored to reduce duplication.

The same also applies to their counterparts on the server side.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I will also modify this by creating a generic function, then using a conditional statement to increment either the like or dislike button.

(msg) =>
`<div>
<p>
<strong>${msg.user}: ${msg.message} </strong>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What if the user's name or message contains characters like < or >? For example, <javascript src="..."></script>.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

This is quite interesting about innerHTML. Thank you for pointing this out; I never thought about users passing HTML tags. I will rectify this by creating DOM elements and assigning them values using textContent

}
}

function displayMessages() {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If this function is design to accept messages as a parameter, it would make the rendering logic easier to develop and test independently.

As a general rule, prefer passing data through parameters instead of relying on global variables.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I will modify this to accept messages as a parameter, rather than a global variable.

Comment on lines +151 to +155
feedbackEl.innerHTML = `<p>Message sent!</p>`;

setTimeout(() => {
feedbackEl.innerHTML = "";
}, 3000);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could consider isolating the logic for showing feedback in a function showFeedback(msg, timeoutDuration).

if (longPoll) {
keepFetchingMessages();
} else {
setTimeout(keepFetchingMessages, 2000);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

2000 is a magic number and best practice is to represent all magic numbers as named constants.

@cjyuan cjyuan added Reviewed Volunteer to add when completing a review with trainee action still to take. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels May 29, 2026
@JanefrancessC
Copy link
Copy Markdown
Author

  1. Code works well on normal circumstances. Well done.

  2. Code could use some documentation (comments).
    A useful rule of thumb is to ask yourself whether you could still explain or figure out how the code works few months from now. If the answer is uncertain, consider adding a comment to help future readers understand the intent and reasoning behind it.

  3. The README has this requirement:

    It must also support at least one additional feature.

    In the PR description, can you list the extra features you implemented?

Thank you for the thorough feedback. I have edited the PR to include the extra feature and will modify my code per the review.

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

Labels

Module-Decomposition The name of the module. Reviewed Volunteer to add when completing a review with trainee action still to take. 📅 Sprint 2 Assigned during Sprint 2 of this module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants