Der Anmelde-Vorgang der Abteilung (erst Platz anfragen, dann Aufnahmeantrag) stand nirgends auf der Seite. Auf der alten Seite gab es dafür einen Block „ANMELDUNG" mit zwei Knöpfen. Erst als eigene Sektion unter den Beiträgen gebaut (cta-band), auf Wunsch von Felix wieder entfernt und stattdessen als eigene FAQ-Frage umgesetzt. Zwei Sektionen mit denselben Knöpfen auf einer Seite schwächen beide Stellen, und man weiß nicht mehr, welcher der richtige Weg ist. Deshalb ist auch overview.cta ganz aus data/turnen.json raus statt unbenutzt liegen zu bleiben — genau so ein toter Block hat heute schon einmal in die Irre geführt (die Notiz „NOCH unbenutzt" stand monatelang im Docblock von turnen.php). faq.php bekommt dafür ein optionales ctas-Feld pro Eintrag, gerendert über die bestehende cta-Komponente, also keine neue Knopf-Variante. .faq__actions bricht um, weil zwei Knöpfe auf einem schmalen Handy nicht nebeneinander passen. Die Antwort nennt beide Wege bewusst AUCH in Worten: faq_schema() liest nur q und a, Knöpfe landen nie im FAQPage-Schema. Stünde in der Antwort nur „so geht's" plus zwei Knöpfe, hätte Google eine Antwort ohne Ziel. Nachgeprüft: sechs Fragen im Schema, der neue Antworttext ist HTML- und Markup-frei. Gemessen bei 390px: kein Überlauf, Knöpfe 130x44 und 193x44 (Trefferfläche erfüllt). Die fünf Turn-Unterseiten hatten als einzige von 105 PHP-Dateien keinen Zeilenumbruch am Dateiende, das ist mitkorrigiert. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NzeVVgMCrzCDJAKeLEdKr7
131 lines
8.0 KiB
PHP
131 lines
8.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Turn-Übersichtsseite (Hub + Beiträge + Abteilungskontakt). Inhalt: data/turnen.json.
|
|
* Struktur: Hero → Disziplin-Karten → Beiträge → FAQ → Anfrageformular.
|
|
*
|
|
* Hier stand vorher „Die Detailinhalte (Beiträge, Trainingszeiten) leben auf den
|
|
* Disziplin-Unterseiten" — das war falsch, und zwar folgenreich: die Seite gab
|
|
* fees/austritt/faq NIE aus, die Unterseiten auch nicht, und damit standen die
|
|
* Turn-Beiträge NIRGENDS auf der Website (nachgeprüft 31.07.2026: 0 Treffer auf
|
|
* /turnen und allen fünf Unterseiten; /mitglied-werden führt nur die Fußball-
|
|
* Beiträge). Die Turnabteilung verlinkt diese Angaben in Einladungen für neue
|
|
* Familien, deshalb ist der Beitragsblock hier verankert (#beitraege).
|
|
* Die Daten selbst stimmen 1:1 mit der alten Seite überein (gegengeprüft an
|
|
* 2024.tsv08kulmbach.de): Zusatzbeitrag 24/48 €, Neumitglieder 84/94/184 €,
|
|
* Förderstufen 120/180/240 €, Austritt zum 30. September.
|
|
*
|
|
* Der Anmelde-Vorgang der Abteilung (erst Platz anfragen, dann Aufnahmeantrag) steht als
|
|
* eigene FAQ-Frage samt den zwei Knöpfen, nicht als eigene Sektion. Das war eine bewusste
|
|
* Entscheidung von Felix (31.07.2026): ein Band unter den Beiträgen war gebaut und wurde
|
|
* wieder entfernt, weil dieselbe Sache dann zweimal auf der Seite stand. Deshalb gibt es
|
|
* `overview.cta` nicht mehr — wer die Knöpfe sucht, findet sie in `overview.faq`.
|
|
*
|
|
* Das Formular ist die allgemeine contact-form-Komponente mit
|
|
* department => 'turnen': Auswahlliste sind die Disziplinen, Empfänger ist die
|
|
* Turnabteilung (club.email_turnen) statt info@. Die alte Seite hatte dafür ein
|
|
* eigenes, zweites Formular — hier ist es dieselbe Komponente und dieselbe
|
|
* Action, damit der Spam-Schutz nicht doppelt gepflegt werden muss.
|
|
*/
|
|
$page = json_load('turnen')['overview'];
|
|
|
|
// Die Kündigung darf formlos per Mail kommen (Turnabteilung, 31.07.2026). Die Adresse
|
|
// steht ausschließlich in club.json — der Austritt-Text in turnen.json markiert ihre
|
|
// Stelle mit {mail}, dasselbe Muster wie der Material-Aufruf auf /historie. Ersetzt
|
|
// wird NACH inline_links_html(): so bleibt der Fließtext escaped und nur der Platzhalter
|
|
// wird zu HTML. Umgekehrt käme der fertige Link escaped als Text auf die Seite.
|
|
$mailTurnen = json_load('club')['email_turnen'];
|
|
$austrittText = strtr(
|
|
inline_links_html($page['austritt']['text'] ?? ''),
|
|
['{mail}' => '<a href="mailto:' . e($mailTurnen) . '">' . e($mailTurnen) . '</a>']
|
|
);
|
|
|
|
// Heros aller Turn-Seiten zeigen VORÜBERGEHEND das Drohnen-Luftbild des
|
|
// Vereinsgeländes (img/pages/vereinsgelaende, Quelle: data/turnen.json) statt des
|
|
// Fußballplatz-Bildes. Ehrlicher wäre ein Bild aus der Turnhalle — liegt eines
|
|
// vor, tauschen die sechs Hero-Blöcke in data/turnen.json und das og_image der
|
|
// sechs Seiten-Dateien. Die Übersichts-Kacheln zeigen weiter die (vorläufigen)
|
|
// themenbezogenen Platzhalter aus public/assets/img/pages/.
|
|
$cards = [
|
|
['name' => 'Erwachsenenturnen', 'slug' => 'turnen/erwachsenenturnen', 'category' => 'Mäximum Gym', 'image' => ['base' => 'img/pages/turnen-erwachsenenturnen', 'widths' => [640, 1000, 1600], 'alt' => 'Erwachsenenturnen beim TSV 08 Kulmbach']],
|
|
['name' => 'Eltern-Kind- & Kinderturnen', 'slug' => 'turnen/eltern-kind-turnen', 'category' => 'ab ca. 2 Jahren', 'image' => ['base' => 'img/pages/turnen-eltern-kind', 'widths' => [640, 1000, 1600], 'alt' => 'Eltern-Kind- und Kinderturnen beim TSV 08 Kulmbach']],
|
|
['name' => 'Fitness & Pilates', 'slug' => 'turnen/fitness-pilates', 'category' => 'Max-Hundt-Schule', 'image' => ['base' => 'img/pages/turnen-fitness-pilates', 'widths' => [640, 1000, 1600], 'alt' => 'Fitness und Pilates beim TSV 08 Kulmbach']],
|
|
// Einziges echtes Foto unter den Kacheln (31.07.2026). Nur 640 breit, weil die
|
|
// Vorlage über WhatsApp kam und dort auf 718 px eingedampft wurde;
|
|
// resize_image_variants() skaliert nie hoch. Liegt das Original vom Handy vor:
|
|
// php bin/img-resize.php <quelle> public/assets/img/pages/turnen-trampolin 640,1000,1600 82
|
|
// und hier wieder alle drei Breiten eintragen.
|
|
['name' => 'Trampolinturnen', 'slug' => 'turnen/trampolin', 'category' => 'Carl-von-Linde-Realschule', 'image' => ['base' => 'img/pages/turnen-trampolin', 'widths' => [640], 'alt' => 'Aufgebaute Trampoline und Sicherheitsmatten in der Dreifachturnhalle, in der wir trainieren']],
|
|
['name' => 'Wettkampfturnen', 'slug' => 'turnen/wettkampfturnen', 'category' => 'Leistungssport', 'image' => ['base' => 'img/pages/turnen-wettkampf', 'widths' => [640, 1000, 1600], 'alt' => 'Wettkampfturnen beim TSV 08 Kulmbach']],
|
|
];
|
|
|
|
$meta = [
|
|
'title' => 'Turnen in Kulmbach',
|
|
'description' => 'Die Turnabteilung des TSV 08 Kulmbach: Eltern-Kind- und Kinderturnen, Erwachsenenturnen, Fitness und Pilates, Trampolin- und Wettkampfturnen.',
|
|
'og_image' => 'img/pages/vereinsgelaende-1600.jpg',
|
|
// Zweiter Parameter = FAQ: sichtbare Fragen und FAQPage-Schema kommen aus
|
|
// derselben Quelle, damit sie nie auseinanderlaufen (CLAUDE.md).
|
|
'schema' => page_schema([
|
|
['name' => 'Startseite', 'slug' => ''],
|
|
['name' => 'Turnen', 'slug' => 'turnen'],
|
|
], $page['faq'] ?? []),
|
|
];
|
|
|
|
component('hero', ['hero' => $page['hero']]);
|
|
component('team-cards', [
|
|
'teams' => $cards,
|
|
'title' => 'Unsere Turngruppen',
|
|
'title_hidden' => true,
|
|
'intro' => $page['cards_intro'] ?? null,
|
|
'anchor' => 'gruppen',
|
|
]);
|
|
?>
|
|
<?php /* Beiträge. Der Anker #beitraege ist die Adresse, die die Turnabteilung in
|
|
Einladungen weitergibt — nicht umbenennen. Drei Tabellen über die
|
|
bestehende fee-table-Komponente (dieselbe wie auf /mitglied-werden),
|
|
darunter die Austrittsregel, weil sie zur Beitragsfrage gehört. */ ?>
|
|
<section class="section section--tinted fees" id="beitraege">
|
|
<div class="container">
|
|
<header class="fees__head">
|
|
<h2><?= e($page['fees_title']) ?></h2>
|
|
<?php if (!empty($page['fees_intro'])): ?>
|
|
<p class="fees__intro"><?= e($page['fees_intro']) ?></p>
|
|
<?php endif; ?>
|
|
</header>
|
|
<div class="fee-tables">
|
|
<?php foreach ($page['fees'] as $feeTable): ?>
|
|
<?php component('fee-table', ['fees' => $feeTable]); ?>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php /* Bewusst NICHT .prose: dort rendert ein h3 mit 21px Abel, also exakt
|
|
Fließtextgröße — in Impressum und Artikeln richtig, hier ist „Austritt"
|
|
aber eine Auszeichnung und wäre nicht von Fließtext zu unterscheiden. */ ?>
|
|
<?php if (!empty($page['austritt']['title'])): ?>
|
|
<div class="fees__note">
|
|
<h3 class="fees__note-title"><?= e($page['austritt']['title']) ?></h3>
|
|
<p><?= $austrittText ?></p>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</section>
|
|
<?php
|
|
component('faq', ['faq' => $page['faq'] ?? []]);
|
|
/* Der Wartelisten-Hinweis steht DIREKT über dem Formular, so wie auf der alten Seite.
|
|
Grund ist Arbeitsaufwand in der Abteilung, kein Design: fuer „Tiger" und „Huehner"
|
|
kommen laufend Anfragen nach einem Wartelistenplatz, den es nicht gibt, und jede muss
|
|
einzeln beantwortet werden. Wer hier schreibt, soll es vorher lesen. Der Text kommt aus
|
|
derselben Stelle wie die Kachel auf der Kinderturn-Unterseite
|
|
(disciplines.eltern-kind-turnen.notice), ein Hinweis und eine Quelle. */
|
|
$kinderturnen = json_load('turnen')['disciplines']['eltern-kind-turnen'] ?? [];
|
|
component('contact-form', [
|
|
'intro' => $page['contact'],
|
|
'return' => 'turnen',
|
|
'department' => 'turnen',
|
|
'notice' => $kinderturnen['notice'] ?? '',
|
|
'noticeTitle' => $kinderturnen['notice_title'] ?? '',
|
|
'noticeTone' => $kinderturnen['notice_tone'] ?? 'info',
|
|
'noticeIcon' => $kinderturnen['notice_icon'] ?? 'info-circle',
|
|
]);
|