Add vote finalize UX and missing-vote warning placement
This commit is contained in:
@@ -118,10 +118,12 @@
|
|||||||
<div class="card subcard phase-nav" id="nav-vote">
|
<div class="card subcard phase-nav" id="nav-vote">
|
||||||
<div class="nav-text">
|
<div class="nav-text">
|
||||||
<p data-i18n="nav.voteHint">Cast votes for every game to unlock results.</p>
|
<p data-i18n="nav.voteHint">Cast votes for every game to unlock results.</p>
|
||||||
|
<span class="badge warning hidden" id="vote-missing" data-i18n="vote.missingWarn">You haven’t voted yet for all games.</span>
|
||||||
<span class="badge warning hidden" id="results-lock" data-i18n="admin.resultsLocked">Results locked by admin</span>
|
<span class="badge warning hidden" id="results-lock" data-i18n="admin.resultsLocked">Results locked by admin</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-actions">
|
<div class="nav-actions">
|
||||||
<button id="nav-vote-prev" class="ghost" data-i18n="nav.prev">Back</button>
|
<button id="nav-vote-prev" class="ghost" data-i18n="nav.prev">Back</button>
|
||||||
|
<button id="finalize-votes" class="secondary" type="button" data-i18n="vote.finalize">Finalize votes</button>
|
||||||
<button id="nav-vote-next" class="primary" data-i18n="nav.next">Next</button>
|
<button id="nav-vote-next" class="primary" data-i18n="nav.next">Next</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ export async function loadState() {
|
|||||||
state.prevPhase = state.phase;
|
state.prevPhase = state.phase;
|
||||||
state.phase = stateData.currentPhase;
|
state.phase = stateData.currentPhase;
|
||||||
state.resultsOpen = stateData.resultsOpen;
|
state.resultsOpen = stateData.resultsOpen;
|
||||||
|
state.votesFinal = stateData.votesFinal ?? me?.votesFinal ?? false;
|
||||||
state.counts = stateData;
|
state.counts = stateData;
|
||||||
if (state.prevPhase !== state.phase && state.phase === "Vote") {
|
if (state.prevPhase !== state.phase && state.phase === "Vote") {
|
||||||
state.votesRendered = false;
|
state.votesRendered = false;
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ const translations = {
|
|||||||
"vote.saved": "Saved vote",
|
"vote.saved": "Saved vote",
|
||||||
"vote.missing": "Missing",
|
"vote.missing": "Missing",
|
||||||
"vote.missingWarn": "You haven’t voted yet. Slide to set a score.",
|
"vote.missingWarn": "You haven’t voted yet. Slide to set a score.",
|
||||||
|
"vote.finalize": "Finalize votes",
|
||||||
|
"vote.unfinalize": "Edit votes",
|
||||||
|
"vote.finalHint": "Finalize when you’re done. You can unfinalize to change scores.",
|
||||||
|
|
||||||
"results.rank": "Rank",
|
"results.rank": "Rank",
|
||||||
"results.game": "Game",
|
"results.game": "Game",
|
||||||
@@ -197,6 +200,9 @@ const translations = {
|
|||||||
"vote.saved": "Stimme gespeichert",
|
"vote.saved": "Stimme gespeichert",
|
||||||
"vote.missing": "Fehlt",
|
"vote.missing": "Fehlt",
|
||||||
"vote.missingWarn": "Du hast hier noch nicht abgestimmt. Schiebe den Regler.",
|
"vote.missingWarn": "Du hast hier noch nicht abgestimmt. Schiebe den Regler.",
|
||||||
|
"vote.finalize": "Abstimmung abschließen",
|
||||||
|
"vote.unfinalize": "Abstimmung bearbeiten",
|
||||||
|
"vote.finalHint": "Schließe ab, wenn du fertig bist. Zum Ändern wieder öffnen.",
|
||||||
|
|
||||||
"results.rank": "Rang",
|
"results.rank": "Rang",
|
||||||
"results.game": "Spiel",
|
"results.game": "Spiel",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export const state = {
|
|||||||
phase: null,
|
phase: null,
|
||||||
prevPhase: null,
|
prevPhase: null,
|
||||||
resultsOpen: false,
|
resultsOpen: false,
|
||||||
|
votesFinal: false,
|
||||||
counts: null,
|
counts: null,
|
||||||
mySuggestions: [],
|
mySuggestions: [],
|
||||||
allSuggestions: [],
|
allSuggestions: [],
|
||||||
@@ -19,6 +20,7 @@ export function clearUserState() {
|
|||||||
state.phase = null;
|
state.phase = null;
|
||||||
state.prevPhase = null;
|
state.prevPhase = null;
|
||||||
state.resultsOpen = false;
|
state.resultsOpen = false;
|
||||||
|
state.votesFinal = false;
|
||||||
state.counts = null;
|
state.counts = null;
|
||||||
state.mySuggestions = [];
|
state.mySuggestions = [];
|
||||||
state.allSuggestions = [];
|
state.allSuggestions = [];
|
||||||
|
|||||||
@@ -642,6 +642,14 @@ function formatMyVote(score) {
|
|||||||
return `${score} ${scoreToEmoji(score)}`;
|
return `${score} ${scoreToEmoji(score)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function missingVotesCount() {
|
||||||
|
const total = state.allSuggestions?.length ?? 0;
|
||||||
|
const mine = state.myVotes?.length ?? 0;
|
||||||
|
const votedIds = new Set(state.myVotes?.map((v) => v.suggestionId));
|
||||||
|
const missing = total - votedIds.size;
|
||||||
|
return missing < 0 ? 0 : missing;
|
||||||
|
}
|
||||||
|
|
||||||
function openDeleteConfirmModal(s) {
|
function openDeleteConfirmModal(s) {
|
||||||
const overlay = document.createElement("div");
|
const overlay = document.createElement("div");
|
||||||
overlay.className = "edit-modal";
|
overlay.className = "edit-modal";
|
||||||
@@ -733,6 +741,18 @@ export function updatePhaseNav() {
|
|||||||
lockBadge.textContent = t("admin.resultsLocked");
|
lockBadge.textContent = t("admin.resultsLocked");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const finalizeBtn = $("finalize-votes");
|
||||||
|
if (finalizeBtn) {
|
||||||
|
finalizeBtn.textContent = state.votesFinal ? t("vote.unfinalize") : t("vote.finalize");
|
||||||
|
}
|
||||||
|
|
||||||
|
const voteMissingBadge = $("vote-missing");
|
||||||
|
if (voteMissingBadge) {
|
||||||
|
const missing = missingVotesCount();
|
||||||
|
voteMissingBadge.classList.toggle("hidden", missing === 0);
|
||||||
|
voteMissingBadge.textContent = missing > 0 ? t("vote.missingWarn") : "";
|
||||||
|
}
|
||||||
|
|
||||||
// Toggle admin-only back buttons
|
// Toggle admin-only back buttons
|
||||||
const backButtons = ["nav-vote-prev"];
|
const backButtons = ["nav-vote-prev"];
|
||||||
backButtons.forEach((id) => {
|
backButtons.forEach((id) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user