180 lines
5.2 KiB
JavaScript
180 lines
5.2 KiB
JavaScript
import { api, adminApi } from "./api.js";
|
|
import {
|
|
handleAuthError,
|
|
renderAllSuggestions,
|
|
renderCounts,
|
|
renderMySuggestions,
|
|
renderPhasePill,
|
|
renderPhaseTitles,
|
|
renderResults,
|
|
renderVotes,
|
|
renderWelcome,
|
|
setAuthUI,
|
|
syncVoteScores,
|
|
updatePhaseNav,
|
|
openResultsRelockModal,
|
|
openSuggestionsChangedModal,
|
|
} from "./ui.js";
|
|
import { state, clearUserState } from "./state.js";
|
|
|
|
export async function loadState() {
|
|
const [me, stateData] = await Promise.all([api.me(), api.state()]);
|
|
state.isAuthenticated = true;
|
|
state.me = me;
|
|
state.hasJoker = me.hasJoker ?? false;
|
|
state.prevPhase = state.phase;
|
|
state.phase = stateData.currentPhase;
|
|
state.resultsOpen = stateData.resultsOpen;
|
|
state.votesFinal = stateData.votesFinal ?? me?.votesFinal ?? false;
|
|
state.counts = stateData;
|
|
if (state.prevPhase !== state.phase && state.phase === "Vote") {
|
|
state.votesRendered = false;
|
|
}
|
|
setAuthUI(true);
|
|
renderWelcome();
|
|
renderPhasePill();
|
|
renderCounts();
|
|
}
|
|
|
|
export async function loadSuggestData() {
|
|
if (state.phase !== "Suggest") return;
|
|
state.mySuggestions = await api.mySuggestions();
|
|
renderMySuggestions();
|
|
updatePhaseNav();
|
|
}
|
|
|
|
export async function loadSuggestionsData() {
|
|
if (state.phase === "Vote" || state.phase === "Results") {
|
|
const prev = state.allSuggestions ?? [];
|
|
const prevById = Object.fromEntries(prev.map((s) => [s.id, s]));
|
|
const latest = await api.allSuggestions();
|
|
const latestSig = signatureSuggestions(latest);
|
|
const changed = latestSig !== state.allSuggestionsSig;
|
|
if (
|
|
changed &&
|
|
state.phase === "Vote" &&
|
|
state.votesRendered &&
|
|
state.allSuggestionsSig
|
|
) {
|
|
const added = latest
|
|
.filter((s) => !prevById[s.id])
|
|
.map((s) => s.name);
|
|
const relinked = latest
|
|
.filter((s) => {
|
|
const prevItem = prevById[s.id];
|
|
return (
|
|
prevItem &&
|
|
prevItem.parentSuggestionId !== s.parentSuggestionId
|
|
);
|
|
})
|
|
.map((s) => s.name);
|
|
const names = [...added, ...relinked];
|
|
openSuggestionsChangedModal(names);
|
|
}
|
|
state.allSuggestions = latest;
|
|
state.allSuggestionsSig = latestSig;
|
|
renderAllSuggestions();
|
|
renderPhaseTitles();
|
|
if (state.phase === "Vote" && changed) {
|
|
state.votesRendered = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function loadVoteData() {
|
|
if (state.phase !== "Vote") return;
|
|
const votes = await api.myVotes();
|
|
state.myVotes = votes;
|
|
if (!state.votesRendered) {
|
|
renderVotes();
|
|
state.votesRendered = true;
|
|
} else {
|
|
syncVoteScores();
|
|
}
|
|
updatePhaseNav();
|
|
}
|
|
|
|
export async function loadResults() {
|
|
if (state.phase !== "Results" || !state.resultsOpen) return;
|
|
state.results = await api.results();
|
|
renderResults();
|
|
}
|
|
|
|
export async function refreshPhaseData() {
|
|
const before = buildRefreshSnapshot();
|
|
try {
|
|
const prevPhase = state.phase;
|
|
const prevResultsOpen = state.resultsOpen;
|
|
await loadState();
|
|
await Promise.all([
|
|
loadSuggestData(),
|
|
loadSuggestionsData(),
|
|
loadResults(),
|
|
]);
|
|
if (state.phase === "Vote") {
|
|
if (!state.votesRendered) await loadVoteData();
|
|
} else {
|
|
state.votesRendered = false;
|
|
await loadVoteData();
|
|
}
|
|
const adminCard = document.getElementById("admin-card");
|
|
const adminPanelVisible =
|
|
!!adminCard && !adminCard.classList.contains("hidden");
|
|
if (state.me?.isAdmin && adminPanelVisible) {
|
|
state.adminVoteStatus = await adminApi.voteStatus();
|
|
}
|
|
if (
|
|
prevPhase === "Results" &&
|
|
state.phase === "Vote" &&
|
|
prevResultsOpen &&
|
|
!state.resultsOpen
|
|
) {
|
|
openResultsRelockModal();
|
|
}
|
|
updatePhaseNav();
|
|
const after = buildRefreshSnapshot();
|
|
return before !== after;
|
|
} catch (err) {
|
|
if (handleAuthError(err, clearUserState)) return;
|
|
throw err;
|
|
}
|
|
}
|
|
|
|
function buildRefreshSnapshot() {
|
|
return JSON.stringify({
|
|
phase: state.phase,
|
|
resultsOpen: state.resultsOpen,
|
|
votesFinal: state.votesFinal,
|
|
hasJoker: state.hasJoker,
|
|
counts: state.counts
|
|
? [
|
|
state.counts.players,
|
|
state.counts.suggestions,
|
|
state.counts.votes,
|
|
]
|
|
: null,
|
|
mineCount: state.mySuggestions?.length ?? 0,
|
|
allSig: state.allSuggestionsSig ?? "",
|
|
voteCount: state.myVotes?.length ?? 0,
|
|
resultsCount: state.results?.length ?? 0,
|
|
});
|
|
}
|
|
|
|
export function signatureSuggestions(list) {
|
|
return JSON.stringify(
|
|
list.map((s) => [
|
|
s.id,
|
|
s.name,
|
|
s.genre,
|
|
s.description,
|
|
s.screenshotUrl,
|
|
s.youtubeUrl,
|
|
s.gameUrl,
|
|
s.minPlayers,
|
|
s.maxPlayers,
|
|
s.parentSuggestionId,
|
|
s.isOwner,
|
|
]),
|
|
);
|
|
}
|