document.addEventListener("DOMContentLoaded", () => { const dataElement = document.getElementById("reporting-data"); let reportingSummaries = []; if (dataElement) { try { const parsed = JSON.parse(dataElement.textContent || "[]"); if (Array.isArray(parsed)) { reportingSummaries = parsed; } } catch (error) { console.error("Unable to parse reporting data", error); } } const REPORT_FIELDS = [ { key: "iterations", label: "Iterations", decimals: 0 }, { key: "mean", label: "Mean Result", decimals: 2 }, { key: "variance", label: "Variance", decimals: 2 }, { key: "std_dev", label: "Std. Dev", decimals: 2 }, { key: "percentile_5", label: "Percentile 5", decimals: 2 }, { key: "percentile_95", label: "Percentile 95", decimals: 2 }, { key: "value_at_risk_95", label: "Value at Risk (95%)", decimals: 2 }, { key: "expected_shortfall_95", label: "Expected Shortfall (95%)", decimals: 2, }, ]; const tableWrapper = document.getElementById("reporting-table-wrapper"); const tableBody = document.getElementById("reporting-table-body"); const emptyState = document.getElementById("reporting-empty"); const refreshButton = document.getElementById("report-refresh"); const feedbackEl = document.getElementById("report-feedback"); const formatNumber = (value, decimals = 2) => { if (value === null || value === undefined || Number.isNaN(Number(value))) { return "—"; } return Number(value).toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals, }); }; const showFeedback = (message, type = "success") => { if (!feedbackEl) { return; } feedbackEl.textContent = message; feedbackEl.classList.remove("hidden", "success", "error"); feedbackEl.classList.add(type); }; const hideFeedback = () => { if (!feedbackEl) { return; } feedbackEl.classList.add("hidden"); feedbackEl.textContent = ""; }; const renderReportingTable = (summaryData) => { if (!tableBody || !tableWrapper || !emptyState) { return; } tableBody.innerHTML = ""; if (!summaryData.length) { emptyState.classList.remove("hidden"); tableWrapper.classList.add("hidden"); return; } emptyState.classList.add("hidden"); tableWrapper.classList.remove("hidden"); summaryData.forEach((entry) => { const row = document.createElement("tr"); const scenarioCell = document.createElement("td"); scenarioCell.textContent = entry.scenario_name; row.appendChild(scenarioCell); REPORT_FIELDS.forEach((field) => { const cell = document.createElement("td"); const source = field.key === "iterations" ? entry : entry.summary || {}; cell.textContent = formatNumber(source[field.key], field.decimals); row.appendChild(cell); }); tableBody.appendChild(row); }); }; const refreshMetrics = async () => { hideFeedback(); showFeedback("Refreshing metrics…", "success"); try { const response = await fetch("/ui/reporting", { method: "GET", headers: { "X-Requested-With": "XMLHttpRequest" }, }); if (!response.ok) { throw new Error("Unable to refresh reporting data."); } const text = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(text, "text/html"); const newTable = doc.querySelector("#reporting-table-wrapper"); const newFeedback = doc.querySelector("#report-feedback"); if (!newTable) { throw new Error("Unexpected response while refreshing."); } const newEmptyState = doc.querySelector("#reporting-empty"); if (emptyState && newEmptyState) { emptyState.className = newEmptyState.className; emptyState.textContent = newEmptyState.textContent; } if (tableWrapper) { tableWrapper.className = newTable.className; tableWrapper.innerHTML = newTable.innerHTML; } if (newFeedback && feedbackEl) { feedbackEl.className = newFeedback.className; feedbackEl.textContent = newFeedback.textContent; } showFeedback("Metrics refreshed.", "success"); } catch (error) { showFeedback(error.message || "An unexpected error occurred.", "error"); } }; renderReportingTable(reportingSummaries); if (refreshButton) { refreshButton.addEventListener("click", refreshMetrics); } });