Files
intranet/web/intranet_repo/projects/contentpanel/insertion/insert.php
T

953 lines
40 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
require_once __DIR__ . '/news_cleanup.php';
// Zugriff nur für Benutzer mit Rolle "Allgemein"
if (!isset($groups["Allgemein"]) || $groups["Allgemein"] != 1) {
header("Location: /intranet_repo/projects/intranet/index.php");
exit();
}
// Abgelaufene Aushänge entfernen
cleanupExpiredNews();
$meldung_gottesdienst = '';
$meldung_ansage = '';
$meldung_dateien = '';
// Funktion, um den Dokumentnamen zu bereinigen
function sanitizeFileName($fileName) {
// Entferne Leerzeichen und ersetze unzulässige Zeichen durch einen Unterstrich
return preg_replace('/[^A-Za-z0-9_\-]/', '_', str_replace(' ', '_', $fileName));
}
/** PDF -> Text per pdftotext (Poppler) */
function pdfToText($pdfFullPath) {
$bin = trim(shell_exec('command -v pdftotext'));
if ($bin === '') { $_SESSION['meldung_gottesdienst'] = "Fehler: 'pdftotext' nicht gefunden."; return false; }
$tmpTxt = tempnam(sys_get_temp_dir(), 'lg_').'.txt';
$cmd = escapeshellcmd($bin).' -layout -enc UTF-8 '.escapeshellarg($pdfFullPath).' '.escapeshellarg($tmpTxt).' 2>&1';
exec($cmd, $out, $ret);
if ($ret !== 0) { @unlink($tmpTxt); $_SESSION['meldung_gottesdienst'] = "Fehler beim PDF-Import:\n".htmlspecialchars(implode("\n", $out)); return false; }
$txt = file_get_contents($tmpTxt);
@unlink($tmpTxt);
return $txt;
}
function parseLeitgedanken($textRaw) {
// Zeilenenden normalisieren + Silbentrennungen (…-\n…) zusammenziehen
$text = preg_replace("/\r\n?/", "\n", $textRaw);
$text = preg_replace("/(?<=\p{L})-\n(?=\p{L})/u", "", $text);
$lines = explode("\n", $text);
// Abschnittsüberschriften mit Datum am Zeilenende
$dateHeaderRegex = '/(?P<prefix>.*?)(?P<d1>\d{1,2})(?:\.\s*\/\s*(?P<d2>\d{1,2}))?\.(?P<m>\d{1,2})\.(?P<y>\d{4})\s*$/u';
// Whitelist der (deutschen) Buchkürzel
$BOOKS = '(?:Mo|Sam|Kön|Chr|Dan|Ps|Spr|Pred|Hld|Hi|Jes|Jer|Klgl|Hes|Ez|Hos|Joel|Am|Ob|Mi|Nah|Hab|Zef|Hag|Sach|Mal|Rut|Ri|Jos|Esra|Neh|Est|'
. 'Mt|Mk|Lk|Joh|Apg|Röm|Kor|Gal|Eph|Phil|Kol|Thess|Tim|Tit|Phlm|Hebr|Jak|Petr|Joh|Jud|Offb)';
// Referenz am Zeilenende
$refRegex = '/(?P<ref>(?:[1-3]\.?\s*)?' . $BOOKS . '\s*\d{1,3}\s*,\s*\d{1,3}(?:[–\-]\d{1,3}(?:[a-z])?|(?:\.\d{1,3})+(?:[a-z])?|[a-z])?)\s*$/u';
// Abschnittsgrenzen sammeln
$sections = [];
for ($i = 0; $i < count($lines); $i++) {
if (preg_match($dateHeaderRegex, $lines[$i], $m)) {
$d = str_pad((int)$m['d1'], 2, '0', STR_PAD_LEFT);
$mn = str_pad((int)$m['m'], 2, '0', STR_PAD_LEFT);
$y = (int)$m['y'];
$sections[] = ['start'=>$i, 'date'=>sprintf('%04d-%02d-%02d',$y,$mn,$d)];
}
}
if (empty($sections)) return [];
$sections[array_key_last($sections)]['end'] = count($lines);
for ($s = 0; $s < count($sections)-1; $s++) { $sections[$s]['end'] = $sections[$s+1]['start']; }
$out = [];
foreach ($sections as $sec) {
for ($i = $sec['start']; $i < $sec['end']; $i++) {
$line = rtrim($lines[$i]); if ($line === '') continue;
if (preg_match($refRegex, $line, $mRef)) {
$beforeRef = trim(preg_replace($refRegex, '', $line));
$blkPrev = [];
for ($k = $i - 1; $k >= $sec['start'] && $k >= $i - 15; $k--) {
$pl = rtrim($lines[$k]); if ($pl === '') break;
if (preg_match($refRegex, $pl)) break;
$blkPrev[] = $pl;
}
$block = array_reverse($blkPrev);
if ($beforeRef !== '') $block[] = $beforeRef;
$vers = trim(preg_replace('/\s+/', ' ', implode(' ', $block)));
if ($vers !== '') {
$out[] = ['bibeldatum'=>$sec['date'], 'bibelwort'=>trim($mRef['ref']), 'bibelvers'=>$vers];
break; // pro Abschnitt nur das erste Bibelwort
}
}
}
}
// Dubletten raus
$uniq=[]; $final=[];
foreach ($out as $e) { $key=$e['bibeldatum'].'|'.$e['bibelwort']; if (!isset($uniq[$key])) { $uniq[$key]=1; $final[]=$e; } }
return $final;
}
// Hilfsfunktion, um PDF in PNG umzuwandeln
function convertPDFtoPNG($pdfFilePath, $outputDirectory, $baseFileName) {
if (!is_file($pdfFilePath)) {
error_log('PDF-Datei nicht gefunden: ' . $pdfFilePath);
return false;
}
$outputFilePath = $outputDirectory . '/' . $baseFileName . '_page_%d.png';
$command =
'gs -dSAFER -dBATCH -dNOPAUSE '
. '-sDEVICE=png16m -r300 '
. '-sOutputFile=' . escapeshellarg($outputFilePath) . ' '
. escapeshellarg($pdfFilePath)
. ' 2>&1';
$output = [];
$returnCode = 0;
exec($command, $output, $returnCode);
if ($returnCode !== 0) {
error_log(
'Ghostscript-Konvertierung fehlgeschlagen: '
. implode("\n", $output)
);
return false;
}
return true;
}
// LG-PDF importieren -> direkt alles in DB
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['leitgedanken_pdf'])) {
if ($_FILES['leitgedanken_pdf']['error'] !== UPLOAD_ERR_OK) {
$_SESSION['meldung_gottesdienst'] = 'Fehler beim Upload der Leitgedanken-PDF.';
} else {
$ext = strtolower(pathinfo($_FILES['leitgedanken_pdf']['name'], PATHINFO_EXTENSION));
if ($ext !== 'pdf') {
$_SESSION['meldung_gottesdienst'] = 'Nur PDF-Dateien sind für den Import erlaubt.';
} else {
$txt = pdfToText($_FILES['leitgedanken_pdf']['tmp_name']);
if ($txt !== false) {
$items = parseLeitgedanken($txt);
// vorbereitete Statements
$stmtExists = $pdo->prepare("SELECT 1 FROM gottesdienst WHERE bibeldatum = ? AND bibelwort = ? LIMIT 1");
$stmtInsert = $pdo->prepare("INSERT INTO gottesdienst (bibelwort, bibelvers, bibeldatum) VALUES (?, ?, ?)");
$ok=0; $dup=0;
foreach ($items as $it) {
$stmtExists->execute([$it['bibeldatum'], $it['bibelwort']]);
if ($stmtExists->fetchColumn() !== false) { $dup++; continue; }
$stmtInsert->execute([$it['bibelwort'], $it['bibelvers'], $it['bibeldatum']]); $ok++;
}
if ($ok > 0) {
$_SESSION['meldung_gottesdienst'] = "Leitgedanken importiert: $ok Einträge angelegt".($dup?(", $dup dupliziert übersprungen"):"").".";
} else {
$_SESSION['meldung_gottesdienst'] = "Keine neuen Einträge erkannt.".($dup?(" ($dup Duplikate)"):"");
}
}
}
}
header("Location: ".$_SERVER['PHP_SELF']);
exit();
}
// Aushang manuell löschen
if (
$_SERVER['REQUEST_METHOD'] === 'POST' &&
isset($_POST['delete_file_base'])
) {
$fileBase = (string) $_POST['delete_file_base'];
if (!isValidNewsFileBase($fileBase)) {
$_SESSION['meldung_dateien'] = 'Ungültiger Dateiname.';
} elseif (deleteNewsFiles($fileBase)) {
$_SESSION['meldung_dateien'] = 'Aushang wurde vollständig gelöscht.';
} else {
$_SESSION['meldung_dateien'] =
'Aushang konnte nicht vollständig gelöscht werden. Bitte Logs prüfen.';
}
header('Location: insert.php#dateien');
exit();
}
// Neuen Aushang hochladen und direkt in PNG-Seiten umwandeln
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['fileToUpload'])) {
$date = (string) ($_POST['date'] ?? '');
$dateObject = DateTimeImmutable::createFromFormat('!Y-m-d', $date);
if ($dateObject === false || $dateObject->format('Y-m-d') !== $date) {
$_SESSION['meldung_dateien'] = 'Ungültiges Verfallsdatum.';
header('Location: insert.php#dateien');
exit();
}
$name = trim(sanitizeFileName((string) ($_POST['name'] ?? '')), '_-');
if ($name === '') {
$_SESSION['meldung_dateien'] = 'Bitte einen gültigen Titel eingeben.';
header('Location: insert.php#dateien');
exit();
}
if (
$_FILES['fileToUpload']['error'] !== UPLOAD_ERR_OK ||
strtolower(pathinfo($_FILES['fileToUpload']['name'], PATHINFO_EXTENSION)) !== 'pdf'
) {
$_SESSION['meldung_dateien'] = 'Bitte eine gültige PDF-Datei hochladen.';
header('Location: insert.php#dateien');
exit();
}
$baseFileName = $date . '-' . $name;
if (!is_dir(NEWS_PNG_DIRECTORY) && !mkdir(NEWS_PNG_DIRECTORY, 0755, true)) {
$_SESSION['meldung_dateien'] = 'Das Aushang-Verzeichnis konnte nicht angelegt werden.';
header('Location: insert.php#dateien');
exit();
}
if (!convertPDFtoPNG(
$_FILES['fileToUpload']['tmp_name'],
NEWS_PNG_DIRECTORY,
$baseFileName
)) {
deleteNewsFiles($baseFileName);
$_SESSION['meldung_dateien'] = 'Fehler bei der Umwandlung der PDF.';
header('Location: insert.php#dateien');
exit();
}
$_SESSION['meldung_dateien'] = 'Aushang wurde erfolgreich hochgeladen.';
header('Location: insert.php#dateien');
exit();
}
// Löschen eines Gottesdienstes
if (isset($_POST['delete_id'])) {
$delete_id = $_POST['delete_id'];
// Löschanfrage vorbereiten
try {
$sql_delete = "DELETE FROM gottesdienst WHERE id = ?";
$stmt = $pdo->prepare($sql_delete);
$stmt->execute([$delete_id]);
$_SESSION['meldung_gottesdienst'] = "Eintrag erfolgreich gelöscht!";
header("Location: " . $_SERVER['PHP_SELF']); // Seite neu laden
exit(); // Skript nach dem Redirect beenden
} catch (Exception $e) {
$_SESSION['meldung_gottesdienst'] = "Fehler beim Löschen: " . $e->getMessage();
}
}
// Gottesdienst anlegen (ohne EL)
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['bibelwort']) && isset($_POST['bibelvers']) && isset($_POST['bibeldatum'])) {
$bibelwort = $_POST['bibelwort'];
$bibelvers = $_POST['bibelvers'];
$bibeldatum = $_POST['bibeldatum'];
try {
$sql = "INSERT INTO gottesdienst (bibelwort, bibelvers, bibeldatum) VALUES (?, ?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute([$bibelwort, $bibelvers, $bibeldatum]);
setlocale(LC_TIME, 'de_DE.UTF-8');
$formattedDate = strftime('%d. %B', strtotime($bibeldatum));
$_SESSION['meldung_gottesdienst'] = "Gottesdienst am " . $formattedDate . " erfolgreich angelegt!";
header("Location: " . $_SERVER['PHP_SELF']); exit();
} catch (Exception $e) {
$_SESSION['meldung_gottesdienst'] = "Fehler beim Einfügen: " . $e->getMessage();
}
}
// Ansage anlegen
if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['ansage_datum_von'])) {
$ansage_datum_von = $_POST['ansage_datum_von'];
$ansage_datum_bis = !empty($_POST['ansage_datum_bis']) ? $_POST['ansage_datum_bis'] : NULL;
$ansage_uhrzeit = !empty($_POST['ansage_uhrzeit']) ? $_POST['ansage_uhrzeit'] : NULL;
$ansage_ort = $_POST['ansage_ort'];
$ansage_titel = $_POST['ansage_titel'];
$ansage_untertitel = $_POST['ansage_untertitel'];
try {
// SQL-Anweisung
$sql = "INSERT INTO ansagen (ansage_datum_von, ansage_datum_bis, ansage_uhrzeit, ansage_ort, ansage_titel, ansage_untertitel)
VALUES (?, ?, ?, ?, ?, ?)";
// Statement vorbereiten
$stmt = $pdo->prepare($sql);
// Statement ausführen
$stmt->execute([$ansage_datum_von, $ansage_datum_bis, $ansage_uhrzeit, $ansage_ort, $ansage_titel, $ansage_untertitel]);
setlocale(LC_TIME, 'de_DE.UTF-8');
$formattedDate = strftime('%d. %B', strtotime($ansage_datum_von));
$_SESSION['meldung_ansage'] = $ansage_titel . " am " . $formattedDate . " erfolgreich angelegt!";
header("Location: " . $_SERVER['PHP_SELF']);
exit();
} catch (Exception $e) {
$_SESSION['meldung_ansage'] = "Fehler beim Einfügen: " . $e->getMessage();
}
}
// Löschen einer Ansage
if (isset($_POST['delete_ansage_id'])) {
$delete_ansage_id = $_POST['delete_ansage_id'];
// Löschanfrage vorbereiten
try {
$sql_delete_ansage = "DELETE FROM ansagen WHERE id = ?";
$stmt = $pdo->prepare($sql_delete_ansage);
$stmt->execute([$delete_ansage_id]);
$_SESSION['meldung_ansage'] = "Ansage erfolgreich gelöscht!";
header("Location: " . $_SERVER['PHP_SELF']);
exit();
} catch (Exception $e) {
$_SESSION['meldung_ansage'] = "Fehler beim Löschen: " . $e->getMessage();
}
}
// Meldungen aus der Session übernehmen
if (isset($_SESSION['meldung_gottesdienst'])) {
$meldung_gottesdienst = $_SESSION['meldung_gottesdienst'];
unset($_SESSION['meldung_gottesdienst']);
}
if (isset($_SESSION['meldung_ansage'])) {
$meldung_ansage = $_SESSION['meldung_ansage'];
unset($_SESSION['meldung_ansage']);
}
if (isset($_SESSION['meldung_dateien'])) {
$meldung_dateien = $_SESSION['meldung_dateien'];
unset($_SESSION['meldung_dateien']);
}
$heute = date('Y-m-d');
// Gottesdienste aus der Datenbank abrufen
$sql_fetch_gottesdienste = "SELECT id, bibelwort, bibelvers, TO_CHAR(bibeldatum, 'DD.MM.YYYY') AS datum FROM gottesdienst WHERE bibeldatum >= ? ORDER BY bibeldatum ASC";
$stmt = $pdo->prepare($sql_fetch_gottesdienste);
$stmt->execute([$heute]);
$planung_gottesdienste = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Ansagen aus der Datenbank abrufen
$sql_fetch_ansagen = "SELECT id, ansage_untertitel, ansage_titel, ansage_ort, ansage_uhrzeit, TO_CHAR(ansage_datum_von, 'DD.MM.YYYY') AS datum_von, TO_CHAR(ansage_datum_bis, 'DD.MM.YYYY') AS datum_bis FROM ansagen WHERE ansage_datum_von >= ? OR ansage_datum_bis >= ? ORDER BY ansage_datum_von ASC";
$stmt = $pdo->prepare($sql_fetch_ansagen);
$stmt->execute([$heute, $heute]);
$planung_ansagen = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Schließe die Datenbankverbindung
$pdo = null;
?>
<!DOCTYPE html>
<html lang="de" dir="ltr">
<head>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
<style>
/* ── Schwarzes Brett – NAK Redesign ── */
/* Page background gradient (matching Hauptmenü) */
.sb-page {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
margin-top: calc(var(--header-height) + var(--header-title-height));
width: 100%;
min-height: calc(100vh - var(--header-height) - var(--header-title-height) - var(--footer-height));
background: linear-gradient(135deg, var(--gray-50) 0%, hsl(330, 60%, 95%) 100%);
padding: var(--space-lg) var(--space-md) var(--space-3xl);
}
/* ── Tab Navigation (uses standard content-tab-bar from nak-design.css) ── */
.sb-page > .content-tab-bar {
margin: calc(-1 * var(--space-lg)) calc(-1 * var(--space-md)) 0;
width: calc(100% + 2 * var(--space-md));
}
/* ── Tab Content ── */
.sb-tab-content {
display: none;
width: 100%;
max-width: 960px;
margin: var(--space-lg) auto 0;
animation: sbFadeIn 300ms ease;
}
.sb-tab-content.active { display: block; }
@keyframes sbFadeIn {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: translateY(0); }
}
/* ── Cards ── */
.sb-card {
background: #ffffff;
box-shadow: var(--shadow-md);
padding: 24px 28px;
margin-bottom: var(--space-lg);
}
.sb-card-title {
font-size: 1rem;
font-weight: 600;
color: var(--gray-800);
margin: 0 0 var(--space-md) 0;
text-transform: uppercase;
letter-spacing: 0.04em;
display: flex;
align-items: center;
gap: 8px;
}
.sb-card-title svg {
width: 20px;
height: 20px;
fill: var(--nak-raspberry);
flex-shrink: 0;
}
/* ── Existing entries list ── */
.sb-entry-list {
display: flex;
flex-direction: column;
gap: 0;
border: 1px solid var(--gray-200);
margin-bottom: var(--space-lg);
max-height: 360px;
overflow-y: auto;
}
.sb-entry-list:empty::after {
content: 'Keine Einträge vorhanden.';
display: block;
padding: 16px;
text-align: center;
color: var(--gray-500);
font-size: var(--font-size-sm);
}
.sb-entry {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
border-bottom: 1px solid var(--gray-100);
gap: 12px;
}
.sb-entry:last-child { border-bottom: none; }
.sb-entry-info {
flex: 1;
min-width: 0;
}
.sb-entry-date {
font-size: var(--font-size-xs);
font-weight: 600;
color: var(--nak-raspberry);
text-transform: uppercase;
letter-spacing: 0.03em;
}
.sb-entry-title {
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--gray-800);
margin-top: 2px;
}
.sb-entry-subtitle {
font-size: var(--font-size-xs);
color: var(--gray-500);
font-style: italic;
margin-top: 2px;
}
.sb-entry-meta {
font-size: var(--font-size-xs);
color: var(--gray-500);
margin-top: 2px;
}
/* ── Form styles ── */
.sb-form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-md);
}
.sb-form-grid-single {
grid-template-columns: 1fr;
}
.sb-form-full {
grid-column: 1 / -1;
}
.sb-field-group {
display: flex;
flex-direction: column;
gap: 4px;
}
.sb-label {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--gray-700);
}
.sb-field {
padding: 10px 14px;
font-size: var(--font-size-base);
font-family: var(--font-primary);
font-weight: 300;
border: 1px solid var(--gray-300);
background: var(--gray-50);
outline: none;
transition: border-color 150ms ease, box-shadow 150ms ease;
width: 100%;
box-sizing: border-box;
}
.sb-field:focus {
border-color: var(--nak-raspberry);
box-shadow: 0 0 0 3px rgba(215, 50, 130, 0.15);
background: #ffffff;
}
/* ── Buttons ── */
.sb-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
min-height: 40px;
padding: 10px 20px;
font-size: var(--font-size-sm);
font-weight: 600;
font-family: var(--font-primary);
border: 1px solid var(--gray-300);
background: #ffffff;
color: var(--gray-700);
cursor: pointer;
transition: background 150ms ease, transform 150ms ease, box-shadow 150ms ease;
white-space: nowrap;
}
.sb-btn:hover {
background: var(--gray-100);
transform: translateY(-1px);
box-shadow: var(--shadow-sm);
}
.sb-btn-primary {
background: linear-gradient(135deg, var(--nak-raspberry), #b8296e);
border-color: var(--nak-raspberry);
color: #ffffff;
}
.sb-btn-primary:hover {
background: linear-gradient(135deg, #b8296e, #9c2260);
border-color: #b8296e;
}
.sb-btn-danger {
background: none;
border: 1px solid var(--gray-300);
color: var(--nak-red);
font-size: var(--font-size-xs);
padding: 6px 12px;
min-height: 30px;
}
.sb-btn-danger:hover {
background: hsl(0, 78%, 96%);
border-color: var(--nak-red);
}
/* ── Meldung / Alert ── */
.sb-alert {
padding: 10px 16px;
margin-bottom: var(--space-md);
font-size: var(--font-size-sm);
font-weight: 500;
background: hsl(145, 50%, 93%);
color: hsl(145, 50%, 28%);
border: 1px solid hsl(145, 50%, 85%);
}
/* ── Dateiverwaltung: Aushang Grid ── */
.sb-aushang-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: var(--space-md);
margin-bottom: var(--space-lg);
}
.sb-aushang-card {
background: var(--gray-50);
border: 1px solid var(--gray-200);
padding: 12px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
transition: box-shadow 200ms ease, transform 200ms ease;
}
.sb-aushang-card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
}
.sb-aushang-card img {
width: 100%;
height: 180px;
object-fit: cover;
border: 1px solid var(--gray-200);
}
.sb-aushang-title {
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--gray-800);
text-align: center;
}
.sb-aushang-meta {
font-size: var(--font-size-xs);
color: var(--gray-500);
text-align: center;
}
/* ── Loading Spinner ── */
.sb-spinner {
display: none;
width: 24px;
height: 24px;
border: 3px solid var(--gray-200);
border-top-color: var(--nak-raspberry);
border-radius: 50%;
animation: sbSpin 0.8s linear infinite;
margin: 0 auto;
}
@keyframes sbSpin { to { transform: rotate(360deg); } }
/* ── Separator ── */
.sb-divider {
border: none;
border-top: 1px solid var(--gray-200);
margin: var(--space-lg) 0;
}
/* ── Responsive ── */
@media (max-width: 768px) {
.sb-page { padding: var(--space-md) var(--space-sm); }
.sb-card { padding: 16px; }
.sb-form-grid { grid-template-columns: 1fr; }
.sb-tab { padding: 10px 8px; font-size: var(--font-size-xs); }
.sb-tab svg { width: 14px; height: 14px; }
.sb-aushang-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}
@media (max-width: 480px) {
.sb-tabs { gap: 0; }
.sb-tab { padding: 8px 4px; font-size: 0.65rem; gap: 4px; }
}
</style>
</head>
<body class="theme-raspberry">
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
<div class="header_title ht_raspberry text_white" id="header_title">
<span class="header_title_text">Schwarzes Brett</span>
</div>
<div class="sb-page">
<!-- Tab Navigation -->
<div class="content-tab-bar">
<div class="content-tab-bar__item active" data-tab="gottesdienst" onclick="sbSwitchTab('gottesdienst')">Gottesdienst</div>
<div class="content-tab-bar__item" data-tab="ansagen" onclick="sbSwitchTab('ansagen')">Ansagen</div>
<div class="content-tab-bar__item" data-tab="dateien" onclick="sbSwitchTab('dateien')">Dateiverwaltung</div>
</div>
<!-- ═══════════════════════════════════════════════ -->
<!-- TAB 1: Gottesdienst -->
<!-- ═══════════════════════════════════════════════ -->
<div class="sb-tab-content active" id="tab-gottesdienst">
<!-- Meldung -->
<?php if (!empty($meldung_gottesdienst)) : ?>
<div class="sb-alert" style="margin-top:var(--space-md);"><?php echo htmlspecialchars($meldung_gottesdienst); ?></div>
<?php endif; ?>
<!-- Bisherige Planung -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z"/></svg>
Geplante Gottesdienste
</div>
<div class="sb-entry-list">
<?php if (count($planung_gottesdienste) > 0) : ?>
<?php foreach ($planung_gottesdienste as $row) : ?>
<div class="sb-entry">
<div class="sb-entry-info">
<div class="sb-entry-date"><?php echo $row['datum']; ?></div>
<div class="sb-entry-title"><?php echo htmlspecialchars($row['bibelwort']); ?></div>
<div class="sb-entry-subtitle"><?php echo htmlspecialchars($row['bibelvers']); ?></div>
</div>
<form method="POST" action="">
<input type="hidden" name="delete_id" value="<?php echo $row['id']; ?>">
<button type="submit" class="sb-btn sb-btn-danger" onclick="return confirm('Eintrag wirklich löschen?')">Löschen</button>
</form>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- Leitgedanken Import -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z"/></svg>
Leitgedanken importieren
</div>
<form action="" method="post" enctype="multipart/form-data">
<div class="sb-form-grid sb-form-grid-single">
<div class="sb-field-group">
<label class="sb-label">PDF hochladen (LG_*.pdf)</label>
<input class="sb-field" type="file" name="leitgedanken_pdf" accept=".pdf" required>
</div>
<div class="sb-field-group">
<button type="submit" class="sb-btn sb-btn-primary">Import starten</button>
</div>
</div>
</form>
</div>
<!-- Neuen Gottesdienst planen -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
Neuen Gottesdienst planen
</div>
<form method="POST" action="">
<div class="sb-form-grid">
<div class="sb-field-group sb-form-full">
<label class="sb-label">Datum des Gottesdienstes <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="date" name="bibeldatum" required>
</div>
<div class="sb-field-group">
<label class="sb-label">Bibelstelle <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="text" name="bibelwort" required placeholder="z.B. Joh 3,16">
</div>
<div class="sb-field-group">
<label class="sb-label">Bibelvers <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="text" name="bibelvers" required placeholder="Bibelvers eingeben">
</div>
<div class="sb-field-group sb-form-full" style="margin-top:var(--space-sm);">
<button type="submit" class="sb-btn sb-btn-primary">Eintragen</button>
</div>
</div>
</form>
</div>
</div>
<!-- ═══════════════════════════════════════════════ -->
<!-- TAB 2: Ansagen -->
<!-- ═══════════════════════════════════════════════ -->
<div class="sb-tab-content" id="tab-ansagen">
<!-- Meldung -->
<?php if (!empty($meldung_ansage)) : ?>
<div class="sb-alert" style="margin-top:var(--space-md);"><?php echo htmlspecialchars($meldung_ansage); ?></div>
<?php endif; ?>
<!-- Bisherige Ansagen -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm0 14H6l-2 2V4h16v12z"/></svg>
Geplante Ansagen
</div>
<div class="sb-entry-list">
<?php if (count($planung_ansagen) > 0) : ?>
<?php foreach ($planung_ansagen as $row) : ?>
<div class="sb-entry">
<div class="sb-entry-info">
<div class="sb-entry-date">
<?php echo $row['datum_von']; ?>
<?php if (!empty($row['datum_bis'])): ?> – <?php echo $row['datum_bis']; ?><?php endif; ?>
</div>
<div class="sb-entry-title"><?php echo htmlspecialchars($row['ansage_titel']); ?></div>
<?php if (!empty($row['ansage_untertitel'])): ?>
<div class="sb-entry-subtitle"><?php echo htmlspecialchars($row['ansage_untertitel']); ?></div>
<?php endif; ?>
<div class="sb-entry-meta">
<?php if (!empty($row['ansage_uhrzeit'])): ?>
<?php echo date('H:i', strtotime($row['ansage_uhrzeit'])); ?> Uhr
<?php endif; ?>
<?php if (!empty($row['ansage_ort'])): ?>
· <?php echo htmlspecialchars($row['ansage_ort']); ?>
<?php endif; ?>
</div>
</div>
<form method="POST" action="">
<input type="hidden" name="delete_ansage_id" value="<?php echo $row['id']; ?>">
<button type="submit" class="sb-btn sb-btn-danger" onclick="return confirm('Ansage wirklich löschen?')">Löschen</button>
</form>
</div>
<?php endforeach; ?>
<?php endif; ?>
</div>
</div>
<!-- Neue Ansage planen -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/></svg>
Neue Ansage planen
</div>
<form method="POST" action="">
<div class="sb-form-grid">
<div class="sb-field-group sb-form-full">
<label class="sb-label">Titel <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="text" name="ansage_titel" required placeholder="Titel der Ansage">
</div>
<div class="sb-field-group">
<label class="sb-label">Datum <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="date" name="ansage_datum_von" required>
</div>
<div class="sb-field-group">
<label class="sb-label">Datum bis <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="sb-field" type="date" name="ansage_datum_bis">
</div>
<div class="sb-field-group">
<label class="sb-label">Uhrzeit <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="sb-field" type="time" name="ansage_uhrzeit">
</div>
<div class="sb-field-group">
<label class="sb-label">Ort <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="sb-field" type="text" name="ansage_ort" placeholder="z.B. Gemeindesaal">
</div>
<div class="sb-field-group sb-form-full">
<label class="sb-label">Weitere Informationen <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="sb-field" type="text" name="ansage_untertitel" placeholder="Zusätzliche Hinweise">
</div>
<div class="sb-field-group sb-form-full" style="margin-top:var(--space-sm);">
<button type="submit" class="sb-btn sb-btn-primary">Eintragen</button>
</div>
</div>
</form>
</div>
</div>
<!-- ═══════════════════════════════════════════════ -->
<!-- TAB 3: Dateiverwaltung -->
<!-- ═══════════════════════════════════════════════ -->
<div class="sb-tab-content" id="tab-dateien">
<!-- Meldung -->
<?php if (!empty($meldung_dateien)) : ?>
<div class="sb-alert" style="margin-top:var(--space-md);"><?php echo htmlspecialchars($meldung_dateien); ?></div>
<?php endif; ?>
<!-- Aktuelle Aushänge -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg>
Aktuelle Aushänge
</div>
<div class="sb-aushang-grid">
<?php
$aushangFiles = glob(NEWS_PNG_DIRECTORY . '/*_page_1.png') ?: [];
if (!$aushangFiles) {
echo '<p style="color:var(--gray-500);font-size:var(--font-size-sm);grid-column:1/-1;text-align:center;padding:var(--space-lg) 0;">Keine Aushänge vorhanden.</p>';
} else {
foreach ($aushangFiles as $file) {
$baseFileName = basename($file, '_page_1.png');
$expiryDate = substr($baseFileName, 0, 10);
$title = substr($baseFileName, 11);
$numPages = count(glob(NEWS_PNG_DIRECTORY . '/' . $baseFileName . '_page_*.png') ?: []);
$formattedExpiryDate = DateTime::createFromFormat('!Y-m-d', $expiryDate)?->format('d.m.Y') ?? $expiryDate;
$safeBase = htmlspecialchars($baseFileName, ENT_QUOTES, 'UTF-8');
echo '<div class="sb-aushang-card">';
echo '<img src="/intranet_repo/projects/contentpanel/insertion/news/png/' . rawurlencode($baseFileName) . '_page_1.png" alt="Aushang">';
echo '<div class="sb-aushang-title">' . htmlspecialchars($title) . '</div>';
echo '<div class="sb-aushang-meta">' . $numPages . ($numPages === 1 ? ' Seite' : ' Seiten') . ' · Verfällt ' . $formattedExpiryDate . '</div>';
echo '<form method="POST" action="" style="width:100%;text-align:center;">';
echo '<input type="hidden" name="delete_file_base" value="' . $safeBase . '">';
echo '<button type="submit" class="sb-btn sb-btn-danger" onclick="return confirm(\'Aushang wirklich löschen?\')">Löschen</button>';
echo '</form>';
echo '</div>';
}
}
?>
</div>
</div>
<!-- Neuen Aushang hochladen -->
<div class="sb-card">
<div class="sb-card-title">
<svg viewBox="0 0 24 24"><path d="M9 16h6v-6h4l-7-7-7 7h4v6zm-4 2h14v2H5v-2z"/></svg>
Neuen Aushang hochladen
</div>
<form action="insert.php" method="post" enctype="multipart/form-data" id="uploadForm">
<div class="sb-form-grid">
<div class="sb-field-group">
<label class="sb-label">Verfallsdatum <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="date" name="date" required>
</div>
<div class="sb-field-group">
<label class="sb-label">Titel des Aushangs <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="text" name="name" required placeholder="Name des Dokuments">
</div>
<div class="sb-field-group sb-form-full">
<label class="sb-label">PDF-Datei auswählen <span style="color:var(--nak-red);">*</span></label>
<input class="sb-field" type="file" name="fileToUpload" accept=".pdf" required>
</div>
<div class="sb-field-group sb-form-full" style="margin-top:var(--space-sm);">
<button type="submit" class="sb-btn sb-btn-primary" id="uploadButton">Datei hochladen</button>
<span class="sb-spinner" id="loadingSpinner"></span>
</div>
</div>
</form>
</div>
</div>
</div><!-- .sb-page -->
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
<script>
function sbSwitchTab(tabName) {
// Deactivate all tabs
document.querySelectorAll('.content-tab-bar__item').forEach(function(t) { t.classList.remove('active'); });
document.querySelectorAll('.sb-tab-content').forEach(function(c) { c.classList.remove('active'); });
// Activate selected
document.querySelector('.content-tab-bar__item[data-tab="' + tabName + '"]').classList.add('active');
document.getElementById('tab-' + tabName).classList.add('active');
// Save to URL hash
history.replaceState(null, '', '#' + tabName);
}
// Restore tab from URL hash
(function() {
var hash = window.location.hash.replace('#', '');
if (hash && document.getElementById('tab-' + hash)) {
sbSwitchTab(hash);
}
})();
// Upload spinner
var uploadForm = document.getElementById('uploadForm');
if (uploadForm) {
uploadForm.addEventListener('submit', function() {
document.getElementById('uploadButton').style.display = 'none';
document.getElementById('loadingSpinner').style.display = 'inline-block';
});
}
// Auto-switch to tab with message
<?php if (!empty($meldung_dateien)) : ?>
sbSwitchTab('dateien');
<?php elseif (!empty($meldung_ansage)) : ?>
sbSwitchTab('ansagen');
<?php endif; ?>
</script>
</body>
</html>