diff --git a/admin/DashboardController.php b/admin/DashboardController.php index 33245c2..bd4e3e1 100644 --- a/admin/DashboardController.php +++ b/admin/DashboardController.php @@ -115,7 +115,7 @@ function togglePause() { paused = !paused; document.getElementById('btnPause').innerHTML = paused ? '▶ Reanudar' : '▮▮ Pausar'; document.getElementById('dot').className = 'dot' + (paused ? ' paused' : ''); - if (paused) { document.getElementById('status').textContent = 'En pausa'; es && es.close(); } + if (paused) { document.getElementById('status').textContent = 'En pausa'; clearInterval(pollTimer); pollTimer = null; } else { connect(); } } @@ -154,17 +154,28 @@ function addCards(rows) { } } -function connect() { - es = new EventSource('/admin/webhook/stream/sse'); - es.onopen = () => { +let lastId = 0; +let pollTimer = null; + +async function poll() { + if (paused) return; + try { + const r = await fetch('/admin/webhook/stream?after=' + lastId + (lastId === 0 ? '&init=1' : '')); + if (!r.ok) throw new Error('HTTP ' + r.status); + const d = await r.json(); + if (d.last_id !== undefined) { lastId = d.last_id; } + if (d.rows && d.rows.length) { lastId = d.rows[d.rows.length-1].id; addCards(d.rows); } document.getElementById('dot').className = 'dot'; - document.getElementById('status').textContent = 'Conectado — tiempo real (SSE)'; - }; - es.onmessage = e => { if (!paused) try { addCards(JSON.parse(e.data)); } catch(_) {} }; - es.onerror = () => { + document.getElementById('status').textContent = 'Conectado — polling cada 3s'; + } catch(e) { document.getElementById('dot').className = 'dot paused'; - document.getElementById('status').textContent = 'Reconectando...'; - }; + document.getElementById('status').textContent = 'Error de conexion, reintentando...'; + } +} + +function connect() { + poll(); + pollTimer = setInterval(poll, 3000); } function esc(s) { @@ -181,7 +192,7 @@ async function showRaw(id) { } function closeModal() { document.getElementById('modal').style.display = 'none'; } document.addEventListener('keydown', e => { if(e.key==='Escape') closeModal(); }); -window.addEventListener('pagehide', () => { es && es.close(); }); +window.addEventListener('pagehide', () => { clearInterval(pollTimer); }); connect(); @@ -261,13 +272,10 @@ HTML; try { if ($isInit) { - // En init devolvemos solo el último ID (sin datos) para anclar - $stmt = db()->query('SELECT id FROM webhook_logs ORDER BY id DESC LIMIT 1'); - $row = $stmt->fetch(); - $afterId = $row ? (int)$row['id'] : 0; - // Devolvemos array vacío — solo queremos anclar lastId en el cliente + $row = db()->query('SELECT id FROM webhook_logs ORDER BY id DESC LIMIT 1')->fetch(); + $lastId = $row ? (int)$row['id'] : 0; header('Content-Type: application/json; charset=utf-8'); - echo json_encode([]); + echo json_encode(['rows' => [], 'last_id' => $lastId]); exit; } @@ -283,12 +291,12 @@ HTML; $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); } catch (\PDOException $e) { header('Content-Type: application/json; charset=utf-8'); - echo '[]'; + echo json_encode(['rows' => [], 'last_id' => $afterId]); exit; } header('Content-Type: application/json; charset=utf-8'); - echo json_encode($rows, JSON_UNESCAPED_UNICODE); + echo json_encode(['rows' => $rows, 'last_id' => $rows ? (int)end($rows)['id'] : $afterId], JSON_UNESCAPED_UNICODE); exit; }