From e6f3998d880d16a848f78fb20ede315794cc533e Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 21 Dec 2025 20:44:14 +0000 Subject: [PATCH] Refactor user stats page to use tabs and cache data Co-authored-by: mathieumoran1 --- public/js/app_user-stat.js | 31 +++++++++-- public/user-stat.html | 104 ++++++++++++++++++++++++------------- 2 files changed, 95 insertions(+), 40 deletions(-) diff --git a/public/js/app_user-stat.js b/public/js/app_user-stat.js index 3599343..b7891af 100644 --- a/public/js/app_user-stat.js +++ b/public/js/app_user-stat.js @@ -1,5 +1,7 @@ window.onload = async function () { const token = localStorage.getItem('auth_token'); + let winnersCache = null; + let completionsCache = null; async function fetchActiveYear() { try { @@ -172,6 +174,11 @@ window.onload = async function () { fetchCompletions(), ]); + winnersCache = winners; + completionsCache = completions; + renderWinners(winnersCache); + renderCompletions(completionsCache); + if (!statsRes.ok) { throw new Error('Failed to fetch user stats'); } @@ -180,9 +187,7 @@ window.onload = async function () { const userTableBody = document.getElementById('user-table-body'); const table = document.querySelector('.user-table'); const spinner = document.getElementById('loading-spinner'); - - renderWinners(winners); - renderCompletions(completions); + const statsError = document.getElementById('stats-error'); // Ensure watchedRatio is treated as a number and sort in descending order stats.sort((a, b) => parseFloat(b.watchedRatio) - parseFloat(a.watchedRatio)); @@ -205,6 +210,7 @@ window.onload = async function () { // Hide spinner and show table after loading spinner.style.display = 'none'; table.style.display = 'table'; + if (statsError) statsError.classList.add('d-none'); // Add event listener for user links document.querySelectorAll('.user-link').forEach(link => { @@ -233,9 +239,24 @@ window.onload = async function () { }); } catch (error) { console.error('Error loading user statistics:', error); + const spinner = document.getElementById('loading-spinner'); + const table = document.querySelector('.user-table'); + const statsError = document.getElementById('stats-error'); + if (spinner) spinner.style.display = 'none'; + if (table) table.style.display = 'none'; + if (statsError) { + statsError.textContent = "Impossible de charger le classement pour le moment."; + statsError.classList.remove('d-none'); + } // Still attempt to render these sections even if stats fail (best effort) - try { renderWinners(await fetchWinners()); } catch (_) {} - try { renderCompletions(await fetchCompletions()); } catch (_) {} + try { + if (winnersCache === null) winnersCache = await fetchWinners(); + renderWinners(winnersCache); + } catch (_) {} + try { + if (completionsCache === null) completionsCache = await fetchCompletions(); + renderCompletions(completionsCache); + } catch (_) {} } // Log-off functionality diff --git a/public/user-stat.html b/public/user-stat.html index f40886a..d76b403 100644 --- a/public/user-stat.html +++ b/public/user-stat.html @@ -30,6 +30,14 @@ .navbar-toggler-icon { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3E%3Cpath stroke='white' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); } + + /* Stats tabs */ + .stats-tabs .nav-link { + font-weight: 600; + } + .stats-tab-panel { + padding-top: 1rem; + } @@ -61,43 +69,69 @@

Statistiques des utilisateurs

- - -
-

Gagnants

-
Définis dans l’admin (optionnel).
-
-
Chargement…
+ + + + +
+ +
+ + + +
+ Loading... +
+ + + + + + + + + + + + + + +
+ + +
+

Gagnants

+
Définis dans l’admin (optionnel).
+
+
Chargement…
+
+
+ + +
+

Utilisateurs ayant terminé 100% (par année)

+
Completion = 100% pour l’année (tous les films de l’année vus).
+
+
Chargement…
+
- - -
-

Utilisateurs ayant terminé 100% (par année)

-
Completion = 100% pour l’année (tous les films de l’année vus).
-
-
Chargement…
-
-
- - -
- Loading... -
- - - - - - - - - - - - - -