From 06906b29d41f749ec85ff144970d0a83da1fee5e Mon Sep 17 00:00:00 2001 From: kcprdev Date: Sun, 31 May 2026 12:38:51 +0530 Subject: [PATCH 1/2] Add pagination to ranking system --- frontend/leaderboard.html | 186 ++++++++++++++++++++++---------------- frontend/styles/main.css | 52 +++++++++++ 2 files changed, 162 insertions(+), 76 deletions(-) diff --git a/frontend/leaderboard.html b/frontend/leaderboard.html index 09fd96b6..27b1d838 100644 --- a/frontend/leaderboard.html +++ b/frontend/leaderboard.html @@ -86,7 +86,9 @@

Leaderboard

-
+
+ +
Rank
Name
@@ -125,31 +127,20 @@

Leaderboard

flex-wrap: wrap; " > - -
@@ -194,35 +185,46 @@

Leaderboard

applyFiltersAndRender(); } }); + document + .getElementById("prev-page-btn") + ?.addEventListener("click", () => { + if (currentPage > 1) { + currentPage--; + applyFiltersAndRender(); + } + }); + + document + .getElementById("next-page-btn") + ?.addEventListener("click", () => { + const totalPages = Math.ceil( + leaderboardData[activeDatasetType].length / + itemsPerPage + ); + if (currentPage < totalPages) { + currentPage++; + applyFiltersAndRender(); + } + }); + + document + .getElementById("items-per-page") + ?.addEventListener("change", (e) => { + itemsPerPage = parseInt(e.target.value); + currentPage = 1; + applyFiltersAndRender(); + }); fetchLeaderboardData(); }); const leaderboardData = {}; - let currentDisplayLimit = 0; + let currentPage = 1; + let itemsPerPage = 25; let activeDatasetType = "overall"; - let fetchMoreClicks = 0; let currentSearchTerm = ""; - function getInitialLimit() { - return window.innerWidth <= 768 ? 12 : 25; - } - - function loadMoreNodes() { - const data = leaderboardData[activeDatasetType]; - const isMobile = window.innerWidth <= 768; - const maxClicks = isMobile ? 3 : 2; - - fetchMoreClicks++; - - if (fetchMoreClicks >= maxClicks) { - currentDisplayLimit = data.length; - } else { - currentDisplayLimit += getInitialLimit(); - } - renderLeaderboard(data); - } async function fetchLeaderboardData() { const endpoints = ["overall", "monthly", "weekly", "daily"]; @@ -294,9 +296,6 @@

Leaderboard

} function applyFiltersAndRender() { - if (currentDisplayLimit === 0) { - currentDisplayLimit = getInitialLimit(); - } if (!leaderboardData[activeDatasetType]) return; const originalData = leaderboardData[activeDatasetType]; @@ -308,27 +307,58 @@

Leaderboard

const filteredData = rankedData.filter((user) => { if (!currentSearchTerm) return true; + return ( user.name.toLowerCase().includes(currentSearchTerm) || user.id.toLowerCase().includes(currentSearchTerm) ); }); - // Update result count const countEl = document.getElementById("search-result-count"); + if (currentSearchTerm) { const total = originalData.length; const matched = filteredData.length; + countEl.textContent = `${matched}/${total}`; countEl.style.opacity = "1"; } else { countEl.textContent = ""; countEl.style.opacity = "0"; } + document.getElementById("prev-page-btn").disabled = + currentPage === 1; + + document.getElementById("next-page-btn").disabled = + currentPage === Math.ceil(filteredData.length / itemsPerPage); + const statsEl = document.getElementById("leaderboard-stats"); + + const totalPages = Math.ceil(filteredData.length / itemsPerPage); + const startRow = + filteredData.length === 0 + ? 0 + : (currentPage - 1) * itemsPerPage + 1; + + const endRow = Math.min( + currentPage * itemsPerPage, + filteredData.length + ); + + statsEl.innerHTML = ` +
+ Total Users: ${filteredData.length} + | Showing: ${startRow}-${endRow} + | Page: ${currentPage}/${totalPages} +
+ `; renderLeaderboard(filteredData); } - function getRankTag(rank) { switch (rank) { case 1: @@ -351,9 +381,12 @@

Leaderboard

const isSearching = currentSearchTerm.length > 0; + const startIndex = (currentPage - 1) * itemsPerPage; + const endIndex = startIndex + itemsPerPage; + const displayData = isSearching - ? data - : data.slice(0, currentDisplayLimit); + ? data + : data.slice(startIndex, endIndex); if (displayData.length === 0) { body.innerHTML = ` @@ -367,10 +400,6 @@

Leaderboard

[SYS]: NO_MATCHING_USERS_FOUND
`; - - document.getElementById("load-more-btn").style.display = "none"; - document.getElementById("scroll-top-btn").style.display = "none"; - return; } @@ -418,30 +447,36 @@

Leaderboard

`; mobileCards.appendChild(card); }); + renderPagination(data.length); + } + function renderPagination(totalItems) { + const pageNumbers = + document.getElementById("page-numbers"); - if (!isSearching && data.length > currentDisplayLimit) { - document.getElementById("load-more-btn").style.display = - "inline-block"; - document.getElementById("scroll-top-btn").style.display = "none"; + if (!pageNumbers) return; - const isMobile = window.innerWidth <= 768; - const textTransitionClick = isMobile ? 2 : 1; + const totalPages = + Math.ceil(totalItems / itemsPerPage); - if (fetchMoreClicks >= textTransitionClick) { - document.getElementById("load-more-btn").innerHTML = - "./fetch_all_nodes"; - } else { - document.getElementById("load-more-btn").innerHTML = - "./fetch_more_nodes"; + pageNumbers.innerHTML = ""; + + for (let i = 1; i <= totalPages; i++) { + const btn = document.createElement("button"); + btn.classList.add("page-btn"); + btn.textContent = i; + + if (i === currentPage) { + btn.classList.add("active-page"); } - } else { - document.getElementById("load-more-btn").style.display = "none"; - document.getElementById("scroll-top-btn").style.display = isSearching - ? "none" - : "inline-block"; + + btn.onclick = () => { + currentPage = i; + applyFiltersAndRender(); + }; + + pageNumbers.appendChild(btn); } } - function setActiveTab(activeTab) { document.querySelectorAll(".tab").forEach((tab) => { tab.classList.remove("active"); @@ -455,8 +490,7 @@

Leaderboard

} activeDatasetType = activeTab; - currentDisplayLimit = getInitialLimit(); - fetchMoreClicks = 0; + currentPage = 1; applyFiltersAndRender(); } diff --git a/frontend/styles/main.css b/frontend/styles/main.css index 8f933711..bd1de8f1 100644 --- a/frontend/styles/main.css +++ b/frontend/styles/main.css @@ -2161,3 +2161,55 @@ body::-webkit-scrollbar-thumb { font-family: "Fira Code", monospace; font-size: 0.85rem; } + +/* Pagination Styling */ + +#pagination-controls { + margin-top: 2rem; + align-items: center; +} + +#pagination-controls button, +#pagination-controls select { + background: var(--bg-surface); + color: var(--green); + border: 1px solid var(--border-bright); + padding: 0.5rem 0.8rem; + font-family: "Fira Code", monospace; + cursor: pointer; +} + +#pagination-controls button:hover, +#pagination-controls select:hover { + border-color: var(--green); + box-shadow: 0 0 8px rgba(0,255,65,0.3); +} + +#page-numbers { + display: flex; + gap: 0.4rem; +} + +#page-numbers button { + min-width: 32px; + height: 32px; + background: var(--bg-surface); + color: var(--green); + border: 1px solid var(--border-bright); + cursor: pointer; +} + +#page-numbers button:hover { + border-color: var(--green); +} + +.active-page { + background: var(--green) !important; + color: black !important; + font-weight: bold; +} + +#pagination-controls button:disabled { + opacity: 0.4; + cursor: not-allowed; +} \ No newline at end of file From 9816c61a91b0cd4699c0b3e4d1f8c7487d386a1d Mon Sep 17 00:00:00 2001 From: kcprdev Date: Sun, 31 May 2026 18:22:42 +0530 Subject: [PATCH 2/2] Format pagination implementation with Prettier --- frontend/leaderboard.html | 58 ++++++++++++++++----------------------- frontend/styles/main.css | 4 +-- 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/frontend/leaderboard.html b/frontend/leaderboard.html index 27b1d838..ccca0d2b 100644 --- a/frontend/leaderboard.html +++ b/frontend/leaderboard.html @@ -86,9 +86,9 @@

Leaderboard

-
- -
+
+ +
Rank
Name
@@ -128,20 +128,16 @@

Leaderboard

" > - +
- +
@@ -198,8 +194,7 @@

Leaderboard

.getElementById("next-page-btn") ?.addEventListener("click", () => { const totalPages = Math.ceil( - leaderboardData[activeDatasetType].length / - itemsPerPage + leaderboardData[activeDatasetType].length / itemsPerPage, ); if (currentPage < totalPages) { @@ -224,8 +219,6 @@

Leaderboard

let activeDatasetType = "overall"; let currentSearchTerm = ""; - - async function fetchLeaderboardData() { const endpoints = ["overall", "monthly", "weekly", "daily"]; const cacheBuster = Date.now(); @@ -326,26 +319,23 @@

Leaderboard

countEl.textContent = ""; countEl.style.opacity = "0"; } - document.getElementById("prev-page-btn").disabled = - currentPage === 1; + document.getElementById("prev-page-btn").disabled = currentPage === 1; document.getElementById("next-page-btn").disabled = currentPage === Math.ceil(filteredData.length / itemsPerPage); - const statsEl = document.getElementById("leaderboard-stats"); + const statsEl = document.getElementById("leaderboard-stats"); - const totalPages = Math.ceil(filteredData.length / itemsPerPage); + const totalPages = Math.ceil(filteredData.length / itemsPerPage); - const startRow = - filteredData.length === 0 - ? 0 - : (currentPage - 1) * itemsPerPage + 1; + const startRow = + filteredData.length === 0 ? 0 : (currentPage - 1) * itemsPerPage + 1; - const endRow = Math.min( - currentPage * itemsPerPage, - filteredData.length - ); + const endRow = Math.min( + currentPage * itemsPerPage, + filteredData.length, + ); - statsEl.innerHTML = ` + statsEl.innerHTML = `
Leaderboard const endIndex = startIndex + itemsPerPage; const displayData = isSearching - ? data - : data.slice(startIndex, endIndex); + ? data + : data.slice(startIndex, endIndex); if (displayData.length === 0) { body.innerHTML = ` @@ -450,13 +440,11 @@

Leaderboard

renderPagination(data.length); } function renderPagination(totalItems) { - const pageNumbers = - document.getElementById("page-numbers"); + const pageNumbers = document.getElementById("page-numbers"); if (!pageNumbers) return; - const totalPages = - Math.ceil(totalItems / itemsPerPage); + const totalPages = Math.ceil(totalItems / itemsPerPage); pageNumbers.innerHTML = ""; diff --git a/frontend/styles/main.css b/frontend/styles/main.css index bd1de8f1..5186e4f1 100644 --- a/frontend/styles/main.css +++ b/frontend/styles/main.css @@ -2182,7 +2182,7 @@ body::-webkit-scrollbar-thumb { #pagination-controls button:hover, #pagination-controls select:hover { border-color: var(--green); - box-shadow: 0 0 8px rgba(0,255,65,0.3); + box-shadow: 0 0 8px rgba(0, 255, 65, 0.3); } #page-numbers { @@ -2212,4 +2212,4 @@ body::-webkit-scrollbar-thumb { #pagination-controls button:disabled { opacity: 0.4; cursor: not-allowed; -} \ No newline at end of file +}