/* UI Logic for temperature and image rendering */ /** * Render a temperature line chart in the #temperature-chart container. * @param {Array<{timestamp: string, value: number}>} temperatures */ export function renderChart(temperatures) { const container = document.querySelector('#temperature-chart'); if (!container) return; container.innerHTML = ''; const canvas = document.createElement('canvas'); canvas.setAttribute('role', 'img'); canvas.setAttribute('aria-label', 'Temperaturverlauf'); canvas.width = container.clientWidth; canvas.height = 200; container.appendChild(canvas); const ctx = canvas.getContext('2d'); if (!ctx || temperatures.length === 0) return; const values = temperatures.map(t => t.value); const minVal = Math.min(...values); const maxVal = Math.max(...values); const range = maxVal - minVal || 1; ctx.strokeStyle = '#2196f3'; ctx.lineWidth = 2; ctx.beginPath(); temperatures.forEach((t, i) => { const x = (i / (temperatures.length - 1)) * canvas.width; const y = canvas.height - ((t.value - minVal) / range) * canvas.height; if (i === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } }); ctx.stroke(); } /** * Render an interactive image gallery. * @param {Array<{filename: string, timestamp: string, metadata?: object}>} images */ export function renderGallery(images) { const container = document.querySelector('#image-gallery'); if (!container) return; container.innerHTML = ''; const galleryGrid = document.createElement('div'); galleryGrid.classList.add('gallery-grid'); images.forEach((imgData, index) => { const imgEl = document.createElement('div'); imgEl.classList.add('gallery-item'); imgEl.tabIndex = 0; imgEl.setAttribute('role', 'button'); imgEl.setAttribute('aria-label', `Bild ${index + 1}`); imgEl.style.backgroundColor = '#e0e0e0'; imgEl.style.display = 'flex'; imgEl.style.alignItems = 'center'; imgEl.style.justifyContent = 'center'; imgEl.style.height = '100px'; imgEl.textContent = `Bild ${index + 1}`; imgEl.addEventListener('click', () => openImageModal(imgData)); imgEl.addEventListener('keypress', e => { if (e.key === 'Enter' || e.key === ' ') { openImageModal(imgData); } }); galleryGrid.appendChild(imgEl); }); container.appendChild(galleryGrid); } /** * Display a modal view for a selected image (textual substitute, no actual image). * @param {{filename: string, timestamp: string, metadata?: object}} imgData */ function openImageModal(imgData) { let modal = document.querySelector('#image-modal'); if (!modal) { modal = document.createElement('div'); modal.id = 'image-modal'; modal.setAttribute('role', 'dialog'); modal.setAttribute('aria-modal', 'true'); modal.style.position = 'fixed'; modal.style.top = 0; modal.style.left = 0; modal.style.right = 0; modal.style.bottom = 0; modal.style.background = 'rgba(0,0,0,0.8)'; modal.style.color = '#fff'; modal.style.display = 'flex'; modal.style.alignItems = 'center'; modal.style.justifyContent = 'center'; const content = document.createElement('div'); content.classList.add('modal-content'); content.style.padding = '1rem'; content.style.background = '#111'; content.style.maxWidth = '90%'; content.style.textAlign = 'center'; const closeBtn = document.createElement('button'); closeBtn.textContent = 'Schließen'; closeBtn.style.marginTop = '1rem'; closeBtn.addEventListener('click', () => { modal.remove(); }); modal.appendChild(content); content.appendChild(closeBtn); document.body.appendChild(modal); } const content = modal.querySelector('.modal-content'); if (content) { content.innerHTML = `
Aufgenommen: ${imgData.timestamp}
`; const closeBtn = document.createElement('button'); closeBtn.textContent = 'Schließen'; closeBtn.style.marginTop = '1rem'; closeBtn.addEventListener('click', () => modal.remove()); content.appendChild(closeBtn); } } /** * Update summary statistics for displayed data. * @param {Array<{timestamp: string, value: number}>} temperatures * @param {Array<{filename: string, timestamp: string}>} images */ export function updateStats(temperatures, images) { const container = document.querySelector('#summary-stats'); if (!container) return; container.innerHTML = ''; const avgTemp = temperatures.length > 0 ? (temperatures.reduce((sum, t) => sum + t.value, 0) / temperatures.length).toFixed(2) : 'N/A'; const imgCount = images.length; const statsText = `Durchschnittstemperatur: ${avgTemp}°C | Bilder: ${imgCount}`; container.textContent = statsText; }