// Centre folder: the weekly decision card as a paper document with two rubber // stamps. Also shows the idle and end-of-term messages. import { t, tx, dateParts } from "../i18n/i18n.js"; import { dateOfDay } from "../engine/index.js"; import { $, esc } from "./desk.js"; const STAMP_MS = 750; // how long the stamp animation plays before the answer is applied export function createDecision(root, { cardsById, characters, onAnswer, onProfile, keysEnabled = () => true }) { root.innerHTML = `

${t("inbox.title")}

`; const body = $(root, ".inbox__body"); let shown = ""; let locked = false; let latest = null; function choose(choice) { if (locked) return; const card = $(body, ".card"); if (!card) return; locked = true; card.dataset.stamped = choice; for (const b of card.querySelectorAll("button")) b.disabled = true; const stamp = document.createElement("div"); stamp.className = `card__stamp card__stamp--${choice}`; stamp.textContent = t(choice === "yes" ? "card.approved" : "card.rejected"); card.append(stamp); setTimeout(() => onAnswer(choice), STAMP_MS); } body.addEventListener("click", (e) => { const b = e.target.closest("button[data-choice]"); if (b) choose(b.dataset.choice); const p = e.target.closest("button[data-pronouns]"); if (p) onProfile(p.dataset.pronouns); }); // The panel is rebuilt on language changes and new games, so its key listener must be removable. const onKey = (e) => { if (!keysEnabled() || !latest?.pendingCard) return; if (latest.pending.review || latest.pending.profile || latest.pending.alert) return; if (e.ctrlKey || e.metaKey || e.altKey) return; if (e.target.closest?.("input, textarea, select")) return; const k = e.key.toLowerCase(); if (k === "y") choose("yes"); else if (k === "n") choose("no"); }; document.addEventListener("keydown", onKey); function option(card, side) { const label = side === "yes" ? t("card.approved") : t("card.rejected"); return ` `; } function cardHtml(card, state) { const from = characters[card.sender]; const date = dateParts(dateOfDay(state.startDate, state.pendingCard.day).iso); const paragraphs = tx(card.body).split("\n\n").map((p) => `

${esc(p)}

`).join(""); return `
${t("kind." + card.doc)} ${esc(date.day)} ${esc(date.month)} ${esc(date.year)}
${esc(from.seal)} ${esc(tx(from.name))}${esc(tx(from.role))}

${esc(tx(card.title))}

${paragraphs}
${option(card, "yes")}${option(card, "no")}

${t("card.keys")}

`; } function update(state) { latest = state; let kind = "idle"; if (state.over) kind = "over"; else if (state.pending.profile) kind = "profile"; else if (state.pendingCard) kind = `card:${state.pendingCard.id}`; if (kind === shown) return; shown = kind; locked = false; body.classList.toggle("is-card", kind.startsWith("card:")); if (kind === "profile") { body.innerHTML = `

${t("profile.title")}

${t("profile.lead")}

${t("profile.body")}

${["he", "she", "they"].map((p) => ``).join("")}

${t("profile.note")}

`; } else if (kind === "idle") { body.innerHTML = `

${t("inbox.idle")}

`; } else if (kind === "over") { body.innerHTML = `

${t("inbox.overTitle")}

${t("inbox.overBody")}

`; } else { body.innerHTML = cardHtml(cardsById.get(state.pendingCard.id), state); } } return { update, destroy: () => document.removeEventListener("keydown", onKey) }; }