638 lines
27 KiB
PHP
638 lines
27 KiB
PHP
<?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"; ?>
|