206 lines
9.6 KiB
PHP
206 lines
9.6 KiB
PHP
<?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 & 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'; ?>
|