'CSRF-Fehler', 'got'=>$_POST['csrf_token']??'', 'expected'=>$_SESSION['csrf_token']??'']); exit; } $newStatus = $_POST['status'] ?? ''; $note = trim($_POST['note'] ?? ''); $allowed = ['available', 'busy', 'break', 'offline']; if (!in_array($newStatus, $allowed, true)) { http_response_code(400); echo json_encode(['error' => 'Ungültiger Status']); exit; } try { staff_set_status($pdo, (int) $staff['id'], $newStatus, $note); staff_touch_activity($pdo, (int) $staff['id']); echo json_encode(['ok' => true, 'status' => $newStatus]); } catch (Throwable $e) { error_log('staff_availability: ' . $e->getMessage()); http_response_code(500); echo json_encode(['error' => 'Status konnte nicht gespeichert werden.']); } exit; } // ── Schichtplan (Admin-Seite) ───────────────────────────────────────────────── $admin = has_permission($staff, 'manage_availability') ? $staff : null; if ($_SERVER['REQUEST_METHOD'] === 'POST') { verify_csrf(); $action = $_POST['action'] ?? ''; // Admin: Status eines Mitarbeiters ändern if ($action === 'set_staff_status' && $admin) { $targetId = (int) ($_POST['staff_id'] ?? 0); $newStatus = (string) ($_POST['status'] ?? ''); $exists = $pdo->prepare('SELECT name FROM staff WHERE id = ? AND is_active = 1'); $exists->execute([$targetId]); $targetName = $exists->fetchColumn(); if (!$targetName || !in_array($newStatus, STAFF_AVAILABILITY_STATUSES, true)) { flash('error', 'Ungültiger Mitarbeiter oder Status.'); } else { staff_set_status($pdo, $targetId, $newStatus, (string) ($_POST['note'] ?? '')); audit_log($admin['id'], "Status von Mitarbeiter #$targetId auf $newStatus gesetzt"); flash('success', 'Status von ' . $targetName . ' geändert.'); } redirect('/staff/availability.php'); } // Admin: Zeit bis zum automatischen Offline einstellen if ($action === 'save_auto_offline' && $admin) { $m = max(0, min(1440, (int) ($_POST['auto_offline_minutes'] ?? 30))); set_setting('staff_auto_offline_minutes', (string) $m); audit_log($admin['id'], 'Automatisch offline nach ' . ($m > 0 ? $m . ' Minuten' : 'aus') . ' gesetzt'); flash('success', $m > 0 ? "Mitarbeiter werden nach $m Minuten ohne Aktivität automatisch auf Offline gesetzt." : 'Automatisch offline ist ausgeschaltet.'); redirect('/staff/availability.php'); } if ($action === 'save_shifts' && $admin) { $targetId = (int)($_POST['staff_id'] ?? 0); $__nameStmt = $pdo->prepare('SELECT name FROM staff WHERE id = ?'); $__nameStmt->execute([$targetId]); $editAgentName = $__nameStmt->fetchColumn() ?: "#$targetId"; if (!$targetId) { flash('error', 'Ungültiger Mitarbeiter.'); redirect('/staff/availability.php'); } // Alte Schichten löschen $pdo->prepare('DELETE FROM staff_shifts WHERE staff_id = ?')->execute([$targetId]); // Neue speichern $days = $_POST['days'] ?? []; foreach ($days as $day => $times) { if (empty($times['active'])) continue; $start = $times['start'] ?? '08:00'; $end = $times['end'] ?? '17:00'; // Keine Zeitvalidierung – Nutzer ist verantwortlich $pdo->prepare( 'INSERT INTO staff_shifts (staff_id, weekday, start_time, end_time, is_active) VALUES (?,?,?,?,1)' )->execute([$targetId, (int)$day, $start, $end]); } audit_log($admin['id'], "Schichtplan für Mitarbeiter #$targetId gespeichert"); flash('success', 'Schichtplan für ' . e($editAgentName ?? "#$targetId") . ' gespeichert.'); redirect('/staff/availability.php?edit=' . $targetId); } } // ── Daten laden ─────────────────────────────────────────────────────────────── staff_run_auto_offline($pdo); $agents = $pdo->query( "SELECT s.*, sa.status AS avail_status, sa.auto_offline AS avail_auto, sa.note AS avail_note, sa.updated_at AS avail_updated FROM staff s LEFT JOIN staff_availability sa ON sa.staff_id = s.id WHERE s.is_active = 1 ORDER BY s.name" )->fetchAll(); // Schichten für alle Mitarbeiter $allShifts = $pdo->query( 'SELECT * FROM staff_shifts WHERE is_active = 1 ORDER BY staff_id, weekday, start_time' )->fetchAll(); $shiftsByStaff = []; foreach ($allShifts as $sh) { $shiftsByStaff[$sh['staff_id']][$sh['weekday']][] = $sh; } // Für den Edit-Modus $editStaffId = (int)($_GET['edit'] ?? 0); $editShifts = $editStaffId ? ($shiftsByStaff[$editStaffId] ?? []) : []; $pageTitle = 'Verfügbarkeit & Schichten'; $activePage = 'availability'; require __DIR__ . '/_header.php'; $statusLabels = [ 'available' => ['Verfügbar', '#22c55e'], 'busy' => ['Beschäftigt', '#f59e0b'], 'break' => ['Pause', '#6366f1'], 'offline' => ['Offline', '#94a3b8'], ]; $weekdays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']; ?>
Ein von dir gesetzter Status bleibt, bis der Mitarbeiter ihn selbst ändert oder du ihn erneut änderst.
| Mitarbeiter | Status und Notiz |
|---|---|
| = e($ag['name']) ?> |
Definiere an welchen Tagen und zu welchen Zeiten dieser Mitarbeiter verfügbar ist. Tickets werden außerhalb der Schicht nicht automatisch zugewiesen.