import { api } from "./api.js";
import { t } from "./i18n.js";
import { state, getSavedUsername, setSavedUsername } from "./state.js";
import { $, toast } from "./dom.js";
import { setupCardVisualHover, triggerCelebration } from "./effects.js";
export function setAuthUI(isAuthed) {
const main = document.querySelector("main");
const statusBar = document.querySelector(".status-bar");
const authCard = $("auth-card");
[main, statusBar].forEach((el) =>
el?.classList.toggle("hidden", !isAuthed),
);
if (authCard) authCard.classList.toggle("hidden", isAuthed);
const adminToggle = $("admin-toggle");
if (adminToggle)
adminToggle.classList.toggle("hidden", !isAuthed || !state.me?.isAdmin);
if (!isAuthed) {
const adminCard = $("admin-card");
if (adminCard) adminCard.classList.add("hidden");
const loginUser = $("login-username");
const cachedUser = getSavedUsername();
if (
loginUser &&
cachedUser &&
!loginUser.dataset.userEditing &&
!loginUser.value
) {
loginUser.value = cachedUser;
}
}
}
export function setAuthMode(mode) {
state.authMode = mode;
document.querySelectorAll(".auth-form").forEach((form) => {
form.classList.toggle("hidden", form.dataset.mode !== mode);
});
const title = $("auth-title");
const toggleBtn = $("auth-toggle");
if (title) {
title.textContent =
mode === "login"
? t("auth.loginHeading")
: t("auth.registerHeading");
}
if (toggleBtn) {
toggleBtn.textContent =
mode === "login"
? t("auth.switchToRegister")
: t("auth.switchToLogin");
}
}
export function handleAuthError(err, clearUserState) {
if (err?.status === 401) {
clearUserState();
state.isAuthenticated = false;
setAuthUI(false);
return true;
}
toast(err?.message || t("toast.unexpected"), true);
return false;
}
export function renderPhasePill() {
const phaseKey = typeof state.phase === "string" ? state.phase.toLowerCase() : null;
$("phase-pill").textContent = phaseKey ? "" : t("phase.loading");
document.querySelectorAll(".phase-view").forEach((el) =>
el.classList.add("hidden"),
);
const viewMap = {
Suggest: "suggest-view",
Reveal: "reveal-view",
Vote: "vote-view",
Results: "results-view",
};
const id = viewMap[state.phase];
if (id) $(id).classList.remove("hidden");
const phaseSelect = $("phase-select");
if (phaseSelect && !phaseSelect.dataset.userEditing) {
phaseSelect.value = state.phase || "Suggest";
}
}
export function renderCounts() {
if (!state.counts) return;
$("counts").textContent = t("counts.format", {
players: state.counts.players,
suggestions: state.counts.suggestions,
votes: state.counts.votes,
});
}
export function renderWelcome() {
const el = $("welcome-text");
if (!el) return;
const name =
state.me?.displayName?.trim() ||
state.me?.username ||
t("auth.defaultName");
el.textContent = t("auth.welcome", { name });
}
export function renderMySuggestions() {
const wrap = $("my-suggestions");
if (!wrap) return;
wrap.innerHTML = "";
const allowEdit = state.phase === "Suggest" || state.me?.isAdmin;
state.mySuggestions.forEach((s) =>
wrap.appendChild(
buildCard(s, { showAuthor: false, allowDelete: true, allowEdit }),
),
);
}
export function renderAllSuggestions() {
const list = $("all-suggestions");
if (!list) return;
list.innerHTML = "";
const allowEdit = !!state.me?.isAdmin;
const allowDelete =
!!state.me?.isAdmin &&
(state.phase === "Reveal" || state.phase === "Suggest");
state.allSuggestions.forEach((s) =>
list.appendChild(
buildCard(s, { showAuthor: true, allowEdit, allowDelete }),
),
);
renderPhaseTitles();
}
export function renderVotes() {
const list = $("vote-list");
if (!list) return;
list.innerHTML = "";
const votesMap = Object.fromEntries(
state.myVotes.map((v) => [v.suggestionId, v.score]),
);
state.allSuggestions.forEach((s) => {
const li = buildCard(s, {
showAuthor: true,
allowEdit: !!state.me?.isAdmin,
});
const hasVote = Object.prototype.hasOwnProperty.call(votesMap, s.id);
const current = hasVote ? votesMap[s.id] : 5; // start neutral when no prior vote
const displayScore = hasVote ? current : "—";
const displayEmoji = hasVote ? scoreToEmoji(current) : neutralEmoji();
const footer = document.createElement("div");
footer.className = "vote-controls";
footer.innerHTML = `
${displayScore}
${displayEmoji}`;
li.querySelector(".card-body").appendChild(footer);
list.appendChild(li);
});
list.querySelectorAll("input[type=range]").forEach((input) => {
input.addEventListener("input", (e) => {
const val = Number(e.target.value);
$("score-" + e.target.dataset.id).textContent = val;
const emojiEl = $("emoji-" + e.target.dataset.id);
if (emojiEl) emojiEl.textContent = scoreToEmoji(val);
});
input.addEventListener("change", async (e) => {
const suggestionId = Number(e.target.dataset.id);
const score = Number(e.target.value);
try {
await api.vote(suggestionId, score);
toast(t("vote.saved"));
await window.loadVoteData();
} catch (err) {
toast(err.message, true);
}
});
});
}
export function syncVoteScores() {
const votesMap = Object.fromEntries(
state.myVotes.map((v) => [v.suggestionId, v.score]),
);
Object.entries(votesMap).forEach(([id, score]) => {
const slider = document.querySelector(
`input[type=range][data-id="${id}"]`,
);
const scoreLabel = $("score-" + id);
const emoji = $("emoji-" + id);
if (slider && score != null) {
slider.value = score;
if (scoreLabel) scoreLabel.textContent = score;
if (emoji) emoji.textContent = scoreToEmoji(score);
}
});
document
.querySelectorAll("input[type=range][data-id]")
.forEach((slider) => {
const id = slider.dataset.id;
if (Object.prototype.hasOwnProperty.call(votesMap, Number(id)))
return;
const scoreLabel = $("score-" + id);
const emoji = $("emoji-" + id);
if (scoreLabel) scoreLabel.textContent = "—";
if (emoji) emoji.textContent = neutralEmoji();
});
}
export function renderResults() {
const container = $("results-list");
container.innerHTML = "";
const table = document.createElement("table");
table.className = "results-table";
table.innerHTML = `
${t("results.rank")}
${t("results.game")}
${t("results.author")}
${t("results.votes")}
${t("results.avg")}
${t("results.total")}
${t("results.links")}
` : ""} ${genreAndPlayers ? genreAndPlayers : ""} ${s.gameUrl ? `${t("card.site")}` : ""} ${s.youtubeUrl ? `${t("card.youtube")}` : ""} ${hasExtraInfo ? `
` : ""} ${s.description ? `${s.description}
` : ""}${title || ""}