diff --git a/result_visualization/js/app.js b/result_visualization/js/app.js new file mode 100644 index 0000000..c5c9408 --- /dev/null +++ b/result_visualization/js/app.js @@ -0,0 +1,144 @@ +'use strict'; + +/** + * Gate v0 Analysis - Result Visualization + * Initializer File: js/app.js + * © 2026 Donau2Space.de + */ + +/** + * Lädt die Analyseergebnisse vom /results-Endpunkt und initialisiert die Visualisierungskomponenten. + * @async + * @function initApp + * @returns {Promise} + */ +async function initApp() { + try { + showLoadingState(true); + + const params = getFilterParams(); + const queryString = new URLSearchParams(params).toString(); + const url = queryString ? `/results?${queryString}` : '/results'; + + const response = await fetch(url, { method: 'GET' }); + if (!response.ok) { + throw new Error(`API-Fehler: ${response.status}`); + } + + const results = await response.json(); + renderResults(results); + bindFilterEvents(); + } catch (error) { + console.error('Fehler beim Initialisieren der Anwendung:', error); + displayError('Es ist ein Fehler beim Laden der Ergebnisse aufgetreten.'); + } finally { + showLoadingState(false); + } +} + +/** + * Bindet Event-Handler an Filterelemente, um bei Änderungen neue Daten zu laden. + * @function bindFilterEvents + * @returns {void} + */ +function bindFilterEvents() { + const runTypeSelect = document.querySelector('#filter-run-type'); + const metricSelect = document.querySelector('#filter-metric'); + + if (runTypeSelect) { + runTypeSelect.addEventListener('change', initApp); + } + + if (metricSelect) { + metricSelect.addEventListener('change', initApp); + } +} + +/** + * Liest aktuelle Filterparameter aus. + * @returns {Object} - Objekt mit Filterparametern + */ +function getFilterParams() { + const runType = document.querySelector('#filter-run-type')?.value || ''; + const metric = document.querySelector('#filter-metric')?.value || ''; + const params = {}; + if (runType) params.run_type = runType; + if (metric) params.metric = metric; + return params; +} + +/** + * Zeigt oder versteckt den Ladezustand. + * @param {boolean} isLoading + */ +function showLoadingState(isLoading) { + const loader = document.querySelector('#loading-indicator'); + if (loader) { + loader.style.display = isLoading ? 'block' : 'none'; + } +} + +/** + * Baut die DOM-Struktur für angezeigte Ergebnisse auf. + * @param {Array} results - Ergebnisse vom /results-Endpunkt + */ +function renderResults(results) { + const container = document.querySelector('#results-container'); + if (!container) return; + + container.innerHTML = ''; + + if (!results?.length) { + container.innerHTML = '

Keine Ergebnisse gefunden.

'; + return; + } + + results.forEach(run => { + const runElement = document.createElement('article'); + runElement.className = 'result-item'; + + const header = document.createElement('h3'); + header.textContent = `Run #${run.id} (${run.type})`; + + const stats = document.createElement('p'); + stats.textContent = `Parameter: ${JSON.stringify(run.parameters)} | Statistik: ${JSON.stringify(run.statistics)}`; + + runElement.appendChild(header); + runElement.appendChild(stats); + + const chart = document.createElement('div'); + chart.className = 'result-chart'; + chart.setAttribute('aria-label', 'Diagramm der Ergebnisse'); + + renderChart(chart, run.chartData); + + runElement.appendChild(chart); + container.appendChild(runElement); + }); +} + +/** + * Simuliert das Rendering eines Diagramms. In der realen Anwendung würde hier ein Chart-Bibliothek genutzt. + * @param {HTMLElement} container + * @param {Object} chartData + */ +function renderChart(container, chartData) { + const chartPlaceholder = document.createElement('div'); + chartPlaceholder.textContent = `Diagramm für ${chartData?.label ?? 'unbekannt'} (Datenpunkte: ${chartData?.points?.length ?? 0})`; + chartPlaceholder.className = 'chart-placeholder'; + container.appendChild(chartPlaceholder); +} + +/** + * Zeigt eine Fehlermeldung im UI an. + * @param {string} message + */ +function displayError(message) { + const errorBox = document.querySelector('#error-message'); + if (errorBox) { + errorBox.textContent = message; + errorBox.style.display = 'block'; + } +} + +window.addEventListener('load', initApp); \ No newline at end of file