73 lines
2.3 KiB
JavaScript
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, "<")
|
|
.replace(/>/g, ">");
|
|
}
|
|
|
|
/** 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();
|
|
});
|