Turn-Anmeldung als eigene FAQ-Frage, Knöpfe in FAQ-Antworten möglich

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
This commit is contained in:
2026-07-31 22:31:57 +02:00
parent 63a045835e
commit 592acf02b0
12 changed files with 57 additions and 20 deletions

View File

@@ -72,6 +72,13 @@ Per-Page-Meta (Title/Description/OG) lebt in der jeweiligen Page-Datei (`app/pag
`sportsevent_nodes()` (SportsEvent-Knoten für kommende Spiele, Matchcenter) und
`job_posting_schema()` (JobPosting `VOLUNTEER` für Ehrenamtsstellen, `/mitmachen`, verweist via `#club`).
Sichtbare FAQ + FAQPage-Schema aus derselben `data/*.json`-Quelle, damit Inhalt und Markup nie auseinanderlaufen.
Ein FAQ-Eintrag darf zusätzlich `ctas[]` tragen (Knöpfe unter der Antwort, gerendert über die
`cta`-Komponente) — für Antworten, an deren Ende ein Handgriff steht, etwa „so meldest du dich an".
**Die Antwort muss den Weg trotzdem in Worten nennen:** `faq_schema()` liest nur `q` und `a`, bei
Google steht sonst eine Antwort ohne Ziel. Und **keine zweite Sektion mit denselben Knöpfen daneben**
— ein `cta-band` unter den Beiträgen von `/turnen` war gebaut und wurde am 31.07.2026 wieder
entfernt (Entscheidung Felix): dieselbe Sache zweimal auf einer Seite schwächt beide Stellen, und
man weiß nicht mehr, welcher der richtige Weg ist.
Redaktioneller Text aus `data/*.json` darf interne Deeplinks als `[Label](slug)` tragen (auch
`[Label](#anker)` bzw. `slug#anker`) — `inline_links_html()` rendert sie als `<a>`,
`inline_links_text()` hält HTML-freie Ausgaben (FAQPage-Schema) sauber. Genutzt von den

View File

@@ -4,7 +4,12 @@ declare(strict_types=1);
/**
* FAQ-Accordion. Props:
* $faq array [{q, a}, …]
* $faq array [{q, a, ctas?: [{label, slug, hash?, style?}]}, …]
* ctas ist optional und rendert Knöpfe unter der Antwort (über die cta-Komponente),
* für Antworten, an deren Ende ein Handgriff steht — etwa „so meldest du dich an".
* Das FAQPage-Schema ist davon unberührt: faq_schema() liest nur q und a. Die
* Antwort muss den Weg deshalb IN WORTEN nennen, sonst steht bei Google eine
* Antwort ohne Ziel.
* $title string (optional, Default 'Häufige Fragen')
* $anchor string (optional, Default 'faq')
* Natives <details>/<summary> → ohne JS bedienbar. Das FAQPage-Schema liefert
@@ -27,7 +32,16 @@ if ($faq === []) {
<?php foreach ($faq as $item): ?>
<details class="faq__item">
<summary class="faq__q"><span><?= e($item['q']) ?></span><?= icon('chevron-down', 'faq__chevron') ?></summary>
<div class="faq__a"><p><?= inline_links_html($item['a']) ?></p></div>
<div class="faq__a">
<p><?= inline_links_html($item['a']) ?></p>
<?php if (!empty($item['ctas'])): ?>
<div class="faq__actions">
<?php foreach ($item['ctas'] as $cta): ?>
<?php component('cta', ['cta' => $cta]); ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</details>
<?php endforeach; ?>
</div>

View File

@@ -33,4 +33,4 @@ component('group-schedule', [
'noticeIcon' => $d['notice_icon'] ?? 'info-circle',
'groups' => $d['groups'] ?? [],
'footnote' => $data['footnote'] ?? '',
]);
]);

View File

@@ -25,4 +25,4 @@ component('group-schedule', [
'location' => $d['location'] ?? [],
'lead' => $d['lead'] ?? '',
'groups' => $d['groups'] ?? [],
]);
]);

View File

@@ -32,4 +32,4 @@ component('group-schedule', [
'location' => $d['location'] ?? [],
'lead' => $d['lead'] ?? '',
'groups' => $d['groups'] ?? [],
]);
]);

View File

@@ -29,4 +29,4 @@ component('group-schedule', [
'noticeTone' => $d['notice_tone'] ?? 'info',
'noticeIcon' => $d['notice_icon'] ?? 'info-circle',
'groups' => $d['groups'] ?? [],
]);
]);

View File

@@ -25,4 +25,4 @@ component('group-schedule', [
'location' => $d['location'] ?? [],
'lead' => $d['lead'] ?? '',
'groups' => $d['groups'] ?? [],
]);
]);

View File

@@ -17,9 +17,11 @@ declare(strict_types=1);
* 2024.tsv08kulmbach.de): Zusatzbeitrag 24/48 €, Neumitglieder 84/94/184 €,
* Förderstufen 120/180/240 €, Austritt zum 30. September.
*
* NOCH unbenutzt: overview.cta („Lust aufs Turnen bekommen?"). Der Block verlinkt
* „Zur Turn-Übersicht" und gehört damit auf die Disziplin-Unterseiten, nicht hierher
* — auf der Übersicht wäre das ein Selbstlink.
* 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
@@ -50,7 +52,12 @@ $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']],
['name' => 'Trampolinturnen', 'slug' => 'turnen/trampolin', 'category' => 'Carl-von-Linde-Realschule', 'image' => ['base' => 'img/pages/turnen-trampolin', 'widths' => [640, 1000, 1600], 'alt' => 'Trampolinturnen 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']],
];

View File

@@ -52,19 +52,19 @@
{ "q": "Ab welchem Alter kann mein Kind mitturnen?", "a": "Beim Eltern-Kind-Turnen starten die Jüngsten bereits ab etwa 2 Jahren gemeinsam mit ihren Eltern. Für ältere Kinder gibt es nach Alter gestaffelte Breitensportgruppen." },
{ "q": "Wo finden die Turnstunden statt?", "a": "Die meisten Gruppen trainieren im Mäximum Gym (Thurnauer Str. 51, 95326 Kulmbach). Fitness und Pilates laufen in der Max-Hundt-Schule, das Trampolinturnen in der Dreifachturnhalle der Carl-von-Linde-Realschule." },
{ "q": "Was kostet die Turnabteilung?", "a": "Bestehende TSV-Mitglieder zahlen einen Zusatzbeitrag von 24,00 € (Einzelperson) bzw. 48,00 € pro Jahr (Familie). Neumitglieder zahlen 84,00 € (Kinder/Jugendliche), 94,00 € (Erwachsene) oder 184,00 € (Familie ab 3 Personen) im Jahr, inklusive Grundbeitrag, Verbandsabgaben und Sportunfall-Versicherung. Bei hohem Trainingsumfang kommt eine Förderstufe hinzu." },
{ "q": "Kann ich vorher zum Probetraining kommen?", "a": "Ja. Schreib uns vorher über unser [Anfrageformular](turnen#kontakt), damit wir die aktuelle Platzverfügbarkeit prüfen können." }
{ "q": "Kann ich vorher zum Probetraining kommen?", "a": "Ja. Schreib uns vorher über unser [Anfrageformular](turnen#kontakt), damit wir die aktuelle Platzverfügbarkeit prüfen können." },
{
"q": "Wie melde ich mich oder mein Kind an?",
"a": "In zwei Schritten. Bei Interesse an einer aktiven Teilnahme schreib uns bitte zunächst über unser Anfrageformular, so prüfen wir die aktuelle Platzverfügbarkeit. Ist ein Platz frei, läuft die Anmeldung über den Aufnahmeantrag als PDF: herunterladen, ausfüllen und beim Übungsleiter abgeben.",
"ctas": [
{ "label": "Platz anfragen", "slug": "turnen", "hash": "kontakt", "style": "outline" },
{ "label": "Anmeldung Turnabteilung", "slug": "mitglied-werden", "hash": "anmeldung-turnen", "style": "primary" }
]
}
],
"contact": {
"title": "Fragen zum Turnen?",
"text": "Schreib direkt der Turnabteilung. Sag uns, welche Gruppe dich interessiert, dann prüfen wir die Platzverfügbarkeit und melden uns bei dir."
},
"cta": {
"title": "Lust aufs Turnen bekommen?",
"text": "Bei Interesse an einer aktiven Teilnahme schreib uns bitte zunächst über unser Anfrageformular, so prüfen wir die aktuelle Platzverfügbarkeit.",
"ctas": [
{ "label": "Mitglied werden", "slug": "mitglied-werden#anmeldung-turnen", "style": "primary" },
{ "label": "Zur Turn-Übersicht", "slug": "turnen", "style": "outline" }
]
}
},
"footnote": "* So im Trainingsplan der Abteilung gekennzeichnet.",

View File

@@ -3211,6 +3211,15 @@
margin: 0;
}
/* Knöpfe unter einer Antwort (optionales ctas-Feld, siehe app/components/faq.php).
flex-wrap, weil zwei Knöpfe auf einem schmalen Handy nicht nebeneinander passen. */
.faq__actions {
display: flex;
flex-wrap: wrap;
gap: var(--space-s);
margin-top: var(--space-m);
}
/* Antwort beim Öffnen sanft einblenden (reduced-motion via reset.css deaktiviert). */
.faq__item[open] .faq__a {
animation: faq-reveal 260ms ease;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 655 KiB