) * tasks_title Überschrift über der Aufgaben-Liste (optional) * tasks[] wobei Hilfe gebraucht wird * contacts_intro Zeile über den Ansprechpartnern (optional) * contacts[] NAMEN — Nummer/Foto zieht die Seite per Namensabgleich aus * data/ansprechpartner.json (geteilte Quelle, nie duplizieren; * wie die Kontakt-Seite bewusst live statt Snapshot: ein Fest * betrifft ohnehin die Zukunft, alte Nummern nützen niemandem) * link interner Slug fürs Ziel (z. B. „veranstaltungen/sportfest-2026"), * liefert Link-Zeile + QR im CTA-Fuß * poster optional, kleines Plakat rechts neben Intro + Aufgaben * (Varianten-Set {base,widths,alt} oder {src,…}) — z. B. das * Sportfest-Vorderplakat aus data/veranstaltungen.json * bin/stadionzeitung-add.php trägt das Feld über erneute Läufe weiter (wie * `vorwort`/`interview`), plant die Seite nur ein wenn das Feld existiert und * erzeugt den QR (qr-aufruf.png im Ausgaben-Ordner) aus `link`. * * Props: $issue (Eintrag aus data/stadionzeitung.json) */ $issue = $issue ?? []; $aufruf = $issue['aufruf'] ?? null; if (!is_array($aufruf)) { return; } $slug = (string) ($issue['slug'] ?? ''); $heading = trim((string) ($aufruf['heading'] ?? 'Mach mit')); $kicker = trim((string) ($aufruf['kicker'] ?? 'Mitmachen')); // intro darf ein String ODER eine Liste von Zeilen sein — mehrere Zeilen // werden als EIN Absatz mit weichen Umbrüchen (
) gesetzt, damit ein kurzer // Aufruf bewusst zeilenweise stehen kann statt als Fließblock. $introLines = array_values(array_filter( array_map(static fn ($l): string => trim((string) $l), (array) ($aufruf['intro'] ?? [])), static fn (string $l): bool => $l !== '' )); $tasksTitle = trim((string) ($aufruf['tasks_title'] ?? '')); $tasks = array_values(array_filter( array_map(static fn ($t): string => trim((string) $t), $aufruf['tasks'] ?? []), static fn (string $t): bool => $t !== '' )); $contactsIntro = trim((string) ($aufruf['contacts_intro'] ?? '')); $link = trim((string) ($aufruf['link'] ?? '')); $ctaLabel = trim((string) ($aufruf['cta_label'] ?? 'Alle Infos')); $ctaTitle = trim((string) ($aufruf['cta_title'] ?? '')); // Kontakte per Namensabgleich aus der geteilten Quelle auflösen (Nummer/Foto), // die Reihenfolge folgt dem `contacts`-Feld. Ein unbekannter Name bleibt als // reiner Name stehen (kein Fehler), damit ein Tippfehler die Seite nicht kippt. $byName = []; foreach (json_load('ansprechpartner')['persons'] ?? [] as $person) { $name = (string) ($person['name'] ?? ''); if ($name !== '') { $byName[$name] = $person; } } $contacts = []; foreach ($aufruf['contacts'] ?? [] as $name) { $name = trim((string) $name); if ($name === '') { continue; } $contacts[] = $byName[$name] ?? ['name' => $name]; } $qr = ($slug !== '' && is_file(PUBLIC_PATH . "/assets/img/stadionzeitung/{$slug}/qr-aufruf.png")) ? "img/stadionzeitung/{$slug}/qr-aufruf.png" : null; $linkLabel = $link !== '' ? club_domain($link) : ''; // Optionales kleines Plakat rechts neben Intro + Aufgaben (z. B. das Sportfest- // Vorderplakat) — Varianten-Set {base,widths,alt} oder Einzeldatei {src,…}. $poster = $aufruf['poster'] ?? null; if (!is_array($poster) || (empty($poster['base']) && empty($poster['src']))) { $poster = null; } ?>

', array_map('e', $introLines)) ?>

$poster, 'sizes' => '150px', 'class' => 'stadionzeitung-aufruf__poster']); ?>

Scan mich