fix: improve historical worker visibility and recent pagination

This commit is contained in:
devRaGonSa
2026-05-22 10:57:30 +02:00
parent 13cba1dcf1
commit dfdb53d2b6
5 changed files with 323 additions and 21 deletions

View File

@@ -589,6 +589,61 @@
gap: 14px;
}
.historical-pagination {
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
margin-top: 16px;
}
.historical-pagination[hidden] {
display: none;
}
.historical-pagination__size,
.historical-pagination__nav {
display: flex;
align-items: center;
gap: 10px;
}
.historical-pagination__size {
color: var(--text-soft);
font-size: 0.86rem;
font-weight: 700;
}
.historical-pagination__size select {
min-height: 42px;
padding: 0 34px 0 12px;
border: 1px solid rgba(159, 168, 141, 0.2);
border-radius: 6px;
color: var(--text);
background: rgba(13, 17, 12, 0.72);
font: inherit;
}
.historical-pagination__nav p {
margin: 0;
min-width: 110px;
color: var(--text-soft);
font-size: 0.86rem;
font-weight: 700;
text-align: center;
}
.historical-pagination .historical-tab {
margin: 0;
}
.historical-pagination .historical-tab:disabled {
transform: none;
border-color: rgba(159, 168, 141, 0.12);
color: rgba(169, 173, 154, 0.48);
cursor: default;
}
.current-match-killfeed-screen {
position: relative;
width: 100%;
@@ -795,9 +850,22 @@
color: var(--accent-warm);
}
.current-match-player-intro {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 10px 18px;
margin-top: 10px;
}
.current-match-player-intro .historical-panel__note {
margin-top: 0;
}
.current-match-player-count {
flex: 0 0 auto;
width: fit-content;
margin: -6px 0 16px;
margin: 0;
padding: 7px 10px;
border: 1px solid rgba(159, 168, 141, 0.16);
border-radius: 6px;
@@ -1004,6 +1072,11 @@
flex-direction: column;
}
.current-match-player-intro {
align-items: flex-start;
flex-direction: column;
}
.historical-mvp-card__meta {
grid-template-columns: 1fr;
}
@@ -1025,6 +1098,16 @@
justify-content: flex-start;
}
.historical-pagination,
.historical-pagination__nav {
align-items: stretch;
flex-direction: column;
}
.historical-pagination__size {
justify-content: space-between;
}
.historical-tab {
width: 100%;
}

View File

@@ -19,11 +19,15 @@ const DEFAULT_HISTORICAL_SERVER = "all-servers";
const SNAPSHOT_CACHE_TTL_MS = 120000;
const STALE_SNAPSHOT_CACHE_TTL_MS = 30000;
const NEGATIVE_SNAPSHOT_CACHE_TTL_MS = 15000;
const RECENT_MATCHES_LIMIT = 100;
const DEFAULT_RECENT_MATCHES_PAGE_SIZE = 10;
const RECENT_MATCHES_PAGE_SIZES = Object.freeze([10, 25, 50, 100]);
let activeServerSlug = DEFAULT_HISTORICAL_SERVER;
let activeLeaderboardMetric;
let activeLeaderboardTimeframe;
let activeServerRequestId = 0;
let activeLeaderboardRequestId = 0;
let recentMatchesPagination;
const LEADERBOARD_TIMEFRAMES = Object.freeze([
{
key: "weekly",
@@ -100,6 +104,7 @@ document.addEventListener("DOMContentLoaded", () => {
const recentSnapshotMetaNode = document.getElementById(
"recent-matches-snapshot-meta",
);
recentMatchesPagination = initializeRecentMatchesPagination(recentListNode);
const params = new URLSearchParams(window.location.search);
activeServerSlug = normalizeServerSlug(params.get("server"));
@@ -126,7 +131,7 @@ document.addEventListener("DOMContentLoaded", () => {
recentMatchesCache,
pendingRequestCache,
buildRecentMatchesSnapshotKey(serverSlug),
`${backendBaseUrl}/api/historical/snapshots/recent-matches?server=${encodeURIComponent(serverSlug)}&limit=10`,
`${backendBaseUrl}/api/historical/snapshots/recent-matches?server=${encodeURIComponent(serverSlug)}&limit=${RECENT_MATCHES_LIMIT}`,
);
const getLeaderboardSnapshot = (serverSlug, timeframeKey, metricKey) =>
@@ -169,6 +174,7 @@ document.addEventListener("DOMContentLoaded", () => {
weeklySnapshotMetaNode,
`Preparando datos ${activeTimeframeConfig.shortLabel}...`,
);
resetRecentMatchesPagination();
recentListNode.innerHTML = "";
recentNoteNode.textContent = buildRecentMatchesNote(activeServerSlug);
setState(recentStateNode, "Cargando partidas recientes...");
@@ -635,20 +641,156 @@ function hydrateRecentMatches(result, stateNode, listNode, snapshotMetaNode) {
buildSnapshotMetaText(payload, "Partidas pendientes de generacion."),
);
if (!payload?.found) {
resetRecentMatchesPagination();
listNode.innerHTML = "";
setState(stateNode, emptyState.recentMessage);
return;
}
const items = payload?.items;
if (!Array.isArray(items) || items.length === 0) {
resetRecentMatchesPagination();
listNode.innerHTML = "";
setState(stateNode, emptyState.recentMessage);
return;
}
listNode.innerHTML = items.map((item) => renderRecentMatchCard(item)).join("");
setRecentMatchesPaginationItems(items.slice(0, RECENT_MATCHES_LIMIT), listNode);
stateNode.hidden = true;
}
function initializeRecentMatchesPagination(listNode) {
if (!listNode) {
return null;
}
listNode.insertAdjacentHTML(
"afterend",
`
<div class="historical-pagination" id="recent-matches-pagination" hidden>
<label class="historical-pagination__size">
<span>Partidas por pagina</span>
<select id="recent-matches-page-size" aria-label="Partidas por pagina">
${RECENT_MATCHES_PAGE_SIZES.map(
(pageSize) => `
<option value="${pageSize}"${pageSize === DEFAULT_RECENT_MATCHES_PAGE_SIZE ? " selected" : ""}>
${pageSize}
</option>
`,
).join("")}
</select>
</label>
<div class="historical-pagination__nav">
<button class="historical-tab" id="recent-matches-page-prev" type="button">
Anterior
</button>
<p id="recent-matches-page-status">Pagina 1 de 1</p>
<button class="historical-tab" id="recent-matches-page-next" type="button">
Siguiente
</button>
</div>
</div>
`,
);
const pagination = {
items: [],
page: 1,
pageSize: DEFAULT_RECENT_MATCHES_PAGE_SIZE,
root: document.getElementById("recent-matches-pagination"),
pageSizeSelect: document.getElementById("recent-matches-page-size"),
previousButton: document.getElementById("recent-matches-page-prev"),
nextButton: document.getElementById("recent-matches-page-next"),
status: document.getElementById("recent-matches-page-status"),
};
pagination.previousButton?.addEventListener("click", () => {
if (pagination.page <= 1) {
return;
}
pagination.page -= 1;
renderRecentMatchesPage(listNode);
});
pagination.nextButton?.addEventListener("click", () => {
if (pagination.page >= getRecentMatchesPageCount(pagination)) {
return;
}
pagination.page += 1;
renderRecentMatchesPage(listNode);
});
pagination.pageSizeSelect?.addEventListener("change", () => {
pagination.pageSize = normalizeRecentMatchesPageSize(
pagination.pageSizeSelect.value,
);
pagination.page = 1;
renderRecentMatchesPage(listNode);
});
return pagination;
}
function resetRecentMatchesPagination() {
if (!recentMatchesPagination) {
return;
}
recentMatchesPagination.items = [];
recentMatchesPagination.page = 1;
recentMatchesPagination.pageSize = DEFAULT_RECENT_MATCHES_PAGE_SIZE;
if (recentMatchesPagination.pageSizeSelect) {
recentMatchesPagination.pageSizeSelect.value = String(
DEFAULT_RECENT_MATCHES_PAGE_SIZE,
);
}
if (recentMatchesPagination.root) {
recentMatchesPagination.root.hidden = true;
}
}
function setRecentMatchesPaginationItems(items, listNode) {
if (!recentMatchesPagination) {
listNode.innerHTML = items.map((item) => renderRecentMatchCard(item)).join("");
return;
}
recentMatchesPagination.items = items;
recentMatchesPagination.page = 1;
renderRecentMatchesPage(listNode);
}
function renderRecentMatchesPage(listNode) {
const pagination = recentMatchesPagination;
if (!pagination) {
return;
}
const pageCount = getRecentMatchesPageCount(pagination);
pagination.page = Math.min(Math.max(1, pagination.page), pageCount);
const pageStart = (pagination.page - 1) * pagination.pageSize;
const visibleItems = pagination.items.slice(pageStart, pageStart + pagination.pageSize);
listNode.innerHTML = visibleItems.map((item) => renderRecentMatchCard(item)).join("");
if (pagination.status) {
pagination.status.textContent = `Pagina ${pagination.page} de ${pageCount}`;
}
if (pagination.previousButton) {
pagination.previousButton.disabled = pagination.page <= 1;
}
if (pagination.nextButton) {
pagination.nextButton.disabled = pagination.page >= pageCount;
}
if (pagination.root) {
pagination.root.hidden = pagination.items.length <= DEFAULT_RECENT_MATCHES_PAGE_SIZE;
}
}
function getRecentMatchesPageCount(pagination) {
return Math.max(1, Math.ceil(pagination.items.length / pagination.pageSize));
}
function normalizeRecentMatchesPageSize(rawValue) {
const pageSize = Number(rawValue);
return RECENT_MATCHES_PAGE_SIZES.includes(pageSize)
? pageSize
: DEFAULT_RECENT_MATCHES_PAGE_SIZE;
}
function hydrateMonthlyMvp(
result,
stateNode,

View File

@@ -225,9 +225,6 @@ function initializePlayerStats(nodes) {
<p class="historical-state" id="current-match-player-stats-state" aria-live="polite">
Cargando estadisticas en vivo...
</p>
<p class="current-match-player-count" id="current-match-player-count">
Jugadores detectados: 0
</p>
<div class="historical-table-shell" id="current-match-player-stats-shell" hidden></div>
`,
);