/** * Live-Anzeige im Mitarbeiterbereich: neue Tickets erscheinen sofort als Hinweis unten rechts, die Zahl steht im Browser-Tab und die * Kennzahlen auf der Übersicht (Elemente mit data-live-count) aktualisieren sich von selbst. Fragt /staff/live_tickets.php ab. */ (function () { 'use strict'; if (window.__deskhubLive) return; window.__deskhubLive = true; var KEY = 'deskhub_live_last_ticket'; var since = 0; try { since = parseInt(sessionStorage.getItem(KEY) || '0', 10) || 0; } catch (e) {} var unseen = 0; var baseTitle = document.title; var stopped = false; var box = null; function container() { if (box) return box; box = document.createElement('div'); box.setAttribute('aria-live', 'polite'); box.style.cssText = 'position:fixed;right:18px;bottom:18px;z-index:2147483000;display:flex;flex-direction:column;gap:10px;max-width:360px;font:14px/1.4 "Segoe UI",system-ui,sans-serif'; document.body.appendChild(box); return box; } function toast(t) { var a = document.createElement('a'); a.href = '/staff/ticket_view.php?n=' + encodeURIComponent(t.number); a.style.cssText = 'display:block;background:#0f172a;color:#fff;text-decoration:none;border-radius:12px;padding:12px 16px;box-shadow:0 10px 30px rgba(0,0,0,.35);border-left:4px solid #2dd4bf;transition:opacity .4s,transform .4s;opacity:0;transform:translateY(10px)'; var h = document.createElement('div'); h.style.cssText = 'font-size:.74rem;letter-spacing:.04em;text-transform:uppercase;color:#5eead4;font-weight:700'; h.textContent = 'Neues Ticket #' + t.number + (t.department ? ' · ' + t.department : ''); var s = document.createElement('div'); s.style.cssText = 'font-weight:600;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'; s.textContent = t.subject; var n = document.createElement('div'); n.style.cssText = 'color:#94a3b8;font-size:.82rem'; n.textContent = t.name; a.appendChild(h); a.appendChild(s); a.appendChild(n); container().appendChild(a); requestAnimationFrame(function () { a.style.opacity = '1'; a.style.transform = 'none'; }); setTimeout(function () { a.style.opacity = '0'; setTimeout(function () { a.remove(); }, 450); }, 14000); a.addEventListener('click', function () { a.remove(); }); } function info(text) { var d = document.createElement('div'); d.style.cssText = 'background:#334155;color:#e2e8f0;border-radius:10px;padding:8px 14px;font-size:.84rem;box-shadow:0 6px 18px rgba(0,0,0,.3)'; d.textContent = text; container().appendChild(d); setTimeout(function () { d.remove(); }, 14000); } function setCounts(c) { document.querySelectorAll('[data-live-count]').forEach(function (el) { var v = c[el.getAttribute('data-live-count')]; if (v === undefined || el.textContent.trim() === String(v)) return; el.textContent = v; el.style.transition = 'transform .3s'; el.style.transform = 'scale(1.25)'; setTimeout(function () { el.style.transform = 'none'; }, 350); }); } function updateTitle() { document.title = unseen > 0 ? '(' + unseen + ') ' + baseTitle : baseTitle; } function seen() { if (unseen === 0) return; unseen = 0; updateTitle(); } document.addEventListener('visibilitychange', function () { if (!document.hidden) seen(); }); window.addEventListener('focus', seen); function poll() { if (stopped) return; fetch('/staff/live_tickets.php?since=' + since, { credentials: 'same-origin', cache: 'no-store' }) .then(function (r) { if (r.status === 401 || r.status === 403) { stopped = true; return null; } return r.ok ? r.json() : null; }) .then(function (d) { if (!d) return; setCounts(d.counts || {}); var list = d.tickets || []; list.forEach(toast); if (d.more > 0) info('… und ' + d.more + ' weitere neue Tickets'); if (list.length) { unseen += list.length + (d.more || 0); if (document.hidden || !document.hasFocus()) updateTitle(); else unseen = 0; } if (d.latest > since) { since = d.latest; try { sessionStorage.setItem(KEY, String(since)); } catch (e) {} } }) .catch(function () {}) .then(function () { if (!stopped) setTimeout(poll, document.hidden ? 30000 : 10000); }); } setTimeout(poll, 1500); })();