';
- return;
- }
-
+/**
+ * Pure renderer: builds and returns the full stats HTML for a player.
+ * Receives the API payload directly so it can be reused by loadStats()
+ * and showAdminPlayerDetail() without coupling to fetch logic.
+ * @param {Object} data Response from /api/players/:id/stats or /api/admin/player/:id/stats
+ * @returns {string} HTML string ready to be injected into a container
+ */
+function renderPlayerStats(data) {
const ls = data.levelStats || {};
const streak = data.currentStreak || 0;
const totalS = data.totalSeconds || 0;
@@ -1320,7 +1314,7 @@ async function loadStats() {
`;
}
- document.getElementById('stats-content').innerHTML = `
+ return `
${data.player.avatar}
${data.player.name}
@@ -1358,6 +1352,23 @@ async function loadStats() {
` : ''}`;
}
+async function loadStats() {
+ if (offlineMode || !currentPlayer) {
+ document.getElementById('stats-content').innerHTML =
+ '
Estadรญstiques no disponibles en mode sense connexiรณ.
`;
}).join('');
@@ -1486,15 +1504,51 @@ async function loadAdmin() {
Jugador
Sessions
โญ
๐ N1
๐งฉ N2
๐ N3
โ๏ธ N4
๐บ๏ธ N5
๐ฎ N6
-
Darrera activitat
+
Darrera activitat
Detall
- ${rows || '
Sense jugadors
'}
+ ${rows || '
Sense jugadors
'}
`;
// Restore chip active state after render
syncChips();
}
+/**
+ * Load and display full stats for a specific player inside the admin detail overlay.
+ * Reuses renderPlayerStats() so the layout is identical to the player-facing stats screen.
+ * @param {number} id Player id
+ * @param {string} name Player display name (for fallback if API fails)
+ * @param {string} avatar Player avatar emoji
+ */
+async function showAdminPlayerDetail(id, name, avatar) {
+ const pin = document.getElementById('admin-pin').value;
+ const overlay = document.getElementById('admin-detail-overlay');
+ const body = document.getElementById('admin-detail-body');
+
+ // Show overlay immediately with a loading indicator
+ body.innerHTML = `