(function () { const app = document.querySelector('[data-bc-home]'); if (!app) return; const chartShell = app.querySelector('[data-bc-chart]'); const instrumentSelect = app.querySelector('[data-bc-instrument]'); const instrumentNameNode = app.querySelector('[data-bc-instrument-name]'); const instrumentMetaNode = app.querySelector('[data-bc-instrument-meta]'); const rangeButtons = Array.from(app.querySelectorAll('[data-range]')); const statusNode = app.querySelector('[data-bc-chart-status]'); const summaryNode = app.querySelector('[data-bc-chart-summary]'); const endpoint = app.getAttribute('data-chart-endpoint') || ''; const instrumentsScript = app.querySelector('[data-bc-instruments-json]'); const instrumentMap = new Map(); if (instrumentsScript?.textContent) { try { const items = JSON.parse(instrumentsScript.textContent); if (Array.isArray(items)) { items.forEach((item) => instrumentMap.set(String(item.instrument_id), item)); } } catch (_error) {} } let activeRange = '1m'; let currentPayload = null; function pointsForRange(payload, range) { if (!payload) return []; const daily = payload.daily || []; const weekly = payload.weekly || []; const monthly = payload.monthly || []; switch (range) { case '1d': return daily.slice(-2); case '5d': return daily.slice(-5); case '1m': return daily.slice(-22); case '3m': return daily.slice(-66); case '6m': return weekly.slice(-26); case '1y': return weekly.slice(-52); case '5y': return monthly.slice(-60); default: return daily.slice(-22); } } function renderChart(points) { if (!chartShell) return; chartShell.classList.remove('bc-panel-fade'); void chartShell.offsetWidth; chartShell.classList.add('bc-panel-fade'); if (!points || points.length === 0) { chartShell.innerHTML = '
Keine Chartdaten verfuegbar.
'; return; } const values = points.map((point) => Number(point.close || 0)); const min = Math.min(...values); const max = Math.max(...values); const width = 920; const height = 340; const paddingX = 24; const paddingY = 28; const usableWidth = width - paddingX * 2; const usableHeight = height - paddingY * 2; const spread = max - min || 1; const coords = points.map((point, index) => { const x = paddingX + (usableWidth * index / Math.max(points.length - 1, 1)); const y = paddingY + usableHeight - ((Number(point.close || 0) - min) / spread) * usableHeight; return { x, y }; }); const path = coords.map((coord, index) => `${index === 0 ? 'M' : 'L'}${coord.x.toFixed(2)},${coord.y.toFixed(2)}`).join(' '); const area = `${path} L${coords[coords.length - 1].x.toFixed(2)},${height - paddingY} L${coords[0].x.toFixed(2)},${height - paddingY} Z`; const grid = [0, 1, 2, 3].map((step) => { const y = paddingY + (usableHeight * step / 3); return ``; }).join(''); chartShell.innerHTML = ` ${grid} `; const first = values[0]; const last = values[values.length - 1]; const delta = last - first; const percent = first !== 0 ? (delta / first) * 100 : 0; if (summaryNode) { summaryNode.textContent = `${last.toFixed(2)} | ${delta >= 0 ? '+' : ''}${delta.toFixed(2)} (${percent.toFixed(2)}%)`; } } async function loadChart() { const instrumentId = instrumentSelect ? instrumentSelect.value : ''; if (!instrumentId || !endpoint) { if (statusNode) statusNode.textContent = 'Keine Aktie fuer den Chart ausgewaehlt.'; if (summaryNode) summaryNode.textContent = '-'; if (chartShell) chartShell.innerHTML = '
Keine Chartdaten verfuegbar.
'; return; } if (statusNode) statusNode.textContent = 'Chartdaten werden geladen...'; try { const response = await fetch(`${endpoint}${endpoint.includes('?') ? '&' : '?'}instrument_id=${encodeURIComponent(instrumentId)}`, { headers: { Accept: 'application/json' } }); const payload = await response.json(); if (!payload.ok) { throw new Error(payload.message || 'Chartdaten konnten nicht geladen werden.'); } currentPayload = payload; renderChart(pointsForRange(payload, activeRange)); if (statusNode) statusNode.textContent = `Quelle: Alpha Vantage | Symbol ${payload.symbol || ''}`; } catch (error) { currentPayload = null; chartShell.innerHTML = `
${error.message}
`; if (statusNode) statusNode.textContent = 'Fehler beim Laden der Chartdaten.'; } } rangeButtons.forEach((button) => { button.addEventListener('click', () => { activeRange = button.getAttribute('data-range') || '1m'; rangeButtons.forEach((item) => item.setAttribute('aria-pressed', item === button ? 'true' : 'false')); renderChart(pointsForRange(currentPayload, activeRange)); }); }); if (instrumentSelect) { instrumentSelect.addEventListener('change', () => { const meta = instrumentMap.get(String(instrumentSelect.value)); if (meta) { if (instrumentNameNode) instrumentNameNode.textContent = meta.instrument_name || 'Keine Aktie ausgewaehlt'; if (instrumentMetaNode) instrumentMetaNode.textContent = `${meta.symbol || ''} ยท ${meta.isin || '-'}`; } loadChart(); }); } loadChart(); })();