Files
GameList/wwwroot/js/data.js

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,
]),
);
}