const setTheme = (theme) => { const root = document.documentElement; root.dataset.theme = theme; }; const setIcon = (button, theme) => { const icon = button.querySelector('i'); if (!icon) return; icon.classList.remove('bi-sun-fill', 'bi-moon-stars-fill'); icon.classList.add(theme === 'dark' ? 'bi-moon-stars-fill' : 'bi-sun-fill'); }; const updateTheme = async (button, theme) => { const url = button.dataset.themeUrl; const csrfKey = button.dataset.csrfKey; const csrfToken = button.dataset.csrfToken; if (!url || !csrfKey || !csrfToken) { return true; } const body = new URLSearchParams({ theme, [csrfKey]: csrfToken }); const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json', 'X-Requested-With': 'fetch' }, body }); return response.ok; }; const initThemeToggle = () => { const button = document.querySelector('[data-theme-toggle]'); if (!button) return; const root = document.documentElement; const getCurrent = () => (root.dataset.theme === 'dark' ? 'dark' : 'light'); setIcon(button, getCurrent()); button.addEventListener('click', async () => { const current = getCurrent(); const next = current === 'dark' ? 'light' : 'dark'; setTheme(next); setIcon(button, next); const ok = await updateTheme(button, next); if (!ok) { setTheme(current); setIcon(button, current); } }); }; if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', initThemeToggle); } else { initThemeToggle(); }