Files
tsv08kulmbach-website/app/components/group-schedule.php
fs 7bbf783562 Flamingos zum Wettkampfturnen, Inhalte gegen die alte Seite abgeglichen
Die Flamingos sind organisatorisch vom Kinderturnen zum Wettkampfturnen
gewechselt. Felix hat dazu die Fassung geschickt, die die Turnabteilung selbst
auf der alten Seite gepflegt hatte — dabei kamen sieben Abweichungen heraus,
alle korrigiert:

- Die zweite Gruppe heißt "Leistungsturnen", nicht "Wettkampfturnen" (so hieß
  bei uns die Gruppe wie die Disziplin).
- Reihenfolge: Flamingos zuerst, Leistungsturnen danach.
- Den Flamingos fehlte eine Trainingszeit: Montag gibt es ZWEI Blöcke
  (18:00–19:00 und 19:00–20:00), wir hatten nur den ersten.
- Ansprechpersonen sind pro Gruppe verschieden (Flamingos: Theresa Diener,
  Leistungsturnen: Franziska Trotzke). Dafür ist `contact` neu an einer Gruppe.
  Die Kontakt-Kachel oben kann nur EINE Person nennen und wäre für die andere
  Gruppe falsch — deshalb ist `lead` bei dieser Disziplin jetzt leer, die Kachel
  trägt nur noch die Abteilungs-Mail. So war es auf der alten Seite auch: dort
  gab es keine Ansprechperson für die Disziplin, nur je Gruppe.
- Theresa Diener steht im Trainerteam vorn und ohne Stern (bei uns hinten).
- Intro, Trainingsinhalte, Wettkämpfe und der Hinweis waren gekürzt; jetzt im
  Wortlaut der Abteilung. Den Gedankenstrich in "(Kür modifiziert –
  Leistungsklasse 3)" ersetzt ein Komma (Sprache & Ton).
- Die Fußnote sagte "* So im Trainingsplan der Abteilung gekennzeichnet" — eine
  Verlegenheitsformulierung, weil wir die Bedeutung nicht kannten. Die alte
  Seite schreibt "* = ÜBUNGSLEITER", also jetzt "* Übungsleiterinnen und
  Übungsleiter" (Paarform, Haus-Stil).

`level` bleibt "Turnen · fortgeschritten" ohne "Alter nach Absprache" — das
hatte Felix am 31.07.2026 ausdrücklich aus dem Chip genommen.

Zwei Folgen, die sonst still kaputtgegangen wären: die Seite hatte eine einzige
Gruppe ohne Beschreibung und lief damit im Einzelgruppen-Layout. Mit zwei
Gruppen, davon eine mit Beschreibung, rendert group-schedule eine Tab-Leiste —
die braucht group-tabs.js, das die Seite nicht lud (tote Tab-Knöpfe). Und drei
Flamingos-Trainerinnen tragen ein Sternchen, die erklärende Fußnote wurde auf
dieser Seite nicht übergeben (drei unerklärte Sterne).

Geprüft: Tabs "Flamingos" und "Leistungsturnen", Skript geladen, Fußnote da,
Flamingos auf /turnen/eltern-kind-turnen nicht mehr erwähnt, kein Überlauf bei
390px, alle sechs Turn-Seiten 200.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
2026-07-31 22:40:25 +02:00

244 lines
11 KiB
PHP

<?php
declare(strict_types=1);
/**
* Turn-Disziplin im einheitlichen Bento-Look (wie die Mannschaftsseiten). Props:
* $location array{venue, street?, zip?, city?} (optional) — Trainingsort + „Route planen"
* $lead string (optional) — verantwortliche Übungsleitung (Akzent-Kachel)
* $notice string (optional) — hervorgehobener Hinweis (z. B. Wartelisten-Status)
* $noticeTitle string (optional) — Überschrift dazu
* $noticeTone 'info' (Default) | 'stop' — Tonlage, siehe components/notice.php
* $noticeIcon string (optional) — Icon-Name, siehe components/notice.php
* Gerendert wird über component('notice') — dieselbe Komponente, die
* contact-form.php über dem Formular benutzt, damit derselbe Hinweis an
* beiden Orten gleich aussieht und nur EINMAL in data/turnen.json steht.
* $groups array von Gruppen:
* { name, level?, contact?, intro?, details?:[{heading,text}], recommendation?,
* note?, trainers?:[…], sessions:[{ label?, day, time, note?, trainers?:[…] }] }
* contact = Ansprechperson NUR dieser Gruppe. Braucht es, sobald eine Disziplin
* mehrere Gruppen mit verschiedenen Ansprechpersonen hat (Wettkampfturnen:
* Flamingos → Theresa Diener, Leistungsturnen → Franziska Trotzke) — die
* Kontakt-Kachel oben kann nur EINE nennen und wäre für die andere falsch.
* Beschriftet als „Kontakt" wie die Kachel, nicht als „Ansprechpartner":
* das Label kennt das Geschlecht der Person nicht (Haus-Stil Paarformen).
* $footnote string (optional) — Erläuterung (z. B. zur Sternchen-Kennzeichnung)
* $groupsTitle string (optional, Default 'Unsere Gruppen')
* $anchor string (optional, Default 'training')
*
* Eine Gruppe → Trainingszeiten landen als Bento-Kachel im Dashboard.
* Mehrere → Dashboard zeigt nur Ort/Verantwortlich, darunter eine Gruppen-Sektion.
* Gruppen mit Beschreibung werden gestapelt, schlichte Gruppen als Raster.
*/
$anchor = $anchor ?? 'training';
$groupsTitle = $groupsTitle ?? 'Unsere Gruppen';
$lead = $lead ?? '';
$notice = $notice ?? '';
$noticeTitle = $noticeTitle ?? '';
$noticeTone = $noticeTone ?? 'info';
$noticeIcon = $noticeIcon ?? 'info-circle';
$footnote = $footnote ?? '';
$groups = $groups ?? [];
$location = $location ?? [];
if ($groups === []) {
return;
}
$club = json_load('club');
$email = $club['email_turnen'] ?? ($club['email'] ?? '');
$single = count($groups) === 1;
$rich = false;
foreach ($groups as $g) {
if (!empty($g['intro']) || !empty($g['details'])) {
$rich = true;
break;
}
}
$hasVenue = !empty($location['venue']);
$mapsQuery = $hasVenue ? rawurlencode(trim(
($location['venue'] ?? '') . ', '
. ($location['street'] ?? '') . ', '
. ($location['zip'] ?? '') . ' ' . ($location['city'] ?? ''),
', '
)) : '';
/** Eine Trainingszeit (Tag/Zeit + optional Label, Notiz, Übungsleitung) ausgeben. */
$renderSession = static function (array $s): void {
?>
<li class="schedule-row">
<?php if (!empty($s['label'])): ?>
<span class="schedule-row__label"><?= e($s['label']) ?></span>
<?php endif; ?>
<span class="schedule-row__when">
<span class="schedule-row__day"><?= e($s['day']) ?></span>
<span class="schedule-row__time"><?= e($s['time']) ?></span>
</span>
<?php if (!empty($s['note'])): ?>
<span class="schedule-row__note text-muted"><?= e($s['note']) ?></span>
<?php endif; ?>
<?php if (!empty($s['trainers'])): ?>
<span class="schedule-row__trainers"><span class="schedule-row__trainers-label">Übungsleitung:</span> <?= e(implode(', ', $s['trainers'])) ?></span>
<?php endif; ?>
</li>
<?php
};
$soleSessions = $single ? ($groups[0]['sessions'] ?? []) : [];
$soleNote = $single ? ($groups[0]['note'] ?? '') : '';
?>
<section class="section turnen-dash-section" id="<?= e($anchor) ?>">
<div class="container">
<div class="turnen-dash<?= $single ? ' turnen-dash--single' : '' ?><?= $notice !== '' ? ' turnen-dash--notice' : '' ?>">
<?php if ($notice !== ''): ?>
<?php component('notice', [
'title' => $noticeTitle,
'text' => $notice,
'tone' => $noticeTone,
'icon' => $noticeIcon,
'class' => 'turnen-dash__notice',
]); ?>
<?php endif; ?>
<?php if ($single): ?>
<article class="bento__tile turnen-dash__training">
<h2 class="bento__heading"><?= icon('clock', 'bento__hicon') ?>Trainingszeiten</h2>
<ul class="bento__sessions">
<?php foreach ($soleSessions as $s): ?>
<li>
<span class="bento__day"><?= e($s['day']) ?></span>
<span class="bento__time"><?= e($s['time']) ?></span>
</li>
<?php endforeach; ?>
</ul>
<?php if ($soleNote !== ''): ?>
<p class="bento__note text-muted"><?= e($soleNote) ?></p>
<?php endif; ?>
<span class="bento__deco" aria-hidden="true"><?= icon('clock') ?></span>
</article>
<?php endif; ?>
<?php if ($lead !== '' || $email !== ''): ?>
<article class="bento__tile bento__tile--accent turnen-dash__contact">
<span class="bento__stat-label">Kontakt</span>
<?php if ($lead !== ''): ?>
<span class="bento__stat-value"><?= e($lead) ?></span>
<?php endif; ?>
<?php if ($email !== ''): ?>
<a class="turnen-dash__mail" href="mailto:<?= e($email) ?>"><?= icon('envelope', 'turnen-dash__mail-icon') ?>E-Mail schreiben</a>
<?php endif; ?>
</article>
<?php endif; ?>
<?php if ($hasVenue): ?>
<article class="bento__tile turnen-dash__venue">
<div class="turnen-dash__venue-main">
<h2 class="bento__heading"><?= icon('geo-alt', 'bento__hicon') ?>Trainingsort</h2>
<p class="bento__address">
<strong><?= e($location['venue']) ?></strong>
<?php if (!empty($location['street'])): ?> · <?= e($location['street']) ?><?php endif; ?>
<?php if (!empty($location['zip']) || !empty($location['city'])): ?>, <?= e(trim(($location['zip'] ?? '') . ' ' . ($location['city'] ?? ''))) ?><?php endif; ?>
</p>
</div>
<a class="btn btn--outline turnen-dash__route" href="https://www.google.com/maps/search/?api=1&amp;query=<?= e($mapsQuery) ?>" target="_blank" rel="noopener">Route planen<span class="visually-hidden"> (öffnet Google Maps in neuem Tab)</span></a>
<span class="bento__deco" aria-hidden="true"><?= icon('geo-alt') ?></span>
</article>
<?php endif; ?>
</div>
</div>
</section>
<?php if (!$single): ?>
<section class="section group-list-section" id="gruppen">
<div class="container">
<h2 class="group-list__title"><?= e($groupsTitle) ?></h2>
<?php if ($rich): ?>
<div class="group-tabs" data-group-tabs>
<div class="group-tabs__bar" role="tablist" aria-label="<?= e($groupsTitle) ?>">
<?php foreach ($groups as $i => $g): ?>
<button class="tab group-tabs__tab" role="tab" type="button"
id="gtab-<?= $i ?>"
aria-controls="gpanel-<?= $i ?>"
aria-selected="<?= $i === 0 ? 'true' : 'false' ?>"
><?= e($g['name']) ?></button>
<?php endforeach; ?>
</div>
<?php foreach ($groups as $i => $g): ?>
<article class="group-card group-tabs__panel" role="tabpanel"
id="gpanel-<?= $i ?>"
aria-labelledby="gtab-<?= $i ?>"
tabindex="0"
>
<div class="group-card__body">
<div class="group-card__header">
<h3 class="group-card__name"><?= e($g['name']) ?></h3>
<?php if (!empty($g['level'])): ?>
<p class="group-card__level"><?= e($g['level']) ?></p>
<?php endif; ?>
</div>
<?php if (!empty($g['intro'])): ?>
<p class="group-card__intro"><?= e($g['intro']) ?></p>
<?php endif; ?>
<?php foreach ($g['details'] ?? [] as $det): ?>
<?php if (!empty($det['heading'])): ?>
<h4 class="group-card__detail-heading"><?= e($det['heading']) ?></h4>
<?php endif; ?>
<?php if (!empty($det['text'])): ?>
<p class="group-card__detail-text"><?= e($det['text']) ?></p>
<?php endif; ?>
<?php endforeach; ?>
<?php if (!empty($g['recommendation'])): ?>
<p class="group-card__recommendation text-muted"><?= e($g['recommendation']) ?></p>
<?php endif; ?>
</div>
<?php if (!empty($g['sessions'])): ?>
<div class="group-card__schedule">
<p class="group-card__schedule-title"><?= icon('clock', 'group-card__schedule-icon') ?>Trainingszeiten</p>
<ul class="schedule-list">
<?php foreach ($g['sessions'] as $s): $renderSession($s); endforeach; ?>
</ul>
<?php if (!empty($g['contact'])): ?>
<p class="group-card__trainers"><span class="schedule-row__trainers-label">Kontakt:</span> <?= e($g['contact']) ?></p>
<?php endif; ?>
<?php if (!empty($g['trainers'])): ?>
<p class="group-card__trainers"><span class="schedule-row__trainers-label">Übungsleitung:</span> <?= e(implode(', ', $g['trainers'])) ?></p>
<?php endif; ?>
<?php if (!empty($g['note'])): ?>
<p class="group-card__note text-muted"><?= e($g['note']) ?></p>
<?php endif; ?>
</div>
<?php endif; ?>
</article>
<?php endforeach; ?>
</div>
<?php else: ?>
<div class="group-list group-list--grid">
<?php foreach ($groups as $g): ?>
<article class="group-card">
<div class="group-card__body">
<div class="group-card__header">
<h3 class="group-card__name"><?= e($g['name']) ?></h3>
<?php if (!empty($g['level'])): ?>
<p class="group-card__level"><?= e($g['level']) ?></p>
<?php endif; ?>
</div>
</div>
<?php if (!empty($g['sessions'])): ?>
<div class="group-card__schedule">
<ul class="schedule-list">
<?php foreach ($g['sessions'] as $s): $renderSession($s); endforeach; ?>
</ul>
</div>
<?php endif; ?>
</article>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($footnote !== ''): ?>
<p class="group-list__footnote text-muted"><?= e($footnote) ?></p>
<?php endif; ?>
</div>
</section>
<?php endif; ?>