// frontend/src/context/ThemeContext.tsx import React, { createContext, useState, useEffect, useContext, useMemo } from 'react'; type Theme = 'light' | 'dark'; interface ThemeContextType { theme: Theme; toggleTheme: () => void; } // Creamos el contexto con un valor por defecto. const ThemeContext = createContext(undefined); // Creamos el proveedor del contexto. export const ThemeProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [theme, setTheme] = useState(() => { // 1. Intentamos leer el tema desde localStorage. const savedTheme = localStorage.getItem('theme') as Theme | null; if (savedTheme) return savedTheme; // 2. Si no hay nada, respetamos la preferencia del sistema operativo. if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { return 'dark'; } // 3. Como última opción, usamos el tema claro por defecto. return 'light'; }); useEffect(() => { // Aplicamos el tema al body y lo guardamos en localStorage cada vez que cambia. document.body.dataset.theme = theme; localStorage.setItem('theme', theme); }, [theme]); const toggleTheme = () => { setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light')); }; // Usamos useMemo para evitar que el valor del contexto se recalcule en cada render. const value = useMemo(() => ({ theme, toggleTheme }), [theme]); return ( {children} ); }; // Hook personalizado para usar el contexto de forma sencilla. export const useTheme = (): ThemeContextType => { const context = useContext(ThemeContext); if (!context) { throw new Error('useTheme debe ser utilizado dentro de un ThemeProvider'); } return context; };