Files
intranet/web/intranet_repo/projects/kalli/kalli.php
T
2026-08-26 16:02:05 +02:00

783 lines
28 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 /* Name: kalli.php
Beschreibung: Kalli: Hauptseite */
require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/general_files/initialise.php';
?>
<!DOCTYPE html>
<html lang="de" dir="ltr">
<head>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/html_head.php'; ?>
</head>
<body class="theme-blue">
<?php // Stelle sicher, dass die Autoload-Datei von PHPSpreadsheet geladen wird
require 'vendor/autoload.php'; ?>
<?php // Durchführung der Aktionen
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
if(isset($_POST['submit'])) {
// if no errors, carry on
if(!isset($error)) {
$name = htmlspecialchars($user["first_name"]) . " " . htmlspecialchars($user["last_name"]);
$info = "Von " . $name . " eingetragen (Eintragungsassistent)";
// Create a new PHPExcel object
$spreadsheet = new Spreadsheet();
$sheet = $spreadsheet->getActiveSheet();
// Set the header row
$sheet->setCellValue('A1', 'ID');
$sheet->setCellValue('B1', 'Lang-ID');
$sheet->setCellValue('C1', 'Termin-Typ');
$sheet->setCellValue('D1', 'Von-Datum');
$sheet->setCellValue('E1', 'Von-Zeit');
$sheet->setCellValue('F1', 'Bis-Datum');
$sheet->setCellValue('G1', 'Bis-Zeit');
$sheet->setCellValue('H1', 'Zeitzusatz');
$sheet->setCellValue('I1', 'Titel');
$sheet->setCellValue('J1', 'Text');
$sheet->setCellValue('K1', 'Ort');
$sheet->setCellValue('L1', 'Planungsstatus');
$sheet->setCellValue('M1', 'Anzeigeziel');
$sheet->setCellValue('N1', 'Gruppenzuordnung');
$sheet->setCellValue('O1', 'Zyklusart');
$sheet->setCellValue('P1', 'Zyklusintervall');
$sheet->setCellValue('Q1', 'Zyklusdetail');
$sheet->setCellValue('R1', 'Notiz');
$sheet->setCellValue('S1', 'Verantwortlich');
$sheet->setCellValue('T1', 'Hintergrundfarbe');
$sheet->setCellValue('U1', 'BucherID');
$sheet->setCellValue('V1', 'Benutzerdefinierte Felder');
$sheet->setCellValue('W1', 'Dokument-Titel');
$sheet->setCellValue('X1', 'Anzeigeziel Ort');
$sheet->setCellValue('Y1', 'Anzeigeziel Notiz');
$sheet->setCellValue('Z1', 'Anzeigeziel Verantwortlicher');
$sheet->setCellValue('AA1', 'Erzeugt');
$sheet->setCellValue('AB1', 'Aktualisiert');
// Set the data row
// Titel
$selectedGroup = isset($_POST['group']) ? $_POST['group'] : '';
$sheet->setCellValue('I2', $selectedGroup);
// Datum
$date_s = isset($_POST['date_s']) ? $_POST['date_s'] : '';
$sheet->setCellValue('D2', date('d.m.Y', strtotime($date_s)));
$date_e = isset($_POST['date_e']) ? $_POST['date_e'] : '';
if (date('d.m.Y', strtotime($date_e)) != "01.01.1970"){
$sheet->setCellValue('F2', date('d.m.Y', strtotime($date_e)));
}
// Zeit
$time_s = isset($_POST['time_s']) ? $_POST['time_s'] : '';
if ($time_s !== '' && preg_match('/^\d{2}:\d{2}$/', $time_s)) {
$sheet->setCellValue('E2', $time_s);
} elseif ($time_s !== '') {
$error[] = "Ungültiges Zeitformat. Verwenden Sie das Format hh:mm.";
}
$time_e = isset($_POST['time_e']) ? $_POST['time_e'] : '';
if ($time_e !== '' && preg_match('/^\d{2}:\d{2}$/', $time_e)) {
$sheet->setCellValue('G2', $time_e);
} elseif ($time_e !== '') {
$error[] = "Ungültiges Zeitformat. Verwenden Sie das Format hh:mm.";
}
// FIX
$sheet->setCellValue('C2', 'Einzel');
$sheet->setCellValue('O2', 'einmalig');
// Setze den Ort in Zelle K2
$location = isset($_POST['location']) ? htmlspecialchars($_POST['location']) : '';
$sheet->setCellValue('K2', $location);
// Setze den Text in Zelle J2
$further_text = isset($_POST['further_text']) ? htmlspecialchars($_POST['further_text']) : '';
$sheet->setCellValue('J2', $further_text);
$sheet->setCellValue('R2', $info);
$responsibility = isset($_POST['responsibility']) ? htmlspecialchars($_POST['responsibility']) : '';
$sheet->setCellValue('S2', $responsibility);
$userInput = isset($_POST['userinput']) ? $_POST['userinput'] : '';
$userInput2 = isset($_POST['userinput2']) ? $_POST['userinput2'] : '';
// DB-Lookup: Preset-Werte für die gewählte Terminart laden
$presetStmt = $pdo->prepare("SELECT planungsstatus, anzeigeziel, gruppenzuordnung, anzeigeziel_ort, anzeigeziel_notiz, anzeigeziel_verantwortlicher, default_text FROM kalli_appointment_types WHERE name = ? LIMIT 1");
$presetStmt->execute([$selectedGroup]);
$preset = $presetStmt->fetch(PDO::FETCH_ASSOC);
if ($preset) {
$sheet->setCellValue('L2', $preset['planungsstatus']);
$sheet->setCellValue('M2', $preset['anzeigeziel']);
$sheet->setCellValue('N2', $preset['gruppenzuordnung']);
$sheet->setCellValue('X2', $preset['anzeigeziel_ort']);
$sheet->setCellValue('Y2', $preset['anzeigeziel_notiz']);
$sheet->setCellValue('Z2', $preset['anzeigeziel_verantwortlicher']);
if (!empty($preset['default_text']) && empty($further_text)) {
$sheet->setCellValue('J2', $preset['default_text']);
}
} elseif ($userInput != "" && $selectedGroup == "oeffentlich") {
$sheet->setCellValue('I2', $userInput);
$sheet->setCellValue('L2', 'fix');
$sheet->setCellValue('M2', 'öffentlich');
$sheet->setCellValue('N2', 'AN ALLE');
$sheet->setCellValue('X2', 'öffentlich');
$sheet->setCellValue('Y2', 'intern');
$sheet->setCellValue('Z2', 'intern');
} elseif ($userInput != "" && $selectedGroup == "intern") {
$sheet->setCellValue('I2', $userInput);
$sheet->setCellValue('L2', 'fix');
$sheet->setCellValue('M2', 'intern');
$sheet->setCellValue('N2', 'AN ALLE');
$sheet->setCellValue('X2', 'intern');
$sheet->setCellValue('Y2', 'intern');
$sheet->setCellValue('Z2', 'intern');
}
// Save the file on the server
$xlsxDir = rtrim(intranet_env('CKAL_XLSX_DIR', '/data/ckal-xlsx'), '/');
if (!is_dir($xlsxDir) && !mkdir($xlsxDir, 0770, true) && !is_dir($xlsxDir)) {
throw new RuntimeException("CKalender-XLSX-Verzeichnis kann nicht angelegt werden: {$xlsxDir}");
}
$FileName = $xlsxDir . "/" . $name . "-" . date("Ymd-His") . ".xlsx";
$writer = new Xlsx($spreadsheet);
$writer->save($FileName);
// Redirect to prevent form resubmission on page reload
print "<script language='javascript'>window.location.href='/intranet_repo/projects/intranet/index.php?kalli_success=1';</script>";
//header("Location: kalli.php");
//exit();
}
}
// ACHTUNG: Die PHP-Header Weiterleitungen müssen hier abgeschlossen sein.
?>
<?php
// Es folgen ab hier die HTML-Ausgaben beginnend mit dem HTML-Header:
?>
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/header.php'; ?>
<?php include $g_phpSnippetsPath.'overlay_message.php'; ?>
<div class="header_title ht_kalli text_white" id="header_title">
<span class="header_title_text">Kalli: Eintragungsassistent</span>
</div>
<div class="content" id="base">
<?php if (isset($_SESSION["user_id"])): ?>
<?php
if (isset($_GET["error"])) {
$error = $_GET["error"];
$isSuccess = in_array($error, [3]);
$toastType = $isSuccess ? 'success' : 'error';
$toastIcon = $isSuccess
? '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><path d="M20 6L9 17l-5-5"/></svg>'
: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="square" stroke-linejoin="miter"><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>';
$toastText = ($error == 3) ? 'Eintragung erfolgreich! Kalli wird Ihren Termin direkt vermerken.' : 'Es gab einen Fehler. Bitte kontaktieren Sie uns!';
echo "<div class='nak-toast nak-toast--{$toastType}' id='nakToast'>";
echo "<div class='nak-toast__icon'>{$toastIcon}</div>";
echo "<span class='nak-toast__text'>" . htmlspecialchars($toastText) . "</span>";
echo "<button class='nak-toast__close' onclick='dismissNakToast()' aria-label='Schließen'><svg viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2.5' stroke-linecap='square' stroke-linejoin='miter'><line x1='18' y1='6' x2='6' y2='18'/><line x1='6' y1='6' x2='18' y2='18'/></svg></button>";
echo "</div>";
echo "<script>
requestAnimationFrame(function(){document.getElementById('nakToast').classList.add('nak-toast--visible');});
setTimeout(function(){dismissNakToast();},4000);
function dismissNakToast(){var t=document.getElementById('nakToast');if(!t||t.classList.contains('nak-toast--hiding'))return;t.classList.add('nak-toast--hiding');t.classList.remove('nak-toast--visible');setTimeout(function(){t.remove();},350);}
</script>";
}
?>
<style>
/* ── Kalli Page Wizard ── */
.kalli-wizard {
max-width: 1400px;
width: 90%;
margin: var(--space-xl) auto;
background: #ffffff;
box-shadow: var(--shadow-md);
overflow: hidden;
}
/* ── Progress Bar ── */
.kalli-progress {
display: flex;
align-items: center;
justify-content: center;
gap: 0;
padding: 20px 28px 16px;
background: var(--gray-50);
border-bottom: 1px solid var(--gray-200);
}
.kalli-progress-step {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
flex-shrink: 0;
}
.kalli-progress-circle {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--gray-500);
background: var(--gray-200);
border: 2px solid var(--gray-300);
transition: all 250ms ease;
}
.kalli-progress-step.active .kalli-progress-circle {
background: var(--nak-blue);
border-color: var(--nak-blue);
color: #ffffff;
box-shadow: 0 2px 8px rgba(39,134,207,0.35);
}
.kalli-progress-step.done .kalli-progress-circle {
background: #ffffff;
border-color: var(--nak-blue);
color: var(--nak-blue);
}
.kalli-progress-label {
font-size: var(--font-size-xs);
font-weight: 500;
color: var(--gray-500);
white-space: nowrap;
transition: color 250ms ease;
}
.kalli-progress-step.active .kalli-progress-label,
.kalli-progress-step.done .kalli-progress-label {
color: var(--nak-blue);
}
.kalli-progress-line {
flex: 1;
height: 2px;
min-width: 20px;
max-width: 60px;
background: var(--gray-300);
margin: 0 6px;
margin-bottom: 20px;
transition: background 250ms ease;
}
.kalli-progress-line.done {
background: var(--nak-blue);
}
/* ── Body ── */
.kalli-modal-body {
padding: 22px 28px 16px;
}
.kalli-section-title {
margin: 0 0 16px 0;
font-size: var(--font-size-sm);
font-weight: 600;
letter-spacing: 0.04em;
text-transform: uppercase;
color: var(--gray-600);
}
/* ── Category Grid (Step 1) ── */
.kalli-category-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: var(--space-lg);
}
.kalli-category {
display: flex;
flex-direction: column;
gap: 2px;
}
.kalli-category-label {
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--gray-700);
margin-bottom: 4px;
text-transform: uppercase;
letter-spacing: 0.03em;
}
label.kalli-radio-item {
display: flex;
align-items: center;
gap:8px;
padding: 0px 5px;
cursor: pointer;
font-size: var(--font-size-sm);
font-weight: 300;
color: var(--gray-600);
border: 1px solid transparent;
transition: background 150ms ease, border-color 150ms ease;
text-transform: none;
letter-spacing: normal;
}
label.kalli-radio-item input[type="radio"],
label.kalli-radio-item input[type="checkbox"] {
width: 16px;
height: 16px;
accent-color: var(--nak-blue);
margin: 0;
flex-shrink: 0;
align-self: center;
}
label.kalli-radio-item span {
hyphens: auto;
-webkit-hyphens: auto;
-ms-hyphens: auto;
word-break: break-word;
overflow-wrap: break-word;
line-height: 1.4;
}
label.kalli-radio-item:hover {
background: var(--gray-50);
border-color: var(--gray-200);
}
.kalli-custom-section {
margin-top: var(--space-lg);
padding: var(--space-md);
background: hsl(0,60%,98%);
border: 1px solid hsl(0,60%,90%);
}
/* ── Field Grid (Steps 2 & 3) ── */
.kalli-field-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-md);
}
.kalli-field-grid-single {
grid-template-columns: 1fr;
}
.kalli-field-group {
display: flex;
flex-direction: column;
gap: 4px;
}
.kalli-label {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--gray-700);
}
.kalli-field {
padding: 12px 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;
}
.kalli-field:focus {
border-color: var(--nak-blue);
box-shadow: 0 0 0 3px rgba(39,134,207,0.2);
background: #ffffff;
}
/* ── Summary (Step 4) ── */
.kalli-summary {
display: flex;
flex-direction: column;
gap: 0;
border: 1px solid var(--gray-200);
}
.kalli-summary-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 16px;
border-bottom: 1px solid var(--gray-100);
}
.kalli-summary-row:last-child { border-bottom: none; }
.kalli-summary-label {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--gray-600);
}
.kalli-summary-value {
font-size: var(--font-size-sm);
font-weight: 500;
color: var(--gray-900);
text-align: right;
}
.kalli-validation-error {
margin-top: var(--space-md);
padding: 10px 14px;
background: hsl(0,78%,95%);
color: hsl(0,78%,40%);
font-weight: 600;
font-size: var(--font-size-sm);
}
/* ── Actions ── */
.kalli-modal-actions {
display: flex;
justify-content: space-between;
align-items: center;
gap: 10px;
padding: 16px 28px 20px;
border-top: 1px solid var(--gray-200);
}
.kalli-modal-actions-left,
.kalli-modal-actions-right {
display: flex;
gap: 8px;
}
.kalli-btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 38px;
padding: 8px 18px;
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-800);
cursor: pointer;
transition: background 150ms ease, transform 150ms ease;
white-space: nowrap;
}
.kalli-btn:hover {
background: var(--gray-100);
transform: translateY(-1px);
}
.kalli-btn-primary {
background: var(--nak-blue);
border-color: var(--nak-blue);
color: #ffffff;
}
.kalli-btn-primary:hover {
background: var(--nak-blue-hover);
border-color: var(--nak-blue-hover);
}
.kalli-btn-submit {
background: linear-gradient(135deg, var(--nak-blue), var(--nak-blue-hover));
border-color: var(--nak-blue-hover);
color: #ffffff;
padding: 10px 24px;
font-weight: 700;
}
.kalli-btn-submit:hover {
background: linear-gradient(135deg, var(--nak-blue-hover), #185d8f);
}
/* ── Responsive ── */
@media (max-width: 600px) {
.kalli-wizard { margin: 0; width: 100%; }
.kalli-progress { padding: 14px 12px 10px; }
.kalli-progress-label { font-size: 0.65rem; }
.kalli-progress-circle { width: 26px; height: 26px; font-size: 0.7rem; }
.kalli-progress-line { min-width: 12px; margin-bottom: 16px; }
.kalli-modal-body { padding: 16px; }
.kalli-category-grid { grid-template-columns: 1fr; }
.kalli-field-grid { grid-template-columns: 1fr; }
.kalli-modal-actions { padding: 12px 16px 16px; flex-wrap: wrap; }
}
</style>
<div class="kalli-wizard">
<!-- Progress Bar -->
<div class="kalli-progress">
<div class="kalli-progress-step active" data-step="1">
<div class="kalli-progress-circle">1</div>
<span class="kalli-progress-label">Terminart</span>
</div>
<div class="kalli-progress-line"></div>
<div class="kalli-progress-step" data-step="2">
<div class="kalli-progress-circle">2</div>
<span class="kalli-progress-label">Zeitraum</span>
</div>
<div class="kalli-progress-line"></div>
<div class="kalli-progress-step" data-step="3">
<div class="kalli-progress-circle">3</div>
<span class="kalli-progress-label">Informationen</span>
</div>
<div class="kalli-progress-line"></div>
<div class="kalli-progress-step" data-step="4">
<div class="kalli-progress-circle">4</div>
<span class="kalli-progress-label">Übersicht</span>
</div>
</div>
<!-- Form wraps all steps -->
<form id="kalliForm" action="" method="post">
<!-- STEP 1: Terminart -->
<div class="kalli-step" id="kalliStep1">
<div class="kalli-modal-body">
<div class="kalli-section-title">Terminart auswählen</div>
<div class="kalli-category-grid">
<?php
// Kategorien und Terminarten aus der Datenbank laden
$catQuery = $pdo->query("SELECT * FROM kalli_categories ORDER BY sort_order, name");
$kalliCategories = [];
while ($cat = $catQuery->fetch(PDO::FETCH_ASSOC)) {
$kalliCategories[] = $cat;
}
$typeQuery = $pdo->query("SELECT * FROM kalli_appointment_types ORDER BY sort_order, name");
$kalliTypesByCategory = [];
while ($type = $typeQuery->fetch(PDO::FETCH_ASSOC)) {
$kalliTypesByCategory[$type['category_id']][] = $type;
}
// Alle verwendeten Rollen sammeln für die "Terminart nicht aufgelistet"-Sektion
$kalliAllRoles = [];
$isAdminUser = (isset($groups["Admin"]) && $groups["Admin"] == 1);
foreach ($kalliCategories as $cat):
$role = $cat['permission_role'];
$kalliAllRoles[$role] = 1;
if (!$isAdminUser && !(isset($groups[$role]) && $groups[$role] == 1)) continue;
$types = $kalliTypesByCategory[$cat['id']] ?? [];
if (empty($types)) continue;
?>
<div class="kalli-category">
<div class="kalli-category-label"><?= htmlspecialchars($cat['name']) ?></div>
<?php foreach ($types as $type):
$displayLabel = !empty($type['display_label']) ? $type['display_label'] : $type['name'];
?>
<label class="kalli-radio-item"><input type="radio" name="group" value="<?= htmlspecialchars($type['name']) ?>"><span><?= htmlspecialchars($displayLabel) ?></span></label>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div>
<?php
$hasAnyKalliRole = $isAdminUser || count(array_intersect_key($groups, $kalliAllRoles)) > 0;
if ($hasAnyKalliRole): ?>
<div class="kalli-custom-section">
<div class="kalli-category-label" style="color:var(--nak-red);">Terminart nicht aufgelistet?</div>
<p style="margin:0 0 var(--space-sm) 0;font-size:var(--font-size-sm);color:var(--gray-600);">Nur ausfüllen, wenn die Terminart oben nicht vorhanden ist.</p>
<div style="display:flex;gap:var(--space-lg);flex-wrap:wrap;margin-bottom:var(--space-sm);">
<label class="kalli-radio-item"><input type="radio" name="group" value="oeffentlich"><span>Öffentlich</span></label>
<label class="kalli-radio-item"><input type="radio" name="group" value="intern"><span>Intern</span></label>
</div>
<input class="kalli-field" type="text" name="userinput" id="kalliUserInput" placeholder="Titel (nur für benutzerdefinierte Termine)">
</div>
<?php endif; ?>
</div>
<div class="kalli-modal-actions">
<div></div>
<div class="kalli-modal-actions-right">
<button type="button" class="kalli-btn kalli-btn-primary" onclick="kalliNextStep(2)">Weiter</button>
</div>
</div>
</div>
<!-- STEP 2: Zeitraum -->
<div class="kalli-step" id="kalliStep2" style="display:none;">
<div class="kalli-modal-body">
<div class="kalli-section-title">Zeitraum festlegen</div>
<div class="kalli-field-grid">
<div class="kalli-field-group">
<label class="kalli-label">Datum <span style="color:var(--nak-red);">*</span></label>
<input class="kalli-field" type="date" name="date_s" id="kalliDateS" required>
</div>
<div class="kalli-field-group">
<label class="kalli-label">Enddatum <span style="font-weight:300;color:var(--gray-500);">(falls mehrtägig)</span></label>
<input class="kalli-field" type="date" name="date_e" id="kalliDateE">
</div>
<div class="kalli-field-group">
<label class="kalli-label">Zeit von <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="kalli-field" type="time" name="time_s" id="kalliTimeS">
</div>
<div class="kalli-field-group">
<label class="kalli-label">Zeit bis <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="kalli-field" type="time" name="time_e" id="kalliTimeE">
</div>
</div>
</div>
<div class="kalli-modal-actions">
<div class="kalli-modal-actions-left">
<button type="button" class="kalli-btn" onclick="kalliPrevStep(1)">Zurück</button>
</div>
<div class="kalli-modal-actions-right">
<button type="button" class="kalli-btn kalli-btn-primary" onclick="kalliNextStep(3)">Weiter</button>
</div>
</div>
</div>
<!-- STEP 3: Informationen -->
<div class="kalli-step" id="kalliStep3" style="display:none;">
<div class="kalli-modal-body">
<div class="kalli-section-title">Zusätzliche Informationen</div>
<div class="kalli-field-grid kalli-field-grid-single">
<div class="kalli-field-group">
<label class="kalli-label">Textfeld <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="kalli-field" type="text" name="further_text" id="kalliFurtherText" placeholder="z.B. betreffende Person, etc.">
</div>
<div class="kalli-field-group">
<label class="kalli-label">Ort <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="kalli-field" type="text" name="location" id="kalliLocation">
</div>
<div class="kalli-field-group">
<label class="kalli-label">Verantwortliche/r <span style="font-weight:300;color:var(--gray-500);">(optional)</span></label>
<input class="kalli-field" type="text" name="responsibility" id="kalliResponsibility">
</div>
</div>
</div>
<div class="kalli-modal-actions">
<div class="kalli-modal-actions-left">
<button type="button" class="kalli-btn" onclick="kalliPrevStep(2)">Zurück</button>
</div>
<div class="kalli-modal-actions-right">
<button type="button" class="kalli-btn kalli-btn-primary" onclick="kalliNextStep(4)">Weiter</button>
</div>
</div>
</div>
<!-- STEP 4: Übersicht -->
<div class="kalli-step" id="kalliStep4" style="display:none;">
<div class="kalli-modal-body">
<div class="kalli-section-title">Übersicht – Bitte prüfen Sie Ihre Eingaben</div>
<div class="kalli-summary">
<div class="kalli-summary-row">
<span class="kalli-summary-label">Terminart</span>
<span class="kalli-summary-value" id="sumGroup">–</span>
</div>
<div class="kalli-summary-row">
<span class="kalli-summary-label">Datum</span>
<span class="kalli-summary-value" id="sumDateS">–</span>
</div>
<div class="kalli-summary-row" id="sumDateERow" style="display:none;">
<span class="kalli-summary-label">Enddatum</span>
<span class="kalli-summary-value" id="sumDateE">–</span>
</div>
<div class="kalli-summary-row" id="sumTimeSRow" style="display:none;">
<span class="kalli-summary-label">Zeit von</span>
<span class="kalli-summary-value" id="sumTimeS">–</span>
</div>
<div class="kalli-summary-row" id="sumTimeERow" style="display:none;">
<span class="kalli-summary-label">Zeit bis</span>
<span class="kalli-summary-value" id="sumTimeE">–</span>
</div>
<div class="kalli-summary-row" id="sumTextRow" style="display:none;">
<span class="kalli-summary-label">Textfeld</span>
<span class="kalli-summary-value" id="sumText">–</span>
</div>
<div class="kalli-summary-row" id="sumLocRow" style="display:none;">
<span class="kalli-summary-label">Ort</span>
<span class="kalli-summary-value" id="sumLoc">–</span>
</div>
<div class="kalli-summary-row" id="sumRespRow" style="display:none;">
<span class="kalli-summary-label">Verantwortlich</span>
<span class="kalli-summary-value" id="sumResp">–</span>
</div>
</div>
<div id="kalliValidationError" class="kalli-validation-error" style="display:none;"></div>
</div>
<div class="kalli-modal-actions">
<div class="kalli-modal-actions-left">
<button type="button" class="kalli-btn" onclick="kalliPrevStep(3)">Zurück</button>
</div>
<div class="kalli-modal-actions-right">
<button type="submit" name="submit" class="kalli-btn kalli-btn-submit">Eintragung absenden</button>
</div>
</div>
</div>
</form>
</div>
<script>
var kalliCurrentStep = 1;
function kalliGoToStep(step) {
for (var i = 1; i <= 4; i++) {
document.getElementById('kalliStep' + i).style.display = (i === step) ? '' : 'none';
}
kalliCurrentStep = step;
kalliUpdateProgress(step);
window.scrollTo({top: 0, behavior: 'smooth'});
// Header wieder einblenden, falls er durch Scrollen ausgeblendet war
var headerHeight = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--header-height')) || 64;
var elemHeaderMenue = document.getElementById('header_menue');
var elemHeaderTitle = document.getElementById('header_title');
if (elemHeaderMenue) { elemHeaderMenue.style.top = '0'; }
if (elemHeaderTitle) { elemHeaderTitle.style.top = headerHeight + 'px'; }
}
function kalliUpdateProgress(step) {
var steps = document.querySelectorAll('.kalli-progress-step');
var lines = document.querySelectorAll('.kalli-progress-line');
steps.forEach(function(el, idx) {
var s = idx + 1;
el.classList.remove('active', 'done');
if (s === step) el.classList.add('active');
else if (s < step) el.classList.add('done');
});
lines.forEach(function(el, idx) {
el.classList.toggle('done', idx < step - 1);
});
}
function kalliNextStep(step) {
var errEl = document.getElementById('kalliValidationError');
if (errEl) { errEl.style.display = 'none'; errEl.textContent = ''; }
if (step === 2) {
var sel = document.querySelector('#kalliForm input[name="group"]:checked');
if (!sel) { alert('Bitte wählen Sie eine Terminart aus.'); return; }
if ((sel.value === 'oeffentlich' || sel.value === 'intern') && !document.getElementById('kalliUserInput').value.trim()) {
alert('Bitte geben Sie einen Titel für den benutzerdefinierten Termin ein.'); return;
}
}
if (step === 3) {
if (!document.getElementById('kalliDateS').value) { alert('Bitte geben Sie ein Datum ein.'); return; }
}
if (step === 4) { kalliBuildSummary(); }
kalliGoToStep(step);
}
function kalliPrevStep(step) { kalliGoToStep(step); }
function kalliBuildSummary() {
var grp = document.querySelector('#kalliForm input[name="group"]:checked');
var grpVal = grp ? grp.value : '–';
if ((grpVal === 'oeffentlich' || grpVal === 'intern') && document.getElementById('kalliUserInput')) {
var custom = document.getElementById('kalliUserInput').value.trim();
grpVal = custom ? custom + ' (' + (grpVal === 'oeffentlich' ? 'Öffentlich' : 'Intern') + ')' : grpVal;
}
document.getElementById('sumGroup').textContent = grpVal;
document.getElementById('sumDateS').textContent = kalliFormatDate(document.getElementById('kalliDateS').value);
kalliShowSummaryRow('sumDateERow', document.getElementById('kalliDateE').value, 'sumDateE', kalliFormatDate(document.getElementById('kalliDateE').value));
kalliShowSummaryRow('sumTimeSRow', document.getElementById('kalliTimeS').value, 'sumTimeS', document.getElementById('kalliTimeS').value);
kalliShowSummaryRow('sumTimeERow', document.getElementById('kalliTimeE').value, 'sumTimeE', document.getElementById('kalliTimeE').value);
kalliShowSummaryRow('sumTextRow', document.getElementById('kalliFurtherText').value.trim(), 'sumText', document.getElementById('kalliFurtherText').value.trim());
kalliShowSummaryRow('sumLocRow', document.getElementById('kalliLocation').value.trim(), 'sumLoc', document.getElementById('kalliLocation').value.trim());
kalliShowSummaryRow('sumRespRow', document.getElementById('kalliResponsibility').value.trim(), 'sumResp', document.getElementById('kalliResponsibility').value.trim());
}
function kalliShowSummaryRow(rowId, value, valId, displayVal) {
var row = document.getElementById(rowId);
if (value) { row.style.display = ''; document.getElementById(valId).textContent = displayVal; }
else { row.style.display = 'none'; }
}
function kalliFormatDate(iso) {
if (!iso) return '–';
var parts = iso.split('-');
return parts.length === 3 ? parts[2] + '.' + parts[1] + '.' + parts[0] : iso;
}
</script>
<?php endif; ?>
</div><!-- content -->
<?php require_once $_SERVER['DOCUMENT_ROOT'].'/intranet_repo/projects/_central/php/footer.php'; ?>
</body>
</html>