// Admin alerts — bell icon + dropdown panel const adminAlerts = new Map(); let alertsPanelOpen = false; function escapeAlertText(value) { const esc = window.escapeHtml || ((text) => String(text)); return esc(value); } function renderAdminAlerts() { const badge = document.getElementById('admin-alerts-badge'); const list = document.getElementById('admin-alerts-list'); const empty = document.getElementById('admin-alerts-empty'); const count = adminAlerts.size; if (badge) { badge.textContent = count > 99 ? '99+' : String(count); badge.classList.toggle('admin-alerts-badge--visible', count > 0); } const bell = document.getElementById('admin-alerts-button'); if (bell) { bell.classList.toggle('admin-alerts-bell--active', count > 0); bell.setAttribute('aria-label', count > 0 ? `${count} active alert${count === 1 ? '' : 's'}` : 'Alerts'); } if (!list) return; if (count === 0) { list.innerHTML = ''; if (empty) empty.classList.add('admin-alerts-empty--visible'); return; } if (empty) empty.classList.remove('admin-alerts-empty--visible'); const items = Array.from(adminAlerts.values()).sort((a, b) => { const severityOrder = { error: 0, warning: 1, info: 2 }; const sa = severityOrder[a.severity] ?? 3; const sb = severityOrder[b.severity] ?? 3; if (sa !== sb) return sa - sb; return (a.title || '').localeCompare(b.title || ''); }); list.innerHTML = items.map(alert => { const severity = alert.severity || 'warning'; const icon = severity === 'error' ? 'fa-circle-exclamation' : severity === 'info' ? 'fa-circle-info' : 'fa-triangle-exclamation'; const source = alert.source ? `${escapeAlertText(alert.source)}` : ''; const details = Array.isArray(alert.details) && alert.details.length > 0 ? `
${escapeAlertText(item)}