Files
deskhub/DeskHub-Webseite/staff/business_hours.php
T
2026-10-16 19:12:21 +00:00

206 lines
9.6 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 __DIR__ . '/../includes/bootstrap.php';
require_once __DIR__ . '/_ui.php';
$staff = require_admin_or_permission('manage_business_hours');
$pdo = get_db();
$weekdayNames = [1 => 'Montag', 2 => 'Dienstag', 3 => 'Mittwoch', 4 => 'Donnerstag', 5 => 'Freitag', 6 => 'Samstag', 0 => 'Sonntag'];
$weekdayOrder = [1, 2, 3, 4, 5, 6, 0];
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$action = $_POST['action'] ?? '';
if ($action === 'save_hours') {
$enabled = !empty($_POST['business_hours_enabled']) ? '1' : '0';
set_setting('business_hours_enabled', $enabled);
$stmt = $pdo->prepare('UPDATE business_hours SET is_open=?, open_time=?, close_time=? WHERE weekday=?');
foreach ($weekdayOrder as $wd) {
$isOpen = !empty($_POST["open_{$wd}"]) ? 1 : 0;
$openTime = trim($_POST["from_{$wd}"] ?? '09:00') . ':00';
$closeTime = trim($_POST["to_{$wd}"] ?? '17:00') . ':00';
$stmt->execute([$isOpen, $openTime, $closeTime, $wd]);
}
audit_log($staff['id'], 'Geschäftszeiten aktualisiert');
flash('success', 'Geschäftszeiten gespeichert.');
redirect('/staff/business_hours.php');
}
if ($action === 'add_holiday') {
$date = trim($_POST['holiday_date'] ?? '');
$name = trim($_POST['holiday_name'] ?? '');
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date)) {
$errors[] = 'Bitte ein gültiges Datum angeben.';
} elseif ($name === '') {
$errors[] = 'Bitte einen Namen für den Feiertag angeben.';
} else {
$pdo->prepare('INSERT INTO business_holidays (holiday_date, name) VALUES (?,?)')->execute([$date, $name]);
audit_log($staff['id'], "Feiertag hinzugefügt: {$name} ({$date})");
flash('success', 'Feiertag hinzugefügt.');
redirect('/staff/business_hours.php?tab=holidays');
}
}
if ($action === 'delete_holiday') {
$id = (int) $_POST['id'];
$pdo->prepare('DELETE FROM business_holidays WHERE id = ?')->execute([$id]);
redirect('/staff/business_hours.php?tab=holidays');
}
if ($action === 'import_holidays') {
$stateCode = $_POST['state_code'] ?? '';
$importYear = (int) ($_POST['import_year'] ?? 0);
if (!isset(GERMAN_STATE_NAMES[$stateCode])) {
$errors[] = 'Bitte ein gültiges Bundesland auswählen.';
} elseif ($importYear < 2000 || $importYear > 2100) {
$errors[] = 'Bitte ein gültiges Jahr auswählen.';
} else {
$newHolidays = german_public_holidays($stateCode, $importYear);
$existingDates = array_flip($pdo->query('SELECT holiday_date FROM business_holidays')->fetchAll(PDO::FETCH_COLUMN));
$insertStmt = $pdo->prepare('INSERT INTO business_holidays (holiday_date, name) VALUES (?,?)');
$added = 0;
$skipped = 0;
foreach ($newHolidays as $h) {
if (isset($existingDates[$h['date']])) { $skipped++; continue; }
$insertStmt->execute([$h['date'], $h['name']]);
$existingDates[$h['date']] = true;
$added++;
}
$stateName = GERMAN_STATE_NAMES[$stateCode];
audit_log($staff['id'], "Feiertage {$importYear} für {$stateName} importiert ({$added} hinzugefügt, {$skipped} bereits vorhanden)");
flash('success', "{$added} Feiertag(e) für {$stateName} {$importYear} hinzugefügt" . ($skipped ? ", {$skipped} waren bereits vorhanden." : '.'));
redirect('/staff/business_hours.php?tab=holidays');
}
}
}
$hoursEnabled = get_setting('business_hours_enabled', '0') === '1';
$hoursByWeekday = [];
foreach ($pdo->query('SELECT * FROM business_hours')->fetchAll() as $r) $hoursByWeekday[(int) $r['weekday']] = $r;
$holidays = $pdo->query('SELECT * FROM business_holidays ORDER BY holiday_date')->fetchAll();
$pageTitle = 'Geschäftszeiten';
$activePage = 'business_hours';
require __DIR__ . '/_header.php';
?>
<h1>Geschäftszeiten</h1>
<p class="muted">Legt fest, innerhalb welcher Zeiten die SLA-Fristen (Reaktion/Lösung) laufen. Bei deaktivierten Geschäftszeiten gelten die Fristen wie bisher rund um die Uhr. <strong>Achtung:</strong> Wenige Stunden pro Tag (z. B. nur abends) lassen die Fälligkeit in <a href="/staff/priorities.php">Prioritäten &amp; SLA-Zeiten</a> entsprechend weiter in die Zukunft rücken – eine 72-Std-Lösungsfrist kann bei 3 offenen Stunden/Tag mehrere Wochen dauern.</p>
<?php foreach ($errors as $err): ?>
<div class="flash error"><?= e($err) ?></div>
<?php endforeach; ?>
<?php
$startTab = (($_GET['tab'] ?? '') === 'holidays' || in_array($_POST['action'] ?? '', ['add_holiday', 'import_holidays'], true)) ? 'holidays' : 'hours';
?>
<div class="card" style="padding:0">
<?php ui_tab_bar(['hours' => 'Wochenzeiten', 'holidays' => 'Feiertage (' . count($holidays) . ')']); ?>
<div class="tab-pane" data-pane="hours" style="padding:16px 20px">
<h3 style="margin-top:0">Öffnungszeiten je Wochentag</h3>
<form method="post">
<?= csrf_field() ?>
<input type="hidden" name="action" value="save_hours">
<label style="display:flex; align-items:center; gap:6px; font-weight:600; margin-bottom:14px">
<input type="checkbox" name="business_hours_enabled" style="width:auto" <?= $hoursEnabled ? 'checked' : '' ?>>
Geschäftszeiten für SLA-Berechnung verwenden
</label>
<table>
<thead><tr><th>Tag</th><th>Geöffnet</th><th>Von</th><th>Bis</th></tr></thead>
<tbody>
<?php foreach ($weekdayOrder as $wd):
$h = $hoursByWeekday[$wd] ?? ['is_open' => 0, 'open_time' => '09:00:00', 'close_time' => '17:00:00'];
?>
<tr>
<td><?= $weekdayNames[$wd] ?></td>
<td><input type="checkbox" name="open_<?= $wd ?>" style="width:auto" <?= $h['is_open'] ? 'checked' : '' ?>></td>
<td><input type="time" name="from_<?= $wd ?>" value="<?= substr($h['open_time'], 0, 5) ?>" style="max-width:130px"></td>
<td><input type="time" name="to_<?= $wd ?>" value="<?= substr($h['close_time'], 0, 5) ?>" style="max-width:130px"></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="btn-row">
<button type="submit" class="btn">Änderungen speichern</button>
</div>
</form>
</div>
<div class="tab-pane" data-pane="holidays" style="padding:16px 20px;display:none">
<h3 style="margin-top:0">Feiertage</h3>
<p class="muted">An diesen Tagen laufen keine SLA-Fristen, unabhängig vom Wochentag.</p>
<div style="background:var(--primary-lt);border-radius:8px;padding:12px 14px;margin-bottom:14px">
<form method="post" style="display:flex;gap:8px;align-items:flex-end;flex-wrap:wrap">
<?= csrf_field() ?>
<input type="hidden" name="action" value="import_holidays">
<div>
<label for="state_code" style="font-size:.78rem;font-weight:600;color:var(--muted);display:block;margin-bottom:3px">Bundesland</label>
<select id="state_code" name="state_code" required>
<option value="">– auswählen –</option>
<?php foreach (GERMAN_STATE_NAMES as $code => $name): ?>
<option value="<?= e($code) ?>"><?= e($name) ?></option>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="import_year" style="font-size:.78rem;font-weight:600;color:var(--muted);display:block;margin-bottom:3px">Jahr</label>
<select id="import_year" name="import_year" required>
<?php $curYear = (int) date('Y'); foreach ([$curYear, $curYear + 1, $curYear + 2] as $yr): ?>
<option value="<?= $yr ?>"><?= $yr ?></option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" class="btn secondary" style="white-space:nowrap">Feiertage automatisch übernehmen</button>
</form>
<p class="muted" style="font-size:.76rem;margin:8px 0 0">Trägt die gesetzlichen Feiertage des gewählten Bundeslandes für das gewählte Jahr ein (inkl. beweglicher Feiertage wie Ostern). Bereits vorhandene Daten werden übersprungen, nichts wird doppelt angelegt.</p>
</div>
<table>
<thead><tr><th>Datum</th><th>Name</th><th></th></tr></thead>
<tbody>
<?php foreach ($holidays as $h): ?>
<tr>
<td><?= e(date('d.m.Y', strtotime($h['holiday_date']))) ?></td>
<td><?= e($h['name']) ?></td>
<td>
<form method="post" style="display:inline" onsubmit="return confirm('Feiertag entfernen?');">
<?= csrf_field() ?>
<input type="hidden" name="action" value="delete_holiday">
<input type="hidden" name="id" value="<?= $h['id'] ?>">
<button type="submit" style="background:none;border:none;color:#dc2626;cursor:pointer;padding:0;font-size:.9rem">✕</button>
</form>
</td>
</tr>
<?php endforeach; ?>
<?php if (!$holidays): ?>
<tr><td colspan="3" class="muted">Noch keine Feiertage eingetragen.</td></tr>
<?php endif; ?>
</tbody>
</table>
<form method="post" style="margin-top:14px">
<?= csrf_field() ?>
<input type="hidden" name="action" value="add_holiday">
<label for="holiday_date">Datum</label>
<input type="date" id="holiday_date" name="holiday_date" required>
<label for="holiday_name">Name</label>
<input type="text" id="holiday_name" name="holiday_name" placeholder="z.B. Tag der Deutschen Einheit" required>
<div class="btn-row">
<button type="submit" class="btn secondary">Hinzufügen</button>
</div>
</form>
</div>
</div>
</div>
<?php ui_tab_assets($startTab); ?>
<?php require __DIR__ . '/_footer.php'; ?>