73 lines
2.3 KiB
JavaScript

// leaderboard.js — leaderboard page logic
document.addEventListener("DOMContentLoaded", () => {
const currentPlayer = Storage.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, "&lt;")
.replace(/>/g, "&gt;");
}
/** Render the leaderboard from localStorage data. */
function render() {
const board = Storage.getLeaderboard();
body.innerHTML = "";
if (!board.length) {
body.innerHTML = `
<div class="lb-empty">
<div class="lb-empty__icon">🏁</div>
<p class="lb-empty__text">No games played yet. Be the first on the board!</p>
<a href="lobby.html" class="btn btn--primary btn--sm">Play now →</a>
</div>`;
return;
}
const medals = ["🥇", "🥈", "🥉"];
const scoreClasses = ["gold", "silver", "bronze"];
board.forEach((entry, index) => {
const rank = index + 1;
const isYou = entry.name === 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 = `
<span class="lb-rank">${rank <= 3 ? `<span class="lb-medal">${medals[rank - 1]}</span>` : rank}</span>
<span class="lb-name${isYou ? " is-you" : ""}">${escHtml(entry.name)}</span>
<span class="lb-rounds hide-sm">${escHtml(rounds)}</span>
<span class="lb-date hide-sm">${date}</span>
<span class="lb-score${rank <= 3 ? ` ${scoreClasses[rank - 1]}` : ""}">${entry.totalScore}</span>
`;
body.appendChild(row);
});
// Show the current player's latest score bar
const latest = board.find((entry) => entry.name === currentPlayer);
if (latest) {
document.getElementById("your-bar").style.display = "flex";
document.getElementById("your-bar-name").textContent = latest.name;
document.getElementById("your-bar-score").textContent = latest.totalScore;
}
}
render();
});