147 lines
7.3 KiB
PHP
147 lines
7.3 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Zeilen-Liste für die News-Seite: mischt redaktionelle Meldungen, Instagram-
|
||
|
|
* Posts und Ergebnisse. Props:
|
||
|
|
* $items array{date, title, text, image?, href?, link_text?, source}
|
||
|
|
* `link_text` (optional) ist die sichtbare Weiterlesen-Zeile —
|
||
|
|
* gesetzt vom Normalizer, nicht hier abgeleitet: die Komponente
|
||
|
|
* soll die Quellen nicht kennen (gleiche Prop wie in
|
||
|
|
* upcoming_highlights()/event-feature)
|
||
|
|
* $empty_text string (optional)
|
||
|
|
* $featured bool (optional) — neuester Eintrag als großer Aufmacher über
|
||
|
|
* der Liste (gleiche Hierarchie-Idee wie das „Nächste Spiele"-
|
||
|
|
* Band: ein Aufmacher, darunter Zeilen)
|
||
|
|
* $filterable bool (optional) — Filter-Leiste nach Quelle (Alle/Meldungen/
|
||
|
|
* Ergebnisse/Instagram), gleiche Bausteine wie der Stellen-Filter
|
||
|
|
* auf /mitmachen (.filter-bar + .tab, assets/js/news-filter.js).
|
||
|
|
* Ohne JS sind alle Einträge sichtbar — reine Progressive
|
||
|
|
* Enhancement. Die Seite muss news-filter.js laden.
|
||
|
|
* Kennt nichts von den drei Quellstrukturen — bekommt nur die normalisierte
|
||
|
|
* Form (app/pages/news.php baut sie).
|
||
|
|
*
|
||
|
|
* Bewusst eine Zeilen-Liste statt eines Karten-Grids (wie termine-list.php):
|
||
|
|
* die Einträge sind zu unterschiedlich hoch (hohe Bild-Posts neben kurzen
|
||
|
|
* Text-Ergebnissen) — ein Grid reißt dabei Löcher, weil kurze Karten den
|
||
|
|
* Platz neben einer hohen Karte nicht auffüllen können. Eine einspaltige
|
||
|
|
* Liste hat dieses Problem nicht, jede Zeile ist einfach so hoch wie ihr
|
||
|
|
* eigener Inhalt.
|
||
|
|
*/
|
||
|
|
$items = $items ?? [];
|
||
|
|
$emptyText = $empty_text ?? 'Aktuell keine News.';
|
||
|
|
$featured = !empty($featured);
|
||
|
|
$filterable = !empty($filterable);
|
||
|
|
|
||
|
|
$sourceLabels = [
|
||
|
|
'news' => 'Meldung',
|
||
|
|
'instagram' => 'Instagram',
|
||
|
|
'ergebnis' => 'Ergebnis',
|
||
|
|
];
|
||
|
|
$filters = [
|
||
|
|
'all' => 'Alle',
|
||
|
|
'news' => 'Meldungen',
|
||
|
|
'ergebnis' => 'Ergebnisse',
|
||
|
|
'instagram' => 'Instagram',
|
||
|
|
];
|
||
|
|
?>
|
||
|
|
<?php if ($items === []): ?>
|
||
|
|
<p class="text-muted"><?= e($emptyText) ?></p>
|
||
|
|
<?php else: ?>
|
||
|
|
<?php if ($filterable): ?>
|
||
|
|
<div class="filter-bar" role="group" aria-label="News nach Quelle filtern" data-news-filter>
|
||
|
|
<?php $i = 0; foreach ($filters as $value => $label): ?>
|
||
|
|
<button type="button" class="tab filter-bar__tab" data-filter="<?= e($value) ?>" aria-pressed="<?= $i++ === 0 ? 'true' : 'false' ?>"><?= e($label) ?></button>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
<?php if ($featured):
|
||
|
|
$feature = array_shift($items);
|
||
|
|
$featureTag = !empty($feature['href']) ? 'a' : 'div';
|
||
|
|
$featureExternal = $feature['source'] === 'instagram';
|
||
|
|
$featureAttrs = !empty($feature['href'])
|
||
|
|
? ' href="' . e($feature['href']) . '"' . ($featureExternal ? ' target="_blank" rel="noopener"' : '')
|
||
|
|
: '';
|
||
|
|
$featureHasMedia = !empty($feature['image']) || !empty($feature['crest']);
|
||
|
|
?>
|
||
|
|
<div class="news-feature" data-source="<?= e($feature['source']) ?>">
|
||
|
|
<<?= $featureTag ?> class="news-feature__link<?= $featureHasMedia ? ' news-feature__link--media' : '' ?>"<?= $featureAttrs ?>>
|
||
|
|
<?php if (!empty($feature['image'])): ?>
|
||
|
|
<div class="news-feature__media">
|
||
|
|
<?php component('img', ['image' => $feature['image'], 'sizes' => '(max-width: 768px) 100vw, 40vw', 'class' => 'news-feature__img', 'eager' => true]); ?>
|
||
|
|
</div>
|
||
|
|
<?php elseif (!empty($feature['crest'])): ?>
|
||
|
|
<div class="news-feature__media news-feature__media--crest">
|
||
|
|
<?php component('crest', ['src' => $feature['crest']['src'], 'name' => $feature['crest']['name']]); ?>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
<div class="news-feature__body">
|
||
|
|
<p class="news-row__meta">
|
||
|
|
<span class="news-row__badge news-row__badge--<?= e($feature['source']) ?>"><?= e($sourceLabels[$feature['source']] ?? $feature['source']) ?></span>
|
||
|
|
<?php if ($feature['date'] !== ''): ?>
|
||
|
|
<time datetime="<?= e($feature['date']) ?>"><?= e(german_date($feature['date'])) ?></time>
|
||
|
|
<?php endif; ?>
|
||
|
|
<?php if ($featureExternal): ?>
|
||
|
|
<span class="visually-hidden"> (öffnet in neuem Tab)</span>
|
||
|
|
<?php endif; ?>
|
||
|
|
</p>
|
||
|
|
<p class="news-feature__title"><?= e($feature['title']) ?></p>
|
||
|
|
<?php if (!empty($feature['text']) && $feature['text'] !== $feature['title']): ?>
|
||
|
|
<p class="news-feature__text"><?= e($feature['text']) ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
<?php if (!empty($feature['link_text'])): ?>
|
||
|
|
<p class="news-feature__more"><?= e($feature['link_text']) ?> <?= icon('arrow-right') ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
</div>
|
||
|
|
</<?= $featureTag ?>>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
<ul class="news-list">
|
||
|
|
<?php foreach ($items as $item): ?>
|
||
|
|
<?php
|
||
|
|
$tag = !empty($item['href']) ? 'a' : 'div';
|
||
|
|
$external = $item['source'] === 'instagram';
|
||
|
|
$attrs = '';
|
||
|
|
if (!empty($item['href'])) {
|
||
|
|
$attrs = ' href="' . e($item['href']) . '"' . ($external ? ' target="_blank" rel="noopener"' : '');
|
||
|
|
}
|
||
|
|
?>
|
||
|
|
<li class="news-row" data-source="<?= e($item['source']) ?>">
|
||
|
|
<<?= $tag ?> class="news-row__link"<?= $attrs ?>>
|
||
|
|
<?php if (!empty($item['image'])): ?>
|
||
|
|
<div class="news-row__media">
|
||
|
|
<?php component('img', ['image' => $item['image'], 'sizes' => '96px', 'class' => 'news-row__img']); ?>
|
||
|
|
</div>
|
||
|
|
<?php elseif (!empty($item['crest'])): ?>
|
||
|
|
<div class="news-row__media news-row__media--crest">
|
||
|
|
<?php component('crest', ['src' => $item['crest']['src'], 'name' => $item['crest']['name']]); ?>
|
||
|
|
</div>
|
||
|
|
<?php endif; ?>
|
||
|
|
<div class="news-row__body">
|
||
|
|
<p class="news-row__meta">
|
||
|
|
<span class="news-row__badge news-row__badge--<?= e($item['source']) ?>"><?= e($sourceLabels[$item['source']] ?? $item['source']) ?></span>
|
||
|
|
<?php if ($item['date'] !== ''): ?>
|
||
|
|
<time datetime="<?= e($item['date']) ?>"><?= e(german_date($item['date'])) ?></time>
|
||
|
|
<?php endif; ?>
|
||
|
|
<?php if ($external): ?>
|
||
|
|
<span class="visually-hidden"> (öffnet in neuem Tab)</span>
|
||
|
|
<?php endif; ?>
|
||
|
|
</p>
|
||
|
|
<p class="news-row__title"><?= e($item['title']) ?></p>
|
||
|
|
<?php if (!empty($item['text']) && $item['text'] !== $item['title']): ?>
|
||
|
|
<p class="news-row__text"><?= e($item['text']) ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
<?php if (!empty($item['link_text'])): ?>
|
||
|
|
<p class="news-row__more"><?= e($item['link_text']) ?> <?= icon('arrow-right') ?></p>
|
||
|
|
<?php endif; ?>
|
||
|
|
</div>
|
||
|
|
</<?= $tag ?>>
|
||
|
|
</li>
|
||
|
|
<?php endforeach; ?>
|
||
|
|
</ul>
|
||
|
|
<?php if ($filterable): ?>
|
||
|
|
<p class="text-muted" data-news-empty hidden>In dieser Kategorie gibt es gerade nichts Neues.</p>
|
||
|
|
<?php endif; ?>
|
||
|
|
<?php endif; ?>
|