Files
kaffeekasse-saas/mitarbeiterverwalten.php
T

638 lines
27 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
ob_start();
include "functions.php";
require_once __DIR__ . "/app/ledger.php";
require_once __DIR__ . "/app/saas-mail.php";
require_once __DIR__ . "/app/audit.php";
require_once __DIR__ . "/app/billing.php";
require_once __DIR__ . "/app/imports.php";
app_require_csrf();
include "header.php";
include "headerline.php";
include "nav.php";
?>
<!-- Banner -->
<section id="banner">
<div class="content">
<?php
$pdo = app_db_pdo();
$saasUser = saas_current_user($pdo);
$tenantId = 0;
$hasAccess = false;
if ($saasUser !== null && saas_user_has_role(['owner', 'admin'], $saasUser)) {
$tenantId = (int)$saasUser['tenant_id'];
$hasAccess = true;
}
function mitglieder_parse_filters(array $source): array
{
$status = (string)($source['status'] ?? 'alle');
if (!in_array($status, ['alle', 'aktiv', 'inaktiv'], true)) {
$status = 'alle';
}
$zugang = (string)($source['zugang'] ?? 'alle');
if (!in_array($zugang, ['alle', 'mit_zugang', 'ohne_zugang', 'entzogen'], true)) {
$zugang = 'alle';
}
$paypal = (string)($source['paypal'] ?? 'alle');
if (!in_array($paypal, ['alle', 'hinterlegt', 'fehlt', 'doppelt'], true)) {
$paypal = 'alle';
}
return [
'q' => trim((string)($source['q'] ?? '')),
'status' => $status,
'zugang' => $zugang,
'paypal' => $paypal,
];
}
function mitglieder_build_filter_query(array $filters): string
{
$params = [];
foreach (['q', 'status', 'zugang', 'paypal'] as $key) {
$value = (string)($filters[$key] ?? '');
if ($value !== '' && !in_array($value, ['alle'], true)) {
$params[$key] = $value;
}
}
return http_build_query($params);
}
function mitglieder_filter_fields(array $filters): string
{
return '<input type="hidden" name="filter_q" value="' . saas_html((string)$filters['q']) . '">'
. '<input type="hidden" name="filter_status" value="' . saas_html((string)$filters['status']) . '">'
. '<input type="hidden" name="filter_zugang" value="' . saas_html((string)$filters['zugang']) . '">'
. '<input type="hidden" name="filter_paypal" value="' . saas_html((string)$filters['paypal']) . '">';
}
function mitglieder_status_badge(bool $active): string
{
return '<span class="status-badge ' . ($active ? 'success' : 'muted') . '">' . ($active ? 'Aktiv' : 'Inaktiv') . '</span>';
}
function mitglieder_access_label(array $mitglied, array $rollenLabels): string
{
if ($mitglied['membership_status'] === 'active') {
return $rollenLabels[$mitglied['role']] ?? (string)$mitglied['role'];
}
return $mitglied['membership_status'] === 'revoked' ? 'Zugang entzogen' : 'Kein Zugang';
}
if($hasAccess){
$meldung = null;
$fehler = null;
$einladungslink = null;
$bearbeitenId = null;
$actorUserId = $saasUser['user_id'] ?? null;
$filterSource = $_SERVER['REQUEST_METHOD'] === 'POST'
? [
'q' => $_POST['filter_q'] ?? '',
'status' => $_POST['filter_status'] ?? 'alle',
'zugang' => $_POST['filter_zugang'] ?? 'alle',
'paypal' => $_POST['filter_paypal'] ?? 'alle',
]
: $_GET;
$filter = mitglieder_parse_filters($filterSource);
$filterQuery = mitglieder_build_filter_query($filter);
$filterSuffix = $filterQuery !== '' ? '?' . $filterQuery : '';
if (isset($_SESSION['flash_mitglieder']) && is_array($_SESSION['flash_mitglieder'])) {
$flash = $_SESSION['flash_mitglieder'];
unset($_SESSION['flash_mitglieder']);
$meldung = isset($flash['meldung']) ? (string)$flash['meldung'] : null;
$fehler = isset($flash['fehler']) ? (string)$flash['fehler'] : null;
$einladungslink = isset($flash['einladungslink']) ? (string)$flash['einladungslink'] : null;
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$aktion = $_POST["aktion"] ?? '';
if ($aktion === 'bearbeiten') {
$bearbeitenId = (int)$_POST["mitgliedID"];
} elseif ($aktion === 'anlegen') {
$name = trim((string)($_POST["name"] ?? ''));
$email = trim((string)($_POST["email"] ?? ''));
$paypalname = trim((string)($_POST["paypalname"] ?? ''));
$aktiv = isset($_POST["aktiv"]);
if ($name === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fehler = 'Bitte einen Namen und eine gültige E-Mail-Adresse angeben.';
} elseif ($aktiv && !billing_has_capacity_for($pdo, $tenantId)) {
$fehler = billing_capacity_error_message($pdo, $tenantId);
} else {
try {
$neueId = ledger_create_participant($pdo, $tenantId, $name, $email, $paypalname, $aktiv);
app_audit_log($pdo, $tenantId, $actorUserId, 'participant.created', 'participant', $neueId, ['name' => $name, 'email' => $email]);
$meldung = 'Mitglied wurde angelegt.';
} catch (Throwable $e) {
$fehler = 'Das Mitglied konnte nicht angelegt werden (E-Mail eventuell schon vergeben).';
}
}
} elseif ($aktion === 'bearbeitenspeichern') {
$participantId = (int)$_POST["mitgliedID"];
$name = trim((string)($_POST["name"] ?? ''));
$email = trim((string)($_POST["email"] ?? ''));
$paypalname = trim((string)($_POST["paypalname"] ?? ''));
$aktiv = isset($_POST["aktiv"]);
$warAktiv = false;
foreach (ledger_fetch_participants_for_admin($pdo, $tenantId) as $m) {
if ($m['participant_id'] === $participantId) {
$warAktiv = (bool)$m['active'];
break;
}
}
if ($name === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$fehler = 'Bitte einen Namen und eine gültige E-Mail-Adresse angeben.';
} elseif ($aktiv && !$warAktiv && !billing_has_capacity_for($pdo, $tenantId)) {
$fehler = billing_capacity_error_message($pdo, $tenantId);
} elseif (ledger_update_participant($pdo, $tenantId, $participantId, $name, $email, $paypalname, $aktiv)) {
app_audit_log($pdo, $tenantId, $actorUserId, 'participant.updated', 'participant', $participantId, ['name' => $name, 'email' => $email]);
$meldung = 'Mitglied wurde gespeichert.';
} else {
$fehler = 'Das Mitglied konnte nicht gespeichert werden.';
}
} elseif ($aktion === 'aktivieren' || $aktion === 'deaktivieren') {
$participantId = (int)$_POST["mitgliedID"];
if ($aktion === 'aktivieren' && !billing_has_capacity_for($pdo, $tenantId)) {
$fehler = billing_capacity_error_message($pdo, $tenantId);
} elseif (ledger_set_participant_active($pdo, $tenantId, $participantId, $aktion === 'aktivieren')) {
app_audit_log($pdo, $tenantId, $actorUserId, $aktion === 'aktivieren' ? 'participant.activated' : 'participant.deactivated', 'participant', $participantId);
$meldung = $aktion === 'aktivieren' ? 'Mitglied wurde aktiviert.' : 'Mitglied wurde deaktiviert.';
} else {
$fehler = 'Der Status konnte nicht geändert werden.';
}
} elseif ($aktion === 'zugang_gewaehren') {
$participantId = (int)$_POST["mitgliedID"];
$rolle = (string)($_POST["rolle"] ?? '');
// Einladungen legen fremde Konten an und verschicken Mails nach
// aussen. Wer die eigene Adresse noch nicht bestaetigt hat, kann
// das nicht im Namen eines womoeglich fremden Postfachs tun.
if (!saas_email_verified($saasUser)) {
$ergebnis = ['ok' => false, 'errors' => [
'Bevor du Mitglieder einladen kannst, muss deine eigene E-Mail-Adresse bestätigt sein. Den Link kannst du unter "Kundenkonto" erneut anfordern.',
]];
} else {
$ergebnis = saas_grant_participant_access($pdo, $tenantId, $participantId, $rolle);
}
if ($ergebnis['ok']) {
$einladendeTenantSettings = saas_fetch_tenant_settings($pdo, $tenantId);
$mailErgebnis = saas_send_invite_mail(
$ergebnis['user_email'],
$einladendeTenantSettings['name'] ?? 'Kaffeeliste',
$rolle,
$ergebnis['token']
);
app_audit_log($pdo, $tenantId, $actorUserId, 'participant.access_granted', 'participant', $participantId, ['role' => $rolle]);
$meldung = 'Zugang wurde gewährt, Einladung wurde verschickt.';
if (saas_should_show_auth_links()) {
$einladungslink = saas_app_url('passwort-zuruecksetzen.php?token=' . urlencode($ergebnis['token']));
}
} else {
$fehler = implode(' ', $ergebnis['errors']);
}
} elseif ($aktion === 'zugang_entziehen') {
$participantId = (int)$_POST["mitgliedID"];
$ergebnis = saas_revoke_participant_access($pdo, $tenantId, $participantId);
if ($ergebnis['ok']) {
app_audit_log($pdo, $tenantId, $actorUserId, 'participant.access_revoked', 'participant', $participantId);
$meldung = 'Zugang wurde entzogen.';
} else {
$fehler = implode(' ', $ergebnis['errors']);
}
} elseif ($aktion === 'anonymisieren') {
$participantId = (int)$_POST["mitgliedID"];
$mitgliedRolle = null;
foreach (ledger_fetch_participants_for_admin($pdo, $tenantId) as $m) {
if ($m['participant_id'] === $participantId) {
$mitgliedRolle = $m['role'];
break;
}
}
if ($mitgliedRolle === 'owner') {
$fehler = 'Der Inhaber kann nicht anonymisiert werden.';
} elseif (ledger_anonymize_participant($pdo, $tenantId, $participantId)) {
app_audit_log($pdo, $tenantId, $actorUserId, 'participant.anonymized', 'participant', $participantId);
$meldung = 'Mitglied wurde anonymisiert. Name und E-Mail sind entfernt, Buchungen bleiben für die Kassenführung erhalten.';
} else {
$fehler = 'Das Mitglied konnte nicht anonymisiert werden.';
}
} elseif ($aktion === 'csv_import') {
$file = $_FILES['mitglieder_csv'] ?? null;
if ($file === null || ($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
$fehler = 'Bitte eine CSV-Datei auswählen.';
} elseif (($file['size'] ?? 0) <= 0 || $file['size'] > 2 * 1024 * 1024) {
$fehler = 'Die CSV-Datei ist leer oder größer als 2 MB.';
} elseif (strtolower(pathinfo((string)$file['name'], PATHINFO_EXTENSION)) !== 'csv') {
$fehler = 'Es sind nur CSV-Dateien erlaubt.';
} elseif (!is_uploaded_file((string)$file['tmp_name'])) {
$fehler = 'Die hochgeladene Datei konnte nicht verifiziert werden.';
} else {
try {
$zeilen = imports_parse_member_csv((string)$file['tmp_name']);
$angelegt = 0;
$uebersprungen = 0;
$inaktivWegenKapazitaet = 0;
$fehlerhaft = 0;
foreach ($zeilen as $z) {
if ($z['name'] === '' || !filter_var($z['email'], FILTER_VALIDATE_EMAIL)) {
$fehlerhaft++;
continue;
}
$aktiv = $z['active'];
if ($aktiv && !billing_has_capacity_for($pdo, $tenantId)) {
$aktiv = false;
$inaktivWegenKapazitaet++;
}
try {
$neueId = ledger_create_participant($pdo, $tenantId, $z['name'], $z['email'], $z['paypal_name'] !== '' ? $z['paypal_name'] : null, $aktiv);
app_audit_log($pdo, $tenantId, $actorUserId, 'participant.created', 'participant', $neueId, ['name' => $z['name'], 'email' => $z['email'], 'quelle' => 'csv_import']);
$angelegt++;
} catch (Throwable $e) {
$uebersprungen++;
}
}
$teile = ["{$angelegt} angelegt"];
if ($uebersprungen > 0) {
$teile[] = "{$uebersprungen} übersprungen (bereits vorhanden)";
}
if ($inaktivWegenKapazitaet > 0) {
$teile[] = "{$inaktivWegenKapazitaet} als inaktiv angelegt (Tarif-Kapazität erschöpft)";
}
if ($fehlerhaft > 0) {
$teile[] = "{$fehlerhaft} fehlerhaft (Name/E-Mail ungültig)";
}
$meldung = 'CSV-Import: ' . implode(', ', $teile) . '.';
} catch (Throwable $e) {
$fehler = 'Die CSV-Datei konnte nicht verarbeitet werden.';
}
}
}
if ($aktion !== 'bearbeiten') {
$_SESSION['flash_mitglieder'] = [
'meldung' => $meldung,
'fehler' => $fehler,
'einladungslink' => $einladungslink,
];
header('Location: mitarbeiterverwalten.php' . $filterSuffix);
exit;
}
}
$mitglieder = ledger_fetch_participants_for_admin($pdo, $tenantId);
$billingInfo = billing_fetch_or_init($pdo, $tenantId);
$billingPlan = billing_plans()[$billingInfo['plan_code']] ?? null;
$aktiveMitgliederAnzahl = billing_count_active_participants($pdo, $tenantId);
$rollenLabels = ['owner' => 'Inhaber', 'admin' => 'Administrator', 'treasurer' => 'Kassenwart', 'member' => 'Mitglied', 'viewer' => 'Betrachter'];
$paypalNameCounts = [];
foreach ($mitglieder as $mitglied) {
$paypalNorm = imports_normalize_match_text((string)($mitglied['paypal_name'] ?? ''));
if ($paypalNorm !== '') {
$paypalNameCounts[$paypalNorm] = ($paypalNameCounts[$paypalNorm] ?? 0) + 1;
}
}
$mitgliederStats = [
'gesamt' => count($mitglieder),
'aktiv' => 0,
'inaktiv' => 0,
'mit_zugang' => 0,
'ohne_zugang' => 0,
'paypal_fehlt' => 0,
'paypal_doppelt' => 0,
];
$gefilterteMitglieder = [];
foreach ($mitglieder as $mitglied) {
$isActive = (bool)$mitglied['active'];
$hasAccessAccount = $mitglied['membership_status'] === 'active';
$paypalName = trim((string)($mitglied['paypal_name'] ?? ''));
$paypalNorm = imports_normalize_match_text($paypalName);
$paypalDuplicate = $paypalNorm !== '' && ($paypalNameCounts[$paypalNorm] ?? 0) > 1;
$mitgliederStats[$isActive ? 'aktiv' : 'inaktiv']++;
$mitgliederStats[$hasAccessAccount ? 'mit_zugang' : 'ohne_zugang']++;
if ($paypalName === '') {
$mitgliederStats['paypal_fehlt']++;
}
if ($paypalDuplicate) {
$mitgliederStats['paypal_doppelt']++;
}
$matches = true;
$q = imports_normalize_match_text((string)$filter['q']);
if ($q !== '') {
$searchText = imports_normalize_match_text(
(string)$mitglied['display_name'] . ' ' . (string)($mitglied['email'] ?? '') . ' ' . $paypalName
);
$matches = str_contains($searchText, $q);
}
if ($matches && $filter['status'] === 'aktiv') {
$matches = $isActive;
}
if ($matches && $filter['status'] === 'inaktiv') {
$matches = !$isActive;
}
if ($matches && $filter['zugang'] === 'mit_zugang') {
$matches = $hasAccessAccount;
}
if ($matches && $filter['zugang'] === 'ohne_zugang') {
$matches = $mitglied['membership_status'] === null || $mitglied['membership_status'] === 'pending';
}
if ($matches && $filter['zugang'] === 'entzogen') {
$matches = $mitglied['membership_status'] === 'revoked';
}
if ($matches && $filter['paypal'] === 'hinterlegt') {
$matches = $paypalName !== '';
}
if ($matches && $filter['paypal'] === 'fehlt') {
$matches = $paypalName === '';
}
if ($matches && $filter['paypal'] === 'doppelt') {
$matches = $paypalDuplicate;
}
if ($matches) {
$mitglied['paypal_duplicate'] = $paypalDuplicate;
$gefilterteMitglieder[] = $mitglied;
}
}
$bearbeitenMitglied = null;
if ($bearbeitenId !== null) {
foreach ($mitglieder as $m) {
if ($m['participant_id'] === $bearbeitenId) {
$bearbeitenMitglied = $m;
break;
}
}
}
?>
<h2>Mitglieder verwalten</h2>
<?php if ($meldung !== null): ?>
<div class="hint-box success"><p><?php echo saas_html($meldung); ?></p></div>
<?php endif; ?>
<?php if ($fehler !== null): ?>
<div class="hint-box error"><p><?php echo saas_html($fehler); ?></p></div>
<?php endif; ?>
<?php if ($einladungslink !== null): ?>
<div class="hint-box"><p>Dev-Link zur Einladung: <a href="<?php echo saas_html($einladungslink); ?>"><?php echo saas_html($einladungslink); ?></a></p></div>
<?php endif; ?>
<p>Aktive Mitglieder: <?php echo (int)$aktiveMitgliederAnzahl; ?><?php echo $billingPlan['max_participants'] !== null ? ' von maximal ' . (int)$billingPlan['max_participants'] . ' im Tarif „' . saas_html($billingPlan['label']) . '"' : ' (Tarif „' . saas_html($billingPlan['label'] ?? $billingInfo['plan_code']) . '", unbegrenzt)'; ?>.
<?php if ($billingPlan['max_participants'] !== null && $aktiveMitgliederAnzahl >= $billingPlan['max_participants']): ?>
Limit erreicht für weitere aktive Mitglieder ist ein <a href="mandant-einstellungen.php">Upgrade</a> nötig.
<?php endif; ?></p>
<div class="admin-summary-grid">
<div><strong><?php echo (int)$mitgliederStats['gesamt']; ?></strong><span>Mitglieder</span></div>
<div><strong><?php echo (int)$mitgliederStats['aktiv']; ?></strong><span>aktiv</span></div>
<div><strong><?php echo (int)$mitgliederStats['mit_zugang']; ?></strong><span>mit Zugang</span></div>
<div><strong><?php echo (int)$mitgliederStats['paypal_fehlt']; ?></strong><span>ohne PayPal-Name</span></div>
<div><strong><?php echo (int)$mitgliederStats['paypal_doppelt']; ?></strong><span>PayPal-Konflikte</span></div>
</div>
<?php if ($bearbeitenMitglied !== null): ?>
<h3>Bearbeiten von <?php echo saas_html($bearbeitenMitglied['display_name']); ?></h3>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<input type="hidden" name="aktion" value="bearbeitenspeichern">
<input type="hidden" name="mitgliedID" value="<?php echo $bearbeitenMitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<label for="name">Name:</label>
<input type="text" name="name" id="name" value="<?php echo saas_html($bearbeitenMitglied['display_name']); ?>" required>
<label for="email">E-Mail:</label>
<input type="email" name="email" id="email" value="<?php echo saas_html($bearbeitenMitglied['email'] ?? ''); ?>" required>
<label for="paypalname">PayPal-Name:</label>
<input type="text" name="paypalname" id="paypalname" value="<?php echo saas_html($bearbeitenMitglied['paypal_name'] ?? ''); ?>">
<br>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="aktiv" id="aktiv" <?php echo $bearbeitenMitglied['active'] ? 'checked' : ''; ?>>
<label class="form-check-label" for="aktiv">Aktiv:</label>
</div>
<button type="submit">Speichern</button>
</form>
<?php endif; ?>
<!-- Formular für das Anlegen von Mitgliedern -->
<h3>Neues Mitglied anlegen</h3>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<input type="hidden" name="aktion" id="aktion" value="anlegen">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<label for="new-name">Name:</label>
<input type="text" name="name" id="new-name" required>
<label for="new-email">E-Mail:</label>
<input type="email" name="email" id="new-email" required>
<label for="new-paypalname">PayPal-Name:</label>
<input type="text" name="paypalname" id="new-paypalname">
<br>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="aktiv" id="new-aktiv" checked>
<label class="form-check-label" for="new-aktiv">Aktiv</label>
</div>
<button type="submit">Mitglied anlegen</button>
</form>
<h3>Mitglieder per CSV importieren</h3>
<p>Lade zunächst die Vorlage herunter, trage eure Mitglieder ein (Name, E-Mail,
optional PayPal-Name und „ja/nein" für aktiv) und lade die Datei anschließend
wieder hoch. Bereits vorhandene E-Mail-Adressen werden übersprungen.</p>
<p><a class="button" href="mitglieder-vorlage.php">Vorlage herunterladen</a></p>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" enctype="multipart/form-data">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<input type="hidden" name="aktion" value="csv_import">
<label for="mitglieder_csv">CSV-Datei mit Mitgliedern:</label>
<input type="file" name="mitglieder_csv" id="mitglieder_csv" accept=".csv" required>
<button type="submit">Mitglieder importieren</button>
</form>
<p>Name und E-Mail dienen der Kaffeeliste und Benachrichtigungen. Ein Login-Zugang
ist davon unabhängig und wird separat je Mitglied gewährt oder entzogen.</p>
<form method="get" action="mitarbeiterverwalten.php" class="admin-filter-bar">
<label for="mitglieder-q">Suche</label>
<input type="search" name="q" id="mitglieder-q" value="<?php echo saas_html((string)$filter['q']); ?>" placeholder="Name, E-Mail oder PayPal">
<label for="mitglieder-status">Status</label>
<select name="status" id="mitglieder-status">
<option value="alle" <?php echo $filter['status'] === 'alle' ? 'selected' : ''; ?>>Alle</option>
<option value="aktiv" <?php echo $filter['status'] === 'aktiv' ? 'selected' : ''; ?>>Aktiv</option>
<option value="inaktiv" <?php echo $filter['status'] === 'inaktiv' ? 'selected' : ''; ?>>Inaktiv</option>
</select>
<label for="mitglieder-zugang">Zugang</label>
<select name="zugang" id="mitglieder-zugang">
<option value="alle" <?php echo $filter['zugang'] === 'alle' ? 'selected' : ''; ?>>Alle</option>
<option value="mit_zugang" <?php echo $filter['zugang'] === 'mit_zugang' ? 'selected' : ''; ?>>Mit Zugang</option>
<option value="ohne_zugang" <?php echo $filter['zugang'] === 'ohne_zugang' ? 'selected' : ''; ?>>Ohne Zugang</option>
<option value="entzogen" <?php echo $filter['zugang'] === 'entzogen' ? 'selected' : ''; ?>>Entzogen</option>
</select>
<label for="mitglieder-paypal">PayPal</label>
<select name="paypal" id="mitglieder-paypal">
<option value="alle" <?php echo $filter['paypal'] === 'alle' ? 'selected' : ''; ?>>Alle</option>
<option value="hinterlegt" <?php echo $filter['paypal'] === 'hinterlegt' ? 'selected' : ''; ?>>Hinterlegt</option>
<option value="fehlt" <?php echo $filter['paypal'] === 'fehlt' ? 'selected' : ''; ?>>Fehlt</option>
<option value="doppelt" <?php echo $filter['paypal'] === 'doppelt' ? 'selected' : ''; ?>>Konflikte</option>
</select>
<button type="submit">Filtern</button>
<a class="button alt" href="mitarbeiterverwalten.php">Zurücksetzen</a>
</form>
<p><?php echo count($gefilterteMitglieder); ?> von <?php echo count($mitglieder); ?> Mitgliedern angezeigt.</p>
<!-- Tabelle zur Anzeige und Bearbeitung von Mitgliedern -->
<div class="table-wrapper">
<table class="table table-striped admin-table">
<tr>
<th>Name</th>
<th>E-Mail</th>
<th>PayPal-Name</th>
<th>Aktiv</th>
<th>Zugang</th>
<th>Aktionen</th>
</tr>
<?php foreach ($gefilterteMitglieder as $mitglied): ?>
<tr>
<td><?php echo saas_html($mitglied['display_name']); ?></td>
<td><?php echo saas_html($mitglied['email'] ?? ''); ?></td>
<td>
<?php echo saas_html($mitglied['paypal_name'] ?? ''); ?>
<?php if (!empty($mitglied['paypal_duplicate'])): ?>
<br><span class="status-badge warning">Konflikt</span>
<?php endif; ?>
</td>
<td><?php echo mitglieder_status_badge((bool)$mitglied['active']); ?></td>
<td>
<?php if ($mitglied['membership_status'] === 'active'): ?>
<?php if ($mitglied['role'] === 'owner'): ?>
<span class="status-badge info">Inhaber</span>
<?php else: ?>
<span class="status-badge success"><?php echo saas_html($rollenLabels[$mitglied['role']] ?? $mitglied['role']); ?></span>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" class="inline-admin-form">
<input type="hidden" name="aktion" value="zugang_gewaehren">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<select name="rolle">
<?php foreach (saas_grantable_roles() as $rolle): ?>
<option value="<?php echo saas_html($rolle); ?>" <?php echo $rolle === $mitglied['role'] ? 'selected' : ''; ?>><?php echo saas_html($rollenLabels[$rolle] ?? $rolle); ?></option>
<?php endforeach; ?>
</select>
<button type="submit">Rolle ändern</button>
</form>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" class="inline-admin-form">
<input type="hidden" name="aktion" value="zugang_entziehen">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<button type="submit">Zugang entziehen</button>
</form>
<?php endif; ?>
<?php else: ?>
<span class="status-badge <?php echo $mitglied['membership_status'] === 'revoked' ? 'warning' : 'muted'; ?>"><?php echo saas_html(mitglieder_access_label($mitglied, $rollenLabels)); ?></span>
<?php if ($mitglied['email'] !== null && $mitglied['email'] !== ''): ?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" class="inline-admin-form">
<input type="hidden" name="aktion" value="zugang_gewaehren">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<select name="rolle">
<?php foreach (saas_grantable_roles() as $rolle): ?>
<option value="<?php echo saas_html($rolle); ?>"><?php echo saas_html($rollenLabels[$rolle] ?? $rolle); ?></option>
<?php endforeach; ?>
</select>
<button type="submit">Zugang gewähren</button>
</form>
<?php endif; ?>
<?php endif; ?>
</td>
<td>
<ul class="actions compact-actions">
<li>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<input type="hidden" name="aktion" value="bearbeiten">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<button type="submit">Bearbeiten</button>
</form>
</li>
<li>
<?php if ($mitglied['active']): ?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<input type="hidden" name="aktion" value="deaktivieren">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<button type="submit">Deaktivieren</button>
</form>
<?php else: ?>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>">
<input type="hidden" name="aktion" value="aktivieren">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<button type="submit">Aktivieren</button>
</form>
<?php endif; ?>
</li>
<?php if ($mitglied['role'] !== 'owner'): ?>
<li>
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" onsubmit="return confirm('Name und E-Mail dieses Mitglieds unwiderruflich entfernen? Buchungen bleiben erhalten.');">
<input type="hidden" name="aktion" value="anonymisieren">
<input type="hidden" name="mitgliedID" value="<?php echo $mitglied['participant_id']; ?>">
<?php echo app_csrf_field(); ?>
<?php echo mitglieder_filter_fields($filter); ?>
<button type="submit">Anonymisieren</button>
</form>
</li>
<?php endif; ?>
</ul>
</td>
</tr>
<?php endforeach; ?>
<?php if ($gefilterteMitglieder === []): ?>
<tr><td colspan="6">Keine Mitglieder für diese Filter gefunden.</td></tr>
<?php endif; ?>
</table>
</div>
<?php
}else{
echo "<h2>Sie haben keinen Zugang zu dieser Webseite</h2>";
}
?>
</div>
</section>
<?php include "footer.php"; ?>