upload v1
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
<?php
|
||||
// admin.php
|
||||
declare(strict_types=1);
|
||||
session_start();
|
||||
require_once __DIR__ . '/functions.php';
|
||||
|
||||
$loggedIn = isset($_SESSION['admin']) && $_SESSION['admin'] === true;
|
||||
|
||||
// Login
|
||||
if (isset($_POST['action']) && $_POST['action'] === 'login') {
|
||||
if (($_POST['password'] ?? '') === ADMIN_PASSWORD_PLAIN) {
|
||||
$_SESSION['admin'] = true;
|
||||
header('Location: admin.php');
|
||||
exit;
|
||||
} else {
|
||||
$error = 'Falsches Passwort.';
|
||||
}
|
||||
}
|
||||
|
||||
// Logout
|
||||
if (isset($_GET['logout'])) {
|
||||
$_SESSION = [];
|
||||
session_destroy();
|
||||
header('Location: admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($loggedIn) {
|
||||
// CREATE/UPDATE
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_event'])) {
|
||||
$events = load_events();
|
||||
$id = $_POST['id'] ?: 'evt_' . bin2hex(random_bytes(6));
|
||||
$title = sanitize_text($_POST['title'] ?? '');
|
||||
$speaker = sanitize_text($_POST['speaker'] ?? '');
|
||||
$date = sanitize_text($_POST['date'] ?? '');
|
||||
$time = sanitize_text($_POST['time'] ?? '19:30');
|
||||
$venue_name = sanitize_text($_POST['venue_name'] ?? '');
|
||||
$venue_address = sanitize_text($_POST['venue_address'] ?? '');
|
||||
$price = sanitize_text($_POST['price'] ?? '');
|
||||
$doors_open = sanitize_text($_POST['doors_open'] ?? '');
|
||||
$tickets_info = sanitize_text($_POST['tickets_info'] ?? '');
|
||||
$catering = sanitize_text($_POST['catering'] ?? '');
|
||||
$tags = sanitize_text($_POST['tags'] ?? '');
|
||||
$description = trim($_POST['description'] ?? '');
|
||||
$existing_image = sanitize_text($_POST['existing_image'] ?? '');
|
||||
|
||||
if ($title === '' || $date === '') {
|
||||
$error = 'Titel und Datum sind Pflichtfelder.';
|
||||
} else {
|
||||
try {
|
||||
$imagePath = $existing_image;
|
||||
if (!empty($_FILES['image']['name'])) {
|
||||
$imagePath = handle_image_upload($_FILES['image']);
|
||||
}
|
||||
$slug = make_slug($title, $date);
|
||||
|
||||
// Update falls vorhanden
|
||||
$events = load_events();
|
||||
$idx = null;
|
||||
foreach ($events as $k => $ev) {
|
||||
if ($ev['id'] === $id) { $idx = $k; break; }
|
||||
}
|
||||
$record = [
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'speaker' => $speaker,
|
||||
'date' => $date,
|
||||
'time' => $time,
|
||||
'venue_name' => $venue_name,
|
||||
'venue_address' => $venue_address,
|
||||
'price' => $price,
|
||||
'doors_open' => $doors_open,
|
||||
'tickets_info' => $tickets_info,
|
||||
'catering' => $catering,
|
||||
'tags' => $tags,
|
||||
'description' => $description,
|
||||
'image' => $imagePath,
|
||||
'slug' => $slug,
|
||||
'updated_at' => now_iso()
|
||||
];
|
||||
if ($idx !== null) {
|
||||
$events[$idx] = $record;
|
||||
} else {
|
||||
$record['created_at'] = now_iso();
|
||||
$events[] = $record;
|
||||
}
|
||||
save_events($events);
|
||||
header('Location: admin.php?ok=1');
|
||||
exit;
|
||||
} catch (Throwable $e) {
|
||||
$error = 'Fehler: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE
|
||||
if (isset($_GET['delete'])) {
|
||||
$events = load_events();
|
||||
$id = $_GET['delete'];
|
||||
$events = array_values(array_filter($events, fn($e) => $e['id'] !== $id));
|
||||
save_events($events);
|
||||
header('Location: admin.php?deleted=1');
|
||||
exit;
|
||||
}
|
||||
|
||||
// EDIT load
|
||||
$editEvent = null;
|
||||
if (isset($_GET['edit'])) {
|
||||
$id = $_GET['edit'];
|
||||
foreach (load_events() as $e) {
|
||||
if ($e['id'] === $id) { $editEvent = $e; break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Admin | <?= h(SITE_NAME) ?></title>
|
||||
<meta name="robots" content="noindex,nofollow">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/assets/styles.css">
|
||||
<link rel="icon" href="/assets/logo.png" sizes="32x32" type="image/png">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg bg-body-tertiary border-bottom sticky-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand brand-logo" href="index.html">
|
||||
<img src="/assets/logo.png" alt="Walschleber KulTour Logo" height="34" width="34">
|
||||
<span><?= h(SITE_NAME) ?></span>
|
||||
</a>
|
||||
<div class="ms-auto">
|
||||
<?php if ($loggedIn): ?>
|
||||
<a class="btn btn-outline-secondary btn-sm" href="admin.php?logout=1">Logout</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<?php if (!$loggedIn): ?>
|
||||
<header class="py-5 bg-light border-bottom">
|
||||
<div class="container">
|
||||
<div class="akzent-line mb-3"></div>
|
||||
<h1 class="display-6 mb-2">Admin-Login</h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container my-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-5">
|
||||
<div class="p-4 border rounded-3 bg-white">
|
||||
<?php if (!empty($error)): ?><div class="alert alert-danger"><?= h($error) ?></div><?php endif; ?>
|
||||
<form method="post" autocomplete="off">
|
||||
<input type="hidden" name="action" value="login">
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Passwort</label>
|
||||
<input type="password" class="form-control form-control-lg" name="password" required>
|
||||
</div>
|
||||
<button class="btn btn-brand btn-lg w-100">Einloggen</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php else: ?>
|
||||
<header class="py-5 bg-light border-bottom">
|
||||
<div class="container">
|
||||
<div class="akzent-line mb-3"></div>
|
||||
<h1 class="display-6 mb-2">Vorträge verwalten</h1>
|
||||
<p class="text-muted mb-0">Anlegen, bearbeiten, Bilder hochladen.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container my-4">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<?php if (isset($_GET['ok'])): ?><span class="badge text-bg-success">Gespeichert</span><?php endif; ?>
|
||||
<?php if (isset($_GET['deleted'])): ?><span class="badge text-bg-warning">Gelöscht</span><?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-5">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3"><?= $editEvent ? 'Vortrag bearbeiten' : 'Neuen Vortrag anlegen' ?></h2>
|
||||
<?php if (!empty($error)): ?><div class="alert alert-danger"><?= h($error) ?></div><?php endif; ?>
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="id" value="<?= h($editEvent['id'] ?? '') ?>">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Titel*</label>
|
||||
<input type="text" class="form-control" name="title" required value="<?= h($editEvent['title'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Referent/Autor</label>
|
||||
<input type="text" class="form-control" name="speaker" value="<?= h($editEvent['speaker'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Datum*</label>
|
||||
<input type="date" class="form-control" name="date" required value="<?= h($editEvent['date'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Uhrzeit</label>
|
||||
<input type="time" class="form-control" name="time" value="<?= h($editEvent['time'] ?? '19:30') ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Veranstaltungsort (Name)</label>
|
||||
<input type="text" class="form-control" name="venue_name" value="<?= h($editEvent['venue_name'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Adresse (Straße, PLZ Ort)</label>
|
||||
<input type="text" class="form-control" name="venue_address" value="<?= h($editEvent['venue_address'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Eintritt (z. B. 12 €)</label>
|
||||
<input type="text" class="form-control" name="price" value="<?= h($editEvent['price'] ?? '') ?>">
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Einlass (z. B. 18:30)</label>
|
||||
<input type="text" class="form-control" name="doors_open" value="<?= h($editEvent['doors_open'] ?? '') ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Ticket/VVK-Info</label>
|
||||
<input type="text" class="form-control" name="tickets_info" value="<?= h($editEvent['tickets_info'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Verpflegung/Service</label>
|
||||
<input type="text" class="form-control" name="catering" value="<?= h($editEvent['catering'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Tags (Kommagetrennt)</label>
|
||||
<input type="text" class="form-control" name="tags" value="<?= h($editEvent['tags'] ?? '') ?>">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Beschreibung</label>
|
||||
<textarea class="form-control" name="description" rows="6"><?= h($editEvent['description'] ?? '') ?></textarea>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($editEvent['image'])): ?>
|
||||
<div class="mb-2">
|
||||
<img src="<?= h($editEvent['image']) ?>" alt="aktuelles Bild" class="img-fluid rounded">
|
||||
</div>
|
||||
<input type="hidden" name="existing_image" value="<?= h($editEvent['image']) ?>">
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Bild (JPG/PNG/WEBP)</label>
|
||||
<input type="file" class="form-control" name="image" accept=".jpg,.jpeg,.png,.webp">
|
||||
</div>
|
||||
|
||||
<button class="btn btn-brand" name="save_event" value="1">Speichern</button>
|
||||
<?php if ($editEvent): ?>
|
||||
<a href="admin.php" class="btn btn-outline-secondary ms-2">Abbrechen</a>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-7">
|
||||
<div class="card shadow-sm">
|
||||
<div class="card-body">
|
||||
<h2 class="h5 mb-3">Alle Vorträge</h2>
|
||||
<?php
|
||||
$events = load_events();
|
||||
usort($events, 'by_datetime_desc');
|
||||
?>
|
||||
<?php if (!$events): ?>
|
||||
<p class="text-muted">Noch keine Einträge.</p>
|
||||
<?php else: ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Datum</th>
|
||||
<th>Titel</th>
|
||||
<th>Ort</th>
|
||||
<th class="text-end"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($events as $e): ?>
|
||||
<tr>
|
||||
<td><?= h($e['date']) ?> <?= h($e['time']) ?></td>
|
||||
<td>
|
||||
<div class="fw-semibold"><?= h($e['title']) ?></div>
|
||||
<div class="text-muted small"><?= h($e['speaker']) ?></div>
|
||||
</td>
|
||||
<td><?= h($e['venue_name']) ?></td>
|
||||
<td class="text-end">
|
||||
<a class="btn btn-sm btn-outline-primary" href="admin.php?edit=<?= h($e['id']) ?>">Bearbeiten</a>
|
||||
<a class="btn btn-sm btn-outline-danger" href="admin.php?delete=<?= h($e['id']) ?>" onclick="return confirm('Wirklich löschen?')">Löschen</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="my-4">
|
||||
<div class="cta-band p-4 d-md-flex justify-content-between align-items-center rounded-4">
|
||||
<div class="mb-3 mb-md-0">
|
||||
<p class="section-kicker mb-1">Tipp</p>
|
||||
<div class="h6 mb-0">Wenn „Ticket/VVK-Info“ eine URL enthält, zeigt die Programmseite automatisch den Button <em>„Tickets sichern“</em>.</div>
|
||||
</div>
|
||||
<a class="btn btn-accent" href="programm.php" target="_blank" rel="noopener">Programm ansehen</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<?php endif; ?>
|
||||
|
||||
<footer class="py-4 border-top mt-5">
|
||||
<div class="container small d-flex gap-3 flex-wrap">
|
||||
<span>© <?= date('Y') ?> <?= h(SITE_NAME) ?></span>
|
||||
<a href="impressum.html">Impressum</a>
|
||||
<a href="datenschutz.html">Datenschutz</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user