fix: load dynamic recent matches in historical UI

* fix: load dynamic recent matches in historical UI

* fix: load dynamic recent matches in historical UI
This commit is contained in:
devRaGonSa
2026-05-19 11:35:28 +02:00
committed by GitHub
parent 93a9fb8028
commit 9baf20b569
2 changed files with 161 additions and 0 deletions

View File

@@ -0,0 +1,160 @@
(() => {
const RECENT_MATCHES_ENDPOINT = "/api/historical/recent-matches";
const REFRESH_DELAYS_MS = [150, 1000, 3000];
document.addEventListener("DOMContentLoaded", () => {
REFRESH_DELAYS_MS.forEach((delay) => {
window.setTimeout(() => {
void refreshDynamicRecentMatches();
}, delay);
});
document.querySelectorAll("[data-server-slug]").forEach((button) => {
button.addEventListener("click", () => {
REFRESH_DELAYS_MS.forEach((delay) => {
window.setTimeout(() => {
void refreshDynamicRecentMatches(button.dataset.serverSlug);
}, delay);
});
});
});
});
async function refreshDynamicRecentMatches(forcedServerSlug) {
const listNode = document.getElementById("recent-matches-list");
const stateNode = document.getElementById("recent-matches-state");
const metaNode = document.getElementById("recent-matches-snapshot-meta");
const noteNode = document.getElementById("recent-matches-note");
if (!listNode || !stateNode || !metaNode) {
return;
}
const backendBaseUrl =
document.body.dataset.backendBaseUrl || "http://127.0.0.1:8000";
const serverSlug = normalizeDynamicServerSlug(forcedServerSlug || readServerFromUrl());
try {
const response = await fetch(
`${backendBaseUrl}${RECENT_MATCHES_ENDPOINT}?server=${encodeURIComponent(
serverSlug,
)}&limit=10`,
{ cache: "no-store" },
);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
const payload = await response.json();
const data = payload?.data || {};
const items = Array.isArray(data.items) ? data.items : [];
if (!items.length) {
setDynamicState(stateNode, "No hay partidas recientes disponibles para este alcance.");
listNode.innerHTML = "";
metaNode.textContent = "Datos recientes sin partidas disponibles.";
return;
}
listNode.innerHTML = items.map((item) => renderDynamicRecentMatchCard(item)).join("");
stateNode.hidden = true;
if (noteNode) {
noteNode.textContent = "Lista dinamica de partidas registradas por el modelo RCON reciente.";
}
metaNode.textContent = buildDynamicRecentMeta(data, items);
} catch (error) {
setDynamicState(stateNode, "No se pudieron cargar las partidas recientes dinamicas.", true);
metaNode.textContent = "Error al leer las partidas recientes dinamicas.";
}
}
function readServerFromUrl() {
return new URLSearchParams(window.location.search).get("server") || "all-servers";
}
function normalizeDynamicServerSlug(value) {
const normalized = String(value || "").trim();
if (["comunidad-hispana-01", "comunidad-hispana-02", "all-servers"].includes(normalized)) {
return normalized;
}
return "all-servers";
}
function renderDynamicRecentMatchCard(item) {
if (typeof window.renderRecentMatchCard === "function") {
return window.renderRecentMatchCard(item);
}
const mapName = item?.map?.pretty_name || item?.map?.name || "Mapa no disponible";
const serverName = item?.server?.name || "Servidor no disponible";
const closedAt = item?.closed_at || item?.ended_at || item?.started_at;
return `
<article class="historical-match-card">
<div class="historical-match-card__top">
<div>
<p class="historical-match-meta__label">Partida ${escapeDynamicHtml(item?.match_id || "sin id")}</p>
<h3 class="historical-match-card__title">${escapeDynamicHtml(mapName)}</h3>
</div>
<div class="historical-match-card__actions">
<span class="historical-match-card__result">${escapeDynamicHtml(formatDynamicScore(item?.result))}</span>
</div>
</div>
<div class="historical-match-meta">
<article><p class="historical-match-meta__label">Servidor</p><strong>${escapeDynamicHtml(serverName)}</strong></article>
<article><p class="historical-match-meta__label">Cierre</p><strong>${escapeDynamicHtml(formatDynamicTimestamp(closedAt))}</strong></article>
<article><p class="historical-match-meta__label">Jugadores</p><strong>${escapeDynamicHtml(formatDynamicNumber(item?.player_count))}</strong></article>
<article><p class="historical-match-meta__label">Marcador</p><strong>${escapeDynamicHtml(formatDynamicScore(item?.result))}</strong></article>
</div>
</article>
`;
}
function buildDynamicRecentMeta(data, items) {
const newest = items[0]?.closed_at || items[0]?.ended_at || items[0]?.started_at;
const source = data.selected_source || data.source || "rcon";
const captureText = newest ? `Actualizado: ${formatDynamicTimestamp(newest)}` : "Actualizado recientemente";
return `${captureText} | Fuente: ${source}`;
}
function setDynamicState(node, message, isError = false) {
node.textContent = message;
node.hidden = false;
node.classList.toggle("is-error", Boolean(isError));
}
function formatDynamicTimestamp(value) {
if (!value) {
return "Fecha no disponible";
}
const date = new Date(value);
if (Number.isNaN(date.getTime())) {
return String(value);
}
return new Intl.DateTimeFormat("es-ES", {
day: "numeric",
month: "numeric",
year: "2-digit",
hour: "2-digit",
minute: "2-digit",
}).format(date);
}
function formatDynamicNumber(value) {
const number = Number(value);
return Number.isFinite(number) ? new Intl.NumberFormat("es-ES").format(number) : "0";
}
function formatDynamicScore(result) {
const allied = result?.allied_score;
const axis = result?.axis_score;
if (Number.isFinite(Number(allied)) && Number.isFinite(Number(axis))) {
return `${allied} - ${axis}`;
}
return "- - -";
}
function escapeDynamicHtml(value) {
return String(value ?? "")
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;")
.replaceAll("'", "&#039;");
}
})();

View File

@@ -223,5 +223,6 @@
</div>
<script src="./assets/js/historico.js"></script>
<script src="./assets/js/historico-recent-live.js"></script>
</body>
</html>