try to fix this spaghetti of a code
This commit is contained in:
+59
-373
@@ -1,382 +1,68 @@
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
const logoutButton = document.getElementById("logout");
|
||||
const balance = document.getElementById("balance");
|
||||
const hostButton = document.getElementById("host");
|
||||
const joinButton = document.getElementById("join");
|
||||
const hostForm = document.getElementById("host-form");
|
||||
const createLobbyButton = document.getElementById("create-lobby");
|
||||
const lobbyVisibilityInputs = document.querySelectorAll("input[name='lobby-visibility']");
|
||||
const joinForm = document.getElementById("join-form");
|
||||
const joinCodeInput = document.getElementById("join-code");
|
||||
const joinSubmit = document.getElementById("submit-join");
|
||||
const refreshLobbies = document.getElementById("refresh-lobbies");
|
||||
const publicLobbies = document.getElementById("public-lobbies");
|
||||
const leaveButton = document.getElementById("leave-button");
|
||||
const joinError = document.getElementById("join-error");
|
||||
const lobbyRoom = document.getElementById("lobby-room");
|
||||
const lobbyIdDisplay = document.getElementById("lobby-id");
|
||||
const playerList = document.getElementById("player-list");
|
||||
const startGameButton = document.getElementById("start-game");
|
||||
let socket = null;
|
||||
let socketReady = null;
|
||||
let currentUsername = null;
|
||||
let currentLobbyId = null;
|
||||
|
||||
const showJoinError = (message) => {
|
||||
joinError.textContent = message;
|
||||
joinError.classList.remove("hidden");
|
||||
};
|
||||
|
||||
const clearJoinError = () => {
|
||||
joinError.textContent = "";
|
||||
joinError.classList.add("hidden");
|
||||
};
|
||||
|
||||
const renderPlayers = (players) => {
|
||||
playerList.innerHTML = "";
|
||||
|
||||
if (!players.length) {
|
||||
playerList.innerHTML = "<p>No players yet</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
for (const player of players) {
|
||||
const entry = document.createElement("p");
|
||||
entry.textContent = player;
|
||||
playerList.appendChild(entry);
|
||||
}
|
||||
};
|
||||
|
||||
const updateStartButton = (host, canStart) => {
|
||||
const isHost = currentUsername && host === currentUsername;
|
||||
startGameButton.classList.toggle("hidden", !isHost);
|
||||
startGameButton.disabled = !isHost || !canStart;
|
||||
startGameButton.textContent = canStart ? "Start Game" : "Waiting for 2 players";
|
||||
};
|
||||
|
||||
const showLobby = (lobbyId, players = [], host = null, canStart = false) => {
|
||||
currentLobbyId = lobbyId;
|
||||
lobbyIdDisplay.textContent = lobbyId;
|
||||
lobbyRoom.classList.remove("hidden");
|
||||
joinForm.classList.add("hidden");
|
||||
hostForm.classList.add("hidden");
|
||||
renderPlayers(players);
|
||||
updateStartButton(host, canStart);
|
||||
};
|
||||
|
||||
const joinLobby = (lobbyId) => {
|
||||
if (!currentUsername) {
|
||||
showJoinError("User not authenticated.");
|
||||
return Promise.reject(new Error("User not authenticated"));
|
||||
}
|
||||
return sendSocketMessage({type: "lobby:join", lobbyId});
|
||||
};
|
||||
|
||||
const renderPublicLobbies = (lobbies = []) => {
|
||||
publicLobbies.innerHTML = "";
|
||||
|
||||
if (!lobbies.length) {
|
||||
publicLobbies.innerHTML = "<p>No public lobbies found</p>";
|
||||
return;
|
||||
}
|
||||
|
||||
lobbies.forEach((lobby) => {
|
||||
const row = document.createElement("div");
|
||||
row.className = "public-lobby";
|
||||
|
||||
const info = document.createElement("div");
|
||||
info.className = "public-lobby-info";
|
||||
|
||||
const title = document.createElement("strong");
|
||||
title.textContent = lobby.host ? `${lobby.host}'s lobby` : "Public lobby";
|
||||
info.appendChild(title);
|
||||
|
||||
const meta = document.createElement("span");
|
||||
meta.textContent = `${lobby.players} player${lobby.players === 1 ? "" : "s"} - ${lobby.gameStarted ? "Game running" : "Waiting"}`;
|
||||
info.appendChild(meta);
|
||||
|
||||
const join = document.createElement("button");
|
||||
join.type = "button";
|
||||
join.textContent = "Join";
|
||||
join.addEventListener("click", () => {
|
||||
clearJoinError();
|
||||
joinLobby(lobby.lobbyId).catch(() => showJoinError("Could not join lobby."));
|
||||
});
|
||||
|
||||
row.appendChild(info);
|
||||
row.appendChild(join);
|
||||
publicLobbies.appendChild(row);
|
||||
});
|
||||
};
|
||||
|
||||
const loadPublicLobbies = async () => {
|
||||
try {
|
||||
publicLobbies.innerHTML = "<p>Loading lobbies...</p>";
|
||||
const res = await fetch("/lobby/public", {credentials: "same-origin"});
|
||||
if (!res.ok) {
|
||||
throw new Error("Failed to load lobbies");
|
||||
}
|
||||
const data = await res.json();
|
||||
renderPublicLobbies(data.lobbies || []);
|
||||
} catch (error) {
|
||||
publicLobbies.innerHTML = "<p>Could not load lobbies</p>";
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
const byId = id => document.getElementById(id);
|
||||
const client = new RealtimeClient();
|
||||
let username; let lobbyId;
|
||||
const error = message => {byId('join-error').textContent = message; byId('join-error').classList.toggle('hidden', !message);};
|
||||
const send = async message => {try {error(''); await client.send(message);} catch (problem) {error(problem.message);}};
|
||||
const hideLobby = () => {
|
||||
currentLobbyId = null;
|
||||
lobbyRoom.classList.add("hidden");
|
||||
lobbyIdDisplay.textContent = "N/A";
|
||||
playerList.innerHTML = "<p>Waiting for players...</p>";
|
||||
startGameButton.classList.add("hidden");
|
||||
startGameButton.disabled = true;
|
||||
lobbyId = null; localStorage.removeItem('activeLobbyId'); byId('lobby-room').classList.add('hidden');
|
||||
byId('host').disabled = false; byId('join').disabled = false;
|
||||
};
|
||||
|
||||
const sendSocketMessage = async (message) => {
|
||||
const ws = await connectSocket();
|
||||
ws.send(JSON.stringify(message));
|
||||
};
|
||||
|
||||
const connectSocket = () => {
|
||||
if (socket && socket.readyState === WebSocket.OPEN && socket.authenticated) {
|
||||
return Promise.resolve(socket);
|
||||
}
|
||||
|
||||
if (socketReady) {
|
||||
return socketReady;
|
||||
}
|
||||
|
||||
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||
socket = new WebSocket(`${protocol}//${window.location.host}`);
|
||||
|
||||
socketReady = new Promise((resolve, reject) => {
|
||||
socket.addEventListener("error", () => reject(new Error("WebSocket connection failed")), {once: true});
|
||||
socket.addEventListener("close", (event) => {
|
||||
reject(new Error(`WebSocket closed before authentication: ${event.reason || event.code}`));
|
||||
}, {once: true});
|
||||
socket.addEventListener("message", (event) => {
|
||||
const message = JSON.parse(event.data);
|
||||
if (message.type === "auth:success") {
|
||||
currentUsername = message.username;
|
||||
socket.authenticated = true;
|
||||
resolve(socket);
|
||||
}
|
||||
if (message.type === "auth:error") {
|
||||
reject(new Error(message.message || "WebSocket authentication failed"));
|
||||
}
|
||||
}, {once: true});
|
||||
});
|
||||
|
||||
socket.addEventListener("message", (event) => {
|
||||
const message = JSON.parse(event.data);
|
||||
|
||||
if (message.type === "auth:error") {
|
||||
showJoinError(message.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === "auth:success") {
|
||||
currentUsername = message.username;
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === "lobby:state") {
|
||||
clearJoinError();
|
||||
if (message.gameStarted) {
|
||||
localStorage.setItem("activeLobbyId", message.lobbyId);
|
||||
window.location.href = message.gameUrl || `/poker.html?lobbyId=${encodeURIComponent(message.lobbyId)}`;
|
||||
return;
|
||||
}
|
||||
showLobby(message.lobbyId, message.players || [], message.host, Boolean(message.canStart));
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === "poker:started") {
|
||||
localStorage.setItem("activeLobbyId", message.lobbyId);
|
||||
window.location.href = message.url || `/poker.html?lobbyId=${encodeURIComponent(message.lobbyId)}`;
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === "lobby:left") {
|
||||
hideLobby();
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === "lobby:error" || message.type === "error" || message.type === "poker:error") {
|
||||
showJoinError(message.message || "WebSocket request failed");
|
||||
}
|
||||
});
|
||||
|
||||
socket.addEventListener("close", () => {
|
||||
socket = null;
|
||||
socketReady = null;
|
||||
});
|
||||
|
||||
return socketReady;
|
||||
};
|
||||
|
||||
const getUsernameFromToken = async () => {
|
||||
async function refreshBalance() {
|
||||
try {
|
||||
const res = await fetch("/verify", {
|
||||
method: "POST",
|
||||
credentials: "same-origin"
|
||||
});
|
||||
if (!res.ok) {
|
||||
console.error("Token verification failed", res.status, await res.text());
|
||||
return null;
|
||||
}
|
||||
const data = await res.json();
|
||||
return data.user?.username;
|
||||
} catch (err) {
|
||||
console.error("Failed to get username from token", err);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
currentUsername = await getUsernameFromToken();
|
||||
if (!currentUsername) {
|
||||
showJoinError("User not authenticated.");
|
||||
const [balance, ranks] = await Promise.all([apiRequest('/balance'), apiRequest('/leaderboard')]);
|
||||
byId('balance').textContent = balance.balance;
|
||||
byId('leaderboard-list').replaceChildren(...ranks.leaderboard.map((player, index) => {
|
||||
const item = document.createElement('li'); item.textContent = `${index + 1}. ${player.username}: ${player.money}`;
|
||||
item.classList.toggle('you', player.username === username); return item;
|
||||
}));
|
||||
byId('your-rank').textContent = `Your rank: #${ranks.self.position}`;
|
||||
} catch (problem) {error(problem.message);}
|
||||
}
|
||||
|
||||
connectSocket().catch((error) => {
|
||||
console.error("Home WebSocket connection failed:", error);
|
||||
showJoinError("Real-time poker connection failed.");
|
||||
client.addEventListener('status', event => {error(event.detail); byId('start-game').disabled = !client.ready || byId('start-game').dataset.allowed !== 'true';});
|
||||
client.addEventListener('message', event => {
|
||||
const message = event.detail;
|
||||
if (message.type === 'auth:success') username = message.username;
|
||||
if (message.type === 'lobby:left') {hideLobby(); refreshBalance();}
|
||||
if (message.type !== 'lobby:state') return;
|
||||
lobbyId = message.lobbyId;
|
||||
if (message.gameStarted) {
|
||||
localStorage.setItem('activeLobbyId', lobbyId);
|
||||
location.assign(`/poker.html?lobbyId=${encodeURIComponent(lobbyId)}`); return;
|
||||
}
|
||||
byId('lobby-id').textContent = lobbyId; byId('lobby-room').classList.remove('hidden');
|
||||
byId('host-form').classList.add('hidden'); byId('join-form').classList.add('hidden');
|
||||
byId('host').disabled = true; byId('join').disabled = true;
|
||||
byId('player-list').replaceChildren(...message.players.map(player => {const item = document.createElement('p'); item.textContent = player; return item;}));
|
||||
const allowed = message.host === username && message.canStart;
|
||||
byId('start-game').dataset.allowed = String(allowed);
|
||||
byId('start-game').disabled = !allowed; byId('start-game').classList.toggle('hidden', message.host !== username);
|
||||
});
|
||||
|
||||
try {
|
||||
const balanceRes = await fetch("/balance", {
|
||||
method: "GET",
|
||||
credentials: "same-origin"
|
||||
});
|
||||
if (balanceRes.ok) {
|
||||
const balanceData = await balanceRes.json();
|
||||
balance.textContent = balanceData.balance;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Balance error:", error);
|
||||
}
|
||||
|
||||
logoutButton.addEventListener("click", async (e) => {
|
||||
e.preventDefault();
|
||||
byId('host').addEventListener('click', () => {byId('host-form').classList.toggle('hidden'); byId('join-form').classList.add('hidden');});
|
||||
byId('create-lobby').addEventListener('click', () => send({type: 'lobby:create', private: document.querySelector('[name="lobby-visibility"]:checked').value === 'private'}));
|
||||
async function loadLobbies() {
|
||||
try {
|
||||
if (socket && socket.readyState === WebSocket.OPEN && socket.authenticated) {
|
||||
socket.close();
|
||||
const {lobbies} = await apiRequest('/lobby/public');
|
||||
byId('public-lobbies').replaceChildren();
|
||||
if (!lobbies.length) {byId('public-lobbies').textContent = 'No public lobbies found'; return;}
|
||||
for (const lobby of lobbies) {
|
||||
const row = document.createElement('div'); row.className = 'public-lobby';
|
||||
const info = document.createElement('span'); info.textContent = `${lobby.host}: ${lobby.players}/10 players`;
|
||||
const button = document.createElement('button'); button.textContent = 'Join'; button.type = 'button';
|
||||
button.addEventListener('click', () => send({type: 'lobby:join', lobbyId: lobby.lobbyId}));
|
||||
row.append(info, button); byId('public-lobbies').append(row);
|
||||
}
|
||||
const logoutRes = await fetch("/logout", {
|
||||
method: "DELETE",
|
||||
credentials: "same-origin"
|
||||
});
|
||||
if (logoutRes.ok) {
|
||||
localStorage.removeItem("activeLobbyId");
|
||||
window.location.href = "/login.html";
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("Logout error:", err);
|
||||
}
|
||||
});
|
||||
|
||||
hostButton.addEventListener("click", async (e) => {
|
||||
e.preventDefault();
|
||||
clearJoinError();
|
||||
hostForm.classList.toggle("hidden");
|
||||
joinForm.classList.add("hidden");
|
||||
});
|
||||
|
||||
createLobbyButton.addEventListener("click", async (e) => {
|
||||
e.preventDefault();
|
||||
clearJoinError();
|
||||
if (!currentUsername) {
|
||||
showJoinError("User not authenticated.");
|
||||
return;
|
||||
}
|
||||
const selectedVisibility = [...lobbyVisibilityInputs].find(input => input.checked)?.value || "public";
|
||||
sendSocketMessage({type: "lobby:create", private: selectedVisibility === "private"}).catch(() => {
|
||||
showJoinError("Could not create lobby.");
|
||||
});
|
||||
});
|
||||
|
||||
joinButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
joinForm.classList.toggle("hidden");
|
||||
hostForm.classList.add("hidden");
|
||||
if (!joinForm.classList.contains("hidden")) {
|
||||
joinCodeInput.focus();
|
||||
loadPublicLobbies();
|
||||
}
|
||||
});
|
||||
|
||||
refreshLobbies.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
loadPublicLobbies();
|
||||
});
|
||||
|
||||
joinSubmit.addEventListener("click", async (e) => {
|
||||
e.preventDefault();
|
||||
clearJoinError();
|
||||
|
||||
const lobbyId = joinCodeInput.value.trim();
|
||||
if (!lobbyId) {
|
||||
showJoinError("Please enter a lobby ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!currentUsername) {
|
||||
showJoinError("User not authenticated.");
|
||||
return;
|
||||
}
|
||||
|
||||
joinLobby(lobbyId).then(() => {
|
||||
joinForm.classList.add("hidden");
|
||||
joinCodeInput.value = "";
|
||||
}).catch(() => {
|
||||
showJoinError("Could not join lobby. Please try again.");
|
||||
});
|
||||
});
|
||||
|
||||
leaveButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
const lobbyId = lobbyIdDisplay.textContent;
|
||||
if (!lobbyId || lobbyId === "N/A") return;
|
||||
sendSocketMessage({type: "lobby:leave", lobbyId}).catch(() => {
|
||||
showJoinError("Could not leave lobby.");
|
||||
});
|
||||
});
|
||||
|
||||
startGameButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
if (!currentLobbyId || startGameButton.disabled) return;
|
||||
sendSocketMessage({type: "poker:start", lobbyId: currentLobbyId}).catch(() => {
|
||||
showJoinError("Could not start game.");
|
||||
});
|
||||
});
|
||||
|
||||
async function loadLeaderboard() {
|
||||
try {
|
||||
const res = await fetch("/leaderboard", {credentials: "same-origin"});
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
const list = document.getElementById("leaderboard-list");
|
||||
const yourRank = document.getElementById("your-rank");
|
||||
|
||||
list.innerHTML = "";
|
||||
data.leaderboard.forEach((player, i) => {
|
||||
const item = document.createElement("li");
|
||||
item.textContent = `${i + 1}. ${player.username} - $${player.money}`;
|
||||
if (player.username === data.self.username) {
|
||||
item.classList.add("you");
|
||||
item.textContent += " (you)";
|
||||
}
|
||||
list.appendChild(item);
|
||||
});
|
||||
|
||||
yourRank.textContent = `You are ranked #${data.self.position} with $${data.self.money}`;
|
||||
} else {
|
||||
console.error("Failed to load leaderboard.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Leaderboard error:", err);
|
||||
}
|
||||
} catch (problem) {error(problem.message);}
|
||||
}
|
||||
|
||||
await loadLeaderboard();
|
||||
byId('join').addEventListener('click', () => {byId('join-form').classList.toggle('hidden'); byId('host-form').classList.add('hidden'); byId('join-code').focus(); loadLobbies();});
|
||||
byId('refresh-lobbies').addEventListener('click', loadLobbies);
|
||||
byId('submit-join').addEventListener('click', () => send({type: 'lobby:join', lobbyId: byId('join-code').value.trim().toLowerCase()}));
|
||||
byId('leave-button').addEventListener('click', () => send({type: 'lobby:leave', lobbyId}));
|
||||
byId('start-game').addEventListener('click', () => send({type: 'poker:start', lobbyId}));
|
||||
byId('logout').addEventListener('click', async () => {
|
||||
try {await apiRequest('/logout', {method: 'DELETE'}); client.close(); localStorage.removeItem('activeLobbyId'); location.assign('/login');}
|
||||
catch (problem) {error(`Logout failed: ${problem.message}`);}
|
||||
});
|
||||
try {username = (await apiRequest('/verify', {method: 'POST'})).user.username; await client.connect(); await refreshBalance();}
|
||||
catch (problem) {error(problem.message);}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user