From 1bec30544796d9ab28f1a15296805b01cb484517 Mon Sep 17 00:00:00 2001 From: Sergio Nicolas Lavaise Date: Tue, 14 Apr 2026 22:29:11 -0300 Subject: [PATCH] Implementar modo oscuro con toggle en sidebar --- src/App.tsx | 11 ++++++- src/contexts/ThemeContext.tsx | 40 ++++++++++++++++++++++++ src/sections/Layout.tsx | 59 ++++++++++++++++++++++++++--------- 3 files changed, 94 insertions(+), 16 deletions(-) create mode 100644 src/contexts/ThemeContext.tsx diff --git a/src/App.tsx b/src/App.tsx index 4e52897..8197b01 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,8 +12,9 @@ import { NuevoIngreso } from '@/sections/NuevoIngreso'; import { EditIngreso } from '@/sections/EditIngreso'; import { Spinner } from '@/components/ui/spinner'; import { Button } from '@/components/ui/button'; +import { ThemeProvider } from '@/contexts/ThemeContext'; -function App() { +function AppContent() { const store = useHospitalStore(); if (!store.isLoaded) { @@ -207,4 +208,12 @@ case 'nuevoingreso': ); } +function App() { + return ( + + + + ); +} + export default App; diff --git a/src/contexts/ThemeContext.tsx b/src/contexts/ThemeContext.tsx new file mode 100644 index 0000000..86a446c --- /dev/null +++ b/src/contexts/ThemeContext.tsx @@ -0,0 +1,40 @@ +import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'; + +interface ThemeContextType { + isDarkMode: boolean; + toggleDarkMode: () => void; +} + +const ThemeContext = createContext(undefined); + +export function ThemeProvider({ children }: { children: ReactNode }) { + const [isDarkMode, setIsDarkMode] = useState(() => { + const saved = localStorage.getItem('darkMode'); + return saved ? JSON.parse(saved) : false; + }); + + useEffect(() => { + localStorage.setItem('darkMode', JSON.stringify(isDarkMode)); + if (isDarkMode) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + }, [isDarkMode]); + + const toggleDarkMode = () => setIsDarkMode((prev: boolean) => !prev); + + return ( + + {children} + + ); +} + +export function useTheme() { + const context = useContext(ThemeContext); + if (!context) { + throw new Error('useTheme must be used within ThemeProvider'); + } + return context; +} \ No newline at end of file diff --git a/src/sections/Layout.tsx b/src/sections/Layout.tsx index 00068fa..509028e 100644 --- a/src/sections/Layout.tsx +++ b/src/sections/Layout.tsx @@ -7,10 +7,13 @@ import { FlaskConical, Activity, Microscope, - Menu + Menu, + Sun, + Moon } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet'; +import { useTheme } from '@/contexts/ThemeContext'; import type { Vista } from '@/types'; interface LayoutProps { @@ -31,6 +34,8 @@ const menuItems: { vista: Vista; label: string; icon: React.ElementType }[] = [ ]; export function Layout({ children, vistaActual, onCambiarVista }: LayoutProps) { + const { isDarkMode, toggleDarkMode } = useTheme(); + const NavContent = () => (