strtotime($to)) {
echo json_encode(['error' => 'Bitte wählen Sie einen gültigen Zeitraum.'], JSON_UNESCAPED_UNICODE);
exit;
}
$sql = "SELECT e.title, DATE(e.starts_at) AS event_day, r.name FROM sufw_booking_registrations r JOIN sufw_booking_events e ON e.id = r.event_id WHERE r.status = 'confirmed' AND e.starts_at BETWEEN :fromDate AND :toDate";
$parameters = ['fromDate' => $from.' 00:00:00', 'toDate' => $to.' 23:59:59'];
if ($exportProject !== 'all') { $sql .= ' AND e.project = :exportProject'; $parameters['exportProject'] = $exportProject; }
$statement = $database->prepare($sql.' ORDER BY e.starts_at, r.name');
$statement->execute($parameters);
echo json_encode(['registrations' => $statement->fetchAll()], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
exit;
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!hash_equals($csrf, (string) ($_POST['csrf'] ?? ''))) { http_response_code(403); exit('Ungültige Sitzung.'); }
$action = (string) ($_POST['action'] ?? '');
if ($action === 'save_event') {
$id = (string) ($_POST['id'] ?? '') ?: bookingUuid();
$title = trim((string) ($_POST['title'] ?? ''));
$startsAt = str_replace('T', ' ', (string) ($_POST['starts_at'] ?? ''));
$endsAt = str_replace('T', ' ', (string) ($_POST['ends_at'] ?? ''));
$capacity = (int) ($_POST['capacity'] ?? 0);
$format = (string) ($_POST['format'] ?? 'vor_ort');
$contactName = trim((string) ($_POST['contact_name'] ?? ''));
$contactEmail = trim((string) ($_POST['contact_email'] ?? ''));
$contactPhone = trim((string) ($_POST['contact_phone'] ?? ''));
if ($title === '' || $capacity < 1 || $capacity > 100 || !in_array($format, ['vor_ort', 'telefonisch'], true) || $contactName === '' || $contactPhone === '' || !filter_var($contactEmail, FILTER_VALIDATE_EMAIL) || !isQuarterHourDateTime($startsAt) || !isQuarterHourDateTime($endsAt) || strtotime($endsAt) <= strtotime($startsAt)) adminBack($project, 'events', 'Bitte prüfen Sie die Termindaten. Uhrzeiten sind nur im 15-Minuten-Raster zulässig.');
$save = $database->prepare("INSERT INTO sufw_booking_events (id, project, title, starts_at, ends_at, capacity, format, introduction_required, contact_name, contact_email, contact_phone) VALUES (:id, :project, :title, :startsAt, :endsAt, :capacity, :format, :introductionRequired, :contactName, :contactEmail, :contactPhone) ON DUPLICATE KEY UPDATE title = VALUES(title), starts_at = VALUES(starts_at), ends_at = VALUES(ends_at), capacity = VALUES(capacity), format = VALUES(format), introduction_required = VALUES(introduction_required), contact_name = VALUES(contact_name), contact_email = VALUES(contact_email), contact_phone = VALUES(contact_phone)");
$save->execute(['id' => $id, 'project' => $project, 'title' => $title, 'startsAt' => $startsAt, 'endsAt' => $endsAt, 'capacity' => $capacity, 'format' => $format, 'introductionRequired' => isset($_POST['introduction_required']) ? 1 : 0, 'contactName' => $contactName, 'contactEmail' => $contactEmail, 'contactPhone' => $contactPhone]);
adminBack($project, 'events', 'Termin gespeichert.');
}
if ($action === 'toggle_event') {
$database->prepare('UPDATE sufw_booking_events SET is_active = 1 - is_active WHERE id = :id AND project = :project')->execute(['id' => $_POST['id'] ?? '', 'project' => $project]);
adminBack($project, 'events', 'Terminstatus geändert.');
}
if ($action === 'remove_registration') {
$database->prepare("UPDATE sufw_booking_registrations SET status = 'removed', removed_at = UTC_TIMESTAMP() WHERE id = :id AND status IN ('pending_confirmation', 'confirmed')")->execute(['id' => $_POST['id'] ?? '']);
adminBack($project, 'registrations', 'Teilnahme entfernt; die Kapazität ist wieder frei.');
}
}
$titles = $database->prepare('SELECT DISTINCT title FROM sufw_booking_events WHERE project = :project ORDER BY title');
$titles->execute(['project' => $project]);
$titles = $titles->fetchAll(PDO::FETCH_COLUMN);
$contacts = $database->prepare('SELECT DISTINCT contact_name, contact_email, contact_phone FROM sufw_booking_events WHERE project = :project ORDER BY contact_name, contact_email');
$contacts->execute(['project' => $project]);
$contactByName = [];
$contactByEmail = [];
foreach ($contacts as $contact) { $contactByName[$contact['contact_name']] ??= ['email' => $contact['contact_email'], 'phone' => $contact['contact_phone']]; $contactByEmail[$contact['contact_email']] ??= ['name' => $contact['contact_name'], 'phone' => $contact['contact_phone']]; }
$settings = $database->prepare('SELECT feed_token FROM sufw_booking_project_settings WHERE project = :project');
$settings->execute(['project' => $project]);
$feedToken = (string) $settings->fetchColumn();
$notice = (string) ($_GET['notice'] ?? '');
$events = [];
$edit = null;
if ($view === 'events') {
$statement = $database->prepare("SELECT e.*, COUNT(CASE WHEN r.status = 'confirmed' THEN 1 END) AS confirmed_count FROM sufw_booking_events e LEFT JOIN sufw_booking_registrations r ON r.event_id = e.id WHERE e.project = :project GROUP BY e.id ORDER BY e.starts_at");
$statement->execute(['project' => $project]);
$events = $statement->fetchAll();
foreach ($events as $event) if ($event['id'] === ($_GET['edit'] ?? '')) $edit = $event;
}
$registrations = [];
if ($view === 'registrations') {
$statement = $database->prepare("SELECT r.*, e.title, e.starts_at FROM sufw_booking_registrations r JOIN sufw_booking_events e ON e.id = r.event_id WHERE e.project = :project ORDER BY r.created_at DESC LIMIT 200");
$statement->execute(['project' => $project]);
$registrations = $statement->fetchAll();
}
$nextMonth = new DateTimeImmutable('first day of next month');
$defaultFrom = $nextMonth->format('Y-m-01');
$defaultTo = $nextMonth->format('Y-m-t');
?>
Terminbuchung · Testverwaltung
=h($notice)?>
= $edit ? 'Termin bearbeiten' : 'Termin anlegen' ?>
Termine
| Termin | Zeit | Kapazität | Status | |
|---|
=h($event['title'])?> =h($event['format'])?>=!empty($event['introduction_required']) ? ' · Einführung erforderlich' : ''?> | =h($event['starts_at'])?> bis =h($event['ends_at'])?> | =h($event['confirmed_count'])?> / =h($event['capacity'])?> bestätigt | = $event['is_active'] ? 'Aktiv' : 'Inaktiv' ?> | Bearbeiten |
Teilnahmen · =h(bookingProjectTitle($project))?>
| Person | Termin | Status | |
|---|
=h($registration['name'])?> =h($registration['email'])?> =h($registration['phone'])?> | =h($registration['title'])?> =h($registration['starts_at'])?> | =h($registration['status'])?> | |
Bestätigte Teilnahmen anzeigen
Der Zeitraum umfasst jeweils vollständige Kalendertage (00:00 bis 23:59 Uhr) und aktualisiert die Liste unmittelbar.
Lade Teilnahmen …