gchk,
This commit is contained in:
parent
ac03d796bf
commit
fed7951a98
@ -1537,3 +1537,23 @@ body:not(.admin-body) > * {
|
|||||||
.member-row-pending::before {
|
.member-row-pending::before {
|
||||||
content: '⏳';
|
content: '⏳';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Neue Mitglieder Hervorhebung ---- */
|
||||||
|
.stat-card-new {
|
||||||
|
border: 1.5px solid #bae6fd !important;
|
||||||
|
background: #f0f9ff !important;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: box-shadow 0.2s;
|
||||||
|
}
|
||||||
|
.stat-card-new:hover {
|
||||||
|
box-shadow: 0 0 0 3px rgba(8,145,178,0.15);
|
||||||
|
}
|
||||||
|
.member-row-new td {
|
||||||
|
background: #f0f9ff !important;
|
||||||
|
}
|
||||||
|
.member-row-new td:first-child::before {
|
||||||
|
content: '🆕 ';
|
||||||
|
}
|
||||||
|
.member-row-new:hover td {
|
||||||
|
background: #e0f2fe !important;
|
||||||
|
}
|
||||||
|
|||||||
@ -51,7 +51,8 @@ router.get('/', requireAdmin, async (req, res) => {
|
|||||||
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active_count,
|
SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active_count,
|
||||||
SUM(CASE WHEN is_minor = 1 THEN 1 ELSE 0 END) as minors,
|
SUM(CASE WHEN is_minor = 1 THEN 1 ELSE 0 END) as minors,
|
||||||
SUM(CASE WHEN created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY) THEN 1 ELSE 0 END) as last_30_days,
|
SUM(CASE WHEN created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY) THEN 1 ELSE 0 END) as last_30_days,
|
||||||
SUM(CASE WHEN status = 'pending' THEN 1 ELSE 0 END) as pending_count
|
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
|
FROM memberships
|
||||||
`);
|
`);
|
||||||
res.render('admin/dashboard', {
|
res.render('admin/dashboard', {
|
||||||
@ -334,4 +335,15 @@ router.post('/members/:id/confirm', requireAdmin, async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Mitglied als gesehen markieren
|
||||||
|
router.post('/members/:id/reviewed', requireAdmin, async (req, res) => {
|
||||||
|
try {
|
||||||
|
await db.query('UPDATE memberships SET reviewed = 1 WHERE id = ?', [req.params.id]);
|
||||||
|
res.json({ success: true });
|
||||||
|
} catch (err) {
|
||||||
|
res.json({ success: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
@ -190,8 +190,8 @@ router.post('/submit-membership', async (req, res) => {
|
|||||||
start_package_price,
|
start_package_price,
|
||||||
signup_date, contract_start, contract_end, effective_end,
|
signup_date, contract_start, contract_end, effective_end,
|
||||||
first_payment_date, first_payment_amt,
|
first_payment_date, first_payment_amt,
|
||||||
status)
|
status, reviewed)
|
||||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
||||||
`, [
|
`, [
|
||||||
tariff_id, salutation, title || '', first_name, last_name, birth_date,
|
tariff_id, salutation, title || '', first_name, last_name, birth_date,
|
||||||
email, phone || '', street, address_addition || '', zip, city,
|
email, phone || '', street, address_addition || '', zip, city,
|
||||||
@ -208,7 +208,7 @@ router.post('/submit-membership', async (req, res) => {
|
|||||||
contractEnd.toISOString().split('T')[0],
|
contractEnd.toISOString().split('T')[0],
|
||||||
contractStart.toISOString().split('T')[0],
|
contractStart.toISOString().split('T')[0],
|
||||||
firstPaymentAmt,
|
firstPaymentAmt,
|
||||||
'pending'
|
'pending', 0
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Bestätigungs-E-Mail senden
|
// Bestätigungs-E-Mail senden
|
||||||
|
|||||||
@ -17,8 +17,8 @@
|
|||||||
<a href="#" class="nav-link" onclick="showSection('kategorien', this)">🏷️ Kategorien</a>
|
<a href="#" class="nav-link" onclick="showSection('kategorien', this)">🏷️ Kategorien</a>
|
||||||
<a href="#" class="nav-link" onclick="showSection('mitglieder', this)">
|
<a href="#" class="nav-link" onclick="showSection('mitglieder', this)">
|
||||||
👥 Mitglieder
|
👥 Mitglieder
|
||||||
<% if (stats.pending_count > 0) { %>
|
<% if ((stats.pending_count || 0) + (stats.new_count || 0) > 0) { %>
|
||||||
<span class="nav-badge"><%= stats.pending_count %></span>
|
<span class="nav-badge"><%= (stats.pending_count || 0) + (stats.new_count || 0) %></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
</a>
|
</a>
|
||||||
<a href="/admin/contracts" class="nav-link">📑 Verträge</a>
|
<a href="/admin/contracts" class="nav-link">📑 Verträge</a>
|
||||||
@ -50,9 +50,15 @@
|
|||||||
<div class="stat-label">Letzte 30 Tage</div>
|
<div class="stat-label">Letzte 30 Tage</div>
|
||||||
</div>
|
</div>
|
||||||
<% if (stats.pending_count > 0) { %>
|
<% if (stats.pending_count > 0) { %>
|
||||||
<div class="stat-card stat-card-pending" onclick="showSection('mitglieder', document.querySelector('[onclick*=mitglieder]'))" style="cursor:pointer" title="Klicken um ausstehende Verträge anzuzeigen">
|
<div class="stat-card stat-card-pending" onclick="showSection('mitglieder', document.querySelector('[onclick*=mitglieder]'))" style="cursor:pointer" title="Ausstehende Bestätigungen">
|
||||||
<div class="stat-number" style="color:var(--error)"><%= stats.pending_count %></div>
|
<div class="stat-number" style="color:var(--error)"><%= stats.pending_count %></div>
|
||||||
<div class="stat-label">⚠️ Ausstehend</div>
|
<div class="stat-label">⏳ Ausstehend</div>
|
||||||
|
</div>
|
||||||
|
<% } %>
|
||||||
|
<% if (stats.new_count > 0) { %>
|
||||||
|
<div class="stat-card stat-card-new" onclick="showSection('mitglieder', document.querySelector('[onclick*=mitglieder]'))" style="cursor:pointer" title="Neue Mitglieder die noch nicht bearbeitet wurden">
|
||||||
|
<div class="stat-number" style="color:#0891b2"><%= stats.new_count %></div>
|
||||||
|
<div class="stat-label">🆕 Neu</div>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
<div class="stat-card">
|
<div class="stat-card">
|
||||||
@ -165,7 +171,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% memberships.forEach(m => { %>
|
<% memberships.forEach(m => { %>
|
||||||
<tr class="member-row <%= m.status === 'pending' ? 'member-row-pending' : '' %>" onclick="window.location='/admin/members/<%= m.id %>'" style="cursor:pointer">
|
<tr class="member-row <%= m.status === 'pending' ? 'member-row-pending' : (!m.reviewed ? 'member-row-new' : '') %>" onclick="openMember(<%= m.id %>, <%= m.reviewed ? 1 : 0 %>)" style="cursor:pointer">
|
||||||
<td><strong><%= m.salutation %> <%= m.first_name %> <%= m.last_name %></strong></td>
|
<td><strong><%= m.salutation %> <%= m.first_name %> <%= m.last_name %></strong></td>
|
||||||
<td><%= m.email %></td>
|
<td><%= m.email %></td>
|
||||||
<td><%= m.tariff_name || '–' %></td>
|
<td><%= m.tariff_name || '–' %></td>
|
||||||
@ -378,6 +384,13 @@
|
|||||||
toggleModal('editCategoryModal');
|
toggleModal('editCategoryModal');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openMember(id, reviewed) {
|
||||||
|
if (!reviewed) {
|
||||||
|
fetch('/admin/members/' + id + '/reviewed', { method: 'POST' });
|
||||||
|
}
|
||||||
|
window.location = '/admin/members/' + id;
|
||||||
|
}
|
||||||
|
|
||||||
function filterMembers() {
|
function filterMembers() {
|
||||||
const q = document.getElementById('memberSearch').value.toLowerCase();
|
const q = document.getElementById('memberSearch').value.toLowerCase();
|
||||||
document.querySelectorAll('.member-row').forEach(row => {
|
document.querySelectorAll('.member-row').forEach(row => {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user