diff --git a/wwwroot/app.js b/wwwroot/app.js index 399c33a..cb97f3c 100644 --- a/wwwroot/app.js +++ b/wwwroot/app.js @@ -1,3 +1,5 @@ +import { api, adminApi } from "./js/api.js"; + const state = { me: null, phase: null, @@ -5,44 +7,22 @@ const state = { mySuggestions: [], allSuggestions: [], myVotes: [], - results: [], - adminKey: "" + results: [] }; const $ = (id) => document.getElementById(id); const toastEl = $("toast"); function toast(msg, isError = false) { + if (!toastEl) return; toastEl.textContent = msg; toastEl.classList.remove("hidden"); toastEl.classList.toggle("error", isError); - setTimeout(() => toastEl.classList.add("hidden"), 2400); -} - -async function api(path, options = {}) { - const res = await fetch(path, { - headers: { - "Content-Type": "application/json", - ...(options.adminKey ? { "X-Admin-Key": options.adminKey } : {}) - }, - ...options - }); - if (!res.ok) { - let msg = `${res.status}`; - try { - const body = await res.json(); - msg = body.error || JSON.stringify(body); - } catch (_) { /* ignore */ } - throw new Error(msg); - } - return res.status === 204 ? null : res.json(); + setTimeout(() => toastEl.classList.add("hidden"), 2000); } async function loadState() { - const [me, stateData] = await Promise.all([ - api("/api/me"), - api("/api/state") - ]); + const [me, stateData] = await Promise.all([api.me(), api.state()]); state.me = me; state.phase = stateData.currentPhase; state.counts = stateData; @@ -57,26 +37,26 @@ async function loadState() { async function loadSuggestData() { if (state.phase !== "Suggest") return; - state.mySuggestions = await api("/api/suggestions/mine"); + state.mySuggestions = await api.mySuggestions(); renderMySuggestions(); } async function loadRevealData() { if (state.phase === "Reveal" || state.phase === "Vote" || state.phase === "Results") { - state.allSuggestions = await api("/api/suggestions/all"); + state.allSuggestions = await api.allSuggestions(); renderAllSuggestions(); } } async function loadVoteData() { if (state.phase !== "Vote") return; - state.myVotes = await api("/api/votes/mine"); + state.myVotes = await api.myVotes(); renderVotes(); } async function loadResults() { if (state.phase !== "Results") return; - state.results = await api("/api/results"); + state.results = await api.results(); renderResults(); } @@ -119,6 +99,7 @@ function renderAllSuggestions() { 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) => { @@ -141,7 +122,7 @@ function renderVotes() { const suggestionId = Number(e.target.dataset.id); const score = Number(e.target.value); try { - await api("/api/votes", { method: "POST", body: JSON.stringify({ suggestionId, score }) }); + await api.vote(suggestionId, score); toast("Saved vote"); await loadVoteData(); } catch (err) { @@ -211,7 +192,7 @@ function setupHandlers() { const name = nameInput.value.trim(); if (!name) return toast("Name required", true); try { - const me = await api("/api/me/name", { method: "POST", body: JSON.stringify({ name }) }); + const me = await api.setName(name); state.me = me; nameInput.dataset.userEditing = ""; toast("Saved name"); @@ -227,7 +208,7 @@ function setupHandlers() { const data = Object.fromEntries(new FormData(form).entries()); if (!data.name) return toast("Name required", true); try { - await api("/api/suggestions", { method: "POST", body: JSON.stringify(data) }); + await api.createSuggestion(data); form.reset(); toast("Suggestion added"); await loadSuggestData(); @@ -240,11 +221,7 @@ function setupHandlers() { const phase = $("phase-select").value; const adminKey = $("admin-key").value; try { - await api("/api/admin/phase", { - method: "POST", - body: JSON.stringify({ phase }), - adminKey - }); + await adminApi.setPhase(phase, adminKey); toast("Phase updated"); state.phase = phase; $("phase-select").dataset.userEditing = ""; @@ -260,8 +237,8 @@ function setupHandlers() { }); phaseSelect.addEventListener("blur", () => { phaseSelect.dataset.userEditing = ""; }); - $("reset").addEventListener("click", () => adminAction("/api/admin/reset", "Reset complete")); - $("factory-reset").addEventListener("click", () => adminAction("/api/admin/factory-reset", "Factory reset complete")); + $("reset").addEventListener("click", () => adminAction(adminApi.reset, "Reset complete")); + $("factory-reset").addEventListener("click", () => adminAction(adminApi.factoryReset, "Factory reset complete")); const adminToggle = $("admin-toggle"); const adminCard = $("admin-card"); @@ -273,10 +250,10 @@ function setupHandlers() { } } -async function adminAction(path, successMessage) { +async function adminAction(fn, successMessage) { const adminKey = $("admin-key").value; try { - await api(path, { method: "POST", adminKey }); + await fn(adminKey); toast(successMessage); await refreshPhaseData(); } catch (err) { @@ -301,8 +278,8 @@ function buildCard(s, { showAuthor = false, allowDelete = false }) {