/* eslint-disable no-undef */ // charts.js — UX v2 (fixed quick-top) (function () { const $ = (sel, root = document) => root.querySelector(sel); const $$ = (sel, root = document) => Array.from(root.querySelectorAll(sel)); // Kolory dla dark mode const palette = { grid: 'rgba(255,255,255,0.1)', tick: 'rgba(255,255,255,0.7)', bar: 'rgba(54, 162, 235, 0.8)', bar2: 'rgba(255, 159, 64, 0.85)', line: 'rgba(255, 99, 132, 1)', lineFill: 'rgba(255, 99, 132, 0.2)', pie: [ 'rgba(255, 99, 132, 0.85)', 'rgba(54, 162, 235, 0.85)', 'rgba(255, 206, 86, 0.85)', 'rgba(75, 192, 192, 0.85)', 'rgba(153, 102, 255, 0.85)', 'rgba(255, 159, 64, 0.85)', 'rgba(199, 199, 199, 0.85)' ] }; function emptyState(canvasId, emptyId, labels, dataArr) { const hasData = Array.isArray(labels) && labels.length > 0 && Array.isArray(dataArr) && dataArr.some(v => v > 0); const empty = document.getElementById(emptyId); const canvas = document.getElementById(canvasId); if (!hasData) { canvas?.classList.add('d-none'); empty?.classList.remove('d-none'); return true; } canvas?.classList.remove('d-none'); empty?.classList.add('d-none'); return false; } function csvFromSeries(labels, data, headerX = 'Label', headerY = 'Value') { const rows = [[headerX, headerY], ...labels.map((l, i) => [l, data[i] ?? 0])]; return rows.map(r => r.map(v => `"${String(v).replace(/"/g, '""')}"`).join(',')).join('\n'); } function download(filename, content, mime) { const blob = new Blob([content], { type: mime }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; a.click(); URL.revokeObjectURL(url); } function bindDownloads(id, labels, data) { $$('.chart-download').forEach(btn => { if (btn.dataset.target !== id) return; btn.addEventListener('click', () => { const type = btn.dataset.type; if (type === 'csv') { download(`${id}.csv`, csvFromSeries(labels, data), 'text/csv;charset=utf-8'); } else if (type === 'png') { const c = document.getElementById(id); if (!c) return; const url = c.toDataURL('image/png'); const a = document.createElement('a'); a.href = url; a.download = `${id}.png`; a.click(); } }); }); } function bindFullscreen(id) { $$('.chart-fullscreen').forEach(btn => { if (btn.dataset.target !== id) return; btn.addEventListener('click', () => { const src = document.getElementById(id); const dst = document.getElementById('chartModalCanvas'); const chart = Chart.getChart(src); if (!chart) return; const modal = new bootstrap.Modal(document.getElementById('chartModal')); modal.show(); setTimeout(() => { const old = Chart.getChart(dst); old && old.destroy(); new Chart(dst.getContext('2d'), { type: chart.config.type, data: JSON.parse(JSON.stringify(chart.config.data)), options: Object.assign({}, chart.config.options, { maintainAspectRatio: false }) }); }, 150); }); }); } // Bind przycisków szybkiego wyboru: nie wysyłamy duplikatu name, // tylko ustawiamy nadal auto-submituje: select.addEventListener('change', () => form.requestSubmit()); } // Auto-inicjalizacja niezależnie od kolejności ładowania if (document.readyState === 'loading') { window.addEventListener('DOMContentLoaded', bindQuickTop); } else { bindQuickTop(); } function bindQuickPeriod() { const form = document.getElementById('options-form'); const select = document.getElementById('period'); if (!form || !select) return; // Szybkie przyciski okresu (Tydzień/Miesiąc/Rok) $$('.quick-period').forEach(btn => { btn.addEventListener('click', () => { const val = btn.dataset.value; if (val) select.value = String(val); // natychmiastowy feedback w UI $$('.quick-period').forEach(b => b.classList.remove('active')); btn.classList.add('active'); form.requestSubmit(); }); }); // Zmiana w