Files
tsv08kulmbach-website/app/components/contact-form.php
Felix Schneider 0f19729a88 Neubau Fundament + Startseite: Designsystem, PHP-Komponenten, Brevo-Formular, Instagram-Sync
- Ordnerstruktur mit public/-Docroot, Deny-.htaccess für app/bin/config/data/storage
- CLAUDE.md mit Leitplanken (self-hosted only, Single Source of Truth, Component-first)
- Design-Tokens aus alter Seite extrahiert (Akzent #e20612, Coolvetica/Abel als woff2)
- Front Controller mit Routen-Register, Sitemap, Canonical, JSON-LD (SportsClub)
- Startseite: Hero, Instagram-Feed (lokaler Cache), Historie/Sportheim, Stats, Partner, Kontakt
- Kontaktformular via PHPMailer/Brevo mit Honeypot + HMAC-Time-Trap (kein reCAPTCHA)
- bin/instagram-sync.php: Scraper mit Strategie-Kette, flock, atomarem Cache, lokalen Bildern

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 21:16:44 +02:00

93 lines
4.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
/**
* Kontaktformular (Felder wie auf der alten Seite). Props:
* $intro array{title, text}
* Liest Flash-Status aus Query-Params (?sent=1 / ?error=...) — PRG-Muster.
* Spam-Schutz: Honeypot "website" + signierter Timestamp "ft" (form_token()).
*/
$club = json_load('club');
$interests = ['Herrenfußball', 'Damenfußball', 'Jugendfußball', 'Turnen', 'Sonstiges'];
$sent = isset($_GET['sent']);
$error = isset($_GET['error']) ? (string) $_GET['error'] : null;
$errorMessages = [
'validation' => 'Bitte prüfe deine Eingaben Pflichtfelder fehlen oder die E-Mail-Adresse ist ungültig.',
'mail' => 'Deine Nachricht konnte gerade nicht versendet werden. Bitte versuche es später erneut oder schreib uns direkt an ' . $club['email'] . '.',
];
?>
<section class="section contact" id="kontakt">
<div class="container contact__inner">
<div class="contact__intro">
<h2><?= e($intro['title']) ?></h2>
<p><?= e($intro['text']) ?></p>
<p class="text-muted">Oder direkt per Mail an <a href="mailto:<?= e($club['email']) ?>"><?= e($club['email']) ?></a></p>
</div>
<form class="form" method="post" action="<?= e(url('kontakt-senden')) ?>" novalidate>
<div class="form__status" role="status" aria-live="polite" data-form-status>
<?php if ($sent): ?>
<p class="form__success">Danke für deine Anfrage! Wir melden uns so schnell wie möglich bei dir.</p>
<?php elseif ($error !== null): ?>
<p class="form__error"><?= e($errorMessages[$error] ?? $errorMessages['mail']) ?></p>
<?php endif; ?>
</div>
<div class="form__row">
<div class="form__field">
<label for="contact-name">Name *</label>
<input type="text" id="contact-name" name="name" required autocomplete="name" maxlength="200">
</div>
<div class="form__field">
<label for="contact-email">E-Mail *</label>
<input type="email" id="contact-email" name="email" required autocomplete="email" maxlength="200">
</div>
</div>
<div class="form__row">
<div class="form__field">
<label for="contact-phone">Telefonnummer</label>
<input type="tel" id="contact-phone" name="phone" autocomplete="tel" maxlength="50">
</div>
<div class="form__field">
<label for="contact-interest">Ich interessiere mich für</label>
<select id="contact-interest" name="interest">
<option value="">Bitte wählen</option>
<?php foreach ($interests as $interest): ?>
<option value="<?= e($interest) ?>"><?= e($interest) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form__field">
<label for="contact-subject">Betreff *</label>
<input type="text" id="contact-subject" name="subject" required maxlength="200">
</div>
<div class="form__field">
<label for="contact-message">Nachricht *</label>
<textarea id="contact-message" name="message" rows="6" required maxlength="5000"></textarea>
</div>
<div class="form__field form__field--checkbox">
<input type="checkbox" id="contact-privacy" name="privacy" value="1" required>
<label for="contact-privacy">Ich stimme den <a href="<?= e(url('datenschutz')) ?>">Datenschutzbestimmungen</a> zu. *</label>
</div>
<?php /* Honeypot — für Menschen unsichtbar, Bots füllen es aus */ ?>
<div class="visually-hidden" aria-hidden="true">
<label for="contact-website">Website (bitte leer lassen)</label>
<input type="text" id="contact-website" name="website" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="ft" value="<?= e(form_token()) ?>">
<p class="form__submit">
<button class="btn" type="submit">Nachricht senden</button>
</p>
</form>
</div>
</section>