89 lines
3.2 KiB
JavaScript
89 lines
3.2 KiB
JavaScript
/**
|
|
* Theme Toggle Manager - Edu-Space Admin
|
|
* Manejo de Modo Claro y Modo Oscuro con persistencia en localStorage y anti-flickering.
|
|
*/
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
// 1. Obtener tema almacenado o preferencia del sistema
|
|
function getPreferredTheme() {
|
|
const storedTheme = localStorage.getItem('theme');
|
|
if (storedTheme) {
|
|
return storedTheme;
|
|
}
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
}
|
|
|
|
// 2. Aplicar tema al elemento <html>
|
|
function applyTheme(theme) {
|
|
document.documentElement.setAttribute('data-bs-theme', theme);
|
|
updateToggleButtons(theme);
|
|
}
|
|
|
|
// 3. Actualizar iconos de los botones de toggle
|
|
function updateToggleButtons(theme) {
|
|
const buttons = document.querySelectorAll('.theme-toggle-btn');
|
|
buttons.forEach(btn => {
|
|
const icon = btn.querySelector('i');
|
|
if (icon) {
|
|
if (theme === 'dark') {
|
|
icon.className = 'bi bi-sun-fill';
|
|
btn.setAttribute('aria-label', 'Cambiar a modo claro');
|
|
btn.setAttribute('title', 'Modo Claro');
|
|
} else {
|
|
icon.className = 'bi bi-moon-stars-fill';
|
|
btn.setAttribute('aria-label', 'Cambiar a modo oscuro');
|
|
btn.setAttribute('title', 'Modo Oscuro');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// 4. Función global para alternar tema
|
|
window.toggleTheme = function() {
|
|
const currentTheme = document.documentElement.getAttribute('data-bs-theme') || getPreferredTheme();
|
|
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
|
|
|
localStorage.setItem('theme', newTheme);
|
|
applyTheme(newTheme);
|
|
|
|
// Si el usuario está autenticado, sincronizar asíncronamente con su perfil en el backend
|
|
if (document.body && document.body.getAttribute('data-user-authenticated') === 'true') {
|
|
fetch('/api/user/theme', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify({ theme: newTheme })
|
|
}).catch(err => {
|
|
console.warn('No se pudo sincronizar el tema con el servidor:', err);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
// 5. Inicializar tema inmediatamente (anti-flicker)
|
|
const initialTheme = getPreferredTheme();
|
|
applyTheme(initialTheme);
|
|
|
|
// 6. Al cargar el DOM, registrar eventos en los botones de toggle
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
updateToggleButtons(document.documentElement.getAttribute('data-bs-theme') || initialTheme);
|
|
|
|
document.querySelectorAll('.theme-toggle-btn').forEach(btn => {
|
|
btn.addEventListener('click', (e) => {
|
|
e.preventDefault();
|
|
window.toggleTheme();
|
|
});
|
|
});
|
|
});
|
|
|
|
// 7. Escuchar cambios de preferencia del sistema si el usuario no fijó una manual
|
|
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
|
if (!localStorage.getItem('theme')) {
|
|
applyTheme(e.matches ? 'dark' : 'light');
|
|
}
|
|
});
|
|
})();
|