From 9dc8f554b9112e15028048431d52f1f98eb0d54f Mon Sep 17 00:00:00 2001 From: cay Date: Sat, 28 Mar 2026 09:37:52 +0000 Subject: [PATCH] tdfj --- routes/admin.js | 17 +++++++++++++ views/admin/dashboard.ejs | 50 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/routes/admin.js b/routes/admin.js index 145996b..7ad23ed 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -346,4 +346,21 @@ router.post('/members/:id/reviewed', requireAdmin, async (req, res) => { } }); + +// GET /admin/api/badge-count – für Live-Update +router.get('/api/badge-count', requireAdmin, async (req, res) => { + try { + const [rows] = await db.query(` + SELECT + SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending_count, + SUM(CASE WHEN reviewed = 0 AND status = 'active' THEN 1 ELSE 0 END) as new_count + FROM memberships + `); + const total = (rows[0].pending_count || 0) + (rows[0].new_count || 0); + res.json({ total, pending: rows[0].pending_count || 0, new: rows[0].new_count || 0 }); + } catch (err) { + res.json({ total: 0, pending: 0, new: 0 }); + } +}); + module.exports = router; diff --git a/views/admin/dashboard.ejs b/views/admin/dashboard.ejs index 44ec3a8..f95679f 100644 --- a/views/admin/dashboard.ejs +++ b/views/admin/dashboard.ejs @@ -391,6 +391,56 @@ window.location = '/admin/members/' + id; } + // Live Badge Update alle 30 Sekunden + function updateBadge() { + fetch('/admin/api/badge-count') + .then(r => r.json()) + .then(data => { + const badge = document.querySelector('.nav-badge'); + if (data.total > 0) { + if (badge) { + badge.textContent = data.total; + } else { + // Badge neu erstellen + const link = document.querySelector('[onclick*="mitglieder"]'); + if (link) { + const span = document.createElement('span'); + span.className = 'nav-badge'; + span.textContent = data.total; + link.appendChild(span); + } + } + // Stat-Karten aktualisieren + if (data.new > 0) { + let newCard = document.getElementById('stat-new'); + if (!newCard) { + const statsRow = document.querySelector('.stats-row'); + newCard = document.createElement('div'); + newCard.id = 'stat-new'; + newCard.className = 'stat-card stat-card-new'; + newCard.style.cursor = 'pointer'; + newCard.onclick = () => showSection('mitglieder', document.querySelector('[onclick*="mitglieder"]')); + newCard.innerHTML = '
' + data.new + '
🆕 Neu
'; + statsRow.appendChild(newCard); + } else { + newCard.querySelector('.stat-number').textContent = data.new; + } + } else { + const newCard = document.getElementById('stat-new'); + if (newCard) newCard.remove(); + } + } else { + if (badge) badge.remove(); + const newCard = document.getElementById('stat-new'); + if (newCard) newCard.remove(); + } + }).catch(() => {}); + } + + // Sofort + alle 30 Sekunden + updateBadge(); + setInterval(updateBadge, 30000); + function filterMembers() { const q = document.getElementById('memberSearch').value.toLowerCase(); document.querySelectorAll('.member-row').forEach(row => {