168 lines
9.1 KiB
PHP
168 lines
9.1 KiB
PHP
<?php
|
||
require_once __DIR__ . '/../includes/bootstrap.php';
|
||
require_once __DIR__ . '/_ui.php';
|
||
$staff = require_admin();
|
||
$pdo = get_db();
|
||
|
||
$errors = [];
|
||
|
||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||
verify_csrf();
|
||
$action = $_POST['action'] ?? '';
|
||
|
||
if ($action === 'create' || $action === 'update') {
|
||
$id = (int) ($_POST['id'] ?? 0);
|
||
$title = trim($_POST['title'] ?? '');
|
||
$slug = preg_replace('/[^a-z0-9\-]/', '', strtolower(str_replace(' ', '-', trim($_POST['slug'] ?? ''))));
|
||
$content = sanitize_staff_html(trim($_POST['content'] ?? ''));
|
||
$showNav = !empty($_POST['show_in_nav']) ? 1 : 0;
|
||
$isActive = ($_POST['status'] ?? 'active') === 'active' ? 1 : 0;
|
||
$sortOrder = (int) ($_POST['sort_order'] ?? 0);
|
||
|
||
if ($title === '') $errors[] = 'Bitte einen Titel angeben.';
|
||
if ($slug === '') $errors[] = 'Bitte einen URL-Slug angeben (nur a-z, 0-9, -)';
|
||
|
||
// Duplikat
|
||
if (!$errors) {
|
||
$dup = $pdo->prepare('SELECT COUNT(*) FROM site_pages WHERE slug = ? AND id <> ?');
|
||
$dup->execute([$slug, $id]);
|
||
if ((int) $dup->fetchColumn()) $errors[] = 'Dieser Slug wird bereits verwendet.';
|
||
}
|
||
|
||
if (!$errors) {
|
||
if ($action === 'create') {
|
||
$pdo->prepare('INSERT INTO site_pages (slug,title,content,show_in_nav,is_active,sort_order,created_at,updated_at) VALUES (?,?,?,?,?,?,?,?)')
|
||
->execute([$slug, $title, $content, $showNav, $isActive, $sortOrder, db_now(), db_now()]);
|
||
audit_log($staff['id'], "Seite erstellt: {$title}");
|
||
flash('success', 'Seite erstellt.');
|
||
} else {
|
||
$pdo->prepare('UPDATE site_pages SET slug=?,title=?,content=?,show_in_nav=?,is_active=?,sort_order=?,updated_at=? WHERE id=?')
|
||
->execute([$slug, $title, $content, $showNav, $isActive, $sortOrder, db_now(), $id]);
|
||
audit_log($staff['id'], "Seite aktualisiert: {$title}");
|
||
flash('success', 'Änderungen gespeichert.');
|
||
}
|
||
redirect('/staff/site_pages.php');
|
||
}
|
||
}
|
||
|
||
if ($action === 'delete') {
|
||
$pdo->prepare('DELETE FROM site_pages WHERE id = ?')->execute([(int) $_POST['id']]);
|
||
audit_log($staff['id'], 'Seite gelöscht: #' . (int) $_POST['id']);
|
||
flash('success', 'Seite gelöscht.');
|
||
redirect('/staff/site_pages.php');
|
||
}
|
||
}
|
||
|
||
$isNew = isset($_GET['new']);
|
||
$editId = (int) ($_GET['edit'] ?? 0);
|
||
$showForm = $isNew || $editId || ($errors && in_array($_POST['action'] ?? '', ['create', 'update'], true));
|
||
|
||
$pages = $pdo->query('SELECT * FROM site_pages ORDER BY sort_order, title')->fetchAll();
|
||
$editPage = null;
|
||
if ($editId) { $es = $pdo->prepare('SELECT * FROM site_pages WHERE id = ?'); $es->execute([$editId]); $editPage = $es->fetch() ?: null; }
|
||
|
||
$pageTitle = 'Seiten-Verwaltung'; $activePage = 'site_pages';
|
||
require __DIR__ . '/_header.php';
|
||
?>
|
||
|
||
<?php foreach ($errors as $err): ?><div class="flash error"><?= e($err) ?></div><?php endforeach; ?>
|
||
|
||
<?php if ($showForm): ?>
|
||
<?php
|
||
$f = fn(string $k, $default = '') => $_POST[$k] ?? $default;
|
||
$v = fn(string $k, string $col, $default = '') => $f($k, $editPage[$col] ?? $default);
|
||
$curActive = $_POST ? (($_POST['status'] ?? 'active') === 'active') : (bool) ($editPage['is_active'] ?? 1);
|
||
$showNavChecked = $_POST ? !empty($_POST['show_in_nav']) : (bool) ($editPage['show_in_nav'] ?? 1);
|
||
// Inhalt wird beim Absenden als bereinigtes HTML gespeichert; bei Fehlern den eingegebenen Text behalten
|
||
$contentHtml = $_POST ? sanitize_staff_html((string) ($_POST['content'] ?? '')) : (string) ($editPage['content'] ?? '');
|
||
?>
|
||
<h1>
|
||
<?= $editPage ? 'Seite aktualisieren' : 'Neue Seite' ?>
|
||
<?php if ($editPage): ?><span class="muted" style="font-size:1rem;font-weight:400">— <?= e($editPage['title']) ?></span><?php endif; ?>
|
||
</h1>
|
||
|
||
<form method="post" class="card" style="padding:0" onsubmit="document.getElementById('page-content').value=document.getElementById('page-editor').innerHTML">
|
||
<?= csrf_field() ?>
|
||
<input type="hidden" name="action" value="<?= $editPage ? 'update' : 'create' ?>">
|
||
<?php if ($editPage): ?><input type="hidden" name="id" value="<?= (int) $editPage['id'] ?>"><?php endif; ?>
|
||
|
||
<?php ui_tab_bar(['page' => 'Seite', 'content' => 'Inhalt']); ?>
|
||
|
||
<div class="tab-pane" data-pane="page" style="padding:16px 20px">
|
||
<h3 style="margin-top:0">Seiteninformationen</h3>
|
||
<label for="title">Titel *</label>
|
||
<input type="text" id="title" name="title" value="<?= e($v('title', 'title')) ?>" placeholder="z. B. Impressum" required
|
||
oninput="if(!document.getElementById('slug').dataset.manual) document.getElementById('slug').value=this.value.toLowerCase().replace(/[^a-z0-9]+/g,'-').replace(/^-|-$/g,'')">
|
||
<label for="slug">URL-Slug * <span class="muted" style="font-weight:400">(/page/…)</span></label>
|
||
<input type="text" id="slug" name="slug" value="<?= e($v('slug', 'slug')) ?>" pattern="[a-z0-9\-]+" placeholder="impressum" required oninput="this.dataset.manual='1'">
|
||
<?php ui_status_radios($curActive, 'Deaktiviert (nicht erreichbar)'); ?>
|
||
<label style="display:flex;align-items:center;gap:6px;font-weight:400;cursor:pointer;margin-top:6px">
|
||
<input type="checkbox" name="show_in_nav" value="1" style="width:auto" <?= $showNavChecked ? 'checked' : '' ?>>
|
||
Im Navigations-Footer des Portals anzeigen
|
||
</label>
|
||
<label for="sort_order">Sortierung</label>
|
||
<input type="number" id="sort_order" name="sort_order" value="<?= e((string) $v('sort_order', 'sort_order', '0')) ?>" style="max-width:140px">
|
||
<?php if ($editPage): ?>
|
||
<p class="muted" style="font-size:.82rem;margin-top:12px">Erreichbar unter <a href="/page.php?slug=<?= e($editPage['slug']) ?>" target="_blank"><code>/page/<?= e($editPage['slug']) ?></code></a></p>
|
||
<?php endif; ?>
|
||
</div>
|
||
|
||
<div class="tab-pane" data-pane="content" style="padding:16px 20px;display:none">
|
||
<div class="richtext-wrap">
|
||
<div class="richtext-toolbar">
|
||
<button type="button" onclick="document.execCommand('bold')"><strong>B</strong></button>
|
||
<button type="button" onclick="document.execCommand('italic')"><em>I</em></button>
|
||
<button type="button" onclick="document.execCommand('underline')"><u>U</u></button>
|
||
<button type="button" onclick="document.execCommand('insertUnorderedList')">•</button>
|
||
<button type="button" onclick="document.execCommand('insertOrderedList')">1.</button>
|
||
<button type="button" onclick="var u=prompt('URL:','https://');if(u)document.execCommand('createLink',false,u)">🔗</button>
|
||
</div>
|
||
<div class="richtext-editable" id="page-editor" contenteditable="true" style="min-height:260px"><?= $contentHtml ?></div>
|
||
</div>
|
||
<input type="hidden" name="content" id="page-content">
|
||
</div>
|
||
|
||
<div class="btn-row" style="padding:0 20px 18px">
|
||
<button type="submit" class="btn"><?= $editPage ? 'Änderungen speichern' : 'Erstellen' ?></button>
|
||
<a href="/staff/site_pages.php" class="btn secondary">Abbrechen</a>
|
||
</div>
|
||
</form>
|
||
<?php ui_tab_assets('page'); ?>
|
||
|
||
<?php else: ?>
|
||
<div style="display:flex;justify-content:space-between;align-items:center;gap:12px">
|
||
<h1 style="margin:0">Seiten-Verwaltung</h1>
|
||
<a href="/staff/site_pages.php?new=1" class="btn">Neue Seite hinzufügen</a>
|
||
</div>
|
||
<p class="muted">Eigene Inhaltsseiten für das Kundenportal (z. B. Impressum, Datenschutz, Willkommen). Erreichbar unter <code>/page/{slug}</code>.</p>
|
||
|
||
<div class="card">
|
||
<table>
|
||
<thead><tr><th>Titel</th><th>URL</th><th>Navigation</th><th>Status</th><th>Erstellt</th><th>Zuletzt aktualisiert</th><th></th></tr></thead>
|
||
<tbody>
|
||
<?php foreach ($pages as $p): ?>
|
||
<tr>
|
||
<td><a href="/staff/site_pages.php?edit=<?= (int) $p['id'] ?>"><?= e($p['title']) ?></a></td>
|
||
<td><a href="/page.php?slug=<?= e($p['slug']) ?>" target="_blank" style="font-family:var(--font-mono);font-size:.8rem">/page/<?= e($p['slug']) ?></a></td>
|
||
<td><?= $p['show_in_nav'] ? '✓' : '–' ?></td>
|
||
<td><strong><?= $p['is_active'] ? 'Aktiv' : 'Deaktiviert' ?></strong></td>
|
||
<td class="muted" style="font-size:.82rem"><?= e(ui_date($p['created_at'] ?? null)) ?></td>
|
||
<td class="muted" style="font-size:.82rem"><?= e(ui_date($p['updated_at'] ?? null)) ?></td>
|
||
<td style="white-space:nowrap">
|
||
<a href="/staff/site_pages.php?edit=<?= (int) $p['id'] ?>">Bearbeiten</a> ·
|
||
<form method="post" style="display:inline" onsubmit="return confirm('Seite wirklich löschen?')">
|
||
<?= csrf_field() ?>
|
||
<input type="hidden" name="action" value="delete">
|
||
<input type="hidden" name="id" value="<?= (int) $p['id'] ?>">
|
||
<button type="submit" style="background:none;border:none;color:#dc2626;cursor:pointer;padding:0;font-size:.9rem">Löschen</button>
|
||
</form>
|
||
</td>
|
||
</tr>
|
||
<?php endforeach; ?>
|
||
<?php if (!$pages): ?><tr><td colspan="7" class="muted">Noch keine Seiten angelegt.</td></tr><?php endif; ?>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php endif; ?>
|
||
<?php require __DIR__ . '/_footer.php'; ?>
|