document.addEventListener("DOMContentLoaded", () => { const refreshBtn = document.getElementById("refresh-rules"); if (refreshBtn) { refreshBtn.addEventListener("click", async () => { refreshBtn.disabled = true; const original = refreshBtn.textContent; refreshBtn.textContent = "Refreshing…"; try { const res = await fetch("/api/rules/refresh", { method: "POST" }); if (!res.ok) { const data = await res.json().catch(() => ({})); alert("Refresh failed: " + (data.error || res.status)); return; } window.location.reload(); } finally { refreshBtn.disabled = false; refreshBtn.textContent = original; } }); } document.querySelectorAll(".rule-card").forEach(initRuleCard); initSessionControls(); }); function initSessionControls() { const startBtn = document.getElementById("session-start"); const captureBtn = document.getElementById("session-capture"); const stopBtn = document.getElementById("session-stop"); if (!startBtn) return; // not on the Session page async function call(url, btn) { btn.disabled = true; const original = btn.textContent; btn.textContent = "Working…"; try { const res = await fetch(url, { method: "POST" }); const data = await res.json().catch(() => ({})); if (!res.ok) { alert(data.error || "Request failed"); btn.disabled = false; btn.textContent = original; return; } window.location.reload(); } catch (err) { btn.disabled = false; btn.textContent = original; } } startBtn.addEventListener("click", () => call("/api/session/start", startBtn)); captureBtn.addEventListener("click", () => call("/api/session/capture", captureBtn)); stopBtn.addEventListener("click", () => call("/api/session/stop", stopBtn)); } function initRuleCard(card) { const ruleId = card.dataset.ruleId; card.querySelector(".rule-enabled").addEventListener("change", (e) => { saveSchedule(card, { enabledOverride: e.target.checked }); }); card.querySelectorAll(".day-toggle").forEach((btn) => { btn.addEventListener("click", () => btn.classList.toggle("active")); }); card.querySelector(".add-schedule").addEventListener("click", () => { const time = card.querySelector(".new-time").value; const days = [...card.querySelectorAll(".day-toggle.active")].map((b) => b.dataset.day); if (!time || days.length === 0) { alert("Pick a time and at least one day."); return; } addChip(card, time, days); card.querySelectorAll(".day-toggle.active").forEach((b) => b.classList.remove("active")); saveSchedule(card); }); card.querySelectorAll(".chip-remove").forEach((btn) => bindRemove(btn)); card.querySelector(".run-now").addEventListener("click", async (e) => { const btn = e.currentTarget; const original = btn.textContent; btn.disabled = true; btn.textContent = "Queuing…"; try { const res = await fetch(`/api/rules/${ruleId}/run`, { method: "POST" }); btn.textContent = res.ok ? "Queued" : "Failed"; } catch (err) { btn.textContent = "Failed"; } finally { setTimeout(() => { btn.textContent = original; btn.disabled = false; }, 2000); } }); } function bindRemove(btn) { btn.addEventListener("click", () => { const card = btn.closest(".rule-card"); btn.closest(".schedule-chip").remove(); saveSchedule(card); }); } function addChip(card, time, days) { const list = card.querySelector(".schedule-list"); const li = document.createElement("li"); li.className = "schedule-chip"; li.innerHTML = `${time}` + `${days.join(" ")}` + ``; list.appendChild(li); bindRemove(li.querySelector(".chip-remove")); } async function saveSchedule(card, opts = {}) { const ruleId = card.dataset.ruleId; const enabled = opts.enabledOverride !== undefined ? opts.enabledOverride : card.querySelector(".rule-enabled").checked; const schedules = [...card.querySelectorAll(".schedule-chip")].map((chip) => ({ time: chip.querySelector(".chip-time").textContent.trim(), days: chip .querySelector(".chip-days") .textContent.trim() .split(/\s+/) .filter(Boolean), })); await fetch(`/api/rules/${ruleId}/schedule`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ enabled, schedules }), }); }