mirror of
https://github.com/complexcaresolutions/dak.c2s.git
synced 2026-03-17 19:33:41 +00:00
feat: add dark mode toggle in header and login page
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
9d79ba35bc
commit
1edf5835be
3 changed files with 50 additions and 2 deletions
|
|
@ -18,7 +18,8 @@ import {
|
|||
} from '@/components/ui/popover'
|
||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import { Separator } from '@/components/ui/separator'
|
||||
import { Bell, CheckCheck, LogOut, Menu } from 'lucide-react'
|
||||
import { Bell, CheckCheck, LogOut, Menu, Moon, Sun } from 'lucide-react'
|
||||
import { useTheme } from '@/hooks/useTheme'
|
||||
|
||||
interface HeaderProps {
|
||||
onToggleSidebar: () => void
|
||||
|
|
@ -27,6 +28,7 @@ interface HeaderProps {
|
|||
export function Header({ onToggleSidebar }: HeaderProps) {
|
||||
const { user, logout } = useAuth()
|
||||
const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications()
|
||||
const { theme, toggleTheme } = useTheme()
|
||||
|
||||
const initials = user?.username
|
||||
? user.username
|
||||
|
|
@ -54,6 +56,12 @@ export function Header({ onToggleSidebar }: HeaderProps) {
|
|||
|
||||
<div className="flex-1" />
|
||||
|
||||
{/* Dark mode toggle */}
|
||||
<Button variant="ghost" size="icon" onClick={toggleTheme}>
|
||||
{theme === 'dark' ? <Sun className="h-5 w-5" /> : <Moon className="h-5 w-5" />}
|
||||
<span className="sr-only">Design umschalten</span>
|
||||
</Button>
|
||||
|
||||
{/* Notification bell with dropdown */}
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
|
|
|
|||
29
frontend/src/hooks/useTheme.ts
Normal file
29
frontend/src/hooks/useTheme.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
import { useCallback, useEffect, useState } from 'react'
|
||||
|
||||
type Theme = 'light' | 'dark'
|
||||
|
||||
const STORAGE_KEY = 'dak-theme'
|
||||
|
||||
export function useTheme() {
|
||||
const [theme, setThemeState] = useState<Theme>(() => {
|
||||
const stored = localStorage.getItem(STORAGE_KEY)
|
||||
if (stored === 'dark' || stored === 'light') return stored
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
const root = document.documentElement
|
||||
if (theme === 'dark') {
|
||||
root.classList.add('dark')
|
||||
} else {
|
||||
root.classList.remove('dark')
|
||||
}
|
||||
localStorage.setItem(STORAGE_KEY, theme)
|
||||
}, [theme])
|
||||
|
||||
const toggleTheme = useCallback(() => {
|
||||
setThemeState((prev) => (prev === 'dark' ? 'light' : 'dark'))
|
||||
}, [])
|
||||
|
||||
return { theme, toggleTheme }
|
||||
}
|
||||
|
|
@ -9,7 +9,8 @@ import { Input } from '@/components/ui/input'
|
|||
import { Button } from '@/components/ui/button'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { AlertCircle, Loader2 } from 'lucide-react'
|
||||
import { AlertCircle, Loader2, Moon, Sun } from 'lucide-react'
|
||||
import { useTheme } from '@/hooks/useTheme'
|
||||
|
||||
const loginSchema = z.object({
|
||||
email: z.string().email('Bitte geben Sie eine gueltige E-Mail-Adresse ein'),
|
||||
|
|
@ -21,6 +22,7 @@ type LoginFormValues = z.infer<typeof loginSchema>
|
|||
|
||||
export function LoginPage() {
|
||||
const { login } = useAuth()
|
||||
const { theme, toggleTheme } = useTheme()
|
||||
const navigate = useNavigate()
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [showMfa, setShowMfa] = useState(false)
|
||||
|
|
@ -70,6 +72,15 @@ export function LoginPage() {
|
|||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-background px-4">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={toggleTheme}
|
||||
className="absolute top-4 right-4"
|
||||
>
|
||||
{theme === 'dark' ? <Sun className="h-5 w-5" /> : <Moon className="h-5 w-5" />}
|
||||
<span className="sr-only">Design umschalten</span>
|
||||
</Button>
|
||||
<Card className="w-full max-w-md">
|
||||
<CardHeader className="text-center">
|
||||
<CardTitle className="text-2xl">DAK Portal</CardTitle>
|
||||
|
|
|
|||
Loading…
Reference in a new issue