const HISTORICAL_SERVER_SLUGS = Object.freeze([ "comunidad-hispana-01", "comunidad-hispana-02", ]); const DEFAULT_HISTORICAL_SERVER = HISTORICAL_SERVER_SLUGS[0]; document.addEventListener("DOMContentLoaded", () => { const backendBaseUrl = document.body.dataset.backendBaseUrl || "http://127.0.0.1:8000"; const selectorButtons = Array.from( document.querySelectorAll("[data-server-slug]"), ); const summaryNode = document.getElementById("historical-summary"); const rangeNode = document.getElementById("historical-range"); const weeklyStateNode = document.getElementById("weekly-top-kills-state"); const weeklyTableNode = document.getElementById("weekly-top-kills-table"); const weeklyBodyNode = document.getElementById("weekly-top-kills-body"); const recentStateNode = document.getElementById("recent-matches-state"); const recentListNode = document.getElementById("recent-matches-list"); const params = new URLSearchParams(window.location.search); let activeServerSlug = normalizeServerSlug(params.get("server")); const refreshHistoricalView = async () => { syncActiveButtons(selectorButtons, activeServerSlug); setRangeBadge(rangeNode, "Cargando rango temporal", false); renderSummaryLoading(summaryNode); setState(weeklyStateNode, "Cargando ranking semanal..."); setState(recentStateNode, "Cargando partidas recientes..."); weeklyTableNode.hidden = true; recentListNode.innerHTML = ""; const [summaryResult, topKillsResult, recentMatchesResult] = await Promise.allSettled([ fetchJson( `${backendBaseUrl}/api/historical/server-summary?server=${encodeURIComponent(activeServerSlug)}`, ), fetchJson( `${backendBaseUrl}/api/historical/weekly-top-kills?server=${encodeURIComponent(activeServerSlug)}&limit=10`, ), fetchJson( `${backendBaseUrl}/api/historical/recent-matches?server=${encodeURIComponent(activeServerSlug)}&limit=6`, ), ]); hydrateSummary(summaryResult, summaryNode, rangeNode); hydrateWeeklyTopKills( topKillsResult, weeklyStateNode, weeklyTableNode, weeklyBodyNode, ); hydrateRecentMatches(recentMatchesResult, recentStateNode, recentListNode); }; selectorButtons.forEach((button) => { button.addEventListener("click", () => { const nextServerSlug = normalizeServerSlug(button.dataset.serverSlug); if (nextServerSlug === activeServerSlug) { return; } activeServerSlug = nextServerSlug; params.set("server", activeServerSlug); window.history.replaceState({}, "", `?${params.toString()}`); void refreshHistoricalView(); }); }); void refreshHistoricalView(); }); function hydrateSummary(result, summaryNode, rangeNode) { if (result.status !== "fulfilled") { renderSummaryError(summaryNode); setRangeBadge(rangeNode, "Resumen historico no disponible", false); return; } const items = result.value?.data?.items; if (!Array.isArray(items) || items.length === 0) { renderSummaryEmpty(summaryNode); setRangeBadge(rangeNode, "Sin cobertura historica", false); return; } const summary = items[0]; const timeRange = summary.time_range || {}; const rangeLabel = buildRangeLabel(timeRange.start, timeRange.end); setRangeBadge( rangeNode, rangeLabel || "Cobertura parcial disponible", Boolean(rangeLabel), ); summaryNode.innerHTML = [ renderSummaryCard("Servidor", summary.server?.name || "Servidor no disponible"), renderSummaryCard("Partidas", formatNumber(summary.matches_count)), renderSummaryCard("Jugadores unicos", formatNumber(summary.unique_players)), renderSummaryCard("Kills agregadas", formatNumber(summary.total_kills)), renderSummaryCard( "Mapas dominantes", formatTopMaps(summary.top_maps), ), ].join(""); } function hydrateWeeklyTopKills( result, stateNode, tableNode, bodyNode, ) { if (result.status !== "fulfilled") { setState(stateNode, "No se pudo cargar el ranking semanal.", true); tableNode.hidden = true; return; } const items = result.value?.data?.items; if (!Array.isArray(items) || items.length === 0) { setState( stateNode, "Sin datos historicos suficientes para construir el ranking semanal.", ); tableNode.hidden = true; return; } bodyNode.innerHTML = items .map( (item) => `
${escapeHtml(label)}
${escapeHtml(value)}