From 9c0b8df07c0c70dd672d3e05b0fc82b76c4678c4 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 14 Jun 2026 19:50:45 -0300 Subject: [PATCH] operations: add server availability table (seats, taken, available) fetched from webhook --- operations.html | 113 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/operations.html b/operations.html index c3383ef..f2d6337 100644 --- a/operations.html +++ b/operations.html @@ -255,6 +255,59 @@ margin-top: 4px; } + /* ── Servers Table ──────────────────── */ + .server-grid { + display: grid; + grid-template-columns: 1fr; + gap: 6px; + } + .server-card { + display: flex; + justify-content: space-between; + align-items: center; + background: var(--bg-card); + border-radius: var(--radius-card); + padding: 14px 18px; + } + .server-card .server-name { + font-weight: 600; + font-size: 14px; + color: var(--text); + } + .server-card .server-meta { + display: flex; + gap: 16px; + font-size: 12px; + } + .server-card .server-meta span { + color: var(--text-muted); + } + .server-card .server-meta strong { + color: var(--text); + font-weight: 600; + } + .server-card .server-status { + font-size: 11px; + font-weight: 500; + padding: 2px 10px; + border-radius: 4px; + } + .server-card .server-status.ok { + background: rgba(34,197,94,.12); + color: var(--success); + border: 1px solid rgba(34,197,94,.15); + } + .server-card .server-status.low { + background: rgba(245,158,11,.12); + color: var(--warning); + border: 1px solid rgba(245,158,11,.15); + } + .server-card .server-status.full { + background: rgba(239,68,68,.12); + color: var(--danger); + border: 1px solid rgba(239,68,68,.15); + } + /* ── Campaign Cards ──────────────────── */ .campaign-grid { display: grid; @@ -645,6 +698,18 @@
Last updated: —
+ +
+
+

🖥 Servers

+ live + +
+
+
+
+
+
@@ -1184,6 +1249,53 @@ } catch { /* defaults */ } } + /* ── Servers ── */ + const SERVER_WEBHOOK = "https://n8n.derez.ai/webhook/server"; + + function renderServers(servers) { + const grid = document.getElementById('server-grid'); + if (!servers || servers.length === 0) { + grid.innerHTML = '
No server data available.
'; + return; + } + grid.innerHTML = servers.map(function(s) { + const name = s.server || '—'; + const total = parseInt(s.Seats, 10) || 0; + const taken = parseInt(s['Seats taken'], 10) || 0; + const avail = parseInt(s['Seats Available'], 10) || 0; + let statusClass = 'ok'; + let statusLabel = 'Available'; + if (avail <= 0) { + statusClass = 'full'; + statusLabel = 'Full'; + } else if (avail < 10) { + statusClass = 'low'; + statusLabel = 'Low'; + } + return '
' + + '
' + name.charAt(0).toUpperCase() + name.slice(1) + '
' + + '
' + + 'Seats ' + total + '' + + 'Taken ' + taken + '' + + 'Available ' + avail + '' + + '
' + + '' + statusLabel + '' + + '
'; + }).join(''); + } + + async function fetchServers() { + try { + const res = await fetch(SERVER_WEBHOOK); + const raw = await res.json(); + const list = raw && Array.isArray(raw.data) ? raw.data : Array.isArray(raw) ? raw : [raw].filter(Boolean); + const servers = list.filter(function(s) { return s && s.server; }); + renderServers(servers); + } catch { + renderServers(null); + } + } + /* ── Init ── */ document.getElementById('brief-date').textContent = fmtTimestamp(); renderGoals(); @@ -1193,6 +1305,7 @@ renderInfos(); fetchWebsiteStats(); fetchLiveData(); + fetchServers(); \ No newline at end of file