News-Admin-Workflow aufgebohrt:
- News können jetzt als Admin erstellt und gelöscht werden, mit Zwischenseite zur Bestätigung. - Fehler bei den Feldnamen im Model gefixt. - Nach dem Anlegen/Löschen gibt’s jetzt wie beim Login/Registrieren eine kurze Erfolgsmeldung und automatischen Redirect. - Includes und Redirects aufgeräumt, damit keine Warnungen mehr kommen.
This commit is contained in:
parent
4f0f1e5f6d
commit
775b752d59
110
CSS/style.css
110
CSS/style.css
@ -405,4 +405,114 @@ a {
|
|||||||
.nav-links .links {
|
.nav-links .links {
|
||||||
margin: 0 12px;
|
margin: 0 12px;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabellen-Design */
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0,0,0,0.07);
|
||||||
|
margin: 24px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
thead th {
|
||||||
|
background: #BAC8D4;
|
||||||
|
color: #222;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 12px 8px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 2px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
tbody td {
|
||||||
|
padding: 10px 8px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
tbody tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
tbody tr:hover {
|
||||||
|
background: #f5faff;
|
||||||
|
}
|
||||||
|
.admin-btn, .admin-btn:visited {
|
||||||
|
display: inline-block;
|
||||||
|
background: #4d4d4d;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 7px 16px;
|
||||||
|
margin: 8px 0 12px 0;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 500;
|
||||||
|
transition: background 0.2s;
|
||||||
|
}
|
||||||
|
.admin-btn:hover {
|
||||||
|
background: #222;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
td a {
|
||||||
|
color: #09add0;
|
||||||
|
text-decoration: underline;
|
||||||
|
margin: 0 4px;
|
||||||
|
font-size: 0.98em;
|
||||||
|
}
|
||||||
|
td a:hover {
|
||||||
|
color: #007b9e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.news-cards {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 24px;
|
||||||
|
justify-content: flex-start;
|
||||||
|
margin: 24px 0;
|
||||||
|
}
|
||||||
|
.news-card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 12px rgba(0,0,0,0.08);
|
||||||
|
padding: 20px 18px 16px 18px;
|
||||||
|
max-width: 340px;
|
||||||
|
min-width: 220px;
|
||||||
|
flex: 1 1 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.news-card h3 {
|
||||||
|
margin: 0 0 8px 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
|
.news-card .news-date {
|
||||||
|
font-size: 0.95em;
|
||||||
|
color: #888;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
.news-card .news-desc {
|
||||||
|
font-size: 1em;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
white-space: pre-line;
|
||||||
|
}
|
||||||
|
.news-card .admin-btn {
|
||||||
|
align-self: flex-end;
|
||||||
|
margin: 0 0 0 8px;
|
||||||
|
padding: 6px 12px;
|
||||||
|
font-size: 0.97em;
|
||||||
|
}
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.news-cards {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.news-card {
|
||||||
|
max-width: 98vw;
|
||||||
|
min-width: unset;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
@ -48,12 +48,13 @@ class AuthController
|
|||||||
|
|
||||||
$result = $this->model->login($email, $password);
|
$result = $this->model->login($email, $password);
|
||||||
|
|
||||||
if ($result === true) {
|
if ($result['success']) {
|
||||||
$_SESSION['user'] = $email;
|
$_SESSION['user'] = $result['user']['email'];
|
||||||
|
$_SESSION['is_admin'] = $result['user']['is_admin'];
|
||||||
$this->view->setDoMethodName('showLoginSuccess');
|
$this->view->setDoMethodName('showLoginSuccess');
|
||||||
} else {
|
} else {
|
||||||
$this->view->setVars([
|
$this->view->setVars([
|
||||||
'errors' => ['login' => is_string($result) ? $result : "Login fehlgeschlagen."],
|
'errors' => ['login' => $result['error']],
|
||||||
'validData' => ['email' => $email],
|
'validData' => ['email' => $email],
|
||||||
'loginSuccess' => false
|
'loginSuccess' => false
|
||||||
]);
|
]);
|
||||||
|
@ -20,14 +20,38 @@ class NewsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function createNews() {
|
public function createNews() {
|
||||||
|
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||||
|
header('Location: index.php?controller=News&do=showNews');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
$data = [
|
$data = [
|
||||||
'name' => $_POST['name'],
|
'name' => $_POST['name'] ?? '',
|
||||||
'beschreibung' => $_POST['beschreibung'],
|
'description' => $_POST['description'] ?? '',
|
||||||
'datum' => $_POST['datum'],
|
'date' => $_POST['date'] ?? date('Y-m-d'),
|
||||||
];
|
];
|
||||||
$erg = $this->model->createNews($data);
|
$errors = [];
|
||||||
$this->view->setVars(['news' => $erg]);
|
if (empty($data['name']) || empty($data['description']) || empty($data['date'])) {
|
||||||
exit;
|
$errors['news'] = 'Bitte alle Felder ausfüllen.';
|
||||||
|
}
|
||||||
|
if (!empty($errors)) {
|
||||||
|
$this->view->setVars(['errors' => $errors, 'validData' => $data]);
|
||||||
|
$this->view->setDoMethodName('createNewsForm');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->model->createNews($data);
|
||||||
|
$this->view->setDoMethodName('showCreateSuccess');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createNewsForm() {
|
||||||
|
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||||
|
header('Location: index.php?controller=News&do=showNews');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
// Leere Felder für das Formular
|
||||||
|
$this->view->setVars([
|
||||||
|
'errors' => [],
|
||||||
|
'validData' => []
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function editNewsForm() {
|
public function editNewsForm() {
|
||||||
@ -47,7 +71,14 @@ class NewsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function deleteNews() {
|
public function deleteNews() {
|
||||||
$id = $_GET['newsid'] ?? null;
|
if (!isset($_SESSION['is_admin']) || !$_SESSION['is_admin']) {
|
||||||
$this->model->deleteNews($id);
|
header('Location: index.php?controller=News&do=showNews');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
$id = $_GET['id'] ?? null;
|
||||||
|
if ($id) {
|
||||||
|
$this->model->deleteNews($id);
|
||||||
|
}
|
||||||
|
$this->view->setDoMethodName('showDeleteSuccess');
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ class AuthModel extends Database
|
|||||||
public function login(string $email, string $password)
|
public function login(string $email, string $password)
|
||||||
{
|
{
|
||||||
$pdo = $this->linkDB();
|
$pdo = $this->linkDB();
|
||||||
$sql = "SELECT email, password, valid_until FROM user WHERE email = :email";
|
$sql = "SELECT email, password, valid_until, is_admin FROM user WHERE email = :email";
|
||||||
$params = [":email" => $email];
|
$params = [":email" => $email];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -20,15 +20,15 @@ class AuthModel extends Database
|
|||||||
$user = $sth->fetch(PDO::FETCH_ASSOC);
|
$user = $sth->fetch(PDO::FETCH_ASSOC);
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
new \Blog\Library\ErrorMsg("Fehler beim Abrufen der Benutzerdaten.", $e);
|
new \Blog\Library\ErrorMsg("Fehler beim Abrufen der Benutzerdaten.", $e);
|
||||||
return "Interner Datenbankfehler."; // Nur für Debug sichtbar machen, sonst besser allgemein halten
|
return ['success' => false, 'error' => "Interner Datenbankfehler."];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
return "Benutzer mit dieser E-Mail wurde nicht gefunden.";
|
return ['success' => false, 'error' => "Benutzer mit dieser E-Mail wurde nicht gefunden."];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!password_verify($password, $user['password'])) {
|
if (!password_verify($password, $user['password'])) {
|
||||||
return "Das eingegebene Passwort ist falsch.";
|
return ['success' => false, 'error' => "Das eingegebene Passwort ist falsch."];
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -36,14 +36,14 @@ class AuthModel extends Database
|
|||||||
$validUntil = new DateTime($user['valid_until']);
|
$validUntil = new DateTime($user['valid_until']);
|
||||||
|
|
||||||
if ($now > $validUntil) {
|
if ($now > $validUntil) {
|
||||||
return "Ihr Passwort ist abgelaufen. Bitte setzen Sie ein neues über \"Passwort vergessen\".";
|
return ['success' => false, 'error' => "Ihr Passwort ist abgelaufen. Bitte setzen Sie ein neues über \"Passwort vergessen\"."];
|
||||||
}
|
}
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
new \Blog\Library\ErrorMsg("Fehler beim Verarbeiten des Gültigkeitsdatums.", $e);
|
new \Blog\Library\ErrorMsg("Fehler beim Verarbeiten des Gültigkeitsdatums.", $e);
|
||||||
return "Fehler bei der Passwortprüfung.";
|
return ['success' => false, 'error' => "Fehler bei der Passwortprüfung."];
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return ['success' => true, 'user' => $user];
|
||||||
}
|
}
|
||||||
|
|
||||||
public function register($data) {
|
public function register($data) {
|
||||||
|
@ -56,9 +56,9 @@ class NewsModel extends Database {
|
|||||||
$pdo = $this->linkDB();
|
$pdo = $this->linkDB();
|
||||||
$sql = "INSERT INTO news (name, description, date) VALUES (:name, :description, :date);";
|
$sql = "INSERT INTO news (name, description, date) VALUES (:name, :description, :date);";
|
||||||
$params = [
|
$params = [
|
||||||
":name" => $news['titel'],
|
":name" => $news['name'],
|
||||||
":description" => $news['inhalt'],
|
":description" => $news['description'],
|
||||||
":date" => $news['datum']
|
":date" => $news['date']
|
||||||
];
|
];
|
||||||
try {
|
try {
|
||||||
$sth = $pdo->prepare($sql);
|
$sth = $pdo->prepare($sql);
|
||||||
|
20
Views/News/createNewsForm.phtml
Normal file
20
Views/News/createNewsForm.phtml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<div class="inhalt">
|
||||||
|
<div class="form-container">
|
||||||
|
<h1>News erstellen</h1>
|
||||||
|
<?php if (!empty($errors['news'])): ?>
|
||||||
|
<div class="form-error"><?=htmlspecialchars($errors['news'])?></div>
|
||||||
|
<?php endif; ?>
|
||||||
|
<form class="form-horizontal" action="index.php" method="post">
|
||||||
|
<input type="hidden" name="controller" value="News">
|
||||||
|
<input type="hidden" name="do" value="createNews">
|
||||||
|
<label for="name">Titel</label>
|
||||||
|
<input type="text" name="name" id="name" required value="<?=htmlspecialchars($validData['name'] ?? '')?>">
|
||||||
|
<label for="date">Datum</label>
|
||||||
|
<input type="date" name="date" id="date" required value="<?=htmlspecialchars($validData['date'] ?? date('Y-m-d'))?>">
|
||||||
|
<label for="description">Beschreibung</label>
|
||||||
|
<textarea name="description" id="description" rows="7" required><?=htmlspecialchars($validData['description'] ?? '')?></textarea>
|
||||||
|
<button class="button-register" type="submit">News speichern</button>
|
||||||
|
</form>
|
||||||
|
<a href="?controller=News&do=showNews">Zurück zur Übersicht</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
14
Views/News/showCreateSuccess.phtml
Normal file
14
Views/News/showCreateSuccess.phtml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<div class="inhalt">
|
||||||
|
<div class="login-success">
|
||||||
|
<h2>News erfolgreich erstellt!</h2>
|
||||||
|
<p>Du wirst in wenigen Sekunden zur Übersicht weitergeleitet...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = "?controller=News&do=showNews";
|
||||||
|
}, 2000);
|
||||||
|
</script>
|
||||||
|
<noscript>
|
||||||
|
<meta http-equiv="refresh" content="2;url=?controller=News&do=showNews">
|
||||||
|
</noscript>
|
14
Views/News/showDeleteSuccess.phtml
Normal file
14
Views/News/showDeleteSuccess.phtml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<div class="inhalt">
|
||||||
|
<div class="login-success">
|
||||||
|
<h2>News erfolgreich gelöscht!</h2>
|
||||||
|
<p>Du wirst in wenigen Sekunden zur Übersicht weitergeleitet...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setTimeout(function() {
|
||||||
|
window.location.href = "?controller=News&do=showNews";
|
||||||
|
}, 2000);
|
||||||
|
</script>
|
||||||
|
<noscript>
|
||||||
|
<meta http-equiv="refresh" content="2;url=?controller=News&do=showNews">
|
||||||
|
</noscript>
|
@ -1,27 +1,24 @@
|
|||||||
<?php if (!empty($news)): ?>
|
<?php if (!empty($news)): ?>
|
||||||
<div class="inhalt">
|
<div class="inhalt">
|
||||||
<div class="event-container">
|
<div class="event-container">
|
||||||
<h2>Alle Infos</h2>
|
<h2>Alle News</h2>
|
||||||
<div class="event-container-inhalt">
|
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
|
||||||
<table>
|
<a href="?controller=News&do=createNewsForm" class="admin-btn">News erstellen</a>
|
||||||
<thead>
|
<?php endif; ?>
|
||||||
<tr>
|
<div class="news-cards">
|
||||||
<th>Name</th>
|
|
||||||
<th>Beschreibung</th>
|
|
||||||
<th>Datum</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php foreach ($news as $item): ?>
|
<?php foreach ($news as $item): ?>
|
||||||
<tr>
|
<div class="news-card">
|
||||||
<td><?php echo htmlspecialchars($item['name']); ?></td>
|
<h3><?=htmlspecialchars($item['name'])?></h3>
|
||||||
<td><?php echo nl2br(htmlspecialchars($item['name'])); ?></td>
|
<div class="news-date"><?=date('d.m.Y', strtotime($item['date']))?></div>
|
||||||
<td><?php echo nl2br(htmlspecialchars($item['description'])); ?></td>
|
<div class="news-desc"><?=nl2br(htmlspecialchars($item['description']))?></div>
|
||||||
<td><?php echo date('d.m.Y', strtotime($item['date'])); ?></td>
|
<?php if (isset($_SESSION['is_admin']) && $_SESSION['is_admin']): ?>
|
||||||
</tr>
|
<div>
|
||||||
|
<a href="?controller=News&do=editNewsForm&id=<?=$item['news_id']?>" class="admin-btn">Bearbeiten</a>
|
||||||
|
<a href="?controller=News&do=deleteNews&id=<?=$item['news_id']?>" class="admin-btn" onclick="return confirm('Wirklich löschen?');">Löschen</a>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<p>Derzeit sind keine News verfügbar.</p>
|
<p>Derzeit sind keine News verfügbar.</p>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user