Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/test.yml-template
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Test

on:
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [20.x]

steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test
33 changes: 33 additions & 0 deletions client/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Chat</title>
</head>
<body>
<h1>Chat</h1>

<div style="display: flex; gap: 20px">
<div>
<h3>Rooms</h3>

<div id="rooms"></div>
<input id="roomInput" placeholder="room name" />
<button id="createRoom">Create</button>
Comment on lines +11 to +16
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 'rename room' functionality. The task requires 'create / rename / join / delete' rooms. There's no UI element or socket event handler for renaming rooms.

Comment on lines +11 to +16
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 'delete room' functionality. The task requires 'create / rename / join / delete' rooms. There's no UI element or socket event handler for deleting rooms.

<button id="renameRoom">Rename</button>
<button id="deleteRoom">Delete</button>
</div>

<div>
<div id="messages"></div>

<input id="input" placeholder="Type message..." />
<button id="send">Send</button>
</div>
</div>

<!-- socket.io client -->
<script src="https://cdn.socket.io/4.7.5/socket.io.min.js"></script>
<script src="./main.js"></script>
</body>
</html>
161 changes: 161 additions & 0 deletions client/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/* eslint-disable no-undef */
/* eslint-disable no-console */

const socket = io('http://localhost:3000');

const input = document.getElementById('input');
const btn = document.getElementById('send');
const messages = document.getElementById('messages');
const roomsDiv = document.getElementById('rooms');
const roomInput = document.getElementById('roomInput');
const createRoomBtn = document.getElementById('createRoom');
const renameRoomBtn = document.getElementById('renameRoom');
const deleteRoomBtn = document.getElementById('deleteRoom');

let username = localStorage.getItem('username');
let currentRoom = 'general';

function addRoom(name) {
Comment on lines +1 to +18
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 requirements specify 'create / rename / delete' rooms, but only room creation is implemented. Rename and delete room UI elements and functionality are missing from the frontend.

if ([...roomsDiv.children].some((b) => b.textContent === name)) {
return;
}

const button = document.createElement('button');

button.textContent = name;

button.addEventListener('click', () => {
socket.emit('join_room', name);
currentRoom = name;

messages.innerHTML = '';
});

roomsDiv.appendChild(button);
}

if (!username) {
username = prompt('Enter username');
localStorage.setItem('username', username);
}

socket.emit('set_username', username);

socket.on('connect', () => {
console.log('Connected:', socket.id);

socket.emit('join_room', 'general');
currentRoom = 'general';

messages.innerHTML = '';

addRoom('general');
});

socket.on('message', (data) => {
const div = document.createElement('div');

const time = new Date(data.time).toLocaleString();

div.textContent = `${data.author} [${time}]: ${data.text}`;
messages.appendChild(div);
});

socket.on('room_history', (mgss) => {
mgss.forEach((msg) => {
const div = document.createElement('div');

const time = new Date(msg.time).toLocaleTimeString();

div.textContent = `${msg.author} [${time}]: ${msg.text}`;

messages.appendChild(div);
});
});

socket.on('room_created', (roomName) => {
addRoom(roomName);
});

socket.on('room_renamed', ({ oldName, newName }) => {
const btns = [...roomsDiv.children];

btns.forEach((b) => {
if (b.textContent === oldName) {
b.textContent = newName;
}
});

if (currentRoom === oldName) {
currentRoom = newName;
}

messages.innerHTML = '';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This socket event name uses a hyphen ('join-room') but the server listens for 'join_room' with an underscore. The client won't properly join the renamed room after renaming, breaking message delivery. Change 'join-room' to 'join_room' to match the server handler.

socket.emit('join_room', newName);
});

socket.on('room_deleted', (roomName) => {
[...roomsDiv.children].forEach((b) => {
if (b.textContent === roomName) {
b.remove();
}
});

if (currentRoom === roomName) {
currentRoom = 'general';
messages.innerHTML = '';

socket.emit('join_room', 'general');
}
});

btn.addEventListener('click', () => {
const text = input.value;

if (!text) {
return;
}
Comment on lines +27 to +118
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 requirements specify 'create / rename / delete' rooms, but only create_room event is handled. Missing: rename_room and delete_room event handlers on the server.


socket.emit('message', {
text,
author: username,
time: Date.now(),
room: currentRoom,
});

input.value = '';
});

createRoomBtn.addEventListener('click', () => {
const roomName = roomInput.value.trim();

if (!roomName) {
return;
}

socket.emit('create_room', roomName);
socket.emit('join_room', roomName);

currentRoom = roomName;

messages.innerHTML = '';
roomInput.value = '';
Comment on lines +129 to +143
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 requirements specify 'create / rename / delete' rooms, but only createRoom button exists. Missing UI buttons for renaming and deleting rooms.

});

renameRoomBtn.addEventListener('click', () => {
const newName = prompt('New room name');

if (!newName) {
return;
}

socket.emit('rename_room', {
oldName: currentRoom,
newName,
});
});

deleteRoomBtn.addEventListener('click', () => {
socket.emit('delete_room', currentRoom);
});
Loading
Loading