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:
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/gif"
|
||||
@@ -105,8 +106,64 @@ func handleCreateEntry(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// handleInteractions liest den Abstimmungsstand eines Beitrags und schaltet bei
|
||||
// mode=left/right die Stimme des angemeldeten Nutzers um:
|
||||
// - keine bisherige Stimme -> neue Stimme
|
||||
// - gleiche Stimme erneut -> Stimme zurückziehen (Toggle)
|
||||
// - andere Stimme -> auf den neuen Modus wechseln
|
||||
// mode=none liest nur (z. B. beim Laden des Feeds).
|
||||
func handleInteractions(w http.ResponseWriter, r *http.Request) {
|
||||
writeError(w, http.StatusNotImplemented, "Voting ist noch nicht implementiert")
|
||||
pid, err := strconv.ParseInt(chi.URLParam(r, "pid"), 10, 64)
|
||||
if err != nil {
|
||||
writeError(w, http.StatusBadRequest, "Ungültige pid")
|
||||
return
|
||||
}
|
||||
mode := chi.URLParam(r, "mode")
|
||||
|
||||
var uid int64
|
||||
if s, ok := getSession(r); ok {
|
||||
uid = s.UID
|
||||
}
|
||||
|
||||
if mode == "left" || mode == "right" {
|
||||
if uid == 0 {
|
||||
writeError(w, http.StatusUnauthorized, "Melde dich an, um abzustimmen!")
|
||||
return
|
||||
}
|
||||
|
||||
var prev string
|
||||
err := db.QueryRow(`SELECT mode FROM vote WHERE uid = ? AND pid = ?`, uid, pid).Scan(&prev)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
db.Exec(`INSERT INTO vote (uid, pid, mode) VALUES (?, ?, ?)`, uid, pid, mode)
|
||||
case err == nil && prev == mode:
|
||||
db.Exec(`DELETE FROM vote WHERE uid = ? AND pid = ?`, uid, pid)
|
||||
case err == nil:
|
||||
db.Exec(`UPDATE vote SET mode = ? WHERE uid = ? AND pid = ?`, mode, uid, pid)
|
||||
default:
|
||||
writeError(w, http.StatusInternalServerError, "Datenbankfehler")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
selected := "none"
|
||||
if uid != 0 {
|
||||
var cur string
|
||||
if err := db.QueryRow(`SELECT mode FROM vote WHERE uid = ? AND pid = ?`, uid, pid).Scan(&cur); err == nil {
|
||||
selected = cur
|
||||
}
|
||||
}
|
||||
|
||||
var left, right int
|
||||
db.QueryRow(`SELECT COUNT(*) FROM vote WHERE pid = ? AND mode = 'left'`, pid).Scan(&left)
|
||||
db.QueryRow(`SELECT COUNT(*) FROM vote WHERE pid = ? AND mode = 'right'`, pid).Scan(&right)
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"pid": pid,
|
||||
"left": left,
|
||||
"right": right,
|
||||
"selected": selected,
|
||||
})
|
||||
}
|
||||
|
||||
// storeImage skaliert ein hochgeladenes Bild auf max. 1024px und speichert es unter static/media.
|
||||
|
||||
Reference in New Issue
Block a user