Refresh vote cards after suggestion edits
This commit is contained in:
@@ -12,6 +12,7 @@ const state = {
|
|||||||
counts: null,
|
counts: null,
|
||||||
mySuggestions: [],
|
mySuggestions: [],
|
||||||
allSuggestions: [],
|
allSuggestions: [],
|
||||||
|
allSuggestionsSig: null,
|
||||||
myVotes: [],
|
myVotes: [],
|
||||||
results: [],
|
results: [],
|
||||||
votesRendered: false
|
votesRendered: false
|
||||||
@@ -114,9 +115,16 @@ async function loadSuggestData() {
|
|||||||
|
|
||||||
async function loadRevealData() {
|
async function loadRevealData() {
|
||||||
if (state.phase === "Reveal" || state.phase === "Vote" || state.phase === "Results") {
|
if (state.phase === "Reveal" || state.phase === "Vote" || state.phase === "Results") {
|
||||||
state.allSuggestions = await api.allSuggestions();
|
const latest = await api.allSuggestions();
|
||||||
|
const latestSig = signatureSuggestions(latest);
|
||||||
|
const changed = latestSig !== state.allSuggestionsSig;
|
||||||
|
state.allSuggestions = latest;
|
||||||
|
state.allSuggestionsSig = latestSig;
|
||||||
renderAllSuggestions();
|
renderAllSuggestions();
|
||||||
renderPhaseTitles();
|
renderPhaseTitles();
|
||||||
|
if (state.phase === "Vote" && changed) {
|
||||||
|
state.votesRendered = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,12 +207,14 @@ function renderVotes() {
|
|||||||
const li = buildCard(s, { showAuthor: true, allowEdit: !!state.me?.isAdmin });
|
const li = buildCard(s, { showAuthor: true, allowEdit: !!state.me?.isAdmin });
|
||||||
const hasVote = Object.prototype.hasOwnProperty.call(votesMap, s.id);
|
const hasVote = Object.prototype.hasOwnProperty.call(votesMap, s.id);
|
||||||
const current = hasVote ? votesMap[s.id] : 5; // start neutral when no prior vote
|
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");
|
const footer = document.createElement("div");
|
||||||
footer.className = "vote-controls";
|
footer.className = "vote-controls";
|
||||||
footer.innerHTML = `
|
footer.innerHTML = `
|
||||||
<input class="full-slider" type="range" min="0" max="10" value="${current}" data-id="${s.id}">
|
<input class="full-slider" type="range" min="0" max="10" value="${current}" data-id="${s.id}">
|
||||||
<span class="score" id="score-${s.id}">${current}</span>
|
<span class="score" id="score-${s.id}">${displayScore}</span>
|
||||||
<span class="score-emoji" id="emoji-${s.id}">${scoreToEmoji(current)}</span>`;
|
<span class="score-emoji" id="emoji-${s.id}">${displayEmoji}</span>`;
|
||||||
li.querySelector(".card-body").appendChild(footer);
|
li.querySelector(".card-body").appendChild(footer);
|
||||||
list.appendChild(li);
|
list.appendChild(li);
|
||||||
});
|
});
|
||||||
@@ -241,6 +251,14 @@ function syncVoteScores() {
|
|||||||
if (emoji) emoji.textContent = scoreToEmoji(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();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderResults() {
|
function renderResults() {
|
||||||
@@ -482,9 +500,7 @@ async function refreshPhaseData() {
|
|||||||
await loadState();
|
await loadState();
|
||||||
await Promise.all([loadSuggestData(), loadRevealData(), loadResults()]);
|
await Promise.all([loadSuggestData(), loadRevealData(), loadResults()]);
|
||||||
if (state.phase === "Vote") {
|
if (state.phase === "Vote") {
|
||||||
if (!state.votesRendered) {
|
if (!state.votesRendered) await loadVoteData();
|
||||||
await loadVoteData();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
state.votesRendered = false;
|
state.votesRendered = false;
|
||||||
await loadVoteData();
|
await loadVoteData();
|
||||||
@@ -702,6 +718,7 @@ function normalizeSuggestionForm(formData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function scoreToEmoji(score) {
|
function scoreToEmoji(score) {
|
||||||
|
if (score == null || Number.isNaN(score)) return neutralEmoji();
|
||||||
if (score < 1) return "😡";
|
if (score < 1) return "😡";
|
||||||
if (score <= 3) return "😠";
|
if (score <= 3) return "😠";
|
||||||
if (score <= 6) return "😐";
|
if (score <= 6) return "😐";
|
||||||
@@ -709,3 +726,23 @@ function scoreToEmoji(score) {
|
|||||||
if (score <= 9) return "😃";
|
if (score <= 9) return "😃";
|
||||||
return "🤩";
|
return "🤩";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function neutralEmoji() {
|
||||||
|
return "😐";
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -175,6 +175,7 @@ h3 { margin: 0; font-size: 18px; }
|
|||||||
.card-title-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; min-width: 0; }
|
.card-title-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; min-width: 0; }
|
||||||
.card-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
.card-title { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
.title-meta { display: flex; align-items: center; gap: 8px; }
|
.title-meta { display: flex; align-items: center; gap: 8px; }
|
||||||
|
.title-meta .chip { max-width: 140px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
||||||
p { margin: 0; }
|
p { margin: 0; }
|
||||||
.muted { color: #7a6a53; margin: 0; }
|
.muted { color: #7a6a53; margin: 0; }
|
||||||
.link { color: #30afea; text-decoration: none; font-weight: 700; }
|
.link { color: #30afea; text-decoration: none; font-weight: 700; }
|
||||||
|
|||||||
Reference in New Issue
Block a user