import React from 'react' import { RouterProvider, createBrowserRouter, Navigate, NavLink, useLocation, Outlet, } from 'react-router-dom' import { AuthProvider, useAuth } from './context/AuthContext' import { ToastProvider } from './context/ToastContext' import { OrgInboxProvider, useOrgInbox } from './context/OrgInboxContext' import DesktopSidebar from './components/DesktopSidebar' import { getMainNavItems } from './config/appNav' import LoginPage from './pages/LoginPage' import VerifyPage from './pages/VerifyPage' import Dashboard from './pages/Dashboard' import AccountSettingsPage from './pages/AccountSettingsPage' import SettingsSystemInfoPage from './pages/SettingsSystemInfoPage' import ExercisesListPage from './pages/ExercisesListPage' import ExerciseDetailPage from './pages/ExerciseDetailPage' import ExerciseFormPage from './pages/ExerciseFormPage' import ClubsPage from './pages/ClubsPage' import InboxPage from './pages/InboxPage' import SkillsPage from './pages/SkillsPage' import TrainingPlanningPage from './pages/TrainingPlanningPage' import TrainingFrameworkProgramsListPage from './pages/TrainingFrameworkProgramsListPage' import TrainingFrameworkProgramEditPage from './pages/TrainingFrameworkProgramEditPage' import TrainingModulesListPage from './pages/TrainingModulesListPage' import TrainingModuleEditPage from './pages/TrainingModuleEditPage' import TrainingUnitRunPage from './pages/TrainingUnitRunPage' import TrainingCoachPage from './pages/TrainingCoachPage' import AdminCatalogsPage from './pages/AdminCatalogsPage' import AdminHierarchyPage from './pages/AdminHierarchyPage' import AdminMaturityModelsPage from './pages/AdminMaturityModelsPage' import TrainerContextsPage from './pages/TrainerContextsPage' import MediaWikiImportPage from './pages/MediaWikiImportPage' import AdminUsersPage from './pages/AdminUsersPage' import AdminHomeRedirect from './components/AdminHomeRedirect' import PlatformAdminRoute from './components/PlatformAdminRoute' import MediaLibraryPage from './pages/MediaLibraryPage' import LegalPage from './pages/LegalPage' import AdminLegalDocumentsPage from './pages/AdminLegalDocumentsPage' import SettingsLegalPage from './pages/SettingsLegalPage' import ActiveClubSwitcher from './components/ActiveClubSwitcher' import InactiveMembershipBanner from './components/InactiveMembershipBanner' import './app.css' /** Shield „Admin“: nur Super-Admin (global). Vereinsorga: Vereine → Mitglieder. */ function computeShowAdminNav(currentUser) { return currentUser?.role === 'superadmin' } // Bottom Navigation (Mobile) function Nav({ showAdminNav }) { const { canAccessOrgInbox, inboxCount } = useOrgInbox() const items = getMainNavItems(showAdminNav, { showInbox: canAccessOrgInbox }) const loc = useLocation() const navItemActive = (pathname, item, routerIsActive) => { if (item.to.startsWith('/admin')) return pathname.startsWith('/admin') return routerIsActive } return ( ) } function ProtectedLayout() { const { isAuthenticated, loading, user, logout } = useAuth() const handleLogout = () => { if (confirm('Wirklich abmelden?')) { logout() window.location.href = '/' } } if (loading) { return (
) } if (!isAuthenticated) { return } const showAdminNav = computeShowAdminNav(user) return (
🥋 Shinkan
) } function PublicRoute({ children }) { const { isAuthenticated, loading } = useAuth() if (loading) { return (
) } return !isAuthenticated ? children : } /** * Data Router — erforderlich für `useBlocker` (ungespeicherte Änderungen). * Klassisches `BrowserRouter` stellt keinen DataRouterContext bereit; ohne Migration * werfen Seiten mit `useUnsavedChangesBlocker` beim Rendern eine Invariante. */ const appRouter = createBrowserRouter([ { path: '/verify', element: }, { path: '/login', element: ( ), }, { path: '/impressum', element: }, { path: '/datenschutz', element: }, { path: '/nutzungsbedingungen', element: }, { path: '/medienrichtlinie', element: }, { element: , children: [ { index: true, element: }, { path: 'profile', element: }, { path: 'settings', element: }, { path: 'settings/system', element: }, { path: 'settings/legal', element: }, { path: 'media', element: }, { path: 'exercises', children: [ { index: true, element: }, { path: 'new', element: }, { path: ':id/edit', element: }, { path: ':id', element: }, ], }, { path: 'clubs', element: }, { path: 'inbox', element: }, { path: 'skills', element: }, { path: 'planning/framework-programs/new', element: }, { path: 'planning/framework-programs/:id', element: }, { path: 'planning/framework-programs', element: }, { path: 'planning/training-modules/new', element: }, { path: 'planning/training-modules/:id', element: }, { path: 'planning/training-modules', element: }, { path: 'planning/run/:unitId/coach', element: }, { path: 'planning/run/:unitId', element: }, { path: 'planning', element: }, { path: 'admin', element: }, { path: 'admin/users', element: ( ), }, { path: 'admin/hierarchy', element: ( ), }, { path: 'admin/maturity-models', element: ( ), }, { path: 'admin/catalogs', element: ( ), }, { path: 'admin/mediawiki-import', element: ( ), }, { path: 'admin/legal-documents', element: ( ), }, { path: 'trainer-contexts', element: }, ], }, { path: '*', element: }, ]) function App() { return ( ) } export default App