// leaderboard.js - leaderboard page logic import { getLeaderboard } from "./api.js"; import { getLobbyName, getPlayerName } from "./storage.js"; document.addEventListener("DOMContentLoaded", () => { const currentPlayer = getPlayerName(); const body = document.getElementById("lb-body"); /** * Escape HTML special characters to prevent XSS. * @param {string} str - Raw user-provided string. * @returns {string} HTML-safe string. */ function escHtml(str) { return String(str) .replace(/&/g, "&") .replace(//g, ">"); } /** Render the leaderboard from backend data. */ async function render() { const lobbyName = getLobbyName(); let board = []; try { const data = await getLeaderboard(lobbyName); board = data.leaderboard || []; } catch (_error) { body.innerHTML = `

Could not load the leaderboard. Make sure the backend is running.

Back to lobby
`; return; } body.innerHTML = ""; if (!board.length) { body.innerHTML = `
๐Ÿ

No games played yet. Be the first on the board!

Play now โ†’
`; return; } const medals = ["๐Ÿฅ‡", "๐Ÿฅˆ", "๐Ÿฅ‰"]; const scoreClasses = ["gold", "silver", "bronze"]; board.forEach((entry, index) => { const rank = index + 1; const playerName = entry.playerName || entry.name || "Anonymous"; const isYou = playerName === currentPlayer; const date = entry.date ? new Date(entry.date).toLocaleDateString("en-CH", { day: "2-digit", month: "short", }) : "โ€”"; const rounds = (entry.scores || []).join(" ยท ") || "โ€”"; const row = document.createElement("div"); row.className = `lb-row${rank <= 3 ? ` rank-${rank}` : ""}`; row.style.animationDelay = `${index * 0.05}s`; row.innerHTML = ` ${rank <= 3 ? `${medals[rank - 1]}` : rank} ${escHtml(playerName)} ${escHtml(rounds)} ${date} ${entry.totalScore} `; body.appendChild(row); }); const latest = board.find( (entry) => (entry.playerName || entry.name) === currentPlayer, ); if (latest) { document.getElementById("your-bar").style.display = "flex"; document.getElementById("your-bar-name").textContent = latest.playerName || latest.name; document.getElementById("your-bar-score").textContent = latest.totalScore; } } render(); });