Neue Funktion: Supporter-Abstimmungen (Verwaltung + DogiCrew-Bereich)

Naechste "Ausbaustufe" aus Dogfather_VanVan_Supporter_Abo.odt Abschnitt 20
(siehe Supporter-Abo-System.md), auf Nutzerwunsch "perfektioniere meine
Verwaltungsseite": Dogi/VanVan koennen in verwaltung.html eine Frage mit
2-6 Antwortoptionen auf Deutsch erstellen, automatische Uebersetzung beim
Speichern (gleiches Muster wie "Event des Jahres"). Jede aktive DogiCrew-
Person sieht die Abstimmung in ihrem Supporter-Bereich, stimmt genau einmal
ab (UNIQUE-Constraint in der DB, nicht nur Anwendungslogik), sieht danach
die Live-Ergebnisse. Admin-Seite zeigt Ergebnisbalken live, kann schliessen/
wiedereroeffnen/loeschen.

- Neue Migration 0005_supporter_polls.sql (supporter_polls,
  supporter_poll_votes), neue Berechtigung POLLS_MANAGE.
- server-internal/routes/polls.js: 30 End-to-End-Tests gegen eine
  Fake-DB bestanden (better-sqlite3 laesst sich lokal nicht kompilieren).
- verwaltung.html: neue "Abstimmungen"-Kiste im bestehenden
  vw-overview-box-Stil (violett/pink Ergebnisbalken).
- supporter.html: neue "Aktuelle Abstimmung"-Karte im bestehenden
  Gold-Look, Optionen -> Stimme -> Ergebnisbalken, alle 5 Sprachen.

Backend-Teil (server-internal/, cloudflare-worker/migrations/) noch ohne
Deploy-Zugriff -- Dogi muss ihn manuell auf dogiintern ausrollen.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-20 16:07:51 +02:00
co-authored by Claude Opus 5
parent 189b72ec73
commit bda3198c76
8 changed files with 576 additions and 5 deletions
+26
View File
@@ -102,4 +102,30 @@ window.I18N_PAGE = {
de: "Zur DogiCrew 🩵", "de-CH": "Zur DogiCrew 🩵",
en: "Go to the DogiCrew 🩵", fr: "Aller à la DogiCrew 🩵", pt: "Ir para a DogiCrew 🩵",
},
/* Supporter-Abstimmungen (20.08.2026) */
su_poll_eyebrow: {
de: "🗳️ Aktuelle Abstimmung", "de-CH": "🗳️ Aktueui Abstimmig",
en: "🗳️ Current Poll", fr: "🗳️ Sondage en cours", pt: "🗳️ Enquete atual",
},
su_poll_btn_abstimmen: {
de: "Abstimmen", "de-CH": "Abstimme",
en: "Vote", fr: "Voter", pt: "Votar",
},
su_poll_bitte_waehlen: {
de: "Bitte wähle eine Antwort aus.", "de-CH": "Bitte wähl e Antwort us.",
en: "Please choose an answer.", fr: "Merci de choisir une réponse.", pt: "Por favor, escolha uma resposta.",
},
su_poll_danke: {
de: "Danke, deine Stimme wurde gezählt! 💙", "de-CH": "Danke, dini Stimm isch zellt worde! 💙",
en: "Thanks, your vote was counted! 💙", fr: "Merci, ton vote a été pris en compte ! 💙", pt: "Obrigado, seu voto foi contado! 💙",
},
su_poll_stimmen: {
de: "Stimmen", "de-CH": "Stimme",
en: "votes", fr: "votes", pt: "votos",
},
su_poll_fehler: {
de: "Abstimmen hat leider nicht geklappt. Bitte versuch es nochmal.", "de-CH": "Abstimme het leider nid klappt. Bitte versuech's nomol.",
en: "Voting didn't work. Please try again.", fr: "Le vote a échoué. Merci de réessayer.", pt: "A votação falhou. Por favor, tente novamente.",
},
};