111 lines
4.1 KiB
JavaScript
111 lines
4.1 KiB
JavaScript
import { t } from "./i18n.js";
|
|
import { state } from "./state.js";
|
|
import { $ } from "./dom.js";
|
|
import { buildLinkOptionLabel, escapeHtml, truncate } from "./ui-utils.js";
|
|
|
|
function displayPlayerStatus(player) {
|
|
if (!player) return "";
|
|
const phase = player.phase;
|
|
if (phase === "Suggest") return t("admin.statusSuggesting");
|
|
if (phase === "Vote")
|
|
return player.finalized
|
|
? t("admin.statusFinished")
|
|
: t("admin.statusVoting");
|
|
if (phase === "Results") return t("admin.statusFinished");
|
|
return phase;
|
|
}
|
|
|
|
export function renderAdminVoteStatus() {
|
|
if (!state.me?.isAdmin) return;
|
|
const statusBadge = $("admin-ready-status");
|
|
const table = $("admin-player-table")?.querySelector("tbody");
|
|
if (!state.adminVoteStatus || !statusBadge || !table) return;
|
|
|
|
table.innerHTML = "";
|
|
state.adminVoteStatus.voters.forEach((v) => {
|
|
const tr = document.createElement("tr");
|
|
const statusText = displayPlayerStatus(v);
|
|
const gamesTooltip = escapeHtml((v.suggestionTitles || []).join(", "));
|
|
const nameText = escapeHtml(truncate(v.name, 28));
|
|
const userText = escapeHtml(truncate(v.username, 24));
|
|
tr.innerHTML = `
|
|
<td title="${escapeHtml(v.name)}">${nameText}</td>
|
|
<td class="muted small" title="${escapeHtml(v.username)}">${userText}</td>
|
|
<td>${statusText}</td>
|
|
<td title="${gamesTooltip}">${v.suggestionCount ?? 0}</td>
|
|
<td><button class="chip" data-grant-joker="${v.playerId}" type="button">${v.hasJoker ? "🎟" : t("admin.grantJokerChip")}</button></td>
|
|
<td><button class="chip danger-chip" data-delete-player="${v.playerId}" data-name="${v.name}" type="button">✕</button></td>
|
|
`;
|
|
table.appendChild(tr);
|
|
});
|
|
|
|
const waiting = state.adminVoteStatus.waiting;
|
|
const ready = waiting.length === 0;
|
|
const waitingDisplay = waiting.map((name) =>
|
|
name?.length > 24 ? `${name.slice(0, 21)}...` : name,
|
|
);
|
|
statusBadge.textContent = ready
|
|
? t("admin.readyForResults")
|
|
: t("admin.waitingForPlayers", { names: waitingDisplay.join(", ") });
|
|
statusBadge.className = ready ? "badge" : "badge warning";
|
|
}
|
|
|
|
export function renderAdminLinker() {
|
|
const wrap = $("admin-linker");
|
|
const source = $("link-source");
|
|
const target = $("link-target");
|
|
if (!wrap || !source || !target) return;
|
|
|
|
const visible = state.me?.isAdmin && state.phase === "Vote";
|
|
wrap.classList.toggle("hidden", !visible);
|
|
if (!visible) return;
|
|
|
|
const previousSource = source.value;
|
|
const previousTarget = target.value;
|
|
const options = (state.allSuggestions ?? [])
|
|
.slice()
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
|
|
const fillSelect = (select, placeholderKey) => {
|
|
select.innerHTML = "";
|
|
const placeholder = document.createElement("option");
|
|
placeholder.value = "";
|
|
placeholder.textContent = t(placeholderKey);
|
|
placeholder.disabled = true;
|
|
placeholder.selected = true;
|
|
select.appendChild(placeholder);
|
|
|
|
options.forEach((s) => {
|
|
const opt = document.createElement("option");
|
|
opt.value = s.id;
|
|
opt.textContent = buildLinkOptionLabel(s);
|
|
select.appendChild(opt);
|
|
});
|
|
};
|
|
|
|
fillSelect(source, "admin.linkSourcePlaceholder");
|
|
fillSelect(target, "admin.linkTargetPlaceholder");
|
|
|
|
if (previousSource && options.some((s) => String(s.id) === previousSource))
|
|
source.value = previousSource;
|
|
if (previousTarget && options.some((s) => String(s.id) === previousTarget))
|
|
target.value = previousTarget;
|
|
|
|
const preventSameSelection = () => {
|
|
const sourceVal = source.value;
|
|
const targetVal = target.value;
|
|
Array.from(target.options).forEach((opt) => {
|
|
if (!opt.value) return;
|
|
opt.disabled = opt.value === sourceVal;
|
|
});
|
|
Array.from(source.options).forEach((opt) => {
|
|
if (!opt.value) return;
|
|
opt.disabled = opt.value === targetVal;
|
|
});
|
|
};
|
|
|
|
source.onchange = preventSameSelection;
|
|
target.onchange = preventSameSelection;
|
|
preventSameSelection();
|
|
}
|