commented moderation portal and changed textblocks

This commit is contained in:
2026-04-22 15:16:40 +02:00
parent adf863934e
commit 3e73dee40b

View File

@@ -2,13 +2,13 @@
// ===================================================================== // =====================================================================
// Moderation Page // Moderation Page
// Lists Contributions for Review. Moderators can approve, reject, // Lists Contributions for Review. Moderators can approve, reject,
// edit, and delete Contributions. Includes Map Preview and Filtering. // edit and delete Contributions. Includes Map Preview and Filtering.
// //
// ToDo's: // ToDo's:
// - News Management Tab (Phase 3-6) // - Comment Moderation Tab
// - User Management Tab (Phase 3-3) // - News Management Tab
// - Analytics Dashboard Tab (Phase 4-6) // - User Management Tab
// - Comment Moderation Tab (Phase 4-1) // - Analytics Tab
// ===================================================================== // =====================================================================
require_once __DIR__ . '/api/db.php'; require_once __DIR__ . '/api/db.php';
@@ -61,7 +61,7 @@ $categories = get_categories();
// Loads Contributions and Statistics // Loads Contributions and Statistics
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// All Contributions for this Municipality // Loads all Contributions for Municipality
$stmt = $pdo->prepare(" $stmt = $pdo->prepare("
SELECT contribution_id, title, category, description, author_name, SELECT contribution_id, title, category, description, author_name,
geom_type, status, likes_count, dislikes_count, created_at, updated_at geom_type, status, likes_count, dislikes_count, created_at, updated_at
@@ -92,10 +92,27 @@ $counts['total'] = count($all_contributions);
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Moderation — <?= htmlspecialchars($municipality['name']) ?></title> <title>Moderation — <?= htmlspecialchars($municipality['name']) ?></title>
<link rel="icon" href="assets/icon-municipality.png" type="image/png"> <link rel="icon" href="assets/icon-municipality.png" type="image/png">
<!-- Loads CSS Dependencies -->
<!-- Font Awesome for Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<!-- Leaflet -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.min.css">
<!-- Application Styles -->
<link rel="stylesheet" href="admin.css"> <link rel="stylesheet" href="admin.css">
<!-- Loads JavaScript Dependencies -->
<!-- SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.14.0/dist/sweetalert2.all.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.14.0/dist/sweetalert2.all.min.js"></script>
<!-- Loads Municipality Theme from Database -->
<style>:root { --color-primary: <?= htmlspecialchars($municipality['primary_color']) ?>; }</style> <style>:root { --color-primary: <?= htmlspecialchars($municipality['primary_color']) ?>; }</style>
</head> </head>
<body> <body>
@@ -104,9 +121,9 @@ $counts['total'] = count($all_contributions);
<!-- Header --> <!-- Header -->
<!-- ============================================================= --> <!-- ============================================================= -->
<div class="admin-header"> <div class="admin-header">
<h1><i class="fa-solid fa-shield-halved"></i> Moderation <?= htmlspecialchars($municipality['name']) ?></h1> <h1><i class="fa-solid fa-shield-halved"></i> Moderationsportal <?= htmlspecialchars($municipality['name']) ?></h1>
<div class="admin-nav"> <div class="admin-nav">
<a href="index.php"><i class="fa-solid fa-map"></i> Zur Karte</a> <a href="index.php"><i class="fa-solid fa-map"></i> Bürgerportal</a>
<a href="admin.php?page=logout"><i class="fa-solid fa-right-from-bracket"></i> Abmelden</a> <a href="admin.php?page=logout"><i class="fa-solid fa-right-from-bracket"></i> Abmelden</a>
</div> </div>
</div> </div>
@@ -127,7 +144,7 @@ $counts['total'] = count($all_contributions);
<i class="fa-solid fa-chart-bar"></i> Statistik <i class="fa-solid fa-chart-bar"></i> Statistik
</button> </button>
<button class="page-tab" onclick="showPageTab('users')"> <button class="page-tab" onclick="showPageTab('users')">
<i class="fa-solid fa-users"></i> Nutzer <i class="fa-solid fa-users"></i> Benutzer
</button> </button>
</div> </div>
@@ -139,22 +156,23 @@ $counts['total'] = count($all_contributions);
<!-- Statistics Cards --> <!-- Statistics Cards -->
<div class="stats-grid"> <div class="stats-grid">
<div class="stat-card">
<div class="stat-number"><?= $counts['total'] ?></div>
<div class="stat-label">Alle</div>
</div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-number"><?= $counts['pending'] ?></div> <div class="stat-number"><?= $counts['pending'] ?></div>
<div class="stat-label">Ausstehend</div> <div class="stat-label">Ausstehend</div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-number"><?= $counts['approved'] ?></div> <div class="stat-number"><?= $counts['approved'] ?></div>
<div class="stat-label">Freigegeben</div> <div class="stat-label">Akzeptiert</div>
</div> </div>
<div class="stat-card"> <div class="stat-card">
<div class="stat-number"><?= $counts['rejected'] ?></div> <div class="stat-number"><?= $counts['rejected'] ?></div>
<div class="stat-label">Abgelehnt</div> <div class="stat-label">Abgelehnt</div>
</div> </div>
<div class="stat-card">
<div class="stat-number"><?= $counts['total'] ?></div>
<div class="stat-label">Gesamt</div>
</div>
</div> </div>
<!-- Status Filter Tabs --> <!-- Status Filter Tabs -->
@@ -166,7 +184,7 @@ $counts['total'] = count($all_contributions);
Ausstehend <span class="tab-count"><?= $counts['pending'] ?></span> Ausstehend <span class="tab-count"><?= $counts['pending'] ?></span>
</button> </button>
<button class="filter-tab" onclick="filterByStatus('approved', this)"> <button class="filter-tab" onclick="filterByStatus('approved', this)">
Freigegeben <span class="tab-count"><?= $counts['approved'] ?></span> Akzeptiert <span class="tab-count"><?= $counts['approved'] ?></span>
</button> </button>
<button class="filter-tab" onclick="filterByStatus('rejected', this)"> <button class="filter-tab" onclick="filterByStatus('rejected', this)">
Abgelehnt <span class="tab-count"><?= $counts['rejected'] ?></span> Abgelehnt <span class="tab-count"><?= $counts['rejected'] ?></span>
@@ -188,12 +206,12 @@ $counts['total'] = count($all_contributions);
<?php if (empty($all_contributions)): ?> <?php if (empty($all_contributions)): ?>
<div class="empty-state"> <div class="empty-state">
<i class="fa-solid fa-inbox" style="font-size:2rem;margin-bottom:8px;display:block;"></i> <i class="fa-solid fa-inbox" style="font-size:2rem;margin-bottom:8px;display:block;"></i>
Keine Beiträge vorhanden. Noch keine Beiträge vorhanden.
</div> </div>
<?php else: ?> <?php else: ?>
<?php foreach ($all_contributions as $item): <?php foreach ($all_contributions as $item):
$cat = $categories[$item['category']] ?? ['label' => $item['category'], 'faIcon' => 'fa-question', 'color' => '#999']; $cat = $categories[$item['category']] ?? ['label' => $item['category'], 'faIcon' => 'fa-question', 'color' => '#999'];
$status_label = ['pending' => 'Ausstehend', 'approved' => 'Freigegeben', 'rejected' => 'Abgelehnt']; $status_label = ['pending' => 'Ausstehend', 'approved' => 'Akzeptiert', 'rejected' => 'Abgelehnt'];
?> ?>
<div class="contribution-row" <div class="contribution-row"
data-status="<?= $item['status'] ?>" data-status="<?= $item['status'] ?>"
@@ -246,7 +264,7 @@ $counts['total'] = count($all_contributions);
<div class="action-buttons"> <div class="action-buttons">
<?php if ($item['status'] !== 'approved'): ?> <?php if ($item['status'] !== 'approved'): ?>
<button class="btn btn-approve" onclick="changeStatus(<?= $item['contribution_id'] ?>, 'approved')"> <button class="btn btn-approve" onclick="changeStatus(<?= $item['contribution_id'] ?>, 'approved')">
<i class="fa-solid fa-check"></i> Freigeben <i class="fa-solid fa-check"></i> Akzeptieren
</button> </button>
<?php endif; ?> <?php endif; ?>
@@ -283,26 +301,26 @@ $counts['total'] = count($all_contributions);
<!-- ========================================================= --> <!-- ========================================================= -->
<!-- Placeholder Tabs (future Features) --> <!-- Placeholder Tabs for future Features -->
<!-- ========================================================= --> <!-- ========================================================= -->
<div id="tab-news" class="page-tab-content" style="display:none;"> <div id="tab-news" class="page-tab-content" style="display:none;">
<div class="placeholder-content"> <div class="placeholder-content">
<i class="fa-solid fa-newspaper"></i> <i class="fa-solid fa-newspaper"></i>
<p>Neuigkeiten verwalten — kommt in einer zukünftigen Version.</p> <p>Neuigkeiten verwalten - geplant in zukünftiger Version.</p>
</div> </div>
</div> </div>
<div id="tab-stats" class="page-tab-content" style="display:none;"> <div id="tab-stats" class="page-tab-content" style="display:none;">
<div class="placeholder-content"> <div class="placeholder-content">
<i class="fa-solid fa-chart-bar"></i> <i class="fa-solid fa-chart-bar"></i>
<p>Statistiken und Analysen — kommt in einer zukünftigen Version.</p> <p>Statistiken und Analysen - geplant in zukünftiger Version.</p>
</div> </div>
</div> </div>
<div id="tab-users" class="page-tab-content" style="display:none;"> <div id="tab-users" class="page-tab-content" style="display:none;">
<div class="placeholder-content"> <div class="placeholder-content">
<i class="fa-solid fa-users"></i> <i class="fa-solid fa-users"></i>
<p>Nutzerverwaltung — kommt in einer zukünftigen Version.</p> <p>Benutzerverwaltung - geplant in zukünftiger Version.</p>
</div> </div>
</div> </div>
@@ -389,7 +407,7 @@ $counts['total'] = count($all_contributions);
.then(function (data) { .then(function (data) {
if (!data.features) return; if (!data.features) return;
// Finds the specific Contribution // Finds specific Contribution
const feature = data.features.find(function (f) { const feature = data.features.find(function (f) {
return f.properties.contribution_id == contributionId; return f.properties.contribution_id == contributionId;
}); });
@@ -589,11 +607,11 @@ $counts['total'] = count($all_contributions);
function deleteContribution(contributionId) { function deleteContribution(contributionId) {
Swal.fire({ Swal.fire({
title: 'Beitrag endgültig löschen?', title: 'Beitrag löschen?',
text: 'Diese Aktion kann nicht rückgängig gemacht werden.', text: 'Diese Aktion kann nicht rückgängig gemacht werden.',
icon: 'warning', icon: 'warning',
showCancelButton: true, showCancelButton: true,
confirmButtonText: 'Endgültig löschen', confirmButtonText: 'Beitrag löschen',
cancelButtonText: 'Abbrechen', cancelButtonText: 'Abbrechen',
confirmButtonColor: '#c62828' confirmButtonColor: '#c62828'
}).then(function (result) { }).then(function (result) {
@@ -607,7 +625,7 @@ $counts['total'] = count($all_contributions);
Swal.fire('Fehler', response.error, 'error'); Swal.fire('Fehler', response.error, 'error');
return; return;
} }
Swal.fire('Gelöscht!', 'Beitrag wurde entfernt.', 'success') Swal.fire('Gelöscht!', 'Beitrag wurde gelöscht.', 'success')
.then(function () { location.reload(); }); .then(function () { location.reload(); });
}); });
}); });
@@ -629,7 +647,7 @@ function show_login_page($municipality, $error = null) {
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Moderation Anmeldung</title> <title>Moderation - Anmeldung</title>
<link rel="icon" href="assets/icon-municipality.png" type="image/png"> <link rel="icon" href="assets/icon-municipality.png" type="image/png">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<link rel="stylesheet" href="admin.css"> <link rel="stylesheet" href="admin.css">
@@ -638,7 +656,7 @@ function show_login_page($municipality, $error = null) {
<body> <body>
<div class="login-wrapper"> <div class="login-wrapper">
<div class="login-box"> <div class="login-box">
<h1><i class="fa-solid fa-shield-halved"></i> Moderation</h1> <h1><i class="fa-solid fa-shield-halved"></i> Moderationsportal</h1>
<p>Bitte geben Sie das Moderationspasswort ein.</p> <p>Bitte geben Sie das Moderationspasswort ein.</p>
<?php if ($error): ?> <?php if ($error): ?>
<div class="login-error"><?= htmlspecialchars($error) ?></div> <div class="login-error"><?= htmlspecialchars($error) ?></div>
@@ -647,7 +665,7 @@ function show_login_page($municipality, $error = null) {
<input type="password" name="password" placeholder="Passwort" autofocus> <input type="password" name="password" placeholder="Passwort" autofocus>
<button type="submit"><i class="fa-solid fa-right-to-bracket"></i> Anmelden</button> <button type="submit"><i class="fa-solid fa-right-to-bracket"></i> Anmelden</button>
</form> </form>
<div class="back-link"><a href="index.php">Zurück zur Karte</a></div> <div class="back-link"><i class="fa fa-arrow-left"></i></i> <a href="index.php">Zurück zum Bürgerportal</a></div>
</div> </div>
</div> </div>
</body> </body>