From 461c5c78821150c202187a99e99bee87d5846b81 Mon Sep 17 00:00:00 2001 From: mwpn Date: Fri, 6 Mar 2026 16:55:03 +0700 Subject: [PATCH] chore: matikan realtime stream di dashboard Ganti SSE /api/dashboard/stream dengan fetch sekali ke /api/dashboard/realtime supaya halaman dashboard lebih ringan dan cepat dibuka. --- app/Views/dashboard/index.php | 78 ++++++++++++----------------------- 1 file changed, 26 insertions(+), 52 deletions(-) diff --git a/app/Views/dashboard/index.php b/app/Views/dashboard/index.php index 4a7635a..e03b0e5 100644 --- a/app/Views/dashboard/index.php +++ b/app/Views/dashboard/index.php @@ -43,8 +43,8 @@
-

Realtime Attendance

-

Live stream via Server-Sent Events. Newest at top.

+

Riwayat Absensi Terbaru

+

Daftar absen terakhir (tanpa live stream), paling baru di atas.

@@ -57,11 +57,7 @@ - - - - - +
Status
Connecting to stream…
@@ -131,10 +127,7 @@ .catch(function() {}); var tbody = document.getElementById('attendance-tbody'); - var streamUrl = baseUrl + '/api/dashboard/stream'; - var afterId = 0; - var placeholderRow = null; - var connected = false; + var realtimeApiUrl = baseUrl + '/api/dashboard/realtime'; function badgeClass(status) { var s = (status || '').toUpperCase(); @@ -152,10 +145,6 @@ } function addRow(data) { - if (placeholderRow && placeholderRow.parentNode) { - placeholderRow.remove(); - placeholderRow = null; - } var tr = document.createElement('tr'); tr.className = 'hover:bg-gray-50 dark:hover:bg-gray-700/30'; tr.setAttribute('data-id', data.id); @@ -166,8 +155,7 @@ '' + escapeHtml(data.class_name) + '' + '' + escapeHtml(data.subject) + '' + '' + escapeHtml(data.status) + ''; - tbody.insertBefore(tr, tbody.firstChild); - if (data.id > afterId) afterId = data.id; + tbody.appendChild(tr); } function escapeHtml(str) { @@ -177,43 +165,29 @@ return div.innerHTML; } - function setPlaceholder(msg) { - if (placeholderRow && placeholderRow.parentNode) placeholderRow.remove(); - placeholderRow = document.createElement('tr'); - placeholderRow.innerHTML = '' + escapeHtml(msg) + ''; - tbody.appendChild(placeholderRow); + function loadRealtimeOnce() { + fetch(realtimeApiUrl, { method: 'GET', credentials: 'same-origin', headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } }) + .then(function(res) { return res.json().then(function(j) { return { ok: res.ok, data: j }; }); }) + .then(function(r) { + if (!r.ok) return; + var list = (r.data && r.data.data) ? r.data.data : (Array.isArray(r.data) ? r.data : []); + tbody.innerHTML = ''; + if (!list.length) { + var tr = document.createElement('tr'); + tr.innerHTML = 'Belum ada data absensi hari ini.'; + tbody.appendChild(tr); + return; + } + list.forEach(function(row) { addRow(row); }); + }) + .catch(function() { + var tr = document.createElement('tr'); + tr.innerHTML = 'Gagal memuat data absensi.'; + tbody.appendChild(tr); + }); } - function connect() { - var url = streamUrl + (afterId ? '?after_id=' + afterId : ''); - var es = new EventSource(url); - es.addEventListener('attendance', function(e) { - try { - var data = JSON.parse(e.data); - if (data && data.id) addRow(data); - } catch (err) {} - }); - es.addEventListener('heartbeat', function() { - if (!connected) { - connected = true; - setPlaceholder('No attendance records yet. Waiting for new check-ins…'); - } - }); - es.addEventListener('timeout', function() { - es.close(); - connected = false; - setPlaceholder('Stream ended. Reconnecting…'); - setTimeout(connect, 3000); - }); - es.onerror = function() { - es.close(); - connected = false; - setPlaceholder('Connection lost. Reconnecting…'); - setTimeout(connect, 3000); - }; - } - - connect(); + loadRealtimeOnce(); if (typeof window.addEventListener === 'function') { window.addEventListener('beforeunload', function() {