Files
tsv08kulmbach-website/app/components/stadionzeitung-viewer.php
fs f2f193b223 Sportfest-Ausgabe der Stadionzeitung zum Heimspiel gegen ATS Wartenfels
Neue Live-Seiten, geschaltet vom chat-gepflegten Feld `veranstaltung` (Slug aus
data/veranstaltungen.json) — Programm und Turnierpläne kommen damit aus derselben
Quelle wie die Website, nicht als Kopie ins Heft:

- Programm-Seite (programm[], rendert zugleich auf /veranstaltungen/sportfest-2026)
- vier Turnierplan-Seiten (turniere[]) mit leerer Ergebnisspalte und leerer
  Abschlusstabelle zum Eintragen am Platz
- Gegnerseite je Mannschaft mit Heimspiel am Fest statt nur der tragenden:
  stadionzeitung_gegner_fixtures() ist die einzige Stelle, die das entscheidet,
  Seitenplanung und Snapshot lesen beide dort. `gegner` ist deshalb eine Map je
  Team-Key; die Vorschau überspringt jedes Spiel mit eigener Gegnerseite
- Danke-Seite mit Partner-Logo-Wand aus data/partners.json und QR auf
  /partner-werden, dazu das Anzeigen-Feld `platzierung` für Motive mit festem
  Platz auf einer Live-Seite (Emons über der Logo-Wand). Vorher klebte der Dank
  als leere Fläche unten an einem Anzeigen-Bild
- Cover einer Sonderausgabe: das Fest als Titelgeschichte statt einer der drei
  Begegnungen, dazu das Hauptplakat schräg gelegt an Stelle des Spielerfotos

Ausgabe 2026-09-04-ats-wartenfels als ENTWURF angelegt, 48 Seiten (12 Bögen),
Tabellen auf gerader Seite, längster Anzeigenblock zwei. Veröffentlicht wird auf
dem Server, dort liegt der frische Matchcenter-Stand.

Nebenbei behoben: bin/anzeige-add.php räumte beim Anlegen alle Motive weg, deren
Slug mit demselben Text beginnt (`emons` löschte `emons-partnerdank` und
`emons-stuebinger`). Muster jetzt auf die Breiten-Endung eingeschränkt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KubsajzuV6N6QsSd3xKNjC
2026-09-03 10:57:52 +02:00

81 lines
4.0 KiB
PHP

<?php
declare(strict_types=1);
/**
* Swipe-Viewer für eine Stadionzeitung-Ausgabe. Props:
* $issue Eintrag aus data/stadionzeitung.json (opponent, team_key, status,
* images[]{type: 'image'{base,widths,alt} | 'live'{page[,team][,turnier]}})
*
* Ohne JS: alle Seiten normal gestapelt (stadionzeitung-seite-Komponente) —
* voll lesbar, sequentiell auch per Screenreader. Mit JS
* (stadionzeitung-viewer.js) wird der Track zum horizontalen Scroll-Snap-
* Swiper, Zähler + Pfeil-Buttons kommen dazu (vorher [hidden], da ohne JS
* funktionslos).
*
* Das Rendern der einzelnen Seiten (Bild wie Live) liegt in
* stadionzeitung-seite.php — geteilt mit der Druckfassung
* (stadionzeitung-druck.php), damit Bildschirm und Druck nie
* auseinanderlaufen. Die Daten der Live-Seiten kommen EINMAL aus
* stadionzeitung_live_data() (app/helpers.php): Entwürfe rechnen live,
* veröffentlichte Ausgaben lesen ihren eingefrorenen snapshot.
*/
$issue = $issue ?? [];
$images = $issue['images'] ?? [];
$total = count($images);
if ($images === []) {
return;
}
$opponent = (string) ($issue['opponent'] ?? '');
// Live-Daten nur laden, wenn die Ausgabe tatsächlich eine Live-Seite enthält.
$hasLive = false;
foreach ($images as $entry) {
if (($entry['type'] ?? 'image') === 'live') {
$hasLive = true;
break;
}
}
$liveData = $hasLive ? stadionzeitung_live_data($issue) : [];
?>
<section class="stadionzeitung-viewer" data-stadionzeitung-viewer aria-roledescription="Bildergalerie" aria-label="<?= e('Stadionzeitung gegen ' . $opponent . ', Seite für Seite') ?>">
<ul class="stadionzeitung-viewer__track" data-viewer-track>
<?php foreach ($images as $i => $entry): ?>
<li class="stadionzeitung-viewer__page" data-viewer-page>
<?php component('stadionzeitung-seite', [
'entry' => $entry,
'issue' => $issue,
'data' => $liveData,
'eager' => $i === 0,
]); ?>
</li>
<?php endforeach; ?>
</ul>
<div class="stadionzeitung-viewer__controls" data-viewer-controls hidden>
<button class="btn btn--icon stadionzeitung-viewer__nav-btn" type="button" data-viewer-prev aria-label="Vorherige Seite">
<?= icon('chevron-left') ?>
</button>
<p class="stadionzeitung-viewer__counter" data-viewer-counter aria-live="polite">
Seite <span data-viewer-current>1</span> von <?= $total ?>
</p>
<button class="btn btn--icon stadionzeitung-viewer__nav-btn" type="button" data-viewer-next aria-label="Nächste Seite">
<?= icon('chevron-right') ?>
</button>
<?php /* Vollbild-Lesemodus: am Handy fressen Kopfleiste, Navigation und Fußzeile
mehr Platz als die Seite selbst. Beide Icons stehen im Markup, welches
sichtbar ist entscheidet CSS am Zustand — so muss das JS kein Markup
erzeugen. Zustand über aria-pressed, deshalb bleibt das aria-label
unverändert. */ ?>
<button class="btn btn--icon stadionzeitung-viewer__full-btn" type="button" data-viewer-full aria-pressed="false" aria-label="Vollbild">
<span class="stadionzeitung-viewer__icon--open"><?= icon('arrows-fullscreen') ?></span>
<span class="stadionzeitung-viewer__icon--close"><?= icon('x-lg') ?></span>
</button>
</div>
<?php /* Hier stand ein „Druckfassung"-Knopf. Er ist raus (31.07.2026, Felix): die
Druckfassung ist Werkzeug für die Heft-Produktion, nicht für Besucher — und
als sichtbarer Button neben Blättern und Vollbild wurde er versehentlich
geklickt und riss Leute aus dem Lesen. Die Route bleibt unverändert
erreichbar: an die Ausgaben-URL ein `?druck=1` anhängen. Nicht als Link
wieder einbauen; wer sie braucht, kennt sie. */ ?>
</section>