Files
dogfather-universe/assets/js/stimmen.js
T
DogFatherGitandClaude Opus 5 1f87b54351 Nav umbenannt/umsortiert + Stimmen-Kachel und Zitat-Karten aufgewertet
Nutzer-Wuensche 20.08.2026 (2. Runde):
- Kategorie "DogFather" -> "Filipe", Kategorie "HasiDog" -> "Dogi&Hasi".
- Unterpunkt "Streamer" (streamer.html) aus "Filipe" heraus nach
  "Dogi&Hasi" verschoben, dort GANZ NACH OBEN (ueber "HasiDog") und in
  "DogFather" umbenannt.
- Unterpunkt "HasiDog-Welt" -> "HasiDog".
- Fusszeile zieht mit: Spaltenueberschrift nutzt jetzt dieselbe
  Kategorie-Bezeichnung wie die Nav ("Filipe" / "Dogi&Hasi & Manager"),
  streamer.html steht dort ebenfalls in der Dogi&Hasi-Spalte ganz oben.
  Die internen Schluesselnamen (nav_dogfather...) bleiben bewusst
  unveraendert -- reine Bezeichner, ein Umbenennen waere nur Fehlerquelle.

- "die kachel soll noch spezieller und geiler aussehen": Einreich-Kachel
  auf stimmen.html deutlich aufgewertet -- wandernder Farbverlauf-Rahmen
  (Zwei-Ebenen-/background-position-Technik, KEIN rotierender Ring: siehe
  dokumentierte Projekt-Lektion zu Verzerrungen auf eckigen Flaechen),
  schwebende Herz-Partikel, Medaillon statt nacktem Emoji,
  Farbverlauf-Ueberschrift, aufleuchtende Eingabefelder.
- "und auch die die danach kommen ... sollen viel geiler sein": freigegebene
  Stimmen sind jetzt echte Praesentationskarten -- farbige Akzentlinie oben,
  grosses Anfuehrungszeichen als Wasserzeichen, Avatar-Medaillon mit
  Anfangsbuchstabe, TikTok-Handle als eigener Chip, sanftes Anheben beim
  Ueberfahren.

Alles augenschonend gehalten (gedeckte Toene, langsame Bewegungen,
vollstaendiger Stillstand bei prefers-reduced-motion) und per Playwright
visuell geprueft, keine JS-Fehler.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-21 01:02:36 +02:00

94 lines
4.1 KiB
JavaScript

/* =====================================================================
stimmen.js — NUR für stimmen.html (20.08.2026, Nutzer-Wunsch: "eine
richtig geile kachel ... wo die leute mit namen und tiktok namen mir
eine nachricht schreiben können die ich in die verwaltung kriege").
Formular schickt eine Einreichung ab (landet als Entwurf, siehe
server-internal/routes/testimonials.js), zweiter Teil lädt die bereits
freigegebenen Stimmen und zeigt sie an — bleibt komplett unsichtbar,
solange keine einzige freigegeben wurde. ===================================================================== */
(function () {
const API_BASE_URL = "https://postfach.dogfather-universe.com";
const formular = document.getElementById("stimmen-formular");
if (formular) {
const erfolgEl = document.getElementById("stimmen-erfolg");
const fehlerEl = document.getElementById("stimmen-fehler");
formular.addEventListener("submit", async (e) => {
e.preventDefault();
erfolgEl.classList.remove("zeige");
fehlerEl.classList.remove("zeige");
const name = document.getElementById("st-name").value.trim();
const tiktokUsername = document.getElementById("st-tiktok").value.trim();
const nachricht = document.getElementById("st-nachricht").value.trim();
const absendenBtn = formular.querySelector("button[type=submit]");
absendenBtn.disabled = true;
try {
const res = await fetch(`${API_BASE_URL}/testimonials/submit`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name, tiktokUsername, nachricht }),
});
const data = await res.json();
if (!data.ok) {
fehlerEl.textContent = data.error || "Einreichen hat leider nicht geklappt. Bitte versuch es nochmal.";
fehlerEl.classList.add("zeige");
return;
}
formular.hidden = true;
erfolgEl.classList.add("zeige");
} catch {
fehlerEl.textContent = "Verbindung zum Server fehlgeschlagen. Bitte versuch es nochmal.";
fehlerEl.classList.add("zeige");
} finally {
absendenBtn.disabled = false;
}
});
}
function escapeHtml(text) {
return String(text ?? "").replace(/[&<>"']/g, (z) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[z]));
}
/* Erstes sichtbares Zeichen des Namens fürs Avatar-Medaillon. [...name]
statt name[0], damit auch Namen, die mit einem Emoji beginnen, nicht
mitten in einem Zeichen abgeschnitten werden (ein Emoji besteht in
JavaScript aus mehreren "Zeichen" — name[0] lieferte sonst nur ein
kaputtes Halb-Zeichen). */
function erstesZeichen(name) {
const zeichen = [...String(name || "").trim()];
return zeichen.length ? zeichen[0].toUpperCase() : "?";
}
function ladeEchteStimmen() {
fetch(`${API_BASE_URL}/testimonials`, { cache: "no-store" })
.then((res) => res.json())
.then((data) => {
const liste = data && data.ok ? data.testimonials : [];
if (!liste.length) return; // Abschnitt bleibt hidden, kein Platzhalter mehr
const root = document.getElementById("stimmen-echte-root");
const grid = document.getElementById("stimmen-echte-grid");
grid.innerHTML = liste
.map(
(t) => `<div class="stimmen-karte">
<p class="stimmen-karte-text">${escapeHtml(t.nachricht)}</p>
<div class="stimmen-karte-fuss">
<span class="stimmen-karte-avatar" aria-hidden="true">${escapeHtml(erstesZeichen(t.name))}</span>
<span class="stimmen-karte-namen">
<span class="stimmen-karte-name">${escapeHtml(t.name)}</span>
${t.tiktokUsername ? `<span class="stimmen-karte-tiktok">@${escapeHtml(t.tiktokUsername)}</span>` : ""}
</span>
</div>
</div>`
)
.join("");
root.hidden = false;
})
.catch(() => {
/* Abschnitt bleibt einfach unsichtbar -- kein Fehler nötig. */
});
}
ladeEchteStimmen();
})();