${escapeHtml(eyebrowLabel)}
${escapeHtml(serverName)}
${escapeHtml(`${players} / ${maxPlayers}`)}
${actionMarkup}// Progressive enhancement for local frontend-backend checks. const DEFAULT_SERVER_POLL_INTERVAL_MS = 300 * 1000; const SERVER_HISTORY_URLS_FALLBACK = Object.freeze({ "comunidad-hispana-01": "https://scoreboard.comunidadhll.es/games", "comunidad-hispana-02": "https://scoreboard.comunidadhll.es:5443/games", "comunidad-hispana-03": "https://scoreboard.comunidadhll.es:3443/games", }); const COMMUNITY_CLANS = Object.freeze([ { name: "LCM", badge: "Clan CH", description: "Clan activo de la comunidad, con acceso directo a su discord.", logoSrc: "./assets/img/clans/lcm.png", logoAlt: "Logo de LCM", logoClassName: "", discordUrl: "https://discord.gg/9F9S353QZv", discordLabel: "Abrir Discord", }, { name: "La 129", badge: "Clan CH", description: "Clan activo de la comunidad, con acceso directo a su discord.", logoSrc: "./assets/img/clans/la129.png", logoAlt: "Logo de La 129", logoClassName: "clan-card__logo--wide", discordUrl: "", discordLabel: "Proximamente", }, { name: "250 Hispania", badge: "Clan CH", description: "Clan activo de la comunidad, con acceso directo a su discord.", logoSrc: "./assets/img/clans/250hispania-shield.png", logoAlt: "Escudo de 250 Hispania", logoClassName: "clan-card__logo--shield", discordUrl: "https://discord.gg/3E62Yb6Aw3", discordLabel: "Abrir Discord", }, { name: "H9H", badge: "Clan CH", description: "Clan activo de la comunidad, con acceso directo a su discord.", logoSrc: "./assets/img/clans/h9h.png", logoAlt: "", logoClassName: "", discordUrl: "https://discord.gg/tYnXK7MQjB", discordLabel: "Abrir Discord", placeholderLabel: "H9H", }, { name: "BxB", badge: "Clan CH", description: "Clan activo de la comunidad, son raretes.", logoSrc: "./assets/img/clans/bxb.png", logoAlt: "Logo de BxB", logoClassName: "", discordUrl: "", discordLabel: "Proximamente", }, { name: "7dv", badge: "Clan CH", description: "Clan activo de la comunidad, con acceso directo a su discord.", logoSrc: "./assets/img/clans/7dv.png", logoAlt: "Logo de 7dv", logoClassName: "", discordUrl: "https://discord.gg/3sxNQZwrg6", discordLabel: "Abrir Discord", }, ]); document.addEventListener("DOMContentLoaded", () => { console.info("HLL Vietnam frontend ready"); const backendBaseUrl = document.body.dataset.backendBaseUrl || "http://127.0.0.1:8000"; const serverPollIntervalMs = getServerPollIntervalMs( document.body.dataset.serverRefreshMs, ); const statusNode = document.getElementById("backend-status"); const trailerFrame = document.getElementById("trailer-frame"); const trailerTitle = document.getElementById("trailer-title"); const serversTitle = document.getElementById("servers-title"); const serversList = document.getElementById("servers-list"); const serversBadge = document.getElementById("servers-badge"); const communityClansList = document.getElementById("community-clans-list"); updateBackendStatus(statusNode, "Backend comprobando", "status-chip--idle"); setServersDataState(serversBadge, { timestampLabel: "" }); renderServersLoadingState(serversList); hydrateCommunityClans(communityClansList); let serverRefreshInFlight = false; const refreshServers = async () => { if (serverRefreshInFlight) { return; } serverRefreshInFlight = true; try { await hydrateServers( backendBaseUrl, serversTitle, serversList, serversBadge, ); } finally { serverRefreshInFlight = false; } }; Promise.allSettled([ fetchHealth(backendBaseUrl, statusNode), hydrateTrailer(backendBaseUrl, trailerFrame, trailerTitle), refreshServers(), ]).catch((error) => { console.warn("Progressive enhancement failed", error); }); if (serverPollIntervalMs > 0) { window.setInterval(() => { void refreshServers(); }, serverPollIntervalMs); } }); async function fetchHealth(backendBaseUrl, statusNode) { try { const response = await fetch(`${backendBaseUrl}/health`); if (!response.ok) { throw new Error(`Health request failed with ${response.status}`); } const payload = await response.json(); if (payload.status === "ok") { updateBackendStatus(statusNode, "Backend operativo", "status-chip--ok"); return; } throw new Error("Unexpected health payload"); } catch (error) { console.warn("Backend health check unavailable", error); updateBackendStatus( statusNode, "Modo estatico activo", "status-chip--fallback", ); } } async function hydrateTrailer(backendBaseUrl, trailerFrame, trailerTitle) { if (!trailerFrame || !trailerTitle) { return; } try { const response = await fetch(`${backendBaseUrl}/api/trailer`); if (!response.ok) { throw new Error(`Trailer request failed with ${response.status}`); } const payload = await response.json(); const trailer = payload.data; if (!trailer || !trailer.video_url || !trailer.title) { throw new Error("Trailer payload incomplete"); } trailerFrame.src = trailer.video_url; trailerFrame.title = trailer.title; trailerTitle.textContent = trailer.title; } catch (error) { console.warn("Trailer placeholder remains static", error); } } async function hydrateServers( backendBaseUrl, serversTitle, serversList, serversBadge, ) { if (!serversTitle || !serversList || !serversBadge) { return; } try { const payload = await fetchJson(`${backendBaseUrl}/api/servers`); const serversData = payload.data; if (!serversData || !Array.isArray(serversData.items)) { throw new Error("Servers payload incomplete"); } serversTitle.textContent = serversData.title || "Estado actual de servidores"; setServersDataState(serversBadge, deriveSnapshotState(serversData)); if (serversData.items.length === 0) { serversList.innerHTML = '
Informacion de servidores disponible mas adelante.
'; return; } const visibleItems = selectPrimaryServerItems(serversData.items); serversList.innerHTML = renderServerSections(visibleItems); } catch (error) { console.warn("Servers panel failed to hydrate with live data", error); serversList.innerHTML = 'No se pudo cargar el estado real de servidores en este momento.
'; setServersDataState(serversBadge, { label: "Actualizacion no disponible", isFresh: false, }); } } function renderServersLoadingState(serversList) { if (!serversList) { return; } serversList.innerHTML = `Cargando estado real de servidores...
${escapeHtml(eyebrowLabel)}
${escapeHtml(`${players} / ${maxPlayers}`)}
${actionMarkup}${escapeHtml(clan.badge)}
${escapeHtml(clan.description)}
${escapeHtml(item.label)}
${escapeHtml(item.value)}