Vertragsverwaltung_Plusfit24/routes/admin.js
2026-03-27 11:06:03 +00:00

171 lines
6.8 KiB
JavaScript
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.

const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const db = require('../config/database');
const { requireAdmin } = require('../middleware/auth');
// Login
router.get('/login', (req, res) => {
if (req.session.adminId) return res.redirect('/admin');
res.render('admin/login', { error: null });
});
router.post('/login', async (req, res) => {
const { username, password } = req.body;
try {
const [admins] = await db.query('SELECT * FROM admins WHERE username = ?', [username]);
if (admins.length === 0) return res.render('admin/login', { error: 'Ungültige Anmeldedaten.' });
const valid = await bcrypt.compare(password, admins[0].password_hash);
if (!valid) return res.render('admin/login', { error: 'Ungültige Anmeldedaten.' });
req.session.adminId = admins[0].id;
req.session.adminUser = admins[0].username;
res.redirect('/admin');
} catch (err) {
res.render('admin/login', { error: 'Serverfehler.' });
}
});
router.get('/logout', (req, res) => {
req.session.destroy();
res.redirect('/admin/login');
});
// Dashboard
router.get('/', requireAdmin, async (req, res) => {
try {
const [tariffs] = await db.query(`
SELECT t.*, c.name as category_name
FROM tariffs t LEFT JOIN categories c ON t.category_id = c.id
ORDER BY t.active DESC, t.created_at DESC
`);
const [categories] = await db.query('SELECT * FROM categories ORDER BY name ASC');
const [memberships] = await db.query(`
SELECT m.*, t.name as tariff_name, t.price_monthly
FROM memberships m LEFT JOIN tariffs t ON m.tariff_id = t.id
ORDER BY m.created_at DESC
`);
const [stats] = await db.query(`
SELECT
COUNT(*) as total,
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 created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY) THEN 1 ELSE 0 END) as last_30_days
FROM memberships
`);
res.render('admin/dashboard', {
tariffs, categories, memberships, stats: stats[0],
admin: req.session.adminUser,
success: req.query.success || null,
error: req.query.error || null
});
} catch (err) {
console.error(err);
res.render('admin/dashboard', {
tariffs: [], categories: [], memberships: [], stats: {},
admin: req.session.adminUser,
success: null, error: 'Datenbankfehler: ' + err.message
});
}
});
// ===== KATEGORIEN =====
router.post('/categories', requireAdmin, async (req, res) => {
const { name } = req.body;
if (!name || !name.trim()) return res.redirect('/admin?error=Kategoriename+fehlt');
try {
await db.query('INSERT INTO categories (name) VALUES (?)', [name.trim()]);
res.redirect('/admin?success=Kategorie+erstellt#kategorien');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Erstellen');
}
});
router.post('/categories/:id/update', requireAdmin, async (req, res) => {
const { name } = req.body;
if (!name || !name.trim()) return res.redirect('/admin?error=Kategoriename+fehlt');
try {
await db.query('UPDATE categories SET name = ? WHERE id = ?', [name.trim(), req.params.id]);
res.redirect('/admin?success=Kategorie+aktualisiert#kategorien');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Aktualisieren');
}
});
router.post('/categories/:id/delete', requireAdmin, async (req, res) => {
try {
const [used] = await db.query('SELECT COUNT(*) as c FROM tariffs WHERE category_id = ?', [req.params.id]);
if (used[0].c > 0) {
return res.redirect('/admin?error=Kategorie+wird+von+' + used[0].c + '+Tarifen+verwendet++bitte+erst+Tarife+umziehen#kategorien');
}
await db.query('DELETE FROM categories WHERE id = ?', [req.params.id]);
res.redirect('/admin?success=Kategorie+gelöscht#kategorien');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Löschen');
}
});
// ===== TARIFE =====
router.post('/tariffs', requireAdmin, async (req, res) => {
const { name, category_id, duration_months, price_monthly, start_package_price, description } = req.body;
try {
await db.query(
'INSERT INTO tariffs (name, category_id, duration_months, price_monthly, start_package_price, description) VALUES (?, ?, ?, ?, ?, ?)',
[name, category_id || null, duration_months, price_monthly, start_package_price || 35.00, description || '']
);
res.redirect('/admin?success=Tarif+erstellt');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Erstellen+des+Tarifs');
}
});
router.post('/tariffs/:id/toggle', requireAdmin, async (req, res) => {
try {
await db.query('UPDATE tariffs SET active = NOT active WHERE id = ?', [req.params.id]);
res.redirect('/admin?success=Tarif+aktualisiert');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Aktualisieren');
}
});
router.post('/tariffs/:id/update', requireAdmin, async (req, res) => {
const { name, category_id, duration_months, price_monthly, start_package_price, description } = req.body;
try {
await db.query(
'UPDATE tariffs SET name=?, category_id=?, duration_months=?, price_monthly=?, start_package_price=?, description=? WHERE id=?',
[name, category_id || null, duration_months, price_monthly, start_package_price, description, req.params.id]
);
res.redirect('/admin?success=Tarif+aktualisiert');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Aktualisieren');
}
});
router.post('/tariffs/:id/delete', requireAdmin, async (req, res) => {
try {
const [members] = await db.query('SELECT COUNT(*) as c FROM memberships WHERE tariff_id = ?', [req.params.id]);
if (members[0].c > 0) return res.redirect('/admin?error=Tarif+hat+Mitglieder++bitte+deaktivieren');
await db.query('DELETE FROM tariffs WHERE id = ?', [req.params.id]);
res.redirect('/admin?success=Tarif+gelöscht');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Löschen');
}
});
// Passwort ändern
router.post('/change-password', requireAdmin, async (req, res) => {
const { current_password, new_password, confirm_password } = req.body;
if (new_password !== confirm_password) return res.redirect('/admin?error=Passwörter+stimmen+nicht+überein');
try {
const [admins] = await db.query('SELECT * FROM admins WHERE id = ?', [req.session.adminId]);
const valid = await bcrypt.compare(current_password, admins[0].password_hash);
if (!valid) return res.redirect('/admin?error=Aktuelles+Passwort+falsch');
const hash = await bcrypt.hash(new_password, 12);
await db.query('UPDATE admins SET password_hash = ? WHERE id = ?', [hash, req.session.adminId]);
res.redirect('/admin?success=Passwort+geändert');
} catch (err) {
res.redirect('/admin?error=Fehler+beim+Ändern+des+Passworts');
}
});
module.exports = router;