Arbeit der parallelen Session in git gesichert (war nur auf dem Server)

Diese Änderungen liefen bereits live auf dem Server, lagen dort aber
ausschließlich als nicht eingecheckte Arbeitskopie — bei jedem Deploy
(stash/pull/pop) und bei jedem Serverproblem wären sie verloren gewesen.
Deshalb hier unverändert in git übernommen, bevor darauf aufgebaut wird.

Enthalten (nicht von mir gebaut, nur gesichert):
- Supporter: eigener fester Zugangscode statt Einmalcode-Login
  (Migration 0009, lib/crypto.js scrypt-Hash, routes/supporter.js,
  abonnieren.html, supporter.html, i18n-abonnieren/-supporter)
- Stimmen: Profilbilder (Migration 0010, routes/testimonials.js)
- Event-Bild-Upload: voller Pfad statt relativem (routes/events.js)
- Neue/überarbeitete Hintergrundbilder für viele Seiten
- Teilen-Funktion (streamplan.js, i18n-index/-streamplan, main.css)

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-08-21 17:35:14 +02:00
co-authored by Claude Opus 5
parent 4b294f6c6b
commit 5d0ea11570
65 changed files with 992 additions and 139 deletions
+288 -82
View File
@@ -216,6 +216,104 @@
.abo-switch a { color: var(--accent); cursor: pointer; font-weight: 600; }
.abo-switch a:hover { text-decoration: underline; }
/* Registrieren/Einloggen-Umschalter (21.08.2026, Nutzer-Wunsch: "die
sollen dann sofort immer den anmelde knopf auswählen können") — zwei
Segmente in einer Pille, aktiver Tab in Gold hervorgehoben, damit die
Wahl sofort ins Auge fällt, noch bevor überhaupt ein Formularfeld zu
sehen ist. Augenschonend: kein grelles Weiß, ruhiger Farbwechsel. */
/* =====================================================================
Aktionsleiste (21.08.2026) — EIN Element für beide Wege, statt vorher
doppeltem "Registrieren" (Umschalter oben + Knopf unten). Links die
eigentliche Aktion in Gold (unverändert im bestehenden Marken-Look),
rechts der Wechsel in Babyblau — der zweiten Hausfarbe der Seite
(theme-dogfather.css). Beide Hälften nutzen dieselbe Technik wie die
bestehenden Gold-Knöpfe (wandernder Verlauf per background-position +
ein durchlaufender Glanzstreifen als ::after) — dadurch wirken sie wie
ein zusammengehöriges Paar statt wie zwei fremde Knöpfe.
Augenschonend (Projektregel): kein Blinken/Flackern, nur ruhig
wandernde Verläufe, und bei prefers-reduced-motion steht alles still.
===================================================================== */
.abo-aktionsleiste {
display: flex; gap: .6rem; margin-top: .4rem;
}
/* flex-basis "auto" statt "0": jede Hälfte startet bei ihrer eigenen
Textbreite und wächst dann anteilig mit. Dadurch bekommt automatisch
die Seite mit dem längeren Text mehr Platz — egal ob das gerade links
("Login-Code anfordern") oder rechts ("Schon registriert? Einloggen")
ist. Mit fester 0-Basis wären beide exakt gleich breit gewesen und der
jeweils längere Text wäre auf zwei Zeilen umgebrochen. */
.abo-aktionsleiste > button {
position: relative; isolation: isolate; overflow: hidden;
flex: 1 1 auto; min-width: 0;
display: flex; align-items: center; justify-content: center; text-align: center;
padding: 1rem .95rem; border-radius: 14px;
font-weight: 800; font-size: .92rem; line-height: 1.25;
white-space: nowrap;
cursor: pointer;
transition: transform .2s ease, box-shadow .2s ease;
}
.abo-aktionsleiste > button::after {
content: ""; position: absolute; inset: 0; z-index: 1;
background: linear-gradient(100deg, transparent 30%, rgba(255,255,255,.85) 48%, transparent 66%);
background-size: 240% 100%;
mix-blend-mode: overlay;
animation: abo-btn-glare 3.2s ease-in-out infinite;
pointer-events: none;
}
.abo-aktionsleiste > button:hover { transform: translateY(-3px) scale(1.015); }
/* Links: Gold — exakt die bestehende Knopf-Optik der Seite. */
.abo-aktion-haupt {
color: #1a1408;
border: 1.5px solid rgba(255,233,168,.65);
background: linear-gradient(120deg, #ffe9a8 0%, #d4af37 30%, #ffe9a8 55%, #fff2c9 78%, #d4af37 100%);
background-size: 280% 100%;
animation: abo-btn-shine 6s ease-in-out infinite;
box-shadow: 0 10px 26px -12px rgba(212,175,55,.55);
}
.abo-aktion-haupt:hover {
box-shadow: 0 16px 34px -10px rgba(212,175,55,.65), 0 0 26px rgba(212,175,55,.4);
}
/* Babyblau — gleiche Machart, kräftigeres Sky-Blau statt des sehr
blassen Standard-Babyblaus, damit es neben dem Gold nicht untergeht
(dieselbe Lektion wie auf der Verwaltungsseite). Dunkler Tiefsee-Text
darauf für klaren Kontrast; zusätzlich ein sanft atmender Ring, der die
Kachel leicht leuchten lässt, ohne zu blenden.
Zwei Namen, eine Optik: ".abo-aktion-neben" ist der Wechsel-Knopf neben
einer Gold-Aktion (Registrierungs-Seite), ".abo-aktion-blau" ist ein
Knopf, der selbst DIE Hauptaktion ist und trotzdem blau sein soll
(Einloggen-Seite, Nutzer-Wunsch 21.08.2026). Bewusst getrennte Namen,
damit später klar bleibt, warum ein Knopf blau ist. */
.abo-aktion-neben,
.abo-aktion-blau {
color: #05202b;
border: 1.5px solid rgba(224,247,254,.7);
background: linear-gradient(120deg, #e0f7fe 0%, #38bdf8 30%, #7dd3fc 55%, #f0fbff 78%, #38bdf8 100%);
background-size: 280% 100%;
animation: abo-btn-shine 6s ease-in-out infinite, abo-blau-atem 4.5s ease-in-out infinite;
box-shadow: 0 10px 26px -12px rgba(56,189,248,.6), 0 0 0 0 rgba(125,211,252,.5);
}
.abo-aktion-neben:hover,
.abo-aktion-blau:hover {
box-shadow: 0 16px 34px -10px rgba(56,189,248,.75), 0 0 30px rgba(125,211,252,.55);
}
@keyframes abo-blau-atem {
0%, 100% { box-shadow: 0 10px 26px -12px rgba(56,189,248,.55), 0 0 14px rgba(125,211,252,.25); }
50% { box-shadow: 0 12px 30px -12px rgba(56,189,248,.75), 0 0 26px rgba(125,211,252,.5); }
}
@media (prefers-reduced-motion: reduce) {
.abo-aktionsleiste > button,
.abo-aktionsleiste > button::after { animation: none; }
}
/* Auf schmalen Handys untereinander statt gequetscht nebeneinander. */
@media (max-width: 430px) {
.abo-aktionsleiste { flex-direction: column; gap: .55rem; }
.abo-aktionsleiste > button { font-size: .92rem; }
}
.abo-oder {
display: flex; align-items: center; gap: .8rem;
color: var(--text-muted); font-size: .78rem; text-transform: uppercase; letter-spacing: .08em;
@@ -321,62 +419,88 @@
korrekt "nicht bedienbar" meldet. -->
<div class="abo-field">
<label for="reg-name" data-i18n="ab_feld_name">Name oder Anzeigename</label>
<input type="text" id="reg-name" maxlength="60" disabled />
<input type="text" id="reg-name" maxlength="60" />
</div>
<div class="abo-field">
<label for="reg-tiktok" data-i18n="ab_feld_tiktok">TikTok-Benutzername</label>
<input type="text" id="reg-tiktok" placeholder="@benutzername" maxlength="40" disabled />
<input type="text" id="reg-tiktok" placeholder="@benutzername" maxlength="40" />
</div>
<div class="abo-field">
<label for="reg-email" data-i18n="ab_feld_email">E-Mail-Adresse</label>
<input type="email" id="reg-email" maxlength="120" disabled />
<input type="email" id="reg-email" maxlength="120" />
</div>
<!-- Eigener, dauerhafter Zugangscode (21.08.2026, Nutzer-Wunsch:
"die leute sollen nach der registrierung einen festen code
erstellen können für sich selbst und fertig, mit dem sie rein
kommen"). type="password" — der Code soll beim Tippen nicht
für Umstehende lesbar sein. -->
<!-- Beschriftung geschärft 21.08.2026 (Nutzer-Rückmeldung: "auf
dieser seite brauch man doch keine zugangsdaten, da kann man
sich ja noch nicht einloggen"). Genau dieser Eindruck entstand,
weil "Dein Zugangscode" wie die Abfrage eines BESTEHENDEN Codes
klang. Jetzt steht als Aufforderung im Text, dass man ihn sich
hier gerade ausdenkt — plus ein Platzhalter im Feld selbst, der
das nochmal zeigt, falls jemand nur auf die Felder schaut. -->
<div class="abo-field">
<label for="reg-code" data-i18n="ab_feld_code_neu">Denk dir jetzt deinen Zugangscode aus (mindestens 6 Zeichen)</label>
<input type="password" id="reg-code" maxlength="200" autocomplete="new-password"
placeholder="Frei wählbar — z. B. DogiCrew2026"
data-i18n-attr="placeholder:ab_feld_code_platzhalter" />
<p class="small muted" style="margin:.45rem 0 0;" data-i18n="ab_code_hinweis_neu">Mit diesem Code loggst du dich künftig ein — merk ihn dir gut.</p>
</div>
<!-- Nutzer-Wunsch 21.08.2026: "die leute sollen sich auch schon
registrieren können, aber der abo soll noch zu sein, da soll
dann coming soon stehen." Registrierung/Login sind ab jetzt
offen -- Konten können angelegt werden. Gesperrt bleibt NUR
noch der eigentliche Zahlungsschritt danach (siehe
panel-subscribe weiter unten), weil ohne Dogis echte PayPal-
Business-Zugangsdaten niemand wirklich zahlen kann. Wieder
normaler .btn-primary-Stil statt .btn-gold-locked. -->
<!-- Aktionsleiste (21.08.2026, Nutzer-Wunsch: "bringt nichts 2 mal
registrieren da zu haben"). EIN Element statt vorher Umschalter
oben + Knopf unten: links die eigentliche Aktion in Gold,
rechts der Wechsel zum Einloggen in Babyblau. Beide Hälften
sind immer aktiv (kein Tab-Zustand) — links macht etwas,
rechts wechselt die Ansicht. -->
<div class="abo-aktionsleiste">
<button type="button" class="abo-aktion-haupt" id="btn-register" data-i18n="ab_btn_register">Registrieren</button>
<button type="button" class="abo-aktion-neben" id="tab-login" data-i18n="ab_tab_login">Schon registriert? Einloggen</button>
</div>
<!-- Bugfix/Nutzer-Wunsch 20.08.2026: Die DogiCrew-Registrierung ist
technisch fertig, aber ohne Dogis echte PayPal-Business-Zugangsdaten
kann niemand wirklich zahlen (siehe DogFather Website - Offene
Punkte.md). Bis die stehen: Knopf bleibt sichtbar (Teaser, "soll
alles bleiben"), aber NICHT bedienbar — natives disabled-Attribut
(nicht nur optisch/pointer-events, damit es auch für Tastatur/
Screenreader korrekt gesperrt ist). main.js hängt weiterhin
unverändert einen Klick-Listener an dieselbe ID — disabled-Buttons
feuern in allen Browsern keine Click-Events, daher hier bewusst
KEINE JS-Änderung nötig. Eigener Gold/Schloss-Stil (.btn-gold-locked,
siehe main.css) statt des generischen .btn-silver, der auf dieser
Seite schon für die Teddy-Kollektion vergeben ist. -->
<button type="button" class="btn-gold-locked" style="width:100%;margin-top:.2rem;" id="btn-register"
disabled aria-disabled="true">
<span class="btn-gold-locked-lock" aria-hidden="true">🔒</span>
<span class="btn-gold-locked-text" data-i18n="ab_kollektion_coming_soon">Coming soon…</span>
</button>
<p class="abo-fehler" id="register-fehler"></p>
<p class="abo-switch"><a id="switch-to-login" data-i18n="ab_switch_login">Schon Supporter? Hier einloggen</a></p>
</div>
<!-- Zustand 3: Login (E-Mail-Code anfordern) -->
<!-- Bugfix/Nutzer-Wunsch 20.08.2026: War die einzige noch offene Lücke, nachdem
der Registrieren-Knopf gesperrt wurde — über "Schon Supporter? Hier
einloggen" kam man hierher und konnte trotzdem einen echten Login-Code
anfordern, obwohl die DogiCrew noch gar nicht live ist. Jetzt genauso
gesperrt: E-Mail-Feld disabled (nicht eintippbar, wie gewünscht), Knopf
derselbe .btn-gold-locked-Stil wie beim Registrieren-Knopf. Betrifft NUR
diesen öffentlichen Anmelde-Einstieg — bereits eingeloggte Supporter
(Dogi/VanVan als Test-Accounts) merken nichts davon, ihr Zugang läuft
weiterhin über den gespeicherten Token/supporter.html. -->
<!-- Zustand 3: Einloggen mit E-Mail + eigenem Zugangscode.
Umgestellt 21.08.2026 (Nutzer-Wunsch: "wieso sollte ich wieder
ein code bekommen, mach die anmeldung einfach"): vorher wurde
auch hier bei JEDEM Login erst ein Einmalcode per E-Mail
verschickt — für längst registrierte Leute ein völlig
unnötiger Umweg. Der E-Mail-Weg existiert weiterhin, aber nur
noch als "Code vergessen?" (siehe Link unten). -->
<div class="abo-panel" id="panel-login" hidden>
<div class="abo-field">
<label for="login-email" data-i18n="ab_feld_email">E-Mail-Adresse</label>
<input type="email" id="login-email" maxlength="120" disabled />
<input type="email" id="login-email" maxlength="120" autocomplete="email" />
</div>
<div class="abo-field">
<label for="login-code" data-i18n="ab_feld_code_eigen">Dein Zugangscode</label>
<input type="password" id="login-code" maxlength="200" autocomplete="current-password" />
</div>
<!-- Nutzer-Wunsch 21.08.2026: "da soll nur noch einloggen sein und
der knopf soll auch blau sein, der neu registriert soll weg."
Hier steht deshalb nur EIN Knopf, in Babyblau statt Gold —
wer auf dieser Ansicht gelandet ist, will einloggen; der Weg
zurück zur Registrierung führt über den Zurück-Knopf des
Browsers bzw. den blauen Knopf auf der Registrierungs-Seite. -->
<div class="abo-aktionsleiste">
<button type="button" class="abo-aktion-blau" id="btn-login" data-i18n="ab_btn_login">Einloggen</button>
</div>
<button type="button" class="btn-gold-locked" style="width:100%;margin-top:.2rem;" id="btn-login-request"
disabled aria-disabled="true">
<span class="btn-gold-locked-lock" aria-hidden="true">🔒</span>
<span class="btn-gold-locked-text" data-i18n="ab_kollektion_coming_soon">Coming soon…</span>
</button>
<p class="abo-fehler" id="login-fehler"></p>
<p class="abo-switch"><a id="switch-to-register" data-i18n="ab_switch_register">Noch kein Konto? Jetzt registrieren</a></p>
<p class="abo-switch"><a id="code-vergessen" data-i18n="ab_code_vergessen">Code vergessen?</a></p>
</div>
<!-- Zustand 4: Code-Eingabe (nach Registrierung ODER Login-Anfrage) -->
<!-- Zustand 4: Einmalcode aus der E-Mail eingeben. Kommt seit
21.08.2026 NUR noch im "Code vergessen?"-Weg vor — die normale
Registrierung/Anmeldung braucht ihn nicht mehr. -->
<div class="abo-panel" id="panel-code" hidden>
<p class="small" id="code-hinweis" data-i18n="ab_code_hinweis">Wir haben dir einen 6-stelligen Code per E-Mail geschickt.</p>
<div class="abo-field">
@@ -387,6 +511,20 @@
<p class="abo-fehler" id="code-fehler"></p>
</div>
<!-- Zustand 4b: neuen dauerhaften Zugangscode festlegen. Letzter
Schritt des "Code vergessen?"-Weges — an dieser Stelle ist man
durch den Einmalcode bereits eingeloggt, es fehlt nur noch der
neue Code für künftige Anmeldungen. -->
<div class="abo-panel" id="panel-neuer-code" hidden>
<p class="small" data-i18n="ab_neuer_code_hinweis">Fast fertig — leg jetzt deinen neuen Zugangscode fest.</p>
<div class="abo-field">
<label for="neuer-code" data-i18n="ab_feld_code_neu">Dein Zugangscode (mindestens 6 Zeichen)</label>
<input type="password" id="neuer-code" maxlength="200" autocomplete="new-password" />
</div>
<button type="button" class="btn btn-primary" style="width:100%;" id="btn-neuer-code" data-i18n="ab_btn_code_speichern">Zugangscode speichern</button>
<p class="abo-fehler" id="neuer-code-fehler"></p>
</div>
<!-- Zustand 5: eingeloggt, noch kein Abo -> PayPal Smart Buttons.
Zeigt automatisch alle für die Käuferin/den Käufer verfügbaren
Zahlarten (PayPal-Konto, Kreditkarte als Gast, je nach Land) —
@@ -394,24 +532,45 @@
<div class="abo-panel" id="panel-subscribe" hidden>
<p class="abo-erfolg zeige" data-i18n="ab_eingeloggt_als">Eingeloggt.</p>
<!-- Button-Lösung (§ 312j BGB / entspr. Regelung): Preis- und
Zahlungspflicht-Hinweis unmittelbar vor der Zahlung. -->
<p class="small" style="text-align:center;font-weight:700;margin-bottom:.8rem;">4,99 € / Monat · zahlungspflichtiges Abo · monatlich kündbar</p>
<!-- Nutzer-Wunsch 21.08.2026: "die leute sollen sich schon registrieren
können, aber der abo soll noch zu sein, da soll dann coming soon
stehen." Konto ist angelegt/Login hat geklappt -- aber die eigent-
liche Zahlung (PayPal) bleibt gesperrt, bis Dogis echte PayPal-
Business-Zugangsdaten stehen. Die echten Zahlungs-Elemente (Preis-
Hinweis, Widerrufs-Checkbox, PayPal-Container) bleiben unten UNVER-
ÄNDERT im DOM (nur per hidden versteckt), damit das Skript weiter
unten (Checkbox-Listener, ladePaypalButtons() usw.) unangetastet
funktioniert -- einfach das hidden am Wrapper unten entfernen,
sobald PayPal bereitsteht. -->
<div class="btn-gold-locked" style="width:100%;margin-top:.4rem;cursor:default;">
<span class="btn-gold-locked-lock" aria-hidden="true">🔒</span>
<span class="btn-gold-locked-text" data-i18n="ab_kollektion_coming_soon">Coming soon…</span>
</div>
<p class="small muted" style="text-align:center;margin-top:.9rem;" data-i18n="ab_subscribe_locked_hinweis">Dein Konto ist bereit — die Bezahlung startet, sobald das Abo offiziell live geht. Schau einfach bald wieder vorbei.</p>
<!-- Widerrufsrecht bei digitalen Inhalten (§ 356 Abs. 5 BGB /
entspr. Regelung, siehe agb.html Ziffer 6): ohne aktives
Ankreuzen bleibt der Zahlungsbereich gesperrt, es gibt keine
Zahlung ohne diese ausdrückliche, nicht vorausgewählte
Zustimmung. -->
<label class="abo-widerruf-check" for="widerruf-consent">
<input type="checkbox" id="widerruf-consent" />
<span>Ich wünsche ausdrücklich, dass der Zugang zum Supporter-Bereich sofort mit Vertragsschluss beginnt, und weiß, dass mein 14-tägiges Widerrufsrecht dadurch erlischt, sobald der Zugang vollständig bereitgestellt ist (Details in den <a href="agb.html" target="_blank" rel="noopener">AGB</a>, Ziffer 6).</span>
</label>
<!-- Nutzer-Wunsch 21.08.2026: "ich will dass jetzt alles verbunden
ist so dass man mit den klicks pro klick weiter kommt" — vorher
war hier eine Sackgasse (kein Link/Knopf mehr nach dem Login).
Jetzt zwei klare Wege weiter: zurück zur Startseite, oder
direkt zum Streamplan (naheliegendster nächster Klick für
jemanden, der sich gerade für Dogi interessiert). -->
<div class="btn-row" style="justify-content:center;margin-top:1.4rem;">
<a class="btn btn-outline" href="index.html" data-i18n="ab_weiter_startseite">Zur Startseite →</a>
<a class="btn btn-outline" href="streamplan.html" data-i18n="ab_weiter_streamplan">Zum Streamplan →</a>
</div>
<div id="paypal-button-container" class="paypal-gesperrt"></div>
<p class="small muted" id="paypal-gesperrt-hinweis">Bitte bestätige oben die Checkbox, um die Zahlungsoptionen freizuschalten.</p>
<p class="small" id="paypal-laedt" data-i18n="ab_paypal_laedt" hidden>Zahlungsoptionen werden geladen …</p>
<p class="abo-fehler" id="subscribe-fehler"></p>
<div hidden>
<p class="small" style="text-align:center;font-weight:700;margin-bottom:.8rem;">4,99 € / Monat · zahlungspflichtiges Abo · monatlich kündbar</p>
<label class="abo-widerruf-check" for="widerruf-consent">
<input type="checkbox" id="widerruf-consent" />
<span>Ich wünsche ausdrücklich, dass der Zugang zum Supporter-Bereich sofort mit Vertragsschluss beginnt, und weiß, dass mein 14-tägiges Widerrufsrecht dadurch erlischt, sobald der Zugang vollständig bereitgestellt ist (Details in den <a href="agb.html" target="_blank" rel="noopener">AGB</a>, Ziffer 6).</span>
</label>
<div id="paypal-button-container" class="paypal-gesperrt"></div>
<p class="small muted" id="paypal-gesperrt-hinweis">Bitte bestätige oben die Checkbox, um die Zahlungsoptionen freizuschalten.</p>
<p class="small" id="paypal-laedt" data-i18n="ab_paypal_laedt" hidden>Zahlungsoptionen werden geladen …</p>
<p class="abo-fehler" id="subscribe-fehler"></p>
</div>
</div>
<!-- Zustand 6: bereits Supporter -->
@@ -460,7 +619,7 @@
<script>
(function () {
const S = window.DogiSupporter;
const panels = ["panel-lade", "panel-register", "panel-login", "panel-code", "panel-subscribe", "panel-already"];
const panels = ["panel-lade", "panel-register", "panel-login", "panel-code", "panel-neuer-code", "panel-subscribe", "panel-already"];
// panel-social-login (Google-Button) hängt sich an register/login dran,
// ist aber kein "richtiger" exklusiver Zustand — separat gesteuert.
const SOCIAL_LOGIN_PANELS = ["panel-register", "panel-login"];
@@ -498,7 +657,9 @@
el.classList.remove("zeige");
}
let codePurpose = "verify_email"; // oder "login"
// Merkt sich die E-Mail-Adresse zwischen "Code vergessen?" und der
// Eingabe des Einmalcodes (der frühere codePurpose-Schalter entfiel mit
// der Umstellung 21.08.2026 — es gibt nur noch diesen einen Code-Weg).
let codeEmail = "";
async function pruefeStatus() {
@@ -511,11 +672,24 @@
const status = data.subscription?.status || "none";
S.cacheSubStatus(status);
S.cacheDisplayName(data.profile?.displayName || "");
if (["active", "pending", "suspended", "cancelled"].includes(status)) {
zeige("panel-already");
} else {
zeige("panel-subscribe");
}
/* Nutzer-Wunsch 21.08.2026: "anstatt das was du jetzt auf dem screen
siehst, sollen die leute nicht mehr sehen wenn sie angemeldet sind.
sie sollen die richtige seite sehen die wir schon mal vorbereitet
hatten, wo sie ihre persönliche daten sehen und so."
Wer eingeloggt ist, gehört nicht mehr auf diese Anmeldeseite —
egal ob mit oder ohne bezahltes Abo. supporter.html zeigt in BEIDEN
Fällen das Richtige: persönliche Daten, Fortschritt mit allen
Prämien-Meilensteinen, Sammlungsarchiv, Profil bearbeiten,
Ausloggen — bei "kein Abo" eben mit entsprechendem Hinweis statt
echter Laufzeit. Vorher landete man hier stattdessen in einer
Sackgasse ("Coming soon…"), ohne je die eigentliche Seite zu sehen.
replace() statt href: die Anmeldeseite verschwindet damit aus dem
Verlauf — ein "Zurück" führt sonst sofort wieder hierher und von
hier wieder weiter, was sich wie eine Schleife anfühlt. */
location.replace("supporter.html");
return;
} catch (err) {
// Token ungültig/abgelaufen -> zurück zur Registrierung/Login
S.clearToken();
@@ -628,8 +802,10 @@
ladeHinweis.hidden = true;
}
document.getElementById("switch-to-login").addEventListener("click", () => zeige("panel-login"));
document.getElementById("switch-to-register").addEventListener("click", () => zeige("panel-register"));
// Der frühere Gegenstück-Knopf "Neu registrieren" auf der Einloggen-Seite
// wurde am 21.08.2026 auf Wunsch entfernt — deshalb hier nur noch der eine
// Wechsel von der Registrierung zum Einloggen.
document.getElementById("tab-login").addEventListener("click", () => zeige("panel-login"));
// Widerrufsrecht-Checkbox: erst nach aktivem Ankreuzen werden die
// PayPal-Zahlungsoptionen überhaupt geladen/klickbar (siehe agb.html
@@ -656,25 +832,44 @@
const displayName = document.getElementById("reg-name").value.trim();
const tiktokUsername = document.getElementById("reg-tiktok").value.trim();
const email = document.getElementById("reg-email").value.trim();
const accessCode = document.getElementById("reg-code").value;
if (!displayName || !email) return fehlerZeigen(el, "Bitte Name und E-Mail-Adresse angeben.");
if (!accessCode) return fehlerZeigen(el, "Bitte leg einen Zugangscode fest.");
try {
await S.apiFetch("/supporter/register", { displayName, tiktokUsername, email });
codePurpose = "verify_email";
codeEmail = email;
zeige("panel-code");
// Seit 21.08.2026 liefert /supporter/register direkt ein Token zurück —
// kein Bestätigungscode per E-Mail mehr dazwischen, man ist sofort drin.
const data = await S.apiFetch("/supporter/register", { displayName, tiktokUsername, email, accessCode });
S.setToken(data.token);
await pruefeStatus();
} catch (err) {
fehlerZeigen(el, err.message);
}
});
document.getElementById("btn-login-request").addEventListener("click", async () => {
// Normale Anmeldung: E-Mail + eigener Zugangscode, ohne Umweg über E-Mail.
document.getElementById("btn-login").addEventListener("click", async () => {
const el = document.getElementById("login-fehler");
fehlerVerstecken(el);
const email = document.getElementById("login-email").value.trim();
if (!email) return fehlerZeigen(el, "Bitte E-Mail-Adresse angeben.");
const accessCode = document.getElementById("login-code").value;
if (!email || !accessCode) return fehlerZeigen(el, "Bitte E-Mail-Adresse und Zugangscode eingeben.");
try {
const data = await S.apiFetch("/supporter/login-code", { email, accessCode });
S.setToken(data.token);
await pruefeStatus();
} catch (err) {
fehlerZeigen(el, err.message);
}
});
// "Code vergessen?" — hier lebt der alte E-Mail-Einmalcode-Weg weiter.
document.getElementById("code-vergessen").addEventListener("click", async () => {
const el = document.getElementById("login-fehler");
fehlerVerstecken(el);
const email = document.getElementById("login-email").value.trim();
if (!email) return fehlerZeigen(el, "Bitte zuerst deine E-Mail-Adresse eingeben.");
try {
await S.apiFetch("/supporter/login-request", { email });
codePurpose = "login";
codeEmail = email;
zeige("panel-code");
} catch (err) {
@@ -688,9 +883,22 @@
const code = document.getElementById("code-input").value.trim();
if (!code) return fehlerZeigen(el, "Bitte Code eingeben.");
try {
const path = codePurpose === "login" ? "/supporter/verify-login" : "/supporter/verify-email";
const data = await S.apiFetch(path, { email: codeEmail, code });
const data = await S.apiFetch("/supporter/verify-login", { email: codeEmail, code });
S.setToken(data.token);
// Eingeloggt — jetzt fehlt nur noch der neue dauerhafte Zugangscode.
zeige("panel-neuer-code");
} catch (err) {
fehlerZeigen(el, err.message);
}
});
document.getElementById("btn-neuer-code").addEventListener("click", async () => {
const el = document.getElementById("neuer-code-fehler");
fehlerVerstecken(el);
const accessCode = document.getElementById("neuer-code").value;
if (!accessCode) return fehlerZeigen(el, "Bitte leg einen Zugangscode fest.");
try {
await S.apiFetch("/supporter/set-access-code", { accessCode }, true);
await pruefeStatus();
} catch (err) {
fehlerZeigen(el, err.message);
@@ -705,15 +913,13 @@
} catch {
/* Konfiguration konnte nicht geladen werden — Google-Button/PayPal-Buttons bleiben dann aus. */
}
/* Bugfix/Nutzer-Wunsch 20.08.2026: "Mit Google anmelden" wäre ein dritter, bisher
übersehener Weg gewesen, trotz gesperrtem Registrieren-/Login-Knopf doch ein
echtes Konto anzulegen bzw. sich einzuloggen (falls GOOGLE_CLIENT_ID auf dem
Server konfiguriert ist). initGoogleConsent() daher bewusst NICHT mehr
aufgerufen, solange die DogiCrew-Registrierung gesperrt ist — panel-social-login
bleibt dadurch dauerhaft hidden. Einfach diesen Aufruf wieder aktivieren,
sobald die Registrierung selbst (btn-register/btn-login-request, siehe oben)
entsperrt wird. */
// initGoogleConsent();
/* Bugfix 20.08.2026, wieder aktiviert 21.08.2026: "Mit Google anmelden" war ein
dritter, bisher übersehener Weg, trotz gesperrtem Registrieren-/Login-Knopf
doch ein echtes Konto anzulegen bzw. sich einzuloggen. War deshalb deaktiviert,
solange die Registrierung selbst gesperrt war. Registrierung ist jetzt (Nutzer-
Wunsch 21.08.2026) bewusst offen -- Google-Login ist nur ein weiterer,
gleichwertiger Weg zum selben jetzt erlaubten Ziel, kein Schlupfloch mehr. */
initGoogleConsent();
await pruefeStatus();
}