Implement left/right voting on entries

GET /entry/{pid}/interactions/{mode} now reads the vote tally and, for
mode=left/right (auth required), toggles the user's vote: new vote, repeat
same mode removes it, different mode switches. Returns {left, right,
selected}. A UNIQUE(uid, pid) constraint on the vote table prevents
duplicate votes. The JS frontend renders Links/Rechts buttons with live
counts under each entry.

This completes the voting feature that was left commented-out and broken
in the Flask version.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-01 10:58:58 +02:00
parent c904e3e2db
commit be8dbb4902
5 changed files with 130 additions and 5 deletions
+32
View File
@@ -83,10 +83,42 @@ function renderEntry(e) {
<div class="meta"><strong>${escapeHtml(e.username)}</strong> · ${when}</div>
<div class="content">${linkify(e.content)}</div>
${media}
<div class="interactions">
<button class="vote" data-mode="left">Links</button>
<span class="counts"> / </span>
<button class="vote" data-mode="right">Rechts</button>
</div>
`;
setupVoting(el, e.pid);
return el;
}
function setupVoting(el, pid) {
const box = el.querySelector(".interactions");
const counts = box.querySelector(".counts");
const buttons = box.querySelectorAll(".vote");
function render(state) {
if (state.error) {
counts.textContent = state.error;
return;
}
counts.textContent = `${state.left} / ${state.right}`;
buttons.forEach((b) =>
b.classList.toggle("selected", b.dataset.mode === state.selected)
);
}
buttons.forEach((b) =>
b.addEventListener("click", async () => {
render(await api.get(`/entry/${pid}/interactions/${b.dataset.mode}`));
})
);
// Anfangszustand laden, ohne zu werten.
api.get(`/entry/${pid}/interactions/none`).then(render);
}
async function loadMore() {
if (loading || done) return;
loading = true;