import { useState, useEffect } from 'react'; import { Routes, Route, NavLink } from 'react-router-dom'; import { Sun, Moon, Settings } from 'lucide-react'; import DashboardPage from './pages/DashboardPage'; import MatchesPage from './pages/MatchesPage'; import LeaderboardPage from './pages/LeaderboardPage'; import ProfilePage from './pages/ProfilePage'; import AdminPage from './pages/AdminPage'; import BottomNav from './components/BottomNav'; import styles from './App.module.css'; const IS_DEV = import.meta.env.DEV || import.meta.env.VITE_TEST_MODE === 'true'; // Lazy-load DevPanel in Development/Test-Mode let DevPanel: React.ComponentType | null = null; // VITE_TEST_MODE wird erst zur Laufzeit geprüft, daher Import immer einbinden import('./components/DevPanel').then(m => { DevPanel = m.default; }).catch(() => {}); type Theme = 'dark' | 'light'; function getInitialTheme(): Theme { try { const stored = localStorage.getItem('theme') as Theme | null; if (stored === 'light' || stored === 'dark') return stored; } catch {} return 'dark'; } export default function App() { const [theme, setTheme] = useState(getInitialTheme); const [devUser, setDevUser] = useState(1); const [devMatches, setDevMatches] = useState([]); const [refreshKey, setRefreshKey] = useState(0); // Theme auf setzen und in localStorage speichern useEffect(() => { document.documentElement.setAttribute('data-theme', theme); try { localStorage.setItem('theme', theme); } catch {} }, [theme]); function toggleTheme() { setTheme(t => t === 'dark' ? 'light' : 'dark'); } // DevUser als Query-Parameter im API-Fetch setzen useEffect(() => { if (!IS_DEV) return; // Patch fetch für Dev-Mode: devUser Query-Param anhängen const origFetch = window.fetch; window._devUser = devUser; window.fetch = (input, init) => { if (typeof input === 'string' && input.startsWith('/api')) { const url = new URL(input, window.location.origin); url.searchParams.set('devUser', String(window._devUser ?? 1)); return origFetch(url.toString(), init); } return origFetch(input, init); }; return () => { window.fetch = origFetch; }; }, [devUser]); // Matches für DevPanel laden useEffect(() => { if (!IS_DEV) return; fetch('/api/matches').then(r => r.json()).then(d => setDevMatches(d.matches ?? [])).catch(() => {}); }, [refreshKey, devUser]); function handleDevRefresh() { setRefreshKey(k => k + 1); } return (
🏆 WM 2026 Tippspiel {IS_DEV && ( DEV · User {devUser} )}
} /> } /> } /> } /> } />
{IS_DEV && DevPanel && ( { setDevUser(u); setRefreshKey(k => k + 1); }} matches={devMatches} onRefresh={handleDevRefresh} /> )}
); }