Files
tsv08kulmbach-website/app/components/sportheimbuchung-form.php
fs 6a612e52c3 Sportheim mieten: Buchungsseite mit Anfrageformular
Neue Seite /sportheimbuchung mit Bento-Layout (Fotos, Lage, Ausstattung) und
einem Buchungsanfrage-Formular nach Projektkonvention (form-field-Komponente,
Status-Region, Honeypot + ft-Token, Whitelist-Validierung, Rate-Limiting, PRG).
Versand via Brevo SMTP über app/actions/sportheimbuchung-senden.php, POST-Route
in index.php. form-field um min/max-Attribute erweitert (Personenzahl-Feld).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HGzc6GhWhmLJt1jC2q1SRZ
2026-06-20 20:46:44 +02:00

87 lines
4.8 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);
/**
* Sportheim-Buchungsanfrage-Formular. Props:
* $form array{title, text, event_types: string[]}
* PRG-Flash via ?sent=1 / ?error=validation / ?error=mail.
* Felder ausschließlich über component('form-field').
*/
$club = json_load('club');
$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.',
'ratelimit' => 'Zu viele Anfragen in kurzer Zeit. Bitte versuche es in ein paar Minuten erneut.',
'mail' => 'Deine Anfrage konnte gerade nicht gesendet werden. Bitte versuche es später erneut oder schreib uns direkt an ' . $club['email'] . '.',
];
$today = date('Y-m-d');
$f = [
'name' => ['type' => 'text', 'name' => 'name', 'id' => 'buch-name', 'label' => 'Name', 'required' => true, 'autocomplete' => 'name', 'maxlength' => 200],
'email' => ['type' => 'email', 'name' => 'email', 'id' => 'buch-email', 'label' => 'E-Mail', 'required' => true, 'autocomplete' => 'email', 'maxlength' => 200],
'phone' => ['type' => 'tel', 'name' => 'phone', 'id' => 'buch-phone', 'label' => 'Telefonnummer', 'autocomplete' => 'tel', 'maxlength' => 50],
'event_type' => ['type' => 'select', 'name' => 'event_type', 'id' => 'buch-type', 'label' => 'Art der Veranstaltung','options' => $form['event_types']],
'event_date' => ['type' => 'date', 'name' => 'event_date', 'id' => 'buch-date', 'label' => 'Gewünschtes Datum', 'required' => true, 'min' => $today, 'hint' => 'Frühestmögliches Buchungsdatum'],
'attendees' => ['type' => 'number', 'name' => 'attendees', 'id' => 'buch-attendees', 'label' => 'Ungefähre Personenzahl','required' => true, 'min' => '1', 'max' => '500'],
'message' => ['type' => 'textarea', 'name' => 'message', 'id' => 'buch-message', 'label' => 'Weitere Wünsche oder Fragen', 'rows' => 5, 'maxlength' => 3000],
'privacy' => [
'type' => 'checkbox', 'name' => 'privacy', 'id' => 'buch-privacy', 'required' => true,
'label' => 'Ich stimme den Datenschutzbestimmungen zu.',
'label_html' => 'Ich stimme den <a href="' . e(url('datenschutz')) . '">Datenschutzbestimmungen</a> zu.',
],
];
?>
<section class="section" id="buchung">
<div class="container contact__inner">
<div class="contact__intro">
<h2><?= e($form['title']) ?></h2>
<p><?= e($form['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('sportheimbuchung-senden')) ?>" novalidate>
<div class="form__status" role="status" aria-live="polite" tabindex="-1" data-form-status>
<?php if ($sent): ?>
<p class="form__success">Danke für deine Anfrage! Wir melden uns kurzfristig bei dir.</p>
<?php elseif ($error !== null): ?>
<p class="form__error"><?= e($errorMessages[$error] ?? $errorMessages['mail']) ?></p>
<?php endif; ?>
</div>
<p class="form__note">Pflichtfelder sind mit <span class="form__required" aria-hidden="true">*</span><span class="visually-hidden">Stern</span> markiert.</p>
<div class="form__row">
<?php component('form-field', ['field' => $f['name']]); ?>
<?php component('form-field', ['field' => $f['email']]); ?>
</div>
<div class="form__row">
<?php component('form-field', ['field' => $f['phone']]); ?>
<?php component('form-field', ['field' => $f['event_type']]); ?>
</div>
<div class="form__row">
<?php component('form-field', ['field' => $f['event_date']]); ?>
<?php component('form-field', ['field' => $f['attendees']]); ?>
</div>
<?php component('form-field', ['field' => $f['message']]); ?>
<?php component('form-field', ['field' => $f['privacy']]); ?>
<?php /* Honeypot */ ?>
<div class="visually-hidden" aria-hidden="true">
<label for="buch-company-url">Bitte dieses Feld leer lassen</label>
<input type="text" id="buch-company-url" name="company_url" tabindex="-1" autocomplete="off">
</div>
<input type="hidden" name="ft" value="<?= e(form_token()) ?>">
<p class="form__submit">
<button class="btn" type="submit">Anfrage senden</button>
</p>
</form>
</div>
</section>