Skip to content

Instantly share code, notes, and snippets.

@AsaoluElijah
Created June 16, 2025 15:23
Show Gist options
  • Save AsaoluElijah/14fc1d9e8002aed5709d7602971ba242 to your computer and use it in GitHub Desktop.
Save AsaoluElijah/14fc1d9e8002aed5709d7602971ba242 to your computer and use it in GitHub Desktop.
const socket = io({
reconnection: true,
reconnectionAttempts: 5,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
});
let currentUser = null;
let currentRole = null;
let messageHistory = [];
function loadSession() {
const session = localStorage.getItem("chatSession");
if (session) {
const { email, role } = JSON.parse(session);
currentUser = { email };
currentRole = role;
document.getElementById("loginForm").classList.add("hidden");
document.getElementById("chatContainer").classList.remove("hidden");
updateStatusBar();
socket.emit("join", currentUser);
}
}
function saveSession(session) {
localStorage.setItem("chatSession", JSON.stringify(session));
}
function clearSession() {
localStorage.removeItem("chatSession");
currentUser = null;
currentRole = null;
}
function logout() {
socket.disconnect();
clearSession();
document.getElementById("messages").innerHTML = "";
document.getElementById("users").innerHTML = "";
document.getElementById("loginForm").classList.remove("hidden");
document.getElementById("chatContainer").classList.add("hidden");
document.getElementById("statusBar").classList.add("hidden");
document.getElementById("email").value = "";
socket.connect();
}
// UI updates
function showError(message) {
const errorDiv = document.getElementById("errorMessage");
errorDiv.textContent = message;
errorDiv.classList.remove("hidden", "translate-x-full");
setTimeout(() => {
errorDiv.classList.add("translate-x-full");
setTimeout(() => {
errorDiv.classList.add("hidden");
}, 300);
}, 5000);
}
function updateStatusBar() {
const statusBar = document.getElementById("statusBar");
const userStatus = document.getElementById("userStatus");
if (currentUser) {
statusBar.classList.remove("hidden");
userStatus.textContent = `Logged in as ${currentUser.email} (${currentRole})`;
} else {
statusBar.classList.add("hidden");
}
}
function updateUserList(user, isJoining) {
const usersDiv = document.getElementById("users");
const userElement = document.getElementById(`user-${user.email}`);
if (isJoining) {
if (!userElement) {
const newUserElement = document.createElement("div");
newUserElement.id = `user-${user.email}`;
newUserElement.className =
"py-2 border-b border-gray-200 last:border-b-0 flex justify-between items-center";
newUserElement.innerHTML = `
<span class="text-gray-800">${user.email}</span>
<span class="text-xs text-gray-500">(${user.role})</span>
`;
usersDiv.appendChild(newUserElement);
}
} else {
if (userElement) {
userElement.remove();
}
}
}
// Chat actions
function joinChat() {
const email = document.getElementById("email").value;
if (!email) {
showError("Please enter your email");
return;
}
currentUser = { email };
socket.emit("join", currentUser);
document.getElementById("loginForm").classList.add("hidden");
document.getElementById("chatContainer").classList.remove("hidden");
}
function sendMessage() {
const messageInput = document.getElementById("messageInput");
const message = messageInput.value.trim();
if (message) {
socket.emit("sendMessage", { message });
messageInput.value = "";
}
}
function deleteMessage(messageId) {
socket.emit("deleteMessage", messageId);
}
// Socket event handlers
socket.on("session", (session) => {
saveSession(session);
});
socket.on("connect", () => {
console.log("Connected to server");
if (currentUser) {
socket.emit("join", currentUser);
}
});
socket.on("reconnect", () => {
console.log("Reconnected successfully");
if (currentUser) {
socket.emit("join", currentUser);
}
});
socket.on("newMessage", (data) => {
const messagesDiv = document.getElementById("messages");
const messageElement = document.createElement("div");
messageElement.className =
"mb-4 p-4 bg-white rounded-lg shadow-sm relative group";
messageElement.id = `message-${data.id}`;
let actionsHtml = "";
if (currentRole === "admin" || currentRole === "editor") {
actionsHtml = `
<div class="absolute top-2 right-2 opacity-0 group-hover:opacity-100 transition-opacity">
<button onclick="deleteMessage('${data.id}')"
class="px-3 py-1 text-sm bg-red-500 text-white rounded hover:bg-red-600 transition-colors">
Delete
</button>
</div>
`;
}
messageElement.innerHTML = `
<strong class="block text-gray-800 mb-1">${data.email}</strong>
<p class="text-gray-600 mb-1">${data.message}</p>
<small class="text-gray-400 text-xs">${new Date(
data.timestamp
).toLocaleTimeString()}</small>
${actionsHtml}
`;
messagesDiv.appendChild(messageElement);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
// Store message in history
messageHistory.push(data);
});
socket.on("messageDeleted", (messageId) => {
const messageElement = document.getElementById(`message-${messageId}`);
if (messageElement) {
messageElement.remove();
}
// Remove from history
messageHistory = messageHistory.filter((msg) => msg.id !== messageId);
});
socket.on("userJoined", (user) => {
updateUserList(user, true);
});
socket.on("userLeft", (user) => {
updateUserList(user, false);
});
socket.on("currentUsers", (users) => {
const usersDiv = document.getElementById("users");
usersDiv.innerHTML = "";
users.forEach((user) => {
updateUserList(user, true);
});
});
socket.on("userRole", (role) => {
currentRole = role;
updateStatusBar();
});
socket.on("error", (error) => {
showError(error);
});
// Event listeners
document.getElementById("messageInput").addEventListener("keypress", (e) => {
if (e.key === "Enter") {
sendMessage();
}
});
// Initialize
window.addEventListener("load", loadSession);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment