'use strict'; (() => { const status = document.getElementById('chart-status'); if (typeof Chart === 'undefined') { status.textContent = 'Chart.js konnte nicht vom CDN geladen werden. Alle Werte bleiben in den Tabellen verfügbar.'; return; } const data = JSON.parse(document.getElementById('chart-data').textContent); const euro = cents => new Intl.NumberFormat('de-DE', {style: 'currency', currency: 'EUR'}).format(cents / 100); const palette = ['#72e2b0','#79b6ff','#f4c272','#bc9cfa','#f691aa','#67cbd0','#e5db89','#9ec28b','#b2bdec','#daaa81']; Chart.defaults.color = '#a4b3c7'; Chart.defaults.borderColor = '#293548'; Chart.defaults.font.family = 'system-ui, sans-serif'; new Chart(document.getElementById('monthly-chart'), { type: 'line', data: {labels: data.months, datasets: data.years.map((year, i) => ({...year, borderColor: palette[i % palette.length], backgroundColor: palette[i % palette.length], tension: 0.2, pointRadius: 3}))}, options: {responsive:true, maintainAspectRatio:false, animation:false, interaction:{mode:'index',intersect:false}, scales:{y:{ticks:{callback:euro},title:{display:true,text:'Euro'}}}, plugins:{tooltip:{callbacks:{label:ctx => `${ctx.dataset.label}: ${euro(ctx.raw)}`}}}} }); function shares(id, rows) { // Signed corrections cannot be represented truthfully as pie slices. const negative = rows.some(row => row.amount < 0); const total = rows.reduce((sum,row) => sum + row.amount, 0); new Chart(document.getElementById(id), { type: negative ? 'bar' : 'doughnut', data:{labels:rows.map(row => row.name),datasets:[{data:rows.map(row => row.amount),backgroundColor:rows.map((_,i) => palette[i % palette.length]),borderWidth:0}]}, options:{responsive:true,maintainAspectRatio:false,animation:false, ...(negative ? {scales:{y:{ticks:{callback:euro}}}} : {cutout:'68%'}), plugins:{legend:{display:!negative,position:'bottom',labels:{boxWidth:10,font:{size:11}}},tooltip:{callbacks:{label:ctx => { const amount = rows[ctx.dataIndex].amount; const share = total === 0 ? '–' : new Intl.NumberFormat('de-DE',{minimumFractionDigits:2,maximumFractionDigits:2}).format(amount / total * 100) + ' %'; return `${ctx.label}: ${euro(amount)} (${share})`; }}}}} }); } shares('shares-chart', data.shares); shares('kinds-chart', data.kinds); status.textContent = data.years.some(year => year.data.some(value => value !== 0)) ? 'Diagramme zeigen tatsächlich erhaltene Einnahmen. Negative Positionssummen werden als Balken dargestellt.' : 'Noch keine tatsächlichen Einnahmen vorhanden.'; })();