import { adminApi } from "./api.js"; import { t } from "./i18n.js"; import { state } from "./state.js"; import { $, toast } from "./dom.js"; import { openConfirmModal, openResultsRelockModal, renderPhasePill, } from "./ui.js"; function openAdminPasswordModal({ title, body, confirmLabel, onConfirm }) { openConfirmModal({ title, body, confirmLabel, confirmClass: "danger", requirePassword: true, passwordLabel: t("admin.confirmPasswordLabel"), onConfirm: async (close, payload) => { const password = (payload?.password || "").trim(); if (!password) { toast(t("admin.confirmPasswordRequired"), true); return; } await onConfirm(password, close); }, }); } function setupAdminPanelToggle() { const adminToggle = $("admin-toggle"); const adminCard = $("admin-card"); const adminClose = $("admin-close"); if (!adminToggle || !adminCard || !adminClose) return; const togglePanel = (show) => adminCard.classList.toggle("hidden", !show); adminToggle.addEventListener("click", () => togglePanel(adminCard.classList.contains("hidden")), ); adminClose.addEventListener("click", () => togglePanel(false)); } function setupResetButtons(runSerializedRefresh) { $("reset").addEventListener("click", () => { openAdminPasswordModal({ title: t("admin.resetConfirmTitle"), body: t("admin.resetConfirmBody"), confirmLabel: t("admin.reset"), onConfirm: async (password, close) => { try { await adminApi.reset(password); toast(t("admin.resetDone")); close(); await runSerializedRefresh(); } catch (err) { toast(err.message, true); } }, }); }); $("factory-reset").addEventListener("click", () => { openAdminPasswordModal({ title: t("admin.factoryResetConfirmTitle"), body: t("admin.factoryResetConfirmBody"), confirmLabel: t("admin.factoryReset"), onConfirm: async (password, close) => { try { await adminApi.factoryReset(password); toast(t("admin.factoryResetDone")); close(); await runSerializedRefresh(); } catch (err) { toast(err.message, true); } }, }); }); } function setupResultsToggle(runSerializedRefresh) { const resultsToggle = $("results-open"); if (!resultsToggle) return; resultsToggle.addEventListener("click", async () => { const desired = !state.resultsOpen; resultsToggle.disabled = true; try { const resp = await adminApi.setResultsOpen(desired); const wasResultsOpen = state.resultsOpen; const wasPhase = state.phase; state.resultsOpen = resp.resultsOpen; if (wasResultsOpen && !resp.resultsOpen && wasPhase === "Results") { openResultsRelockModal(); } renderPhasePill(); toast(t("admin.resultsUpdated")); await runSerializedRefresh(); } catch (err) { toast(err.message, true); } finally { resultsToggle.disabled = false; } }); } function setupLinkApply(runSerializedRefresh) { const linkApply = $("link-apply"); if (!linkApply) return; linkApply.addEventListener("click", async () => { const source = Number($("link-source")?.value); const target = Number($("link-target")?.value); if (!source || !target || source === target) { return toast(t("admin.linkValidation"), true); } try { await adminApi.linkSuggestions(source, target); toast(t("admin.linkDone")); await runSerializedRefresh(); } catch (err) { toast(err.message, true); } }); } function setupPlayerTableActions(runSerializedRefresh) { const playerTable = $("admin-player-table"); if (!playerTable) return; const phaseSelectSelector = "[data-set-player-phase]"; playerTable.addEventListener("focusin", (e) => { if (e.target.matches?.(phaseSelectSelector)) { state.adminStatusSelectActive = true; } }); playerTable.addEventListener("focusout", (e) => { if (!e.target.matches?.(phaseSelectSelector)) return; window.setTimeout(() => { const focused = document.activeElement; state.adminStatusSelectActive = !!focused?.matches?.(phaseSelectSelector); }, 0); }); playerTable.addEventListener("change", async (e) => { const select = e.target.closest(phaseSelectSelector); if (!select) return; const playerId = select.dataset.setPlayerPhase; const phase = select.value; if (!playerId || !phase) return; select.disabled = true; try { await adminApi.setPlayerPhase(playerId, phase); toast(t("admin.statusUpdated")); state.adminStatusSelectActive = false; await runSerializedRefresh(); } catch (err) { select.value = ""; toast(err.message, true); } finally { select.disabled = false; state.adminStatusSelectActive = false; } }); playerTable.addEventListener("click", async (e) => { const grantBtn = e.target.closest("[data-grant-joker]"); const deleteBtn = e.target.closest("[data-delete-player]"); if (grantBtn) { const playerId = grantBtn.dataset.grantJoker; try { await adminApi.grantJoker(playerId); toast(t("admin.jokerGranted")); await runSerializedRefresh(); } catch (err) { toast(err.message, true); } } else if (deleteBtn) { const playerId = deleteBtn.dataset.deletePlayer; const name = deleteBtn.dataset.name || ""; openAdminPasswordModal({ title: t("admin.deleteTitle"), body: t("admin.deleteBody", { name }), confirmLabel: t("admin.deleteConfirm"), onConfirm: async (password, close) => { try { await adminApi.deletePlayer(playerId, password); toast(t("admin.deleteDone")); close(); await runSerializedRefresh(); } catch (err) { toast(err.message, true); } }, }); } }); } export function setupAdminHandlers({ runSerializedRefresh }) { setupResetButtons(runSerializedRefresh); setupAdminPanelToggle(); setupResultsToggle(runSerializedRefresh); setupLinkApply(runSerializedRefresh); setupPlayerTableActions(runSerializedRefresh); }