Fix Stats review follow-ups

This commit is contained in:
devRaGonSa
2026-06-08 18:38:08 +02:00
parent c4ab38b617
commit 4b6df7d5ed
4 changed files with 370 additions and 109 deletions

View File

@@ -60,12 +60,18 @@ document.addEventListener("DOMContentLoaded", () => {
"Sin datos semanales. El ranking semanal se actualiza al cargar un jugador.",
monthlyPlaceholder:
"Sin datos mensuales. El ranking mensual se actualiza al cargar un jugador.",
weeklyWindowUnavailable:
"No se pudo cargar el bloque semanal; se muestran los datos mensuales.",
monthlyWindowUnavailable:
"No se pudo cargar el bloque mensual; se muestran los datos semanales.",
weeklyWindowUnavailableSummary:
"Resumen semanal no disponible temporalmente.",
monthlyWindowUnavailableSummary:
"Resumen mensual no disponible temporalmente.",
profileReadyTitle: "Perfil personal",
profileEmptyTitle: "Selecciona un jugador para ver sus estadisticas.",
weeklySummaryHelp:
"Resumen semanal: muestra la ventana activa del jugador.",
monthlySummaryHelp:
"Resumen mensual: muestra la ventana activa del jugador.",
partialProfileLoadWarning:
"Algunos bloques de ranking no se cargaron; se mantienen los disponibles.",
};
let isBackendOnline = false;
@@ -427,17 +433,32 @@ document.addEventListener("DOMContentLoaded", () => {
}
try {
const [weeklyData, monthlyData] = await Promise.all([
const [weeklyProfileResult, monthlyProfileResult] = await Promise.allSettled([
fetchPlayerProfile(playerId, "weekly"),
fetchPlayerProfile(playerId, "monthly"),
]);
const weeklyData =
weeklyProfileResult.status === "fulfilled" ? weeklyProfileResult.value : null;
const monthlyData =
monthlyProfileResult.status === "fulfilled" ? monthlyProfileResult.value : null;
const weeklyFailed = weeklyProfileResult.status === "rejected";
const monthlyFailed = monthlyProfileResult.status === "rejected";
if (!weeklyData && !monthlyData) {
throw new Error("Both weekly and monthly profile windows failed.");
}
profilePanel.hidden = false;
profileTitle.textContent = messages.profileReadyTitle;
const playerName = String(weeklyData.player_name || monthlyData.player_name || "Sin nombre");
const playerIdText = String(weeklyData.player_id || monthlyData.player_id || playerId);
const hasWeeklyStats = Number(weeklyData.matches_considered || 0) > 0;
const hasMonthlyStats = Number(monthlyData.matches_considered || 0) > 0;
const playerName = String(
(weeklyData?.player_name || monthlyData?.player_name || "Sin nombre"),
);
const playerIdText = String(weeklyData?.player_id || monthlyData?.player_id || playerId);
const hasWeeklyStats = Number(weeklyData?.matches_considered || 0) > 0;
const hasMonthlyStats = Number(monthlyData?.matches_considered || 0) > 0;
const hasStats = hasWeeklyStats || hasMonthlyStats;
const partialLoadWarning = weeklyFailed || monthlyFailed;
profileStateNode.textContent = hasStats
? `${playerName} (${playerIdText})`
@@ -446,42 +467,46 @@ document.addEventListener("DOMContentLoaded", () => {
? "stats-state stats-state--neutral"
: "stats-state stats-state--warning";
summaryGrid.innerHTML = `
<article class="stats-summary-card">
<p class="stats-summary-title">Identidad</p>
<p><strong>Jugador:</strong> ${escapeHtml(playerName)}</p>
<p><strong>ID:</strong> ${escapeHtml(playerIdText)}</p>
<p><strong>Partidas semanales:</strong> ${safeInt(weeklyData.matches_considered, 0)}</p>
<p><strong>Partidas mensuales:</strong> ${safeInt(monthlyData.matches_considered, 0)}</p>
</article>
<article class="stats-summary-card">
<p class="stats-summary-title">Ventana semanal</p>
<p><strong>Kills:</strong> ${safeInt(weeklyData.kills, 0)}</p>
<p><strong>Deaths:</strong> ${safeInt(weeklyData.deaths, 0)}</p>
<p><strong>Teamkills:</strong> ${safeInt(weeklyData.teamkills, 0)}</p>
</article>
<article class="stats-summary-card">
<p class="stats-summary-title">Ventana mensual</p>
<p><strong>Kills:</strong> ${safeInt(monthlyData.kills, 0)}</p>
<p><strong>Deaths:</strong> ${safeInt(monthlyData.deaths, 0)}</p>
<p><strong>Teamkills:</strong> ${safeInt(monthlyData.teamkills, 0)}</p>
</article>
`;
summaryGrid.innerHTML = renderProfileSummaryCards({
playerName,
playerIdText,
weeklyData,
monthlyData,
weeklyFailed,
monthlyFailed,
});
if (comparisonGrid) {
comparisonGrid.innerHTML = renderComparisonCards(weeklyData, monthlyData);
if (partialLoadWarning) {
profileStateNode.textContent += ` ${messages.partialProfileLoadWarning}`;
}
weeklySummaryNode.innerHTML = formatRankingSummary(
weeklyData.weekly_ranking,
"Semanal",
weeklyData.matches_considered,
);
monthlySummaryNode.innerHTML = formatRankingSummary(
monthlyData.monthly_ranking,
"Mensual",
monthlyData.matches_considered,
);
if (comparisonGrid) {
comparisonGrid.innerHTML = renderComparisonCards({
weeklyData,
weeklyFailed,
monthlyData,
monthlyFailed,
});
}
if (weeklySummaryNode) {
weeklySummaryNode.innerHTML = weeklyFailed
? `<p>${escapeHtml(messages.weeklyWindowUnavailableSummary)}</p>`
: formatRankingSummary(
weeklyData?.weekly_ranking,
"Semanal",
weeklyData?.matches_considered,
);
}
if (monthlySummaryNode) {
monthlySummaryNode.innerHTML = monthlyFailed
? `<p>${escapeHtml(messages.monthlyWindowUnavailableSummary)}</p>`
: formatRankingSummary(
monthlyData?.monthly_ranking,
"Mensual",
monthlyData?.matches_considered,
);
}
setBackendState(messages.backendOnline, true);
isBackendOnline = true;
@@ -507,6 +532,59 @@ document.addEventListener("DOMContentLoaded", () => {
}
}
function renderProfileSummaryCards({
playerName,
playerIdText,
weeklyData,
monthlyData,
weeklyFailed,
monthlyFailed,
}) {
const weeklySummary = weeklyFailed
? `
<article class="stats-summary-card">
<p class="stats-summary-title">Ventana semanal</p>
<p>${escapeHtml(messages.weeklyWindowUnavailable)}</p>
</article>
`
: `
<article class="stats-summary-card">
<p class="stats-summary-title">Ventana semanal</p>
<p><strong>Kills:</strong> ${safeInt(weeklyData?.kills, 0)}</p>
<p><strong>Deaths:</strong> ${safeInt(weeklyData?.deaths, 0)}</p>
<p><strong>Teamkills:</strong> ${safeInt(weeklyData?.teamkills, 0)}</p>
</article>
`;
const monthlySummary = monthlyFailed
? `
<article class="stats-summary-card">
<p class="stats-summary-title">Ventana mensual</p>
<p>${escapeHtml(messages.monthlyWindowUnavailable)}</p>
</article>
`
: `
<article class="stats-summary-card">
<p class="stats-summary-title">Ventana mensual</p>
<p><strong>Kills:</strong> ${safeInt(monthlyData?.kills, 0)}</p>
<p><strong>Deaths:</strong> ${safeInt(monthlyData?.deaths, 0)}</p>
<p><strong>Teamkills:</strong> ${safeInt(monthlyData?.teamkills, 0)}</p>
</article>
`;
return `
<article class="stats-summary-card">
<p class="stats-summary-title">Identidad</p>
<p><strong>Jugador:</strong> ${escapeHtml(playerName)}</p>
<p><strong>ID:</strong> ${escapeHtml(playerIdText)}</p>
<p><strong>Partidas semanales:</strong> ${safeInt(weeklyData?.matches_considered, 0)}</p>
<p><strong>Partidas mensuales:</strong> ${safeInt(monthlyData?.matches_considered, 0)}</p>
</article>
${weeklySummary}
${monthlySummary}
`;
}
function clearProfilePanel(openPanel) {
if (!profilePanel || !summaryGrid || !profileStateNode) {
return;
@@ -544,16 +622,35 @@ document.addEventListener("DOMContentLoaded", () => {
return payload.data || {};
}
function renderComparisonCards(weeklyData, monthlyData) {
return [
renderWindowComparisonCard("Semanal", weeklyData, weeklyData.weekly_ranking),
renderWindowComparisonCard("Mensual", monthlyData, monthlyData.monthly_ranking),
renderDeltaComparisonCard(weeklyData, monthlyData),
].join("");
function renderComparisonCards({
weeklyData,
weeklyFailed,
monthlyData,
monthlyFailed,
}) {
const cards = [
renderWindowComparisonCard(
"Semanal",
weeklyData,
weeklyData?.weekly_ranking,
weeklyFailed,
),
renderWindowComparisonCard(
"Mensual",
monthlyData,
monthlyData?.monthly_ranking,
monthlyFailed,
),
];
if (!weeklyFailed && !monthlyFailed) {
cards.push(renderDeltaComparisonCard(weeklyData, monthlyData));
}
return cards.join("");
}
function renderWindowComparisonCard(label, data, ranking) {
const rankingState = describeRankingState(ranking, data?.matches_considered, label);
function renderWindowComparisonCard(label, data, ranking, failed) {
const rankingState = describeRankingState(ranking, data?.matches_considered, label, failed);
const matches = safeInt(data?.matches_considered, 0);
const kills = safeInt(data?.kills, 0);
const deaths = safeInt(data?.deaths, 0);
@@ -664,9 +761,17 @@ document.addEventListener("DOMContentLoaded", () => {
`;
}
function describeRankingState(ranking, matchesConsidered, timeframeLabel) {
function describeRankingState(ranking, matchesConsidered, timeframeLabel, requestFailed = false) {
const matches = safeInt(matchesConsidered, 0);
const label = String(timeframeLabel || "ranking").toLowerCase();
if (requestFailed) {
return {
tone: "warning",
title: "Bloque no disponible",
detail: `No fue posible cargar los datos de la ventana ${label} en este intento.`,
};
}
if (!ranking) {
return {
tone: "error",