feat: refine team filters and epic profile links

This commit is contained in:
devRaGonSa
2026-05-21 11:00:50 +02:00
parent af1e2a27bd
commit f54ba4dbd3
4 changed files with 239 additions and 31 deletions

View File

@@ -590,3 +590,163 @@
height: 96px;
}
}
.historical-player-control--team-toggle {
border: 0;
margin: 0;
padding: 0;
}
.historical-player-control--team-toggle legend {
color: var(--muted);
display: block;
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.14em;
margin-bottom: 0.45rem;
text-transform: uppercase;
}
.historical-player-team-toggle {
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
}
.historical-player-team-toggle label {
cursor: pointer;
}
.historical-player-team-toggle input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.historical-player-team-toggle span {
border: 1px solid rgba(210, 196, 130, 0.34);
border-radius: 999px;
color: var(--muted);
display: inline-flex;
font-size: 0.75rem;
font-weight: 800;
letter-spacing: 0.08em;
padding: 0.55rem 0.8rem;
text-transform: uppercase;
}
.historical-player-team-toggle input:checked + span {
background: rgba(210, 196, 130, 0.12);
border-color: rgba(210, 196, 130, 0.72);
color: var(--text);
}
.historical-player-team-toggle input:focus-visible + span {
outline: 2px solid rgba(210, 196, 130, 0.9);
outline-offset: 2px;
}
.historical-player-stats-panel__profiles code {
color: var(--text);
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
font-size: 0.82rem;
word-break: break-all;
}
/* Player controls refinement: team selector above search/sort. */
.historical-player-control--team-toggle {
border: 0;
grid-column: 1 / -1;
margin: 0;
order: -1;
padding: 0;
}
.historical-player-control--team-toggle legend {
color: var(--muted);
display: block;
font-size: 0.68rem;
font-weight: 700;
letter-spacing: 0.14em;
margin-bottom: 0.45rem;
text-transform: uppercase;
}
.historical-player-team-toggle {
align-items: center;
display: flex;
flex-wrap: wrap;
gap: 0.55rem;
}
.historical-player-team-toggle label {
cursor: pointer;
}
.historical-player-team-toggle input {
position: absolute;
opacity: 0;
pointer-events: none;
}
.historical-player-team-toggle span {
border: 1px solid rgba(210, 196, 130, 0.34);
border-radius: 999px;
color: var(--muted);
display: inline-flex;
font-size: 0.75rem;
font-weight: 900;
letter-spacing: 0.08em;
padding: 0.58rem 0.9rem;
text-transform: uppercase;
transition:
background 160ms ease,
border-color 160ms ease,
color 160ms ease,
box-shadow 160ms ease;
}
.historical-player-team-toggle__item--all input:checked + span {
background: rgba(210, 196, 130, 0.13);
border-color: rgba(210, 196, 130, 0.78);
color: var(--text);
box-shadow: 0 0 0 1px rgba(210, 196, 130, 0.18);
}
.historical-player-team-toggle__item--allies span {
border-color: rgba(109, 171, 255, 0.42);
color: #b8d7ff;
}
.historical-player-team-toggle__item--allies input:checked + span {
background: rgba(72, 135, 220, 0.24);
border-color: rgba(133, 190, 255, 0.9);
color: #e4f1ff;
box-shadow: 0 0 0 1px rgba(109, 171, 255, 0.22);
}
.historical-player-team-toggle__item--axis span {
border-color: rgba(225, 113, 86, 0.48);
color: #ffb6a6;
}
.historical-player-team-toggle__item--axis input:checked + span {
background: rgba(170, 72, 54, 0.28);
border-color: rgba(255, 143, 113, 0.92);
color: #ffe1d9;
box-shadow: 0 0 0 1px rgba(225, 113, 86, 0.24);
}
.historical-player-team-toggle input:focus-visible + span {
outline: 2px solid rgba(210, 196, 130, 0.9);
outline-offset: 2px;
}
.historical-player-stats-panel__profiles code {
color: var(--text);
font-family: ui-monospace, SFMono-Regular, Consolas, "Liberation Mono", monospace;
font-size: 0.82rem;
word-break: break-all;
}

View File

@@ -16,7 +16,7 @@ document.addEventListener("DOMContentLoaded", () => {
playersState: document.getElementById("match-detail-players-state"),
playerControls: document.getElementById("match-detail-player-controls"),
playerSearch: document.getElementById("match-detail-player-search"),
playerTeamFilter: document.getElementById("match-detail-player-team-filter"),
playerTeamFilters: [...document.querySelectorAll('input[name="match-detail-player-team-filter"]')],
playerSort: document.getElementById("match-detail-player-sort"),
playerSortDirection: document.getElementById("match-detail-player-sort-direction"),
playersTableShell: document.getElementById("match-detail-players-table-shell"),
@@ -227,7 +227,9 @@ function renderPlayerSection(item, nodes) {
const renderRows = () => renderPlayerTable(item, players, state, nodes);
nodes.playerSearch.value = "";
nodes.playerTeamFilter.value = state.team;
nodes.playerTeamFilters.forEach((control) => {
control.checked = control.value === state.team;
});
nodes.playerSort.value = state.sort;
nodes.playerSortDirection.value = state.direction;
bindPlayerTableControls(nodes, state, renderRows);
@@ -245,11 +247,13 @@ function bindPlayerTableControls(nodes, state, renderRows) {
state.search = nodes.playerSearch.value;
renderRows();
};
nodes.playerTeamFilter.onchange = () => {
closePlayerDetailRows(nodes.playersBody);
state.team = nodes.playerTeamFilter.value;
renderRows();
};
nodes.playerTeamFilters.forEach((control) => {
control.onchange = () => {
closePlayerDetailRows(nodes.playersBody);
state.team = control.value;
renderRows();
};
});
nodes.playerSort.onchange = () => {
state.sort = nodes.playerSort.value;
state.isDefaultSort = false;
@@ -483,10 +487,10 @@ function renderPlayerStatsPanel(player, item, context) {
<h4>${escapeHtml(context.playerName)}</h4>
</div>
<div class="historical-player-stats-panel__summary">
${renderPlayerStatChip("K", formatOptionalNumber(player.kills))}
${renderPlayerStatChip("D", formatOptionalNumber(player.deaths))}
${renderPlayerStatChip("Kills", formatOptionalNumber(player.kills))}
${renderPlayerStatChip("Muertes", formatOptionalNumber(player.deaths))}
${renderPlayerStatChip("TK", formatOptionalNumber(player.teamkills))}
${renderPlayerStatChip("K/D", formatKdRatio(player))}
${renderPlayerStatChip("KD", formatKdRatio(player))}
${renderPlayerStatChip("KPM", context.kpm)}
</div>
</div>
@@ -512,6 +516,7 @@ function renderExternalProfilesSection(player) {
["steam", "Steam"],
["hellor", "Hellor"],
["hll_records", "HLL Records"],
["helo", "Helo"],
]
.map(([key, label]) => [label, player.external_profile_links?.[key]])
.filter(([, href]) => typeof href === "string" && href.trim());
@@ -534,12 +539,26 @@ function renderExternalProfilesSection(player) {
.join("")}
</div>
`
: "<p>Perfiles externos no disponibles.</p>"
: renderExternalProfilesUnavailable(player)
}
</article>
`;
}
function renderExternalProfilesUnavailable(player) {
const platform = String(player.platform || "").toLowerCase();
const epicId = typeof player.epic_id === "string" ? player.epic_id.trim() : "";
if (platform === "epic") {
return epicId
? `<p>Jugador detectado como Epic. ID capturado: <code>${escapeHtml(epicId)}</code>. Sin enlaces externos compatibles confirmados para este proveedor.</p>`
: "<p>Jugador detectado como Epic. Sin enlaces externos compatibles confirmados para este proveedor.</p>";
}
return "<p>Perfiles externos no disponibles.</p>";
}
function renderPlayerStatChip(label, value) {
return `
<article>