(() => { /** * chartRenderer.js * Visualization layer rendering measurement data charts. * Uses Chart.js (assumed pre-loaded in the environment) * Handles rendering and updating of multiple measurement charts. */ let charts = {}; /** * Converts measurement data into Chart.js datasets * @param {Array} data - filtered measurement records * @returns {Object} datasets and labels for Chart.js */ const prepareDatasets = (data) => { if (!Array.isArray(data)) return { labels: [], datasets: [] }; const labels = data.map(d => new Date(d.timestamp).toLocaleTimeString()); const temperatureData = data.map(d => d.temperature); const humidityData = data.map(d => d.humidity); const brightnessData = data.map(d => d.brightness); return { labels, datasets: [ { label: 'Temperatur (°C)', data: temperatureData, borderColor: 'rgba(255, 99, 132, 1)', backgroundColor: 'rgba(255, 99, 132, 0.2)', tension: 0.3, yAxisID: 'y', }, { label: 'Luftfeuchte (%)', data: humidityData, borderColor: 'rgba(54, 162, 235, 1)', backgroundColor: 'rgba(54, 162, 235, 0.2)', tension: 0.3, yAxisID: 'y1', }, { label: 'Signalintensität', data: brightnessData, borderColor: 'rgba(75, 192, 192, 1)', backgroundColor: 'rgba(75, 192, 192, 0.2)', tension: 0.3, yAxisID: 'y', } ] }; }; /** * renderCharts * Visualizes data in line charts and appends them into the .chart-panel. * @param {Array} data - filtered measurement data */ const renderCharts = (data) => { const chartPanel = document.querySelector('.chart-panel'); if (!chartPanel) return; chartPanel.innerHTML = ''; const canvas = document.createElement('canvas'); canvas.setAttribute('aria-label', 'Messdaten Diagramm'); canvas.setAttribute('role', 'img'); chartPanel.appendChild(canvas); const ctx = canvas.getContext('2d'); const { labels, datasets } = prepareDatasets(data); const config = { type: 'line', data: { labels, datasets }, options: { responsive: true, interaction: { mode: 'index', intersect: false }, stacked: false, plugins: { tooltip: { enabled: true, callbacks: { title: (items) => items[0]?.label || '', label: (item) => `${item.dataset.label}: ${item.formattedValue}` } }, legend: { labels: { color: '#eee' } }, }, scales: { y: { type: 'linear', display: true, position: 'left', title: { display: true, text: 'Temperatur / Intensität' }, ticks: { color: '#ccc' } }, y1: { type: 'linear', display: true, position: 'right', grid: { drawOnChartArea: false }, title: { display: true, text: 'Luftfeuchte' }, ticks: { color: '#ccc' } }, x: { ticks: { color: '#ccc' } } } } }; charts.main = new Chart(ctx, config); }; /** * updateChart * Updates existing chart data and re-renders with new dataset. * @param {Array} newData - new or filtered measurement data */ const updateChart = (newData) => { if (!charts.main) { renderCharts(newData); return; } const { labels, datasets } = prepareDatasets(newData); charts.main.data.labels = labels; charts.main.data.datasets = datasets; charts.main.update('active'); }; // Expose functions globally window.chartRenderer = { renderCharts, updateChart }; })();