Nutzer-Wunsch 21.08.2026: "wenn ich eine änderung mache ist es auch für
jeden für die die schon da sind und die neuen" + "ich will ich titel
und namen von kategorien und seiten ändern können in der verwaltung".
Backend (braucht Filipes manuellen Deploy):
- Migration 0008: team_members bekommt intro/bioHtml/extraCta-Spalten
-- volle Feld-Parität mit den von Hand gepflegten Profilen (Diene/
Patrick/Bananenstift/Marina nutzen diese Felder).
- routes/team.js: neue importLegacyMember()-Funktion -- übernimmt ein
bestehendes Profil 1:1 in die Datenbank, OHNE erneut zu übersetzen
(die vorhandenen, von Hand geschriebenen Übersetzungen bleiben
erhalten). Idempotent: mehrfacher Import erzeugt keine Duplikate.
- routes/site-texts.js (neu): admin-editierbare Kategorie-Namen und
Seitentitel, generischer key->{de,...}-Override über app_settings
(wie "Event des Jahres"), fester Schlüssel-Katalog aus
Sicherheitsgründen. Leeres Feld setzt auf den Standardtext zurück.
- 27 Tests in isolierter Testumgebung geprüft (kein better-sqlite3
lokal kompilierbar).
Frontend:
- window.dogiTeamZusammenfuehren() (main.js): admin-Mitglieder
ÜBERSCHREIBEN jetzt gleichnamige statische Einträge (per slug) statt
sie zu duplizieren -- eine Bearbeitung wirkt dadurch für alle.
- window.dogiSiteTexteLaden() + applyTranslations() erweitert um
data-site-text-key -- Kategorie-Seitentitel (team-modis.html/
team-scouts.html/creator.html/manager.html) sind jetzt live editierbar.
- Verwaltung: "📥 Bestehende Mitglieder importieren"-Knopf (holt VanVan/
Diene/Funny/Miss/Marina/Ghost/Patrick/Bananenstift aus den data-*.js-
Dateien, VanVan bewusst ausgenommen -- eigene Sonderkarte + Seite),
erweitertes Formular (Intro/ausführliche Vorstellung/zweiter Button,
eingeklappt unter "Erweitert"), neue Sektion "Kategorien &
Seitentitel" (4 Karten, sofort wirksam auf Website UND Verwaltung).
Beim Testen einen echten UX-Bug gefunden und gefixt: die "Gespeichert"-
Meldung nach dem Speichern eines Mitglieds wurde von der direkt
anschließenden Formular-Zurücksetzung sofort wieder überschrieben und
war nie sichtbar.
Cache-Busting-Version auf 20260821k erhöht.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
113 lines
4.9 KiB
HTML
113 lines
4.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de" data-theme="dogfather">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Aktion — DOGFATHER UNIVERSE</title>
|
|
<meta name="description" content="Detailansicht einer Aktion oder eines Projekts von Team Dogi." />
|
|
<link rel="icon" type="image/png" href="assets/img/favicon.png" />
|
|
<link rel="manifest" href="/manifest.json" />
|
|
<meta name="theme-color" content="#0b0d10" />
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:site_name" content="DOGFATHER UNIVERSE" />
|
|
<meta property="og:title" content="Aktion — DOGFATHER UNIVERSE" />
|
|
<meta property="og:description" content="Detailansicht einer Aktion oder eines Projekts von Team Dogi." />
|
|
<meta property="og:image" content="https://dogfather-universe.com/assets/img/og-cover.jpg" />
|
|
<meta property="og:url" content="https://dogfather-universe.com/aktion-detail.html" />
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta name="twitter:title" content="Aktion — DOGFATHER UNIVERSE" />
|
|
<meta name="twitter:description" content="Detailansicht einer Aktion oder eines Projekts von Team Dogi." />
|
|
<meta name="twitter:image" content="https://dogfather-universe.com/assets/img/og-cover.jpg" />
|
|
|
|
<link rel="stylesheet" href="assets/css/main.css?v=20260821k" />
|
|
<link rel="stylesheet" href="assets/css/theme-dogfather.css?v=20260821k" />
|
|
<link rel="stylesheet" href="assets/css/theme-hasidog.css?v=20260821k" />
|
|
<link rel="stylesheet" href="assets/css/theme-spicymedia.css?v=20260821k" />
|
|
</head>
|
|
<body>
|
|
<div id="site-header"></div>
|
|
|
|
<main>
|
|
<section class="hero">
|
|
<div class="container">
|
|
<span class="eyebrow" data-i18n="ad_eyebrow">Aktionen & Projekte</span>
|
|
<h1 id="aktion-title" data-i18n="ad_loading">Aktion wird geladen …</h1>
|
|
<p class="lead worlds" id="aktion-summary"></p>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="section-tight">
|
|
<div class="container grid grid-2" style="align-items:center;">
|
|
<div class="img-placeholder" id="aktion-photo" style="aspect-ratio:4/3;" data-i18n="ad_foto_placeholder">Foto folgt</div>
|
|
<div id="aktion-body"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="container text-center">
|
|
<a class="btn btn-outline" id="aktion-back" data-i18n="ad_back" href="medien-dogfather.html#events">← Zurück zu allen Events</a>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<div id="site-footer"></div>
|
|
<script src="assets/js/data-aktionen.js?v=20260821k"></script>
|
|
<script src="assets/js/i18n-aktion-detail.js?v=20260821k"></script>
|
|
<script src="assets/js/main.js?v=20260821k"></script>
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const params = new URLSearchParams(location.search);
|
|
const id = params.get("id");
|
|
const aktion = (window.AKTIONEN || []).find((a) => a.id === id);
|
|
|
|
const titleEl = document.getElementById("aktion-title");
|
|
const summaryEl = document.getElementById("aktion-summary");
|
|
const bodyEl = document.getElementById("aktion-body");
|
|
const photoEl = document.getElementById("aktion-photo");
|
|
const backEl = document.getElementById("aktion-back");
|
|
|
|
const t = (schluessel) => (window.dogiUebersetzen ? window.dogiUebersetzen(schluessel) : schluessel);
|
|
|
|
if (!aktion) {
|
|
// Diese Aktion existiert nicht — Texte kommen (auch bei Sprachwechsel)
|
|
// aus dem seiteneigenen i18n-Wörterbuch statt aus data-i18n, weil sie
|
|
// per JS gesetzt werden.
|
|
titleEl.removeAttribute("data-i18n");
|
|
const renderNichtGefunden = () => {
|
|
titleEl.textContent = t("ad_notfound_title");
|
|
summaryEl.textContent = t("ad_notfound_summary");
|
|
bodyEl.innerHTML = `<p>${t("ad_notfound_body")}</p>`;
|
|
};
|
|
renderNichtGefunden();
|
|
document.addEventListener("dogi-sprache-geaendert", renderNichtGefunden);
|
|
return;
|
|
}
|
|
|
|
// Zurück-Button zeigt auf die Events-Sektion der passenden Welt
|
|
// (jede Aktion gehört zu DogFather/HasiDog/Casper, siehe data-aktionen.js).
|
|
const welt = ["dogfather", "hasidog", "casper"].includes(aktion.welt) ? aktion.welt : "dogfather";
|
|
if (backEl) backEl.href = `medien-${welt}.html#events`;
|
|
|
|
// Titel/Zusammenfassung kommen aus data-aktionen.js (nicht Teil dieser
|
|
// i18n-Aufgabe) — data-i18n-Attribut entfernen, damit ein Sprachwechsel
|
|
// den geladenen Titel nicht wieder mit dem Lade-Platzhalter überschreibt.
|
|
titleEl.removeAttribute("data-i18n");
|
|
titleEl.textContent = aktion.title;
|
|
summaryEl.textContent = aktion.summary;
|
|
bodyEl.innerHTML = `
|
|
<span class="badge rank-1">${aktion.tag} · ${aktion.status}</span>
|
|
${aktion.description.map((p) => `<p>${p}</p>`).join("")}
|
|
`;
|
|
if (aktion.photo) {
|
|
photoEl.outerHTML = `<img src="${aktion.photo}" alt="${aktion.title}" style="border-radius:var(--radius);" />`;
|
|
} else {
|
|
photoEl.removeAttribute("data-i18n");
|
|
const renderFotoKuerze = () => { photoEl.innerHTML = t("ad_foto_kurze"); };
|
|
renderFotoKuerze();
|
|
document.addEventListener("dogi-sprache-geaendert", renderFotoKuerze);
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|