Files
deskhub/DeskHub-Webseite/staff/profile.php
T
2026-10-25 17:47:01 +00:00

535 lines
26 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
require_once __DIR__ . '/../includes/bootstrap.php';
require_once __DIR__ . '/../includes/totp.php';
$staff = require_staff_login();
$pdo = get_db();
$errors = [];
$tab = $_GET['tab'] ?? 'account';
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$action = $_POST['action'] ?? '';
// ── Konto-Daten ─────────────────────────────────────────────
if ($action === 'save_account') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone = trim($_POST['phone'] ?? '');
if ($name === '') $errors[] = 'Bitte einen Namen angeben.';
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'Bitte eine gültige E-Mail-Adresse angeben.';
// E-Mail-Duplikat prüfen (andere Mitarbeiter)
if (!$errors) {
$dup = $pdo->prepare('SELECT COUNT(*) FROM staff WHERE LOWER(email) = LOWER(?) AND id != ?');
$dup->execute([$email, $staff['id']]);
if ((int)$dup->fetchColumn()) $errors[] = 'Diese E-Mail-Adresse wird bereits von einem anderen Mitarbeiter verwendet.';
}
if (!$errors) {
$pdo->prepare('UPDATE staff SET name=?, email=?, phone=? WHERE id=?')
->execute([$name, $email, $phone ?: null, $staff['id']]);
audit_log($staff['id'], 'Profil aktualisiert: Name/E-Mail/Telefon');
flash('success', 'Kontodaten gespeichert.');
redirect('/staff/profile.php?tab=account');
}
$tab = 'account';
}
// ── Passwort ─────────────────────────────────────────────────
if ($action === 'save_password') {
$current = $_POST['current_password'] ?? '';
$new = $_POST['new_password'] ?? '';
$confirm = $_POST['confirm_password'] ?? '';
if (!password_verify($current, $staff['password_hash'])) {
$errors[] = 'Das aktuelle Passwort ist falsch.';
}
$pwError = validate_password_strength($new);
if ($pwError) {
$errors[] = $pwError;
}
if ($new !== $confirm) {
$errors[] = 'Die Passwörter stimmen nicht überein.';
}
if (!$errors) {
$pdo->prepare('UPDATE staff SET password_hash=? WHERE id=?')
->execute([password_hash($new, PASSWORD_DEFAULT), $staff['id']]);
audit_log($staff['id'], 'Passwort geändert');
flash('success', 'Passwort geändert.');
redirect('/staff/profile.php?tab=account');
}
$tab = 'account';
}
// ── Avatar ────────────────────────────────────────────────────
if ($action === 'save_avatar') {
if (!empty($_FILES['avatar']['name'])) {
$allowed = ['jpg','jpeg','png','gif','webp'];
$ext = strtolower(pathinfo($_FILES['avatar']['name'], PATHINFO_EXTENSION));
if (!in_array($ext, $allowed)) {
$errors[] = 'Erlaubte Bildformate: JPG, PNG, GIF, WEBP.';
} elseif ($_FILES['avatar']['size'] > 2 * 1024 * 1024) {
$errors[] = 'Maximale Dateigröße: 2 MB.';
} elseif (($imgErr = favicon_validate_file($_FILES['avatar']['tmp_name'], $ext)) !== null) {
$errors[] = $imgErr;
} else {
$dir = __DIR__ . '/../assets/avatars/';
if (!is_dir($dir)) mkdir($dir, 0755, true);
// Alten Avatar löschen
if ($staff['avatar_path']) {
$old = __DIR__ . '/..' . $staff['avatar_path'];
if (file_exists($old)) unlink($old);
}
$filename = 'avatar_' . $staff['id'] . '_' . time() . '.' . $ext;
move_uploaded_file($_FILES['avatar']['tmp_name'], $dir . $filename);
$path = '/assets/avatars/' . $filename;
$pdo->prepare('UPDATE staff SET avatar_path=? WHERE id=?')->execute([$path, $staff['id']]);
flash('success', 'Avatar aktualisiert.');
redirect('/staff/profile.php?tab=account');
}
}
$tab = 'account';
}
if ($action === 'delete_avatar') {
if ($staff['avatar_path']) {
$old = __DIR__ . '/..' . $staff['avatar_path'];
if (file_exists($old)) unlink($old);
}
$pdo->prepare('UPDATE staff SET avatar_path=NULL WHERE id=?')->execute([$staff['id']]);
flash('success', 'Avatar entfernt.');
redirect('/staff/profile.php?tab=account');
}
// ── Urlaub/Abwesenheit ─────────────────────────────────────
if ($action === 'save_settings') {
$onVacation = !empty($_POST['is_on_vacation']) ? 1 : 0;
$substituteId = ($_POST['vacation_substitute_id'] ?? '') !== '' ? (int)$_POST['vacation_substitute_id'] : null;
$pdo->prepare('UPDATE staff SET is_on_vacation=?, vacation_substitute_id=? WHERE id=?')
->execute([$onVacation, $substituteId, $staff['id']]);
audit_log($staff['id'], $onVacation ? 'Abwesenheit aktiviert' : 'Abwesenheit deaktiviert');
flash('success', 'Einstellungen gespeichert.');
redirect('/staff/profile.php?tab=settings');
}
// ── Android-Push: welche Popups, stille Zeiten ─────────────────
if ($action === 'save_push_prefs') {
$ev = array_map('strval', (array) ($_POST['push_events'] ?? []));
$qf = trim((string) ($_POST['quiet_from'] ?? ''));
$qt = trim((string) ($_POST['quiet_to'] ?? ''));
if (($qf !== '' || $qt !== '') && (!fcm_time_valid($qf) || !fcm_time_valid($qt))) {
flash('error', 'Stille Zeiten bitte als Uhrzeit von/bis angeben (z. B. 22:00 und 06:00).');
redirect('/staff/profile.php?tab=account');
}
fcm_save_prefs($pdo, (int) $staff['id'], $ev, $qf, $qt, array_keys(fcm_event_types_for($staff)));
flash('success', 'Push-Einstellungen gespeichert.');
redirect('/staff/profile.php?tab=account');
}
// ── 2FA aktivieren ─────────────────────────────────────────────
if ($action === 'enable_2fa') {
$code = trim($_POST['totp_code'] ?? '');
$secret = $_SESSION['totp_setup_secret'] ?? '';
if (!$secret) {
flash('error', 'Sitzungsfehler. Bitte nochmals versuchen.');
} elseif (!totp_verify($secret, $code)) {
flash('error', 'Code ungültig. Bitte erneut versuchen.');
} else {
$pdo->prepare('UPDATE staff SET totp_secret=?, totp_enabled=1 WHERE id=?')->execute([$secret, $staff['id']]);
unset($_SESSION['totp_setup_secret']);
audit_log($staff['id'], 'Zwei-Faktor-Authentifizierung aktiviert');
flash('success', '2FA wurde erfolgreich aktiviert.');
}
redirect('/staff/profile.php?tab=security');
}
// ── 2FA deaktivieren ───────────────────────────────────────────
if ($action === 'disable_2fa') {
$pass = $_POST['confirm_password'] ?? '';
$me = $pdo->prepare('SELECT password_hash FROM staff WHERE id=?');
$me->execute([$staff['id']]);
$me = $me->fetch();
if (!password_verify($pass, $me['password_hash'])) {
flash('error', 'Falsches Passwort.');
} else {
$pdo->prepare('UPDATE staff SET totp_secret=NULL, totp_enabled=0 WHERE id=?')->execute([$staff['id']]);
audit_log($staff['id'], 'Zwei-Faktor-Authentifizierung deaktiviert');
flash('success', '2FA wurde deaktiviert.');
}
redirect('/staff/profile.php?tab=security');
}
// ── Signatur ──────────────────────────────────────────────────
if ($action === 'save_signature') {
$sig = sanitize_staff_html(trim($_POST['signature'] ?? ''));
$pdo->prepare('UPDATE staff SET signature=? WHERE id=?')->execute([$sig ?: null, $staff['id']]);
flash('success', 'Signatur gespeichert.');
redirect('/staff/profile.php?tab=signature');
}
}
// Aktuellen Stand neu laden (nach Redirect relevant wenn $_SESSION cached)
$staffRow = $pdo->prepare('SELECT * FROM staff WHERE id = ?');
$staffRow->execute([$staff['id']]);
$me = $staffRow->fetch();
$pageTitle = 'Mein Profil';
$activePage = 'profile';
require __DIR__ . '/_header.php';
?>
<div style="max-width:740px">
<h1>Mein Profil</h1>
<?php foreach ($errors as $err): ?>
<div class="flash error"><?= e($err) ?></div>
<?php endforeach; ?>
<!-- Tab-Navigation -->
<div style="display:flex; border-bottom:2px solid var(--border); margin-bottom:24px; gap:0">
<?php foreach (['account' => '👤 Konto', 'settings' => '⚙ Einstellungen', 'signature' => '✍ Signatur', 'security' => '🔒 Sicherheit'] as $t => $label): ?>
<a href="/staff/profile.php?tab=<?= $t ?>"
style="padding:10px 22px; font-size:.9rem; font-weight:600; text-decoration:none; border-bottom:3px solid <?= $tab===$t ? 'var(--primary)' : 'transparent' ?>; margin-bottom:-2px; color:<?= $tab===$t ? 'var(--primary)' : 'var(--muted)' ?>">
<?= $label ?>
</a>
<?php endforeach; ?>
</div>
<!-- ══ KONTO ══════════════════════════════════════════════════ -->
<?php if ($tab === 'account'): ?>
<div class="card">
<h3>Profilbild</h3>
<div style="display:flex; gap:20px; align-items:flex-start">
<div style="flex-shrink:0">
<?php if ($me['avatar_path']): ?>
<img src="<?= e($me['avatar_path']) ?>" alt="Avatar"
style="width:80px; height:80px; border-radius:50%; object-fit:cover; border:2px solid var(--border)">
<?php else: ?>
<div style="width:80px; height:80px; border-radius:50%; background:var(--primary-lt); display:flex; align-items:center; justify-content:center; font-size:2rem; border:2px solid var(--border)">
<?= mb_strtoupper(mb_substr($me['name'], 0, 1)) ?>
</div>
<?php endif; ?>
</div>
<div style="flex:1">
<form method="post" enctype="multipart/form-data">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_avatar">
<label for="avatar">Neues Bild hochladen (JPG, PNG, WEBP · max. 2 MB)</label>
<div style="display:flex; gap:8px; align-items:center; margin-top:6px">
<input type="file" id="avatar" name="avatar" accept="image/*" style="flex:1">
<button type="submit" class="btn secondary" style="white-space:nowrap">Hochladen</button>
</div>
</form>
<?php if ($me['avatar_path']): ?>
<form method="post" style="margin-top:8px">
<?= csrf_field() ?>
<input type="hidden" name="action" value="delete_avatar">
<button type="submit" style="background:none;border:none;color:var(--danger);font-size:.82rem;cursor:pointer;padding:0">Bild entfernen</button>
</form>
<?php endif; ?>
</div>
</div>
</div>
<div class="card">
<h3>Kontodaten</h3>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_account">
<label for="name">Name</label>
<input type="text" id="name" name="name" value="<?= e($me['name']) ?>" required>
<label for="email">E-Mail-Adresse</label>
<input type="email" id="email" name="email" value="<?= e($me['email']) ?>" required>
<label for="phone">Telefonnummer (optional)</label>
<input type="text" id="phone" name="phone" value="<?= e($me['phone'] ?? '') ?>" placeholder="z.B. +49 89 123456">
<div class="btn-row">
<button type="submit" class="btn">Speichern</button>
</div>
</form>
</div>
<div class="card">
<h3>Passwort ändern</h3>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_password">
<label for="current_password">Aktuelles Passwort</label>
<input type="password" id="current_password" name="current_password" required autocomplete="current-password">
<div class="field-row">
<div>
<label for="new_password">Neues Passwort</label>
<input type="password" id="new_password" name="new_password" required autocomplete="new-password" minlength="10" placeholder="mind. 10 Zeichen, Groß-/Klein, Ziffer, Sonderzeichen">
</div>
<div>
<label for="confirm_password">Passwort wiederholen</label>
<input type="password" id="confirm_password" name="confirm_password" required autocomplete="new-password">
</div>
</div>
<div class="btn-row">
<button type="submit" class="btn">Passwort ändern</button>
</div>
</form>
</div>
<!-- Push-Benachrichtigungen -->
<?php
$pushVapidKey = '';
if (file_exists(__DIR__ . '/../includes/push.php')) {
require_once __DIR__ . '/../includes/push.php';
$__keys = get_or_create_vapid_keys();
$pushVapidKey = $__keys['public_key'] ?? '';
}
?>
<div class="card">
<h3>Browser-Push-Benachrichtigungen</h3>
<?php if ($pushVapidKey): ?>
<p class="muted" style="font-size:.84rem;margin-bottom:16px">
Erhalte Desktop-Benachrichtigungen bei neuen Tickets und Antworten — auch wenn der Browser-Tab nicht aktiv ist.
Funktioniert in Chrome, Firefox und Edge. Erfordert HTTPS.
</p>
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:16px">
<span id="push-status-icon" style="font-size:1.4rem">🔕</span>
<div>
<div id="push-status-text" style="font-size:.85rem;font-weight:500">Deaktiviert</div>
<div id="push-status-sub" style="font-size:.76rem;color:var(--muted)">Klicken Sie auf Aktivieren um Benachrichtigungen zu erhalten</div>
</div>
<button type="button" id="push-toggle-btn" onclick="togglePushNotifications()"
class="btn secondary" style="margin-left:auto">
Aktivieren
</button>
</div>
<div style="padding-top:14px;border-top:1px solid var(--border-soft)">
<div style="font-size:.75rem;font-weight:600;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin-bottom:8px">Benachrichtigungen erhalten bei:</div>
<div style="display:flex;flex-direction:column;gap:5px;font-size:.83rem;color:var(--ink-soft)">
<div>✅ Neues Ticket in meiner Abteilung</div>
<div>✅ Neue Antwort auf mir zugewiesenes Ticket</div>
</div>
</div>
<input type="hidden" id="push-vapid-key" value="<?= e($pushVapidKey) ?>">
<?php else: ?>
<p class="muted" style="font-size:.84rem">
Push-Benachrichtigungen sind auf diesem Server nicht verfügbar (OpenSSL-Erweiterung fehlt oder PHP zu alt).
</p>
<?php endif; ?>
</div>
<?php $__pp = fcm_prefs($pdo, (int) $staff['id']); ?>
<div class="card">
<h3>📱 Android-App: Welche Popups?</h3>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_push_prefs">
<p class="muted" style="font-size:.84rem;margin-bottom:10px">Wähle, wofür die App ein Popup zeigen soll.</p>
<?php foreach (fcm_event_types_for($staff) as $__k => $__label): ?>
<label style="display:flex;align-items:center;gap:8px;margin:6px 0;font-weight:400"><input type="checkbox" name="push_events[]" value="<?= e($__k) ?>" style="width:auto" <?= in_array($__k, $__pp['events'], true) ? 'checked' : '' ?>> <?= e($__label) ?></label>
<?php endforeach; ?>
<div style="margin-top:12px;font-size:.84rem;font-weight:600">Stille Zeiten (keine Popups)</div>
<div style="display:flex;align-items:center;gap:8px;margin-top:6px">
von <input type="time" name="quiet_from" value="<?= e($__pp['quiet_from']) ?>" style="width:auto"> bis <input type="time" name="quiet_to" value="<?= e($__pp['quiet_to']) ?>" style="width:auto">
</div>
<p class="muted" style="font-size:.78rem;margin-top:4px">Beide Felder leer = immer Popups. Die Zeit gilt nach der Serverzeit (<?= e(date_default_timezone_get()) ?>), auch über Mitternacht (z. B. 22:00 bis 06:00).</p>
<div class="btn-row"><button type="submit" class="btn">Speichern</button></div>
</form>
</div>
<!-- ══ EINSTELLUNGEN ══════════════════════════════════════════ -->
<?php elseif ($tab === 'settings'): ?>
<div class="card">
<h3>Abwesenheit / Urlaub</h3>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_settings">
<?php
$allAgents = get_db()->query('SELECT id, name FROM staff WHERE is_active=1 ORDER BY name')->fetchAll();
?>
<label style="display:flex; align-items:flex-start; gap:12px; cursor:pointer; font-weight:400">
<input type="checkbox" name="is_on_vacation" value="1" style="width:auto; margin-top:3px; flex-shrink:0" <?= $me['is_on_vacation'] ? 'checked' : '' ?>>
<span>
<strong>Urlaubsmodus aktiv</strong><br>
<span class="muted" style="font-size:.84rem">Neue Tickets werden nicht automatisch diesem Konto zugewiesen, während der Urlaubsmodus aktiv ist. Bereits zugewiesene Tickets bleiben unverändert.</span>
</span>
</label>
<label style="margin-top:14px">Vertretung (optional)</label>
<select name="vacation_substitute_id">
<option value="">– keine Vertretung –</option>
<?php foreach ($allAgents as $a): if ($a['id'] == $me['id']) continue; ?>
<option value="<?= $a['id'] ?>" <?= ($me['vacation_substitute_id'] ?? '') == $a['id'] ? 'selected' : '' ?>><?= e($a['name']) ?></option>
<?php endforeach; ?>
</select>
<p class="muted" style="font-size:.8rem">Neue Tickets werden während Ihrer Abwesenheit automatisch dieser Person zugewiesen.</p>
<?php if ($me['is_on_vacation']): ?>
<div class="flash info" style="margin-top:8px">Urlaubsmodus ist aktuell <strong>aktiv</strong>. Sie erhalten keine automatischen Ticket-Zuweisungen.</div>
<?php endif; ?>
<div class="btn-row">
<button type="submit" class="btn">Speichern</button>
</div>
</form>
</div>
<div class="card">
<h3>Übersicht</h3>
<div style="display:flex; flex-direction:column; gap:12px; font-size:.9rem">
<div style="display:flex; gap:16px">
<span style="color:var(--muted); width:130px; flex-shrink:0">Rolle</span>
<span><?= $me['role'] === 'admin' ? '<span class="badge" style="background:var(--accent)">Administrator</span>' : '<span class="badge" style="background:var(--primary)">Mitarbeiter</span>' ?></span>
</div>
<div style="display:flex; gap:16px">
<span style="color:var(--muted); width:130px; flex-shrink:0">Mitglied seit</span>
<span><?= format_dt($me['created_at']) ?></span>
</div>
<?php
$ticketCount = $pdo->prepare('SELECT COUNT(*) FROM tickets WHERE assigned_staff_id = ?');
$ticketCount->execute([$me['id']]);
$myCount = $ticketCount->fetchColumn();
?>
<div style="display:flex; gap:16px">
<span style="color:var(--muted); width:130px; flex-shrink:0">Zugewiesene Tickets</span>
<span><a href="/staff/tickets.php?assigned=me"><?= (int)$myCount ?></a></span>
</div>
</div>
</div>
<!-- ══ SIGNATUR ════════════════════════════════════════════════ -->
<?php elseif ($tab === 'signature'): ?>
<div class="card">
<h3>E-Mail-Signatur</h3>
<p class="muted" style="margin-bottom:14px; font-size:.875rem">
Wird automatisch an Ihre ausgehenden Ticket-Antworten angehängt.
Ist keine Mitarbeiter-Signatur gesetzt, greift die Abteilungs-Signatur.
</p>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_signature">
<textarea id="signature" name="signature" data-richtext data-image-upload-url="/staff/upload_signature_image.php" style="min-height:180px"><?= e($me['signature'] ?? '') ?></textarea>
<p class="muted" style="font-size:.8rem;margin-top:8px">Bilder einfügen mit 🖼️. Zum Verkleinern oder Vergrößern das Bild anklicken: Mit dem runden Anfasser ziehen oder 25 / 50 / 75 % / Original wählen.</p>
<div class="btn-row">
<button type="submit" class="btn">Speichern</button>
<button type="button" class="btn secondary" id="sig-clear">Löschen</button>
</div>
</form>
<?php if ($me['signature']): ?>
<div style="margin-top:20px; padding-top:16px; border-top:1px solid var(--border-soft)">
<p class="muted" style="font-size:.78rem; margin-bottom:8px">Vorschau:</p>
<div style="border:1px solid var(--border); border-radius:8px; padding:14px 16px; font-size:.9rem; line-height:1.65">
<?= $me['signature'] ?>
</div>
</div>
<?php endif; ?>
</div>
<script>
document.getElementById('sig-clear').addEventListener('click', function () {
var ta = document.getElementById('signature');
var ed = ta.previousElementSibling;
if (ed && ed.classList.contains('richtext-editable')) ed.innerHTML = '';
ta.value = '';
});
</script>
<?php elseif ($tab === 'security'): ?>
<?php
require_once __DIR__ . '/../includes/totp.php';
$me2 = get_db()->prepare('SELECT totp_enabled, totp_secret, email FROM staff WHERE id=?');
$me2->execute([$staff['id']]);
$me2 = $me2->fetch();
if (!$me2['totp_enabled'] && empty($_SESSION['totp_setup_secret'])) {
$_SESSION['totp_setup_secret'] = totp_generate_secret();
}
$setupSecret = $_SESSION['totp_setup_secret'] ?? '';
?>
<div class="card">
<h3>🔒 Zwei-Faktor-Authentifizierung (2FA)</h3>
<?php if ($me2['totp_enabled']): ?>
<div class="flash info">2FA ist aktuell <strong>aktiv</strong>.</div>
<p class="muted" style="margin-top:14px">Um 2FA zu deaktivieren, bestätigen Sie mit Ihrem Passwort:</p>
<form method="post" style="margin-top:10px">
<?= csrf_field() ?>
<input type="hidden" name="action" value="disable_2fa">
<input type="password" name="confirm_password" placeholder="Aktuelles Passwort" required>
<div class="btn-row">
<button type="submit" class="btn secondary" style="border-color:var(--danger);color:var(--danger)" onclick="return confirm('2FA wirklich deaktivieren?')">2FA deaktivieren</button>
</div>
</form>
<?php else: ?>
<p class="muted">Schützen Sie Ihr Konto mit einem zeitbasierten Einmalcode (TOTP – kompatibel mit Google Authenticator, Authy, etc.).</p>
<ol style="margin:16px 0; padding-left:20px; line-height:2">
<li>Installieren Sie <strong>Google Authenticator</strong> oder <strong>Authy</strong></li>
<li>Scannen Sie den QR-Code oder geben Sie den Schlüssel manuell ein</li>
<li>Tragen Sie den 6-stelligen Code ein und klicken Sie „2FA aktivieren"</li>
</ol>
<div style="display:flex; gap:24px; align-items:flex-start; flex-wrap:wrap; margin:20px 0">
<img src="<?= e(totp_qr_url($setupSecret, $me2['email'])) ?>" alt="QR-Code" style="width:160px;height:160px;border:4px solid var(--border);border-radius:8px">
<div>
<div style="font-size:.78rem; color:var(--muted); margin-bottom:6px">Manueller Schlüssel:</div>
<code style="font-size:.95rem; letter-spacing:.1em; background:var(--bg-soft); padding:8px 12px; border-radius:6px; display:block"><?= e(chunk_split($setupSecret, 4, ' ')) ?></code>
</div>
</div>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="enable_2fa">
<label for="totp_code">Code aus der App</label>
<input type="text" id="totp_code" name="totp_code" inputmode="numeric" pattern="\d{6}" maxlength="6" required placeholder="000000" style="letter-spacing:.2em;font-size:1.2rem;max-width:160px">
<div class="btn-row"><button type="submit" class="btn">2FA aktivieren</button></div>
</form>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<script>
// Push-Status auf Profilseite prüfen und Button aktualisieren
(function() {
var keyInput = document.getElementById('push-vapid-key');
var btn = document.getElementById('push-toggle-btn');
var statusText = document.getElementById('push-status-text');
var statusSub = document.getElementById('push-status-sub');
var statusIcon = document.getElementById('push-status-icon');
if (!keyInput) return; // Push-Karte nicht sichtbar
if (!('serviceWorker' in navigator) || !('PushManager' in window)) {
statusText.textContent = 'Nicht unterstützt';
statusSub.textContent = 'Ihr Browser unterstützt keine Push-Benachrichtigungen.';
statusIcon.textContent = '⚠️';
btn.style.display = 'none';
return;
}
function setActive(active) {
if (active) {
statusIcon.textContent = '🔔';
statusText.textContent = 'Aktiv';
statusText.style.color = '#22c55e';
statusSub.textContent = 'Sie erhalten Desktop-Benachrichtigungen';
btn.textContent = 'Deaktivieren';
btn.style.borderColor = '#ef4444';
btn.style.color = '#ef4444';
} else {
statusIcon.textContent = '🔕';
statusText.textContent = 'Deaktiviert';
statusText.style.color = '';
statusSub.textContent = 'Klicken Sie auf Aktivieren um Benachrichtigungen zu erhalten';
btn.textContent = 'Aktivieren';
btn.style.borderColor = '';
btn.style.color = '';
}
}
navigator.serviceWorker.ready.then(function(reg) {
reg.pushManager.getSubscription().then(function(sub) {
setActive(!!(sub && Notification.permission === 'granted'));
});
});
})();
</script>
<?php require __DIR__ . '/_footer.php'; ?>