Files
dogfather-universe/team-modis.html
T
DogFatherGitandClaude Sonnet 5 81f55d67db Team-Verwaltung Runde 2: bestehende Mitglieder importieren + Kategorien/Seitentitel editierbar
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]>
2026-08-21 03:47:51 +02:00

152 lines
8.2 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>Modi-Team — DOGFATHER UNIVERSE</title>
<meta name="description" content="VanVan, Diene, Funny, Miss und Marina — das Modi-/Core-Team 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="Modi-Team — DOGFATHER UNIVERSE" />
<meta property="og:description" content="VanVan, Diene, Funny, Miss und Marina — das Modi-/Core-Team 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/team-modis.html" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Modi-Team — DOGFATHER UNIVERSE" />
<meta name="twitter:description" content="VanVan, Diene, Funny, Miss und Marina — das Modi-/Core-Team 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 class="mit-hintergrund" style="--page-bg:url('/assets/img/bg-dogfather.jpg');--page-bg-mobile:url('/assets/img/bg-dogfather-mobile.jpg');">
<div id="site-header"></div>
<main>
<section class="hero page-bg">
<div class="hero-banner"><img src="/assets/img/bg-dogfather.jpg" alt="" loading="eager" /></div>
<div class="container">
<span class="eyebrow" data-i18n="tm_eyebrow">🩵 Team Dogi</span>
<h1 data-i18n="tm_h1" data-site-text-key="seitentitel_modi">Das Modi-Team</h1>
<p class="lead worlds" data-i18n="tm_lead">Das Rückgrat von Team Dogi — von VanVan bis Marina.</p>
<!-- TikTok-Account der Modi-Gang (Nutzer-Wunsch 20.08.2026, umgezogen 21.08.2026 von
streamer.html hierher: "in die modie seite zu den modis hinzufügen"). Passt hier
thematisch besser hin, weil der Account das ganze Modi-Team repräsentiert. -->
<div class="btn-row" style="justify-content:center;">
<a class="btn-tiktok" href="https://www.tiktok.com/@dogis.modi.gang" target="_blank" rel="noopener"><span class="btn-tiktok-note" aria-hidden="true">♪</span><span class="btn-tiktok-text" data-i18n="tm_btn_tiktok_modigang">Zur Modi-Gang TikTok-Seite</span></a>
</div>
</div>
</section>
<section class="section-tight">
<div class="container">
<div class="card" style="margin-bottom:2rem;">
<span class="tag" data-i18n="tm_tag_hervorgehoben">Hervorgehoben</span>
<div class="grid grid-2" style="align-items:center;">
<div>
<h2 style="margin-bottom:.3rem;">VanVan 🩵</h2>
<p class="muted" data-i18n="tm_vanvan_rolle">Rechte Hand von DogFather · Musik-Produzentin</p>
<p data-i18n="tm_vanvan_bio">VanVan ist nicht nur die rechte Hand von DogFather, sondern auch Super Super Sekretärin. Sie bekommt täglich alle Neuigkeiten und Aufgaben und delegiert oder organisiert gemeinsam mit Diene.</p>
<a class="btn btn-primary" href="vanvan.html" data-i18n="tm_vanvan_btn">VanVans exklusive Seite →</a>
</div>
<div class="collage-photo" style="aspect-ratio:1/1;border-radius:var(--radius);">
<img src="assets/img/card-vanvan-team.jpg" alt="VanVan" style="width:100%;height:100%;object-fit:cover;" />
</div>
</div>
</div>
<h2 class="text-center" data-i18n="tm_hierarchie_h2">Team-Hierarchie</h2>
<div id="modis-grid" class="pyramid"></div>
<!-- TODO: Hinweis: Reihenfolge/Rollen basieren auf: VanVan (rechte Hand) → Diene (rechte Hand von VanVan) → Funny (Modi) → Miss (Modi + Cutterin) → Marina (Clip-Account-Kommentare). Änderungen einfach in assets/js/data-modis.js pflegen. -->
<div class="btn-row" style="justify-content:center;">
<a class="btn btn-primary" href="bewerben-modi.html" data-i18n="tm_bewerben_btn">Als Modi bewerben 🩵</a>
</div>
</div>
</section>
</main>
<div id="site-footer"></div>
<script src="assets/js/data-modis.js?v=20260821k"></script>
<script src="assets/js/i18n-team-modis.js?v=20260821k"></script>
<script src="assets/js/main.js?v=20260821k"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
const grid = document.getElementById("modis-grid");
if (!grid || !window.MODIS) return;
const feld = (x) => (window.dogiFeld ? window.dogiFeld(x) : x || "");
const t = (schluessel) => (window.dogiUebersetzen ? window.dogiUebersetzen(schluessel) : schluessel);
const MAX_STUFEN = 5; // fünf definierte Größenstufen im CSS
// 21.08.2026: rest/raenge werden jetzt INNERHALB von renderModis() frisch aus
// window.MODIS berechnet (statt einmalig beim Setup) -- nötig, damit über die
// Verwaltung nachträglich angehängte Modis (siehe dogiTeamLaden weiter unten)
// beim erneuten Aufruf von renderModis() tatsächlich mit auftauchen. Ein
// admin-gepflegter Modi ohne eigenen Rang fällt dabei (?? 999) ganz ans Ende
// der Pyramide, statt die Sortierung der bestehenden Ränge durcheinander zu
// bringen.
const renderModis = () => {
const rest = window.MODIS.filter((m) => m.name !== "VanVan").sort((a, b) => (a.rank ?? 999) - (b.rank ?? 999));
// Pyramide: eine Ebene pro eindeutigem Rang, oben schmal/groß, nach
// unten breiter/kompakter — genau wie ein Organigramm.
const raenge = [...new Set(rest.map((m) => m.rank))];
grid.innerHTML = raenge
.map((rang, i) => {
const stufe = Math.min(i + 1, MAX_STUFEN);
const personen = rest.filter((m) => m.rank === rang);
const karten = personen
.map((m) => {
const profilLink = m.page || `profil.html?p=${m.slug}`;
const kartenInhalt = `
<div class="avatar">${(m.avatar || m.photo) ? `<img src="${m.avatar || m.photo}" alt="${m.name}" loading="lazy">` : `<span class="avatar-initial">${m.name.charAt(0).toUpperCase()}</span>`}</div>
<span class="badge" style="margin-bottom:.5rem;">${t("tm_stufe_prefix")} ${feld(m.rankLabel) || m.rank}</span>
<h3>${m.name}</h3>
<div class="role">${feld(m.role)}</div>
<span class="btn btn-outline" style="pointer-events:none;">${t("tm_profil_ansehen")}</span>`;
// Optionaler zweiter Button pro Person (aktuell nur Marina →
// manager.html, siehe extraCta in data-modis.js). Eigene
// <div>-Karte statt <a>, weil ein zweiter echter Link NICHT in
// einen anderen Link verschachtelt werden darf (ungültiges HTML).
if (m.extraCta) {
return `
<div class="profile-card">
<a href="${profilLink}" style="display:contents;">${kartenInhalt}</a>
<a class="btn-spicy-mini" href="${m.extraCta.href}"><span>${feld(m.extraCta.label)}</span></a>
</div>`;
}
return `
<a class="profile-card" href="${profilLink}">${kartenInhalt}
</a>`;
})
.join("");
return `<div class="pyramid-tier" data-tier="${stufe}">${karten}</div>`;
})
.join("");
};
renderModis();
document.addEventListener("dogi-sprache-geaendert", renderModis);
// 21.08.2026: über die Verwaltung angelegte/importierte Modis einmischen
// (+ Runde 2: "wenn ich eine änderung mache ist es auch für jeden").
// Rang/Rang-Bezeichnung kommen mit, damit sie sich sauber in die
// bestehende Pyramide einordnen. dogiTeamZusammenfuehren() überschreibt
// bereits importierte Modis (gleicher slug) mit ihrem aktuellen DB-Stand.
if (window.dogiTeamLaden) {
window.dogiTeamLaden("modi").then((neue) => {
if (!neue.length) return;
window.MODIS = window.dogiTeamZusammenfuehren(window.MODIS, neue);
renderModis();
});
}
});
</script>
</body>
</html>