diff --git a/DeskHub-Webseite/staff/profile.php b/DeskHub-Webseite/staff/profile.php
index c0e5570b..64b1d14e 100644
--- a/DeskHub-Webseite/staff/profile.php
+++ b/DeskHub-Webseite/staff/profile.php
@@ -113,6 +113,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
redirect('/staff/profile.php?tab=settings');
}
+ // ── Android-Push: welche Popups, stille Zeiten ─────────────────
+ if ($action === 'save_push_prefs') {
+ $ev = array_map('strval', (array) ($_POST['push_events'] ?? []));
+ $qf = trim((string) ($_POST['quiet_from'] ?? ''));
+ $qt = trim((string) ($_POST['quiet_to'] ?? ''));
+ if (($qf !== '' || $qt !== '') && (!fcm_time_valid($qf) || !fcm_time_valid($qt))) {
+ flash('error', 'Stille Zeiten bitte als Uhrzeit von/bis angeben (z. B. 22:00 und 06:00).');
+ redirect('/staff/profile.php?tab=account');
+ }
+ fcm_save_prefs($pdo, (int) $staff['id'], $ev, $qf, $qt, array_keys(fcm_event_types_for($staff)));
+ flash('success', 'Push-Einstellungen gespeichert.');
+ redirect('/staff/profile.php?tab=account');
+ }
+
// ── 2FA aktivieren ─────────────────────────────────────────────
if ($action === 'enable_2fa') {
$code = trim($_POST['totp_code'] ?? '');
@@ -302,6 +316,25 @@ require __DIR__ . '/_header.php';
+
+
+
📱 Android-App: Welche Popups?
+
+
+
diff --git a/DeskHub-Webseite/staff/reports.php b/DeskHub-Webseite/staff/reports.php
index 798f1d25..34502a30 100644
--- a/DeskHub-Webseite/staff/reports.php
+++ b/DeskHub-Webseite/staff/reports.php
@@ -354,6 +354,7 @@ $tsLabels = ['available'=>'Verfügbar','busy'=>'Beschäftigt','break'=>'Pause','
$teamStatus = [];
$myAvailStatus = 'available';
try {
+ staff_run_auto_offline($pdo);
$tsStmt = $pdo->query(
"SELECT s.id, s.name, s.is_on_vacation, sa.status AS avail_status, sa.note AS avail_note
FROM staff s
diff --git a/DeskHub-Webseite/staff/session_ping.php b/DeskHub-Webseite/staff/session_ping.php
index 03e43a3b..4dcb145f 100644
--- a/DeskHub-Webseite/staff/session_ping.php
+++ b/DeskHub-Webseite/staff/session_ping.php
@@ -34,8 +34,9 @@ if ($last && $elapsed > ($timeout * 60)) {
exit;
}
-// Aktivität erneuern
+// Aktivität erneuern (dieser Ping kommt nur bei echten Klicks, Tipps und Mausbewegungen)
$_SESSION['staff_last_activity'] = time();
+staff_touch_activity(get_db(), (int) $_SESSION['staff_id']);
$remaining = $timeout * 60;
echo json_encode(['ok' => true, 'remaining' => $remaining]);
diff --git a/DeskHub-Webseite/staff/settings.php b/DeskHub-Webseite/staff/settings.php
index af2e185e..cc440b9e 100644
--- a/DeskHub-Webseite/staff/settings.php
+++ b/DeskHub-Webseite/staff/settings.php
@@ -350,6 +350,29 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
flash('success', 'Benachrichtigungseinstellungen gespeichert.');
redirect('/staff/settings.php?tab=benachrichtigungen');
}
+ // Push-Benachrichtigungen für die Android-App (Firebase Cloud Messaging)
+ if ($action === 'save_fcm') {
+ set_setting('fcm_enabled', !empty($_POST['fcm_enabled']) ? '1' : '0');
+ set_setting('fcm_show_details', !empty($_POST['fcm_show_details']) ? '1' : '0');
+ set_setting('push_brand', fcm_clean_brand((string) ($_POST['push_brand'] ?? '')));
+ flash('success', 'Einstellungen für die Android-Benachrichtigungen gespeichert.');
+ redirect('/staff/settings.php?tab=benachrichtigungen');
+ }
+ if ($action === 'remove_fcm') {
+ set_setting('fcm_service_account', '');
+ set_setting('fcm_access_token', '');
+ audit_log($staff['id'], 'Firebase-Dienstkonto für Android-Push entfernt');
+ flash('success', 'Der Firebase-Schlüssel wurde vom Server entfernt.');
+ redirect('/staff/settings.php?tab=benachrichtigungen');
+ }
+ if ($action === 'test_fcm') {
+ if (fcm_mode() === 'none') { flash('error', 'Push ist nicht eingerichtet: Es ist kein Push-Dienst eingetragen und kein eigener Firebase-Schlüssel hinterlegt.'); redirect('/staff/settings.php?tab=benachrichtigungen'); }
+ $t = fcm_send_test($pdo, (int) $staff['id']);
+ if ($t['devices'] === 0) { flash('error', 'Auf deinem Konto ist noch kein Android-Gerät angemeldet. Melde dich in der App an (Benachrichtigungen erlauben) und versuche es erneut.'); redirect('/staff/settings.php?tab=benachrichtigungen'); }
+ $t['sent'] > 0 ? flash('success', "Testnachricht an {$t['sent']} Gerät(e) gesendet. Sie sollte jetzt auf dem Handy erscheinen.") : flash('error', 'Senden fehlgeschlagen: ' . ($t['error'] !== '' ? $t['error'] : 'unbekannter Fehler'));
+ redirect('/staff/settings.php?tab=benachrichtigungen');
+ }
+
if ($action === 'test_notifications') {
$sent = [];
if (discord_notify('🔔 Testnachricht von DeskHub')) $sent[] = 'Discord';
@@ -842,7 +865,8 @@ require __DIR__ . '/_header.php';
-
+
+
Discord & Telegram
Mitarbeiter werden bei neuen Tickets und Antworten benachrichtigt. Ticket-Daten werden dabei an den jeweiligen Drittanbieter übermittelt.
@@ -868,6 +892,44 @@ require __DIR__ . '/_header.php';
+query('SELECT COUNT(*) FROM push_devices')->fetchColumn();
+ $__fcmErr = (string) get_setting('fcm_last_error', '');
+ $__fcmOk = (string) get_setting('fcm_last_ok', '');
+ $__fcmFromConfig = (string) (config()['fcm']['service_account_file'] ?? '') !== '';
+?>
+
+
📱 Android-App: Push-Benachrichtigungen
+
Popups auf dem Handy bei neuen Tickets, Kundenantworten und Zuweisungen, auch wenn die App geschlossen ist. Die Nachrichten laufen über Google (Firebase Cloud Messaging).
+
+
+ ✓ Eigenes Firebase-Projekt · = e($__fcmSa['project_id']) ?>= $__fcmFromConfig ? ' (aus config/config.php)' : '' ?>
+
+ ✓ Push ist aktiv · über den DeskHub-Push-Dienst, es ist nichts einzurichten
+
+ Nicht verfügbar. In dieser Version ist kein Push-Dienst eingetragen. Ihr könnt unten ein eigenes Firebase-Projekt verwenden.
+
+ = (int) $__fcmDevices ?> Gerät(e) angemeldet= $__fcmOk !== '' ? ' · letzter erfolgreicher Versand: ' . e($__fcmOk) : '' ?>
+
Letzter Fehler: = e($__fcmErr) ?>
+
+
+
+
+
+
+
+
diff --git a/DeskHub-Webseite/staff/ticket_view.php b/DeskHub-Webseite/staff/ticket_view.php
index d5dbe07f..3f10c5d2 100644
--- a/DeskHub-Webseite/staff/ticket_view.php
+++ b/DeskHub-Webseite/staff/ticket_view.php
@@ -502,6 +502,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$agentName = '';
foreach ($agents as $a) { if ($a['id'] == $assignedTo) $agentName = $a['name']; }
log_activity($pdo, $ticket['id'], $staff['id'], "Mitarbeiter zugewiesen: {$agentName}");
+ fcm_notify_assignment($ticket, (int) $assignedTo, (int) $staff['id']); // Push auf die Android-App des neuen Bearbeiters
} elseif ($assignedTo === null && !empty($ticket['assigned_staff_id'])) {
log_activity($pdo, $ticket['id'], $staff['id'], 'Zuweisung entfernt');
}
diff --git a/DeskHub-Webseite/staff/tickets.php b/DeskHub-Webseite/staff/tickets.php
index 72a1c865..d4094e41 100644
--- a/DeskHub-Webseite/staff/tickets.php
+++ b/DeskHub-Webseite/staff/tickets.php
@@ -98,6 +98,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['bulk_action'] ?? '') !== '
if ($bulkAction === 'assign') {
$newAgent = $_POST['bulk_assigned_staff_id'] !== '' ? (int) $_POST['bulk_assigned_staff_id'] : null;
$pdo->prepare('UPDATE tickets SET assigned_staff_id=?, updated_at=? WHERE id=?')->execute([$newAgent, $now, $t['id']]);
+ if ($newAgent !== null && $newAgent !== (int) ($t['assigned_staff_id'] ?? 0)) fcm_notify_assignment($t, $newAgent, (int) $staff['id']); // Push auf die Android-App
log_activity($pdo, $t['id'], $staff['id'], 'Sammelaktion: Mitarbeiter zugewiesen');
} elseif ($bulkAction === 'priority') {
$newPrio = (int) $_POST['bulk_priority_id'];