const healthEl = document.getElementById("health"); const globalStatus = document.getElementById("globalStatus"); const lastUpdated = document.getElementById("lastUpdated"); const serverDot = document.getElementById("serverDot"); const webDot = document.getElementById("webDot"); const roamDot = document.getElementById("roamDot"); const buildBtn = document.getElementById("buildBtn"); const buildResultEl = document.getElementById("buildResult"); const logOutput = document.getElementById("logOutput"); const orgRoamBtn = document.getElementById("orgRoamBtn"); const orgRoamResult = document.getElementById("orgRoamResult"); const orgRoamLogs = document.getElementById("orgRoamLogs"); let webEventSource = null; let roamEventSource = null; /* ========================================= HEALTH ========================================= */ async function fetchHealth() { try { const res = await fetch("/api/health"); const text = await res.text(); healthEl.textContent = "Online"; healthEl.className = "badge ok"; serverDot.className = "dot green"; globalStatus.className = "global-ok"; globalStatus.textContent = "🟢 All Systems Running Normally"; lastUpdated.textContent = "Last checked: " + new Date().toLocaleTimeString(); } catch { healthEl.textContent = "Offline"; healthEl.className = "badge error"; serverDot.className = "dot red"; globalStatus.className = "global-error"; globalStatus.textContent = "⚠ Attention Required"; } } // Auto refresh every 10s setInterval(fetchHealth, 10000); /* ========================================= LOG TOGGLE ========================================= */ document.querySelectorAll(".toggleLogs").forEach(btn => { btn.addEventListener("click", () => { const target = document.getElementById(btn.dataset.target); target.classList.toggle("hidden"); btn.textContent = target.classList.contains("hidden") ? "Show technical details" : "Hide technical details"; }); }); /* ========================================= STREAM HELPERS ========================================= */ function startLogStream(url, outputEl, setter) { const source = new EventSource(url); source.onmessage = (event) => { outputEl.textContent += event.data + "\n"; outputEl.scrollTop = outputEl.scrollHeight; }; source.onerror = () => { source.close(); }; setter(source); } function closeStream(source) { if (source) source.close(); } /* ========================================= WEBSITE BUILD ========================================= */ async function runWebBuild() { if (!confirm("This will update the website. Continue?")) return; buildBtn.disabled = true; buildResultEl.textContent = "🔄 Updating website..."; webDot.className = "dot yellow"; logOutput.textContent = ""; try { const res = await fetch("/api/build-web", { method: "POST" }); if (!res.ok) throw new Error(); closeStream(webEventSource); startLogStream("/api/build-web/logs", logOutput, src => webEventSource = src); pollWebStatus(); } catch { buildResultEl.textContent = "❌ Could not start update"; buildBtn.disabled = false; webDot.className = "dot red"; } } async function pollWebStatus() { const interval = setInterval(async () => { const res = await fetch("/api/build-web/status"); const status = await res.json(); if (!status.running) { clearInterval(interval); closeStream(webEventSource); buildBtn.disabled = false; if (status.lastExitCode === 0) { buildResultEl.textContent = "✅ Website updated successfully"; webDot.className = "dot green"; } else { buildResultEl.textContent = "⚠ Update finished with issue (code " + status.lastExitCode + ")"; webDot.className = "dot red"; } } }, 2000); } /* ========================================= ORG ROAM BUILD ========================================= */ async function runOrgRoamBuild() { if (!confirm("Refresh the knowledge base?")) return; orgRoamBtn.disabled = true; orgRoamResult.textContent = "🔄 Refreshing notes..."; roamDot.className = "dot yellow"; orgRoamLogs.textContent = ""; try { const res = await fetch("/api/build-roam", { method: "POST" }); if (!res.ok) throw new Error(); closeStream(roamEventSource); startLogStream("/api/build-roam/logs", orgRoamLogs, src => roamEventSource = src); pollRoamStatus(); } catch { orgRoamResult.textContent = "❌ Could not start refresh"; orgRoamBtn.disabled = false; roamDot.className = "dot red"; } } async function pollRoamStatus() { const interval = setInterval(async () => { const res = await fetch("/api/build-roam/status"); const status = await res.json(); if (!status.running) { clearInterval(interval); closeStream(roamEventSource); orgRoamBtn.disabled = false; if (status.lastExitCode === 0) { orgRoamResult.textContent = "✅ Notes refreshed successfully"; roamDot.className = "dot green"; } else { orgRoamResult.textContent = "⚠ Refresh finished with issue (code " + status.lastExitCode + ")"; roamDot.className = "dot red"; } } }, 2000); } /* ========================================= DAILY MESSAGE ========================================= */ const messages = [ "You are my favourite person.", ]; function setDailyMessage() { const today = new Date().toDateString(); const index = today.split("").reduce((acc, char) => acc + char.charCodeAt(0), 0) % messages.length; document.getElementById("dailyMessage").textContent = messages[index]; } setDailyMessage(); /* ========================================= COUNTDOWN (LIVE - UPDATES EVERY SECOND) ========================================= */ function startCountdown() { const targetDate = new Date("2026-08-03T00:00:00"); // change this const label = "Nikah"; const countdownEl = document.getElementById("countdownText"); function updateCountdown() { const now = new Date(); const diff = targetDate - now; if (diff <= 0) { countdownEl.textContent = `${label} is happening now! 🎉`; clearInterval(interval); return; } const days = Math.floor(diff / (1000 * 60 * 60 * 24)); const hours = Math.floor((diff / (1000 * 60 * 60)) % 24); const minutes = Math.floor((diff / (1000 * 60)) % 60); const seconds = Math.floor((diff / 1000) % 60); countdownEl.textContent = `${label} in ${days}d ${hours}h ${minutes}m ${seconds}s`; } updateCountdown(); const interval = setInterval(updateCountdown, 1000); } startCountdown(); /* ========================================= INIT ========================================= */ fetchHealth(); buildBtn.addEventListener("click", runWebBuild); orgRoamBtn.addEventListener("click", runOrgRoamBuild);