Files
sg07-stleon.de/admin.php
2026-04-28 10:10:13 +02:00

421 lines
25 KiB
PHP

<?php
// admin.php - Multi-User Login, Google Authenticator 2FA, 4-Bilder Upload & News Verwaltung
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// ============================================================================
// 1. MINI-KLASSE FÜR GOOGLE AUTHENTICATOR (TOTP)
// ============================================================================
class MiniTOTP {
public static function verify($secret, $code) {
$time = floor(time() / 30);
for ($i = -1; $i <= 1; $i++) {
if (self::getCode($secret, $time + $i) === $code) return true;
}
return false;
}
public static function getCode($secret, $time) {
$secret = self::base32Decode($secret);
$time = pack('N', 0) . pack('N', $time);
$hash = hash_hmac('sha1', $time, $secret, true);
$offset = ord(substr($hash, -1)) & 0x0F;
$code = (unpack('N', substr($hash, $offset, 4))[1] & 0x7FFFFFFF) % 1000000;
return str_pad($code, 6, '0', STR_PAD_LEFT);
}
public static function base32Decode($b32) {
$b32 = strtoupper($b32);
$map = ['A'=>0,'B'=>1,'C'=>2,'D'=>3,'E'=>4,'F'=>5,'G'=>6,'H'=>7,'I'=>8,'J'=>9,'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,'U'=>20,'V'=>21,'W'=>22,'X'=>23,'Y'=>24,'Z'=>25,'2'=>26,'3'=>27,'4'=>28,'5'=>29,'6'=>30,'7'=>31];
$decoded = ''; $buffer = 0; $bits = 0;
for ($i = 0; $i < strlen($b32); $i++) {
$char = $b32[$i];
if (!isset($map[$char])) continue;
$buffer = ($buffer << 5) | $map[$char];
$bits += 5;
if ($bits >= 8) { $bits -= 8; $decoded .= chr(($buffer >> $bits) & 0xFF); }
}
return $decoded;
}
public static function generateSecret($length = 16) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
$secret = '';
for ($i = 0; $i < $length; $i++) $secret .= $chars[random_int(0, 31)];
return $secret;
}
public static function getQRCodeUrl($username, $secret) {
$issuer = urlencode("SG 07 St.Leon");
$account = urlencode($username);
$otpauth = "otpauth://totp/{$issuer}:{$account}?secret={$secret}&issuer={$issuer}";
return "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=" . urlencode($otpauth);
}
}
// ============================================================================
// 2. DATENBANK SETUP (News & Benutzer)
// ============================================================================
try {
$db = new PDO('sqlite:news_database.sqlite');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// News Tabelle initialisieren
$db->exec("CREATE TABLE IF NOT EXISTS news (
id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT, department TEXT, title TEXT, content TEXT, full_text TEXT, image TEXT, link TEXT
)");
// DB-Schema Updates (Falls noch alte Version)
try { $db->exec("ALTER TABLE news ADD COLUMN full_text TEXT"); } catch(PDOException $e) {}
try { $db->exec("ALTER TABLE news ADD COLUMN image2 TEXT"); } catch(PDOException $e) {}
try { $db->exec("ALTER TABLE news ADD COLUMN image3 TEXT"); } catch(PDOException $e) {}
try { $db->exec("ALTER TABLE news ADD COLUMN image4 TEXT"); } catch(PDOException $e) {}
try { $db->exec("ALTER TABLE news ADD COLUMN title_index INTEGER DEFAULT 1"); } catch(PDOException $e) {}
$db->exec("CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE, password_hash TEXT, totp_secret TEXT
)");
} catch(PDOException $e) {
die("Datenbankfehler: " . $e->getMessage());
}
$userCount = $db->query("SELECT COUNT(*) FROM users")->fetchColumn();
// ============================================================================
// 3. ERSTEINRICHTUNG
// ============================================================================
if ($userCount == 0) {
$new_secret = MiniTOTP::generateSecret();
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['do_setup'])) {
$user = trim($_POST['username']);
$pass = $_POST['password'];
$secret = $_POST['totp_secret'];
if (!empty($user) && !empty($pass)) {
$stmt = $db->prepare("INSERT INTO users (username, password_hash, totp_secret) VALUES (?, ?, ?)");
$stmt->execute([$user, password_hash($pass, PASSWORD_DEFAULT), $secret]);
header("Location: admin.php");
exit;
}
}
?>
<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8"><title>Setup | SG 07</title>
<style>body{font-family:sans-serif;background:#f4f4f4;display:flex;justify-content:center;align-items:center;height:100vh;} .box{background:#fff;padding:30px;border-radius:8px;box-shadow:0 4px 15px rgba(0,0,0,0.1);max-width:400px;text-align:center;} input,button{width:100%;padding:10px;margin:10px 0;box-sizing:border-box;} button{background:#d32f2f;color:white;border:none;font-weight:bold;cursor:pointer;} .qr{margin:20px 0;}</style></head>
<body><div class="box"><h1 style="color:#d32f2f;">Ersteinrichtung</h1>
<img src="<?= MiniTOTP::getQRCodeUrl('Admin', $new_secret) ?>" class="qr" alt="QR Code">
<p style="font-size:0.9rem;color:#666;">1. Scanne diesen QR-Code mit dem <b>Google Authenticator</b> oder <b>Authy</b>.</p>
<form method="POST"><input type="text" name="username" placeholder="Benutzername" required><input type="password" name="password" placeholder="Sicheres Passwort" required><input type="hidden" name="totp_secret" value="<?= $new_secret ?>"><button type="submit" name="do_setup">Admin anlegen & weiter</button></form></div></body></html>
<?php exit;
}
// ============================================================================
// 4. LOGIN LOGIK
// ============================================================================
if (isset($_GET['action']) && $_GET['action'] == 'logout') {
session_destroy(); header("Location: admin.php"); exit;
}
$login_error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['do_login'])) {
$stmt = $db->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([trim($_POST['username'])]);
$user = $stmt->fetch(PDO::FETCH_ASSOC);
if ($user && password_verify($_POST['password'], $user['password_hash'])) {
if (MiniTOTP::verify($user['totp_secret'], $_POST['totp_code'])) {
$_SESSION['logged_in'] = true;
$_SESSION['username'] = $user['username'];
header("Location: admin.php"); exit;
} else {
$login_error = "Der 2FA Code ist falsch oder abgelaufen.";
}
} else {
$login_error = "Benutzername oder Passwort falsch.";
}
}
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
?>
<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8"><title>Login | SG 07</title>
<style>body{font-family:'Segoe UI',sans-serif;background:#f4f4f4;display:flex;justify-content:center;align-items:center;height:100vh;} .login-box{background:#fff;padding:40px;border-radius:8px;box-shadow:0 4px 20px rgba(0,0,0,0.1);max-width:350px;width:100%;text-align:center;border-top:5px solid #d32f2f;} input{width:100%;padding:12px;margin-bottom:15px;border:1px solid #ccc;border-radius:4px;box-sizing:border-box;} button{width:100%;padding:14px;background:#d32f2f;color:white;border:none;font-weight:bold;border-radius:4px;cursor:pointer;} button:hover{background:#9a0007;} .err{color:red;margin-bottom:15px;}</style></head>
<body><div class="login-box"><div style="font-size:3rem;">🔒</div><h1 style="color:#d32f2f;margin-bottom:20px;">Admin Login</h1>
<?php if($login_error) echo "<div class='err'>$login_error</div>"; ?>
<form method="POST"><input type="text" name="username" placeholder="Benutzername" required autofocus><input type="password" name="password" placeholder="Passwort" required><input type="text" name="totp_code" placeholder="6-stelliger Authenticator Code" pattern="\d{6}" maxlength="6" required autocomplete="off"><button type="submit" name="do_login">Sicher einloggen</button></form></div></body></html>
<?php exit;
}
// ============================================================================
// 5. ADMIN BEREICH (Eingeloggt)
// ============================================================================
$message = "";
// Bild-Upload Helper für 4 Slots
function handleSingleImage($index) {
$final_path = '';
// Altes Bild behalten, falls im Edit-Modus und nichts Neues hochgeladen wird
if (isset($_POST['existing_image_'.$index]) && !empty($_POST['existing_image_'.$index])) {
$final_path = $_POST['existing_image_'.$index];
}
// 1. Priorität: Neuer Datei-Upload
if (isset($_FILES['image_file_'.$index]) && $_FILES['image_file_'.$index]['error'] === UPLOAD_ERR_OK) {
$year = date('Y');
$upload_dir = __DIR__ . '/img/news/' . $year;
if (!is_dir($upload_dir)) mkdir($upload_dir, 0777, true);
$ext = strtolower(pathinfo($_FILES['image_file_'.$index]['name'], PATHINFO_EXTENSION));
$allowed = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
if (in_array($ext, $allowed)) {
$filename = date('Ymd') . '_' . rand(10000, 99999) . '_img' . $index . '.' . $ext;
if (move_uploaded_file($_FILES['image_file_'.$index]['tmp_name'], $upload_dir . '/' . $filename)) {
$final_path = 'img/news/' . $year . '/' . $filename;
}
}
}
// 2. Priorität: Bild-URL
elseif (isset($_POST['image_url_'.$index]) && !empty($_POST['image_url_'.$index])) {
$final_path = str_replace(['http://new.sg07-stleon.de/', 'https://new.sg07-stleon.de/', 'new.sg07-stleon.de/', 'new.sg07-stleon.de\\'], '', trim($_POST['image_url_'.$index]));
}
// 3. Priorität: Platzhalter
elseif (isset($_POST['placeholder_image_'.$index]) && !empty($_POST['placeholder_image_'.$index])) {
$final_path = $_POST['placeholder_image_'.$index];
}
// Leeres Bild zurücksetzen, wenn der Nutzer explizit "löschen" wollte (hier vereinfacht: wenn URL und Platzhalter leer sind und kein Upload stattfand)
if (empty($_FILES['image_file_'.$index]['name']) && empty($_POST['image_url_'.$index]) && empty($_POST['placeholder_image_'.$index]) && !isset($_POST['keep_existing_'.$index])) {
// Logik zum Behalten wird via Checkboxen geregelt, siehe Formular
}
return $final_path;
}
// --- AKTION: NEWS AKTUALISIEREN (EDIT) ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_news'])) {
$img1 = handleSingleImage(1);
$img2 = handleSingleImage(2);
$img3 = handleSingleImage(3);
$img4 = handleSingleImage(4);
$title_idx = (int)$_POST['title_index'];
$stmt = $db->prepare("UPDATE news SET date=?, department=?, title=?, content=?, full_text=?, image=?, image2=?, image3=?, image4=?, title_index=?, link=? WHERE id=?");
if ($stmt->execute([$_POST['date'], $_POST['department'], $_POST['title'], $_POST['content'], $_POST['full_text'], $img1, $img2, $img3, $img4, $title_idx, $_POST['link'], $_POST['news_id']])) {
$message = "<div class='success'>✓ News (inkl. Galerie) erfolgreich aktualisiert!</div>";
}
}
// --- AKTION: NEWS SPEICHERN (NEU) ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['save_news'])) {
$img1 = handleSingleImage(1);
$img2 = handleSingleImage(2);
$img3 = handleSingleImage(3);
$img4 = handleSingleImage(4);
$title_idx = (int)$_POST['title_index'];
$stmt = $db->prepare("INSERT INTO news (date, department, title, content, full_text, image, image2, image3, image4, title_index, link) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
if ($stmt->execute([$_POST['date'], $_POST['department'], $_POST['title'], $_POST['content'], $_POST['full_text'], $img1, $img2, $img3, $img4, $title_idx, $_POST['link']])) {
$message = "<div class='success'>✓ News (inkl. Galerie) erfolgreich veröffentlicht!</div>";
}
}
// --- AKTION: NEWS LÖSCHEN ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_news'])) {
$stmt = $db->prepare("DELETE FROM news WHERE id = ?");
if ($stmt->execute([$_POST['delete_id']])) {
$message = "<div class='success'>✓ Die News wurde unwiderruflich gelöscht!</div>";
}
}
// Edit-Modus prüfen
$is_edit = false;
$edit_news = null;
if (isset($_GET['edit_id'])) {
$stmt = $db->prepare("SELECT * FROM news WHERE id = ?");
$stmt->execute([$_GET['edit_id']]);
$edit_news = $stmt->fetch(PDO::FETCH_ASSOC);
if ($edit_news) $is_edit = true;
}
$existing_news = $db->query("SELECT id, date, department, title FROM news ORDER BY id DESC")->fetchAll(PDO::FETCH_ASSOC);
// HTML Block für einen der 4 Bilder-Uploads
function renderImageSlot($index, $is_edit, $edit_news) {
$img_key = $index === 1 ? 'image' : 'image'.$index;
$current_val = $is_edit ? ($edit_news[$img_key] ?? '') : '';
$title_idx = $is_edit ? (int)($edit_news['title_index'] ?? 1) : 1;
$is_title = ($title_idx === $index);
echo "<div class='img-slot'>";
echo "<h4>Bild Slot $index</h4>";
// Radio für Titelbild
echo "<label style='color: #d32f2f;'><input type='radio' name='title_index' value='$index' " . ($is_title ? 'checked' : '') . "> <b>Als Titelbild (Cover) nutzen</b></label><hr style='border:0; height:1px; background:#ddd; margin:10px 0;'>";
if($is_edit && $current_val) {
echo "<input type='hidden' name='existing_image_$index' value='".htmlspecialchars($current_val)."'>";
echo "<label><input type='checkbox' name='keep_existing_$index' checked> Altes Bild behalten: <br><small>".htmlspecialchars(substr($current_val, 0, 30))."...</small></label><br>";
}
echo "<label>1. Datei hochladen</label>";
echo "<input type='file' name='image_file_$index' accept='image/*' style='background: white; margin-bottom: 5px;'>";
echo "<label>2. ODER Link (URL)</label>";
echo "<input type='text' name='image_url_$index' placeholder='https://...'>";
echo "<label>3. ODER Platzhalter</label>";
echo "<select name='placeholder_image_$index' style='width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;'>";
echo "<option value=''>-- Kein Bild in diesem Slot --</option>";
echo "<option value=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23f4f4f4'/%3E%3Ccircle cx='50' cy='50' r='35' fill='%23d32f2f'/%3E%3Ctext x='50' y='57' font-size='20' fill='white' text-anchor='middle' font-weight='bold'%3ESG 07%3C/text%3E%3C/svg%3E\">Neutral (SG 07 Logo)</option>";
echo "<option value=\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Crect width='100' height='100' fill='%23e3f2fd'/%3E%3Ccircle cx='50' cy='50' r='35' fill='%232196f3'/%3E%3Ctext x='50' y='60' font-size='30' fill='white' text-anchor='middle' font-weight='bold' font-family='serif'%3Ei%3C/text%3E%3C/svg%3E\">Info (Blaues i)</option>";
echo "</select>";
echo "</div>";
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Admin Dashboard | SG 07 St. Leon</title>
<style>
body { font-family: 'Segoe UI', sans-serif; background: #f4f4f4; padding: 40px 20px; margin: 0; }
.container { max-width: 1200px; background: white; padding: 40px; border-radius: 8px; box-shadow: 0 4px 15px rgba(0,0,0,0.05); margin: 0 auto; }
.header-bar { display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #f4f4f4; padding-bottom: 20px; margin-bottom: 30px; }
.header-bar h1 { color: #d32f2f; margin: 0; }
.logout-btn { background: #555; color: white; padding: 8px 15px; border-radius: 4px; text-decoration: none; font-weight: bold;}
.grid-2 { display: grid; grid-template-columns: 3fr 1fr; gap: 40px; }
label { font-weight: 600; display: block; margin-top: 15px; margin-bottom: 5px; color: #333; font-size: 0.9rem;}
input[type="text"], input[type="password"], textarea { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; font-family: inherit; }
button { margin-top: 20px; padding: 15px; background: #d32f2f; color: white; border: none; font-weight: bold; border-radius: 4px; cursor: pointer; width: 100%; transition: background 0.2s; }
button:hover { background: #9a0007; }
.success { background: #4CAF50; color: white; padding: 15px; border-radius: 4px; margin-bottom: 20px; font-weight: bold;}
.img-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; background: #fafafa; padding: 20px; border: 1px solid #ddd; border-radius: 8px; margin-top: 10px;}
.img-slot { background: white; padding: 15px; border: 1px solid #ccc; border-radius: 4px; }
.img-slot h4 { margin-top: 0; margin-bottom: 10px; color: #555; border-bottom: 2px solid #eee; padding-bottom: 5px;}
.news-table { width: 100%; border-collapse: collapse; margin-top: 20px; font-size: 0.95rem; }
.news-table th { background: #f4f4f4; padding: 12px; text-align: left; border-bottom: 2px solid #ddd; color: #333; }
.news-table td { padding: 12px; border-bottom: 1px solid #eee; vertical-align: middle; }
.edit-btn { background: #2196F3; color: white; padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; text-decoration: none; font-size: 0.9rem; }
.social-btn { background: #E1306C; color: white; padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; font-size: 0.9rem; margin-right: 5px; }
.delete-btn { background: #d32f2f; color: white; padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; margin: 0; width: auto; font-size: 0.9rem; }
@media(max-width: 900px) { .grid-2 { grid-template-columns: 1fr; } }
</style>
</head>
<body>
<div class="container">
<div class="header-bar">
<h1>SG 07 Dashboard <span style="font-size: 0.5em; background: #2196F3; color: white; padding: 3px 8px; border-radius: 10px; vertical-align: middle;">MULTIMEDIA EDITION</span></h1>
<div>
<span style="margin-right:15px; color:#666;">Hallo, <b><?= htmlspecialchars($_SESSION['username']) ?></b></span>
<a href="?action=logout" class="logout-btn">Abmelden</a>
</div>
</div>
<?= $message ?>
<div class="grid-2">
<!-- News Eintragen / Ändern -->
<div>
<h2 style="color: #333; margin-bottom: 10px;"><?= $is_edit ? 'News bearbeiten' : 'News veröffentlichen' ?></h2>
<form method="POST" id="newsForm" enctype="multipart/form-data">
<?php if($is_edit): ?>
<input type="hidden" name="news_id" value="<?= $edit_news['id'] ?>">
<?php endif; ?>
<label>Datum</label>
<input type="text" name="date" value="<?= $is_edit ? htmlspecialchars($edit_news['date']) : date('d.m.Y') ?>" required>
<label>Abteilung</label>
<input type="text" name="department" placeholder="z.B. Turnen" value="<?= $is_edit ? htmlspecialchars($edit_news['department']) : '' ?>" required>
<label>Überschrift</label>
<input type="text" name="title" value="<?= $is_edit ? htmlspecialchars($edit_news['title']) : '' ?>" required>
<label>Kurze Einleitung (Vorschau)</label>
<textarea name="content" rows="3" required><?= $is_edit ? htmlspecialchars($edit_news['content']) : '' ?></textarea>
<label>Kompletter Artikel (Popup)</label>
<textarea name="full_text" rows="8" required><?= $is_edit ? htmlspecialchars($edit_news['full_text']) : '' ?></textarea>
<h3 style="margin-top: 30px; margin-bottom: 5px; color: #333;">Bilder-Galerie (Maximal 4)</h3>
<p style="font-size: 0.85rem; color: #666; margin-top: 0;">Du musst nicht alle Slots füllen. Vergiss nicht das <b>Titelbild</b> auszuwählen!</p>
<!-- Die 4 Bilder Slots -->
<div class="img-grid">
<?php
for($i=1; $i<=4; $i++) {
renderImageSlot($i, $is_edit, $edit_news);
}
?>
</div>
<label style="margin-top: 20px;">Weiterführender Link (Optional)</label>
<input type="text" name="link" value="<?= $is_edit ? htmlspecialchars($edit_news['link']) : '' ?>">
<?php if($is_edit): ?>
<div style="display: flex; gap: 10px;">
<button type="submit" name="update_news" style="background: #2196F3;">Änderungen speichern</button>
<a href="admin.php" style="display: block; text-align: center; margin-top: 20px; padding: 15px; background: #555; color: white; border-radius: 4px; text-decoration: none; font-weight: bold; width: 100%; box-sizing: border-box;">Abbrechen</a>
</div>
<?php else: ?>
<button type="submit" name="save_news">News online stellen</button>
<?php endif; ?>
</form>
</div>
<!-- Randbereich Info -->
<div>
<div style="background: #fafafa; padding: 20px; border-radius: 8px; border: 1px solid #ddd;">
<h2 style="color: #333; margin-top: 0;">Tipps zur Galerie</h2>
<p style="font-size: 0.9rem; color: #666;">
Das <b>Titelbild</b> wird immer auf der Startseite in der kleinen Karte angezeigt.<br><br>
Wenn jemand auf "Weiterlesen" klickt, werden <b>alle</b> Bilder, die du hier hinterlegst, im Artikel angezeigt.<br><br>
<b>Tipp:</b> Bilder werden nun automatisch vom System im perfekten Format zugeschnitten (CSS object-fit). Du sparst dir das nervige manuelle Zurechtschneiden!
</p>
</div>
</div>
</div>
<!-- News Liste -->
<div style="margin-top: 50px; border-top: 2px solid #eee; padding-top: 30px;">
<h2 style="color: #333; margin-bottom: 10px;">Bestehende News verwalten</h2>
<table class="news-table">
<tr>
<th>Datum</th>
<th>Abteilung</th>
<th>Titel</th>
<th style="width: 250px; text-align: right;">Aktion</th>
</tr>
<?php foreach($existing_news as $news_item): ?>
<tr>
<td><?= htmlspecialchars($news_item['date']) ?></td>
<td><span style="background: #eee; padding: 2px 8px; border-radius: 4px; font-size: 0.85rem;"><?= htmlspecialchars($news_item['department']) ?></span></td>
<td><strong><?= htmlspecialchars($news_item['title']) ?></strong></td>
<td style="text-align: right; display: flex; justify-content: flex-end; gap: 5px;">
<button type="button" class="social-btn" onclick="copySocialMediaText('<?= htmlspecialchars(addslashes($news_item['title'])) ?>', '<?= htmlspecialchars(addslashes($news_item['department'])) ?>')">📲 Posten</button>
<a href="?edit_id=<?= $news_item['id'] ?>" class="edit-btn">Ändern</a>
<form method="POST" style="margin: 0;" onsubmit="return confirm('Möchtest du diese News wirklich löschen?');">
<input type="hidden" name="delete_id" value="<?= $news_item['id'] ?>">
<button type="submit" name="delete_news" class="delete-btn">Löschen</button>
</form>
</td>
</tr>
<?php endforeach; ?>
</table>
</div>
</div>
<!-- Javascript -->
<script>
function copySocialMediaText(title, department) {
const cleanDept = department.replace(/\s+/g, '');
const text = `🚨 NEUE NEWS VON DER SG 07 🚨\n\n📢 ${title}\n\nLies jetzt den ganzen Bericht auf unserer Website!\n👉 sg07-stleon.de\n\n#SG07StLeon #Vereinsliebe #${cleanDept} #StLeonRot`;
const tempInput = document.createElement("textarea");
tempInput.value = text;
document.body.appendChild(tempInput);
tempInput.select();
document.execCommand("copy");
document.body.removeChild(tempInput);
alert("✅ Der Text für Instagram & Facebook wurde kopiert!");
}
</script>
</body>
</html>