import { t } from "./i18n.js"; import { toast } from "./dom.js"; import { escapeHtml } from "./ui-utils.js"; export function openLightbox(url, title) { const overlay = document.createElement("div"); overlay.className = "lightbox"; const safeTitle = escapeHtml(title || ""); overlay.innerHTML = ` `; overlay.addEventListener("click", (e) => { if ( e.target.classList.contains("lightbox") || e.target.classList.contains("lightbox-close") ) { overlay.remove(); } }); document.body.appendChild(overlay); } export function openConfirmModal({ title, body, confirmLabel, cancelLabel = t("modal.cancel"), onConfirm, }) { const overlay = document.createElement("div"); overlay.className = "edit-modal"; const panel = document.createElement("div"); panel.className = "edit-panel"; panel.innerHTML = `

${title}

${body}

`; const close = () => overlay.remove(); const actions = document.createElement("div"); actions.className = "stack horizontal"; const confirmBtn = document.createElement("button"); confirmBtn.textContent = confirmLabel ?? t("modal.confirm"); actions.append(confirmBtn); if (cancelLabel !== null && cancelLabel !== undefined) { const cancelBtn = document.createElement("button"); cancelBtn.className = "ghost"; cancelBtn.type = "button"; cancelBtn.textContent = cancelLabel; actions.append(cancelBtn); cancelBtn.addEventListener("click", close); } panel.querySelector(".edit-body")?.appendChild(actions); overlay.addEventListener("click", (e) => { if ( e.target.classList.contains("edit-modal") || e.target.classList.contains("lightbox-close") ) { close(); } }); confirmBtn.addEventListener("click", async () => { try { await onConfirm?.(close); } catch (err) { toast(err.message, true); } }); overlay.appendChild(panel); document.body.appendChild(overlay); } export function openPasswordConfirmModal({ title, body, confirmLabel, cancelLabel = t("modal.cancel"), onConfirm, }) { const overlay = document.createElement("div"); overlay.className = "edit-modal"; const panel = document.createElement("div"); panel.className = "edit-panel"; panel.innerHTML = `

${title}

${body}

`; const close = () => overlay.remove(); const bodyWrap = panel.querySelector(".edit-body"); const fieldWrap = document.createElement("label"); fieldWrap.className = "stack"; fieldWrap.innerHTML = ` ${t("admin.passwordLabel")} `; bodyWrap?.appendChild(fieldWrap); const passwordInput = fieldWrap.querySelector("input"); const actions = document.createElement("div"); actions.className = "stack horizontal"; const confirmBtn = document.createElement("button"); confirmBtn.className = "danger"; confirmBtn.textContent = confirmLabel ?? t("modal.confirm"); actions.append(confirmBtn); if (cancelLabel !== null && cancelLabel !== undefined) { const cancelBtn = document.createElement("button"); cancelBtn.className = "ghost"; cancelBtn.type = "button"; cancelBtn.textContent = cancelLabel; actions.append(cancelBtn); cancelBtn.addEventListener("click", close); } bodyWrap?.appendChild(actions); overlay.addEventListener("click", (e) => { if ( e.target.classList.contains("edit-modal") || e.target.classList.contains("lightbox-close") ) { close(); } }); confirmBtn.addEventListener("click", async () => { const password = passwordInput?.value ?? ""; if (!password.trim()) { toast(t("admin.passwordRequired"), true); passwordInput?.focus(); return; } try { await onConfirm?.(password, close); } catch (err) { toast(err.message, true); } }); overlay.appendChild(panel); document.body.appendChild(overlay); passwordInput?.focus(); } export function openResultsRelockModal() { openConfirmModal({ title: t("results.relockedTitle"), body: t("results.relockedBody"), confirmLabel: t("results.relockedConfirm"), cancelLabel: null, onConfirm: (close) => close(), }); } export function openSuggestionsChangedModal(names) { const uniq = Array.from(new Set(names)).filter(Boolean); if (uniq.length === 0) return; openConfirmModal({ title: t("vote.listUpdatedTitle"), body: t("vote.listUpdatedBody", { names: uniq.join(", ") }), confirmLabel: t("vote.listUpdatedConfirm"), cancelLabel: null, onConfirm: (close) => close(), }); }