import { t } from "./i18n.js"; import { state } from "./state.js"; import { $ } from "./dom.js"; import { buildLinkOptionLabel, 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; } function buildStatusSelect(player) { const canMoveToSuggest = player.phase === "Vote"; const select = document.createElement("select"); select.className = "chip admin-status-select"; select.dataset.setPlayerPhase = player.playerId; select.setAttribute("aria-label", t("admin.playerStatus")); const current = document.createElement("option"); current.value = ""; current.selected = true; current.textContent = displayPlayerStatus(player); const suggest = document.createElement("option"); suggest.value = "Suggest"; suggest.disabled = !canMoveToSuggest; suggest.textContent = t("admin.statusMoveToSuggest"); select.append(current, suggest); return select; } export function renderAdminVoteStatus() { if (!state.me?.isAdmin) return; if (state.adminStatusSelectActive) 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 gamesTooltip = (v.suggestionTitles || []).join(", "); const nameCell = document.createElement("td"); nameCell.title = v.name ?? ""; nameCell.textContent = truncate(v.name, 28); const usernameCell = document.createElement("td"); usernameCell.className = "muted small"; usernameCell.title = v.username ?? ""; usernameCell.textContent = truncate(v.username, 24); const statusCell = document.createElement("td"); statusCell.appendChild(buildStatusSelect(v)); const countCell = document.createElement("td"); countCell.title = gamesTooltip; countCell.textContent = String(v.suggestionCount ?? 0); const jokerCell = document.createElement("td"); const jokerButton = document.createElement("button"); jokerButton.className = "chip"; jokerButton.dataset.grantJoker = v.playerId; jokerButton.type = "button"; jokerButton.textContent = v.hasJoker ? "🎟" : t("admin.grantJokerChip"); jokerCell.appendChild(jokerButton); const adminCell = document.createElement("td"); if (v.isOwner) { const ownerLabel = document.createElement("span"); ownerLabel.className = "muted small"; ownerLabel.textContent = t("admin.owner"); adminCell.appendChild(ownerLabel); } else { const adminCheckbox = document.createElement("input"); adminCheckbox.type = "checkbox"; adminCheckbox.dataset.setPlayerAdmin = v.playerId; adminCheckbox.checked = !!v.isAdmin; adminCheckbox.setAttribute("aria-label", t("admin.playerAdmin")); adminCell.appendChild(adminCheckbox); } const deleteCell = document.createElement("td"); const deleteButton = document.createElement("button"); deleteButton.className = "chip danger-chip"; deleteButton.dataset.deletePlayer = v.playerId; deleteButton.dataset.name = v.name ?? ""; deleteButton.type = "button"; deleteButton.textContent = "✕"; deleteCell.appendChild(deleteButton); tr.append( nameCell, usernameCell, statusCell, countCell, jokerCell, adminCell, deleteCell, ); 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(); }