Files
intranet/web/intranet_repo/projects/adminpanel/admin_inbox.php
T

565 lines
23 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 /* Name: admin_inbox.php
Beschreibung: Admin-Nachrichteninbox
- Registrierungsanfragen
- Kontaktformular-Anfragen
- Systemnachrichten
- Seelsorge-Nachrichten
- Info-Nachrichten */
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
// Admin-Check
$stmt = $pdo->prepare("SELECT \"Admin\" FROM user_permissions WHERE user_id = ?");
$stmt->execute([$_SESSION["user_id"]]);
$isAdmin = $stmt->fetchColumn();
if ((int)$isAdmin !== 1) {
header("Location: {$g_httpHomePath}");
exit();
}
// Typ-Konfiguration für Inbox
$typeConfig = [
'registration' => ['label' => 'Registrierung', 'class' => 'inbox-type-registration'],
'contact' => ['label' => 'Kontakt', 'class' => 'inbox-type-contact'],
'system' => ['label' => 'System', 'class' => 'inbox-type-system'],
];
// Filter
$activeFilter = $_GET['filter'] ?? 'all';
$validFilters = array_merge(['all'], array_keys($typeConfig));
if (!in_array($activeFilter, $validFilters, true)) $activeFilter = 'all';
function getTypeLabel($type, $typeConfig) {
return $typeConfig[$type]['label'] ?? ucfirst($type);
}
function getTypeClass($type, $typeConfig) {
return $typeConfig[$type]['class'] ?? 'inbox-type-system';
}
// Kontaktnachricht als erledigt markieren
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["mark_done"])) {
$msgId = (int)$_POST["mark_done"];
$stmt = $pdo->prepare("UPDATE admin_messages SET status = 'done', processed_at = NOW() WHERE id = ?");
$stmt->execute([$msgId]);
header("Location: admin_inbox.php?inbox_status=done");
exit();
}
// Brandschutz-Eskalation: Admin bestätigt persönliche Erinnerung
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_POST["bs_escalation_confirm"])) {
$msgId = (int)$_POST["bs_escalation_msg_id"];
$bsUserId = (int)$_POST["bs_escalation_user_id"];
// Nachricht als erledigt markieren
$stmt = $pdo->prepare("UPDATE admin_messages SET status = 'done', processed_at = NOW() WHERE id = ?");
$stmt->execute([$msgId]);
// Log-Eintrag erstellen
$adminName = trim(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? ''));
if (empty($adminName)) $adminName = 'Ein Administrator';
$stmtUser = $pdo->prepare("SELECT first_name, last_name, mail FROM user_general_information WHERE user_id = ?");
$stmtUser->execute([$bsUserId]);
$bsUserData = $stmtUser->fetch(PDO::FETCH_ASSOC);
$bsUserName = trim(($bsUserData['first_name'] ?? '') . ' ' . ($bsUserData['last_name'] ?? ''));
if (empty($bsUserName)) $bsUserName = $bsUserData['mail'] ?? 'Unbekannt';
$logSubject = "Persönliche Brandschutz-Erinnerung bestätigt: {$bsUserName}";
$logMessage = "{$adminName} hat bestätigt, {$bsUserName} persönlich an die ausstehende Brandschutzunterweisung erinnert zu haben.";
$stmtLog = $pdo->prepare("INSERT INTO admin_messages (type, sender_name, sender_email, subject, message, status, processed_at, created_at) VALUES ('system', ?, ?, ?, ?, 'done', NOW(), NOW())");
$senderMail = $bsUserData['mail'] ?? '';
$stmtLog->execute([$adminName, $senderMail, $logSubject, $logMessage]);
header("Location: admin_inbox.php?inbox_status=done");
exit();
}
// Nachrichten laden (mit optionalem Filter)
$filterClause = '';
if ($activeFilter !== 'all') {
$filterClause = " AND type = '" . $activeFilter . "'";
}
$pendingMessages = $pdo->query("SELECT * FROM admin_messages WHERE status = 'pending'{$filterClause} ORDER BY created_at DESC")->fetchAll(PDO::FETCH_ASSOC);
$doneMessages = $pdo->query("SELECT * FROM admin_messages WHERE status = 'done'{$filterClause} ORDER BY processed_at DESC LIMIT 20")->fetchAll(PDO::FETCH_ASSOC);
// Rollen laden für Registrierungs-Modal
$permissionRoles = [];
$rolesResult = $pdo->query("SELECT column_name FROM information_schema.columns WHERE table_name = 'user_permissions' AND table_schema = 'public'");
while ($col = $rolesResult->fetch(PDO::FETCH_ASSOC)) {
if (!in_array($col['column_name'], ['p_id', 'user_id'], true)) {
$permissionRoles[] = $col['column_name'];
}
}
?>
<!DOCTYPE html>
<html lang="de" dir="ltr">
<head>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
<style>
.inbox-shell {
padding: 18px;
background: linear-gradient(135deg, var(--gray-50) 0%, var(--theme-light, var(--nak-blue-light)) 100%);
min-height: 100%;
}
.inbox-card {
overflow: hidden;
border: 1px solid rgba(120, 140, 160, 0.22);
background: rgba(255,255,255,0.86);
box-shadow: 0 20px 45px rgba(31, 38, 46, 0.10), 0 1px 0 rgba(255,255,255,0.9) inset;
margin-bottom: 18px;
}
.inbox-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 16px 18px 12px 18px;
border-bottom: 1px solid rgba(120, 140, 160, 0.16);
background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.72));
}
.inbox-title {
font-size: 1.05em;
font-weight: 800;
color: hsl(210, 20%, 15%);
}
.inbox-count {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 24px;
height: 24px;
padding: 0 7px;
background: hsl(0, 78%, 47%);
color: #FFFFFF;
font-size: 0.78em;
font-weight: 850;
}
.inbox-item {
padding: 16px 18px;
border-bottom: 1px solid rgba(120, 140, 160, 0.1);
transition: background 0.18s ease;
}
.inbox-item:last-child { border-bottom: none; }
.inbox-item:hover { background: hsl(210, 57%, 97%); }
.inbox-item-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 6px;
}
.inbox-item-type {
display: inline-flex;
align-items: center;
padding: 3px 8px;
font-size: 0.72em;
font-weight: 800;
}
.inbox-type-registration {
color: hsl(210, 57%, 34%);
background: hsl(210, 57%, 94%);
border: 1px solid hsl(210, 57%, 88%);
}
.inbox-type-contact {
color: hsl(145, 50%, 32%);
background: hsl(145, 50%, 93%);
border: 1px solid hsl(145, 50%, 85%);
}
.inbox-type-system {
color: hsl(30, 70%, 36%);
background: hsl(30, 70%, 94%);
border: 1px solid hsl(30, 70%, 85%);
}
.inbox-item-date {
font-size: 0.82em;
color: hsl(210, 14%, 50%);
font-weight: 600;
}
.inbox-item-subject {
font-weight: 800;
color: hsl(210, 20%, 15%);
margin-bottom: 4px;
}
.inbox-item-sender {
font-size: 0.9em;
color: hsl(210, 14%, 40%);
margin-bottom: 8px;
}
.inbox-item-message {
font-size: 0.9em;
color: hsl(210, 12%, 35%);
white-space: pre-wrap;
background: hsl(210, 12%, 98%);
padding: 10px 12px;
border: 1px solid hsl(210, 12%, 92%);
margin-bottom: 10px;
}
.inbox-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.inbox-actions form { display: inline; }
.inbox-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 32px;
padding: 6px 12px;
border: 1px solid hsl(210, 18%, 84%);
background: #FFFFFF;
color: hsl(210, 20%, 22%);
font-size: 0.82em;
font-weight: 850;
cursor: pointer;
text-decoration: none;
box-shadow: 0 4px 12px rgba(31,38,46,0.06);
transition: background 0.18s ease;
}
.inbox-btn:hover { background: hsl(210, 57%, 96%); }
.inbox-btn-approve {
color: #FFFFFF !important;
background: linear-gradient(135deg, var(--nak-darkgreen), #005a10) !important;
border-color: #005a10 !important;
}
.inbox-btn-reject {
color: var(--nak-red) !important;
border-color: hsl(352, 72%, 88%) !important;
background: hsl(352, 72%, 97%) !important;
}
.inbox-btn-done {
color: hsl(210, 14%, 46%) !important;
background: hsl(210, 12%, 95%) !important;
border-color: hsl(210, 12%, 88%) !important;
}
.inbox-empty {
padding: 24px;
text-align: center;
color: hsl(210, 14%, 50%);
font-weight: 600;
}
.inbox-section-title {
margin: 18px 0 10px 0;
font-size: 0.88em;
font-weight: 850;
text-transform: uppercase;
letter-spacing: 0.04em;
color: hsl(210, 14%, 46%);
}
.inbox-done-item {
opacity: 0.6;
}
@media (max-width: 780px) {
.inbox-shell { padding: 10px; }
.inbox-item-header { flex-direction: column; align-items: flex-start; gap: 4px; }
.inbox-filter-bar { gap: 6px; }
.inbox-filter-btn { font-size: 0.72em; padding: 5px 10px; }
}
.inbox-filter-bar {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 14px;
}
.inbox-filter-btn {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 6px 14px;
border: 1px solid hsl(210, 18%, 84%);
background: #FFF;
color: hsl(210, 18%, 42%);
font-size: 0.82em;
font-weight: 750;
cursor: pointer;
transition: all 0.18s ease;
text-decoration: none;
}
.inbox-filter-btn:hover { background: hsl(210, 57%, 96%); }
.inbox-filter-btn.active {
background: hsl(210, 57%, 94%);
border-color: hsl(210, 57%, 72%);
color: hsl(210, 57%, 30%);
font-weight: 850;
}
</style>
</head>
<body class="theme-admin">
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
<?php include $g_phpSnippetsPath.'overlay_message.php'; ?>
<?php if (isset($_GET["inbox_status"])): ?>
<?php
$inboxStatusMap = [
'done' => ['type' => 'success', 'text' => 'Nachricht als erledigt markiert.'],
'approved' => ['type' => 'success', 'text' => 'Registrierung freigegeben.'],
'rejected' => ['type' => 'success', 'text' => 'Registrierung abgelehnt.'],
'error' => ['type' => 'error', 'text' => 'Ein Fehler ist aufgetreten.'],
];
$statusKey = $_GET["inbox_status"];
$statusInfo = $inboxStatusMap[$statusKey] ?? ['type' => 'success', 'text' => 'Aktion ausgeführt.'];
?>
<div class="nak-toast nak-toast--<?= $statusInfo['type'] ?>" id="nakToast">
<div class="nak-toast__icon">
<?php if ($statusInfo['type'] === 'success'): ?>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg>
<?php else: ?>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
<?php endif; ?>
</div>
<span class="nak-toast__text"><?= htmlspecialchars($statusInfo['text']) ?></span>
<button class="nak-toast__close" onclick="dismissNakToast()" aria-label="Schließen">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</div>
<script>
(function() {
var toast = document.getElementById('nakToast');
if (!toast) return;
requestAnimationFrame(function() { toast.classList.add('nak-toast--visible'); });
var timer = setTimeout(function() { dismissNakToast(); }, 4000);
toast._timer = timer;
if (window.history && window.history.replaceState) {
window.history.replaceState({}, '', 'admin_inbox.php');
}
})();
function dismissNakToast() {
var toast = document.getElementById('nakToast');
if (!toast || toast.classList.contains('nak-toast--hiding')) return;
clearTimeout(toast._timer);
toast.classList.add('nak-toast--hiding');
toast.classList.remove('nak-toast--visible');
setTimeout(function() { toast.remove(); }, 350);
}
</script>
<?php endif; ?>
<div class="header_title ht_admin text_white" id="header_title">
<span class="header_title_text">Adminpanel</span>
</div>
<div class="content" id="fullsize">
<?php $adminActiveTab = 'inbox'; require __DIR__.'/_tabs.php'; ?>
<div class="inbox-shell">
<!-- Filter-Leiste -->
<div class="inbox-filter-bar">
<a href="?filter=all" class="inbox-filter-btn <?= $activeFilter === 'all' ? 'active' : '' ?>">Alle</a>
<?php foreach ($typeConfig as $typeKey => $typeCfg): ?>
<a href="?filter=<?= $typeKey ?>" class="inbox-filter-btn <?= $activeFilter === $typeKey ? 'active' : '' ?>"><?= $typeCfg['label'] ?></a>
<?php endforeach; ?>
</div>
<!-- Offene Nachrichten -->
<div class="inbox-card">
<div class="inbox-header">
<div class="inbox-title">Offene Anfragen</div>
<?php if (count($pendingMessages) > 0): ?>
<span class="inbox-count"><?= count($pendingMessages) ?></span>
<?php endif; ?>
</div>
<?php if (count($pendingMessages) === 0): ?>
<div class="inbox-empty">Keine offenen Anfragen vorhanden.</div>
<?php else: ?>
<?php foreach ($pendingMessages as $msg): ?>
<div class="inbox-item">
<div class="inbox-item-header">
<div>
<span class="inbox-item-type <?= getTypeClass($msg['type'], $typeConfig) ?>">
<?= getTypeLabel($msg['type'], $typeConfig) ?>
</span>
</div>
<span class="inbox-item-date"><?= date('d.m.Y, H:i', strtotime($msg['created_at'])) ?> Uhr</span>
</div>
<div class="inbox-item-subject"><?= htmlspecialchars($msg['subject'] ?? '') ?></div>
<div class="inbox-item-sender">
Von: <?= htmlspecialchars($msg['sender_name'] ?? 'Unbekannt') ?>
(<?= htmlspecialchars($msg['sender_email'] ?? '') ?>)
</div>
<div class="inbox-item-message"><?= htmlspecialchars($msg['message'] ?? '') ?></div>
<div class="inbox-actions">
<?php if ($msg['type'] === 'registration'): ?>
<?php $data = json_decode($msg['data_json'], true); ?>
<button type="button" class="inbox-btn inbox-btn-approve" onclick="openRegistrationModal(<?= (int)($data['pending_id'] ?? 0) ?>, <?= (int)$msg['id'] ?>, '<?= htmlspecialchars($msg['sender_name'] ?? '', ENT_QUOTES) ?>', '<?= htmlspecialchars($msg['sender_email'] ?? '', ENT_QUOTES) ?>')">Anfrage bearbeiten</button>
<?php elseif ($msg['type'] === 'system' && !empty($msg['data_json'])): ?>
<?php
$data = json_decode($msg['data_json'], true);
if (isset($data['action']) && $data['action'] === 'brandschutz_escalation'):
?>
<button type="button" class="inbox-btn inbox-btn-approve" style="background:linear-gradient(135deg,var(--nak-orange),hsl(25,95%,40%)) !important;border-color:hsl(25,95%,40%) !important;" onclick="openBsEscalationModal(<?= (int)$msg['id'] ?>, <?= (int)$data['user_id'] ?>, '<?= htmlspecialchars($data['user_name'] ?? '', ENT_QUOTES) ?>', <?= (int)($data['days_overdue'] ?? 0) ?>)">Persönliche Erinnerung bestätigen</button>
<?php else: ?>
<form method="post" action="">
<input type="hidden" name="mark_done" value="<?= (int)$msg['id'] ?>">
<button type="submit" class="inbox-btn inbox-btn-done">Als erledigt markieren</button>
</form>
<?php endif; ?>
<?php else: ?>
<form method="post" action="">
<input type="hidden" name="mark_done" value="<?= (int)$msg['id'] ?>">
<button type="submit" class="inbox-btn inbox-btn-done">Als erledigt markieren</button>
</form>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
<!-- Erledigte Nachrichten -->
<?php if (count($doneMessages) > 0): ?>
<div class="inbox-section-title">Erledigte Anfragen (letzte 20)</div>
<div class="inbox-card">
<?php foreach ($doneMessages as $msg): ?>
<div class="inbox-item inbox-done-item">
<div class="inbox-item-header">
<div>
<span class="inbox-item-type <?= getTypeClass($msg['type'], $typeConfig) ?>">
<?= getTypeLabel($msg['type'], $typeConfig) ?>
</span>
</div>
<span class="inbox-item-date">Erledigt: <?= date('d.m.Y, H:i', strtotime($msg['processed_at'])) ?> Uhr</span>
</div>
<div class="inbox-item-subject"><?= htmlspecialchars($msg['subject'] ?? '') ?></div>
<div class="inbox-item-sender">
Von: <?= htmlspecialchars($msg['sender_name'] ?? 'Unbekannt') ?>
(<?= htmlspecialchars($msg['sender_email'] ?? '') ?>)
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div><!-- inbox-shell -->
</div><!-- content -->
<!-- Registrierungs-Modal -->
<div class="standard_overlay" id="registrationModal" onclick="if(event.target.id==='registrationModal')closeRegistrationModal()">
<div style="position:relative;width:min(560px,calc(100vw - 24px));max-height:min(700px,calc(100vh - 24px));overflow:auto;background:#FFF;box-shadow:0 24px 70px rgba(0,0,0,0.36);">
<button type="button" aria-label="Schließen" onclick="closeRegistrationModal()" style="position:absolute;top:14px;right:14px;width:34px;height:34px;border:1px solid rgba(255,255,255,0.25);background:rgba(255,255,255,0.16);color:#FFF;font-size:1.35em;cursor:pointer;z-index:1;">×</button>
<div style="padding:24px;color:#FFF;background:radial-gradient(circle at 10% 0%,rgba(255,255,255,0.24),transparent 32%),linear-gradient(135deg,var(--gray-800),var(--gray-900));">
<div style="font-size:1.3em;font-weight:850;">Registrierung bearbeiten</div>
<div id="regModalUserInfo" style="margin-top:6px;color:rgba(255,255,255,0.8);font-weight:600;"></div>
</div>
<div style="padding:22px 24px 24px 24px;">
<form method="post" action="approve-registration.php" id="regModalForm">
<input type="hidden" name="pending_id" id="regModalPendingId">
<input type="hidden" name="message_id" id="regModalMessageId">
<input type="hidden" name="action" id="regModalAction">
<div style="margin-bottom:16px;">
<label style="display:block;margin-bottom:8px;font-weight:750;font-size:0.92em;color:hsl(210,18%,36%);">Rollen zuweisen:</label>
<div style="display:flex;flex-wrap:wrap;gap:8px;">
<?php foreach ($permissionRoles as $role): ?>
<label style="display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:1px solid hsl(210,18%,84%);background:hsl(210,12%,98%);cursor:pointer;font-weight:650;font-size:0.88em;hyphens:auto;-webkit-hyphens:auto;overflow-wrap:break-word;">
<input type="checkbox" name="roles[]" value="<?= htmlspecialchars($role) ?>" style="accent-color:hsl(210,57%,45%);flex-shrink:0;min-width:16px;min-height:16px;">
<?= htmlspecialchars(genderRole($role)) ?>
</label>
<?php endforeach; ?>
</div>
</div>
<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:20px;">
<button type="button" onclick="submitRegistrationAction('reject')" class="inbox-btn inbox-btn-reject" style="padding:10px 18px;font-size:0.9em;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="vertical-align:middle;margin-right:4px;"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>Ablehnen</button>
<button type="button" onclick="submitRegistrationAction('approve')" class="inbox-btn inbox-btn-approve" style="padding:10px 18px;font-size:0.9em;"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="vertical-align:middle;margin-right:4px;"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>Freischalten</button>
</div>
</form>
</div>
</div>
</div>
<script>
function openRegistrationModal(pendingId, messageId, name, email) {
document.getElementById('regModalPendingId').value = pendingId;
document.getElementById('regModalMessageId').value = messageId;
document.getElementById('regModalUserInfo').textContent = name + ' (' + email + ')';
document.getElementById('registrationModal').style.display = 'flex';
}
function closeRegistrationModal() {
document.getElementById('registrationModal').style.display = 'none';
}
function submitRegistrationAction(action) {
var confirmMsg = action === 'approve' ? 'Nutzer mit den gewählten Rollen freischalten?' : 'Registrierung ablehnen?';
if (!confirm(confirmMsg)) return;
document.getElementById('regModalAction').value = action;
document.getElementById('regModalForm').submit();
}
// Brandschutz Eskalation Modal
function openBsEscalationModal(msgId, userId, userName, daysOverdue) {
document.getElementById('bsEscMsgId').value = msgId;
document.getElementById('bsEscUserId').value = userId;
document.getElementById('bsEscUserName').textContent = userName;
document.getElementById('bsEscDaysOverdue').textContent = daysOverdue + ' Tage';
document.getElementById('bsEscalationModal').style.display = 'flex';
}
function closeBsEscalationModal() {
document.getElementById('bsEscalationModal').style.display = 'none';
}
function submitBsEscalation() {
document.getElementById('bsEscForm').submit();
}
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape') {
if (document.getElementById('registrationModal').style.display === 'flex') {
closeRegistrationModal();
}
if (document.getElementById('bsEscalationModal').style.display === 'flex') {
closeBsEscalationModal();
}
}
});
</script>
<!-- Brandschutz Eskalation Modal -->
<div class="standard_overlay" id="bsEscalationModal" onclick="if(event.target.id==='bsEscalationModal')closeBsEscalationModal()">
<div style="position:relative;width:min(520px,calc(100vw - 24px));max-height:min(500px,calc(100vh - 24px));overflow:auto;background:#FFF;box-shadow:0 24px 70px rgba(0,0,0,0.36);">
<button type="button" aria-label="Schließen" onclick="closeBsEscalationModal()" style="position:absolute;top:14px;right:14px;width:34px;height:34px;border:1px solid rgba(255,255,255,0.25);background:rgba(255,255,255,0.16);color:#FFF;font-size:1.35em;cursor:pointer;z-index:1;">×</button>
<div style="padding:24px;color:#FFF;background:radial-gradient(circle at 10% 0%,rgba(255,255,255,0.24),transparent 32%),linear-gradient(135deg,hsl(25,90%,45%),hsl(25,95%,35%));">
<div style="font-size:1.3em;font-weight:850;">Persönliche Erinnerung bestätigen</div>
<div style="margin-top:6px;color:rgba(255,255,255,0.8);font-weight:600;">Brandschutzunterweisung – Eskalation</div>
</div>
<div style="padding:22px 24px 24px 24px;">
<p style="margin:0 0 14px 0;font-size:0.95em;color:hsl(210,20%,25%);line-height:1.6;">
Bitte bestätigen Sie, dass Sie <strong id="bsEscUserName"></strong> persönlich an die ausstehende Brandschutzunterweisung erinnert haben.
</p>
<div style="padding:12px 14px;background:hsl(0,65%,95%);border:1px solid hsl(0,65%,85%);margin-bottom:18px;">
<div style="font-size:0.78em;font-weight:850;text-transform:uppercase;letter-spacing:0.04em;color:hsl(0,65%,38%);margin-bottom:4px;">Überfälligkeit</div>
<div style="font-size:1.1em;font-weight:850;color:hsl(0,65%,35%);" id="bsEscDaysOverdue"></div>
</div>
<form method="post" action="" id="bsEscForm">
<input type="hidden" name="bs_escalation_msg_id" id="bsEscMsgId">
<input type="hidden" name="bs_escalation_user_id" id="bsEscUserId">
<input type="hidden" name="bs_escalation_confirm" value="1">
<div style="display:flex;justify-content:flex-end;gap:8px;margin-top:16px;">
<button type="button" onclick="closeBsEscalationModal()" class="inbox-btn" style="padding:10px 18px;font-size:0.9em;">Abbrechen</button>
<button type="submit" class="inbox-btn inbox-btn-approve" style="padding:10px 18px;font-size:0.9em;background:linear-gradient(135deg,var(--nak-orange),hsl(25,95%,40%)) !important;border-color:hsl(25,95%,40%) !important;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="vertical-align:middle;margin-right:4px;"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>
Bestätigen
</button>
</div>
</form>
</div>
</div>
</div>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
</body>
</html>