Add leaderboard component to UI and API endpoint to fetch player rankings.
This commit is contained in:
+24
@@ -87,6 +87,29 @@ app.post("/register", (request, response) => {
|
|||||||
response.json({lower_username, token});
|
response.json({lower_username, token});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/leaderboard", authenticateToken, (req, res) => {
|
||||||
|
const users = get_data();
|
||||||
|
const sorted = users.sort((a, b) => b.money - a.money);
|
||||||
|
|
||||||
|
const top10 = sorted.slice(0, 10).map(u => ({
|
||||||
|
username: u.username,
|
||||||
|
money: u.money,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const username = req.user.username;
|
||||||
|
const position = sorted.findIndex(u => u.username === username) + 1;
|
||||||
|
const self = sorted.find(u => u.username === username);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
leaderboard: top10,
|
||||||
|
self: {
|
||||||
|
username: self.username,
|
||||||
|
money: self.money,
|
||||||
|
position
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
app.get("/login", (request, response) => {
|
app.get("/login", (request, response) => {
|
||||||
response.sendFile(path.join(__dirname, "./public/login.html"));
|
response.sendFile(path.join(__dirname, "./public/login.html"));
|
||||||
})
|
})
|
||||||
@@ -173,6 +196,7 @@ async function createLobby() {
|
|||||||
await fetch(`https://www.deckofcardsapi.com/api/deck/${lobbyId}/pile/players/add/?cards=`)
|
await fetch(`https://www.deckofcardsapi.com/api/deck/${lobbyId}/pile/players/add/?cards=`)
|
||||||
return lobbyId;
|
return lobbyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.post("/leave-lobby", (req, res) => {
|
app.post("/leave-lobby", (req, res) => {
|
||||||
const {lobbyId, username} = req.body;
|
const {lobbyId, username} = req.body;
|
||||||
if (!lobbyId || !username) {
|
if (!lobbyId || !username) {
|
||||||
|
|||||||
@@ -149,4 +149,34 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
joinError.classList.remove("hidden");
|
joinError.classList.remove("hidden");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function loadLeaderboard() {
|
||||||
|
try {
|
||||||
|
const res = await fetch("/leaderboard");
|
||||||
|
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 += " 👑";
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await loadLeaderboard();
|
||||||
});
|
});
|
||||||
@@ -7,6 +7,15 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<canvas id="matrix-canvas"></canvas>
|
<canvas id="matrix-canvas"></canvas>
|
||||||
|
<div class="leaderboard">
|
||||||
|
<h3>🏆 High Rollers</h3>
|
||||||
|
<ul id="leaderboard-list">
|
||||||
|
<li>Loading...</li>
|
||||||
|
</ul>
|
||||||
|
<div id="your-rank" class="your-rank"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<button class="logout" id="logout">Logout</button>
|
<button class="logout" id="logout">Logout</button>
|
||||||
<div class="balance">
|
<div class="balance">
|
||||||
Balance: $<span id="balance">0</span>
|
Balance: $<span id="balance">0</span>
|
||||||
|
|||||||
@@ -137,3 +137,51 @@ button.logout {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leaderboard {
|
||||||
|
position: absolute;
|
||||||
|
top: 100px;
|
||||||
|
left: 20px;
|
||||||
|
background: rgba(0, 0, 0, 0.7);
|
||||||
|
border: 2px solid #0f0;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
width: 200px;
|
||||||
|
color: #0f0;
|
||||||
|
font-family: monospace;
|
||||||
|
box-shadow: 0 0 10px #0f0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 0 5px #0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard li {
|
||||||
|
margin: 5px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
text-shadow: 0 0 3px #0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaderboard li.you {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ff0;
|
||||||
|
text-shadow: 0 0 5px #ff0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.your-rank {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 0 0 3px #0f0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user