Stadionzeitung, Veranstaltungen, News-Artikel, Lightbox und Anzeigen-Verteilung
Stadionzeitung: Live-Seiten (Tabellen, Ergebnisse, Vorschau, Termine, News,
Kontakt, Historie, Sportheim, Partner, Momente, Impressum), automatisches Cover,
Swipe-Viewer mit Vollbildmodus und die Druckfassung als Falt-Heft. Anzeigen
kommen jetzt aus dem Bestand und werden gleichmäßig verteilt, nie mehr als zwei
hintereinander (vorher vier Blöcke à fünf). Die Doppelseiten-Regel rechnet das
Skript selbst, statt sie von Hand zu prüfen.
Veranstaltungen: Bereich /veranstaltungen mit Detailseite pro Fest, Lebenszyklus
über das Datum (Ankündigung vor dem Fest, Rückblick danach), Galerie mit
Lightbox. veranstaltungen.json ist dritte Termin-Quelle, damit ein Fest nie
doppelt gepflegt wird.
News-Artikel als dritte dynamische Prefix-Route, gemeinsamer detail-head.
Behobene Fehler:
- Wappen-Kontexte setzten Zeilen-Layout auf .crest statt auf die Zeile; das
Wappen wurde zum Grid, Vereinsname und Tore rutschten darunter zusammen
(Ergebnis-Rückblick, Vorschau, Cover).
- --header-h (60px) unterschätzt die Kopfleiste um 32px (Logo 72px + 20px
Versatz): neues abgeleitetes --header-space, sonst klebten Zurück-Links
unter dem Logo.
- base_url in der Produktions-Config ohne www, während .htaccess auf www
umleitet; preflight prüft das jetzt.
- .lightbox brauchte display:none mit (0,2,0), sonst lag das Overlay offen.
Neue Werkzeuge: bin/anzeige-add.php (Anzeigen-Bestand), bin/veranstaltung-bilder.php
(Plakate und Galerien, Alt-Texte folgen der Quelldatei), bin/qr.php (Druck-QR mit
Warnung, wenn base_url nicht auf die echte Domain zeigt).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 14:55:27 +02:00
< ? 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 ]}})
*
* 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 >
2026-07-31 17:36:15 +02:00
< ? 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 . */ ?>
Stadionzeitung, Veranstaltungen, News-Artikel, Lightbox und Anzeigen-Verteilung
Stadionzeitung: Live-Seiten (Tabellen, Ergebnisse, Vorschau, Termine, News,
Kontakt, Historie, Sportheim, Partner, Momente, Impressum), automatisches Cover,
Swipe-Viewer mit Vollbildmodus und die Druckfassung als Falt-Heft. Anzeigen
kommen jetzt aus dem Bestand und werden gleichmäßig verteilt, nie mehr als zwei
hintereinander (vorher vier Blöcke à fünf). Die Doppelseiten-Regel rechnet das
Skript selbst, statt sie von Hand zu prüfen.
Veranstaltungen: Bereich /veranstaltungen mit Detailseite pro Fest, Lebenszyklus
über das Datum (Ankündigung vor dem Fest, Rückblick danach), Galerie mit
Lightbox. veranstaltungen.json ist dritte Termin-Quelle, damit ein Fest nie
doppelt gepflegt wird.
News-Artikel als dritte dynamische Prefix-Route, gemeinsamer detail-head.
Behobene Fehler:
- Wappen-Kontexte setzten Zeilen-Layout auf .crest statt auf die Zeile; das
Wappen wurde zum Grid, Vereinsname und Tore rutschten darunter zusammen
(Ergebnis-Rückblick, Vorschau, Cover).
- --header-h (60px) unterschätzt die Kopfleiste um 32px (Logo 72px + 20px
Versatz): neues abgeleitetes --header-space, sonst klebten Zurück-Links
unter dem Logo.
- base_url in der Produktions-Config ohne www, während .htaccess auf www
umleitet; preflight prüft das jetzt.
- .lightbox brauchte display:none mit (0,2,0), sonst lag das Overlay offen.
Neue Werkzeuge: bin/anzeige-add.php (Anzeigen-Bestand), bin/veranstaltung-bilder.php
(Plakate und Galerien, Alt-Texte folgen der Quelldatei), bin/qr.php (Druck-QR mit
Warnung, wenn base_url nicht auf die echte Domain zeigt).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 14:55:27 +02:00
</ section >