const form = document.querySelector("#incident-form"); const list = document.querySelector("#incidents"); const openCount = document.querySelector("#open-count"); const highCount = document.querySelector("#high-count"); const resolvedCount = document.querySelector("#resolved-count"); const workerState = document.querySelector("#worker-state"); async function requestJson(url, options = {}) { const response = await fetch(url, { headers: { "Content-Type": "application/json" }, ...options, }); if (!response.ok) { const body = await response.json().catch(() => ({})); throw new Error(body.error || `Request failed with ${response.status}`); } return response.json(); } function formatDate(value) { return new Intl.DateTimeFormat("de-CH", { dateStyle: "short", timeStyle: "short", }).format(new Date(value)); } function escapeHtml(value) { return value.replace(/[&<>"']/g, (char) => ({ "&": "&", "<": "<", ">": ">", "\"": """, "'": "'", }[char])); } function render(data) { const metrics = data.metrics || {}; openCount.textContent = metrics.open_count ?? 0; highCount.textContent = metrics.high_count ?? 0; resolvedCount.textContent = metrics.resolved_count ?? 0; workerState.textContent = metrics.updated_at ? `Worker zuletzt aktiv: ${formatDate(metrics.updated_at)}` : "Worker wartet auf Events"; if (!data.incidents.length) { list.innerHTML = `
Noch keine Incidents vorhanden.
`; return; } list.innerHTML = data.incidents.map((incident) => `
${escapeHtml(incident.title)}
#${incident.id} · ${incident.status} · aktualisiert ${formatDate(incident.updated_at)}
${incident.severity}
`).join(""); } async function load() { const data = await requestJson("/api/incidents"); render(data); } form.addEventListener("submit", async (event) => { event.preventDefault(); const button = form.querySelector("button"); button.disabled = true; try { await requestJson("/api/incidents", { method: "POST", body: JSON.stringify({ title: form.title.value, severity: form.severity.value, }), }); form.reset(); form.severity.value = "medium"; await load(); } finally { button.disabled = false; } }); list.addEventListener("click", async (event) => { const button = event.target.closest("[data-resolve]"); if (!button) return; button.disabled = true; await requestJson(`/api/incidents/${button.dataset.resolve}/resolve`, { method: "PATCH" }); await load(); }); load(); setInterval(load, 3000);