import Alpine from 'alpinejs'; import 'htmx.org'; import { Chart, BarController, BarElement, CategoryScale, LinearScale, Tooltip, Title } from 'chart.js'; // Dark mode toggle. Layout's inline script handles the FOUC-free // initial paint; this just wires the toggle button. function applyTheme(theme) { if (theme === 'dark') { document.documentElement.classList.add('dark'); } else { document.documentElement.classList.remove('dark'); } try { localStorage.setItem('irdb-theme', theme); } catch (e) { /* ignore */ } } document.addEventListener('click', (e) => { const target = e.target.closest('[data-theme-toggle]'); if (!target) return; const next = document.documentElement.classList.contains('dark') ? 'light' : 'dark'; applyTheme(next); }); // htmx: send the per-session CSRF token on every state-changing request. document.body.addEventListener('htmx:configRequest', (e) => { const meta = document.querySelector('meta[name="csrf-token"]'); if (meta && meta.content) { e.detail.headers['X-CSRF-Token'] = meta.content; } }); // Dashboard reports-per-hour chart. The canvas carries the buckets in a // `data-buckets` attribute (server-pre-bucketed; no AJAX). Chart.js is // tree-shaken to just the bar/linear pieces we need so the bundle stays // small. Chart.register(BarController, BarElement, CategoryScale, LinearScale, Tooltip, Title); function renderReportsChart() { const canvas = document.getElementById('reports-chart'); if (!canvas) return; let buckets = []; try { buckets = JSON.parse(canvas.dataset.buckets || '[]'); } catch (e) { return; } const labels = buckets.map((b) => (b.hour || '').replace(/.*T(\d{2}).*/, '$1h')); const data = buckets.map((b) => b.count || 0); const isDark = document.documentElement.classList.contains('dark'); const tickColor = isDark ? '#94a3b8' : '#475569'; const gridColor = isDark ? 'rgba(148,163,184,0.15)' : 'rgba(148,163,184,0.3)'; new Chart(canvas, { type: 'bar', data: { labels, datasets: [{ label: 'reports', data, backgroundColor: '#6366f1', }], }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } }, scales: { x: { ticks: { color: tickColor }, grid: { color: gridColor } }, y: { ticks: { color: tickColor, precision: 0 }, grid: { color: gridColor }, beginAtZero: true }, }, }, }); } document.addEventListener('DOMContentLoaded', renderReportsChart); // Locale-aware