Compare commits
3 Commits
06a18a2d19
...
f21224ea84
| Author | SHA1 | Date | |
|---|---|---|---|
| f21224ea84 | |||
| 592acf02b0 | |||
| 63a045835e |
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -29,6 +31,17 @@ declare(strict_types=1);
|
||||
*/
|
||||
$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
|
||||
@@ -39,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']],
|
||||
];
|
||||
|
||||
@@ -87,7 +105,7 @@ component('team-cards', [
|
||||
<?php if (!empty($page['austritt']['title'])): ?>
|
||||
<div class="fees__note">
|
||||
<h3 class="fees__note-title"><?= e($page['austritt']['title']) ?></h3>
|
||||
<p><?= inline_links_html($page['austritt']['text']) ?></p>
|
||||
<p><?= $austrittText ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
"children": [
|
||||
{ "label": "Übersicht", "slug": "turnen" },
|
||||
{ "label": "Erwachsenenturnen", "slug": "turnen/erwachsenenturnen" },
|
||||
{ "label": "Eltern-Kind-Turnen", "slug": "turnen/eltern-kind-turnen" },
|
||||
{ "label": "Fitness und Pilates", "slug": "turnen/fitness-pilates" },
|
||||
{ "label": "Trampolin", "slug": "turnen/trampolin" },
|
||||
{ "label": "Eltern-Kind- & Kinderturnen", "slug": "turnen/eltern-kind-turnen" },
|
||||
{ "label": "Fitness & Pilates", "slug": "turnen/fitness-pilates" },
|
||||
{ "label": "Trampolinturnen", "slug": "turnen/trampolin" },
|
||||
{ "label": "Wettkampfturnen", "slug": "turnen/wettkampfturnen" }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -45,26 +45,26 @@
|
||||
],
|
||||
"austritt": {
|
||||
"title": "Austritt",
|
||||
"text": "Der Austritt aus dem Verein ist nur zum Ende eines Kalenderjahres möglich und muss bis spätestens 30. September schriftlich erklärt werden. Der Beitrag ist in jedem Fall bis zum Jahresende zu entrichten."
|
||||
"text": "Der Austritt aus dem Verein ist nur zum Ende eines Kalenderjahres möglich und muss bis spätestens 30. September schriftlich erklärt werden. Die Kündigung kannst du formlos per E-Mail an {mail} schicken. Der Beitrag ist in jedem Fall bis zum Jahresende zu entrichten."
|
||||
},
|
||||
"faq": [
|
||||
{ "q": "Welche Turngruppen gibt es beim TSV 08 Kulmbach?", "a": "Eltern-Kind- und Kinderturnen, Erwachsenenturnen, Fitness und Pilates, Trampolinturnen sowie Wettkampfturnen, von den Jüngsten ab 2 Jahren bis zu Erwachsenen." },
|
||||
{ "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.",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -176,7 +176,13 @@
|
||||
z-index: 25;
|
||||
display: grid;
|
||||
gap: var(--space-3xs);
|
||||
min-width: 15rem;
|
||||
/* 15,5rem statt 15rem: der längste Punkt „Eltern-Kind- & Kinderturnen" ist 187,6px
|
||||
breit, und im Hover bzw. auf der aktiven Seite wächst padding-left von --space-s
|
||||
auf --space-m. Bei 15rem blieben dafür nur 186px, das Panel wuchs beim Hover um
|
||||
zwei Pixel und war auf dieser Seite dauerhaft breiter — als Flackern sichtbar,
|
||||
weil das Panel mittig sitzt und sich also nach beiden Seiten schiebt. Wer hier
|
||||
einen längeren Menüpunkt einträgt, misst die Textbreite im Hover-Zustand nach. */
|
||||
min-width: 15.5rem;
|
||||
margin: 0;
|
||||
/* Gleichmäßiges Padding rundum — Pillen stehen oben/unten/seitlich gleich dezent frei. */
|
||||
padding: var(--space-2xs);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 302 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 655 KiB |
Reference in New Issue
Block a user