Initiales CMS: Deutschsprachiges Blog-System mit Admin-Bereich
Vollständiges, schlankes PHP/SQLite-CMS für IT-, KI- und Gaming-Inhalte: - Core: DB-Singleton, Auth mit Passwort-Hashing, Session-Cookies, CSRF-Schutz, Login-Rate-Limit, Bild-Upload mit serverseitiger Validierung - Admin: Dashboard, Artikel/Seiten-Verwaltung mit Quill WYSIWYG-Editor, Kategorien, Navigation (Drag & Drop), Medienbibliothek, Profil - Frontend: Responsive Dark-Theme, Artikel-Grid, Kategorie-Filter, Archiv, Paginierung, SEO-Meta-Tags - Sicherheit: Prepared Statements, HTML-Sanitizer, .htaccess-Schutz für sensible Verzeichnisse, PHP-Ausführungsschutz im Upload-Ordner - Installation: install.php erstellt DB-Schema und Admin-Account https://claude.ai/code/session_01Xsg4j2t4S9goMuWVpF3ezG
This commit is contained in:
78
admin/index.php
Normal file
78
admin/index.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../core/auth.php';
|
||||
auth_start_session();
|
||||
auth_require_login();
|
||||
|
||||
$pdo = db();
|
||||
|
||||
$articleCount = (int) $pdo->query("SELECT COUNT(*) FROM articles WHERE status='published'")->fetchColumn();
|
||||
$draftCount = (int) $pdo->query("SELECT COUNT(*) FROM articles WHERE status='draft'")->fetchColumn();
|
||||
$pageCount = (int) $pdo->query("SELECT COUNT(*) FROM pages")->fetchColumn();
|
||||
$categoryCount = (int) $pdo->query("SELECT COUNT(*) FROM categories")->fetchColumn();
|
||||
|
||||
$recentArticles = $pdo->query(
|
||||
"SELECT a.id, a.title, a.status, a.created_at, c.name as category_name
|
||||
FROM articles a LEFT JOIN categories c ON a.category_id = c.id
|
||||
ORDER BY a.created_at DESC LIMIT 5"
|
||||
)->fetchAll();
|
||||
|
||||
$pageTitle = 'Dashboard';
|
||||
$currentPage = 'dashboard';
|
||||
ob_start();
|
||||
?>
|
||||
<div class="dashboard-stats">
|
||||
<div class="stat-card">
|
||||
<span class="stat-number"><?= $articleCount ?></span>
|
||||
<span class="stat-label">Veröffentlicht</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number"><?= $draftCount ?></span>
|
||||
<span class="stat-label">Entwürfe</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number"><?= $pageCount ?></span>
|
||||
<span class="stat-label">Seiten</span>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<span class="stat-number"><?= $categoryCount ?></span>
|
||||
<span class="stat-label">Kategorien</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3>Letzte Artikel</h3>
|
||||
<a href="/admin/article-edit.php" class="btn btn-primary btn-sm">Neuer Artikel</a>
|
||||
</div>
|
||||
<?php if (empty($recentArticles)): ?>
|
||||
<p class="empty-state">Noch keine Artikel vorhanden.</p>
|
||||
<?php else: ?>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Titel</th>
|
||||
<th>Kategorie</th>
|
||||
<th>Status</th>
|
||||
<th>Erstellt</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($recentArticles as $article): ?>
|
||||
<tr>
|
||||
<td><a href="/admin/article-edit.php?id=<?= $article['id'] ?>"><?= e($article['title']) ?></a></td>
|
||||
<td><?= e($article['category_name'] ?? '–') ?></td>
|
||||
<td>
|
||||
<span class="badge badge-<?= $article['status'] === 'published' ? 'success' : 'warning' ?>">
|
||||
<?= $article['status'] === 'published' ? 'Veröffentlicht' : 'Entwurf' ?>
|
||||
</span>
|
||||
</td>
|
||||
<td><?= format_date($article['created_at']) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
$content = ob_get_clean();
|
||||
include __DIR__ . '/templates/layout.php';
|
||||
Reference in New Issue
Block a user