152 lines
5.7 KiB
TypeScript
152 lines
5.7 KiB
TypeScript
import { lazy, Suspense } from 'react';
|
|
import { BrowserRouter, Routes, Route, Navigate, useNavigate, useLocation } from 'react-router-dom';
|
|
import { ConfigProvider, theme, App as AntdApp } from 'antd';
|
|
import deDE from 'antd/locale/de_DE';
|
|
import { AuthProvider, useAuth } from './auth/AuthContext';
|
|
import { saveReturnUrl } from './auth/sessionRedirect';
|
|
import { ThemeProvider, useTheme } from './theme/ThemeContext';
|
|
import AuthCallback from './auth/AuthCallback';
|
|
import AppLayout from './layouts/AppLayout';
|
|
import { Spin, Result, Button } from 'antd';
|
|
import type { ReactNode } from 'react';
|
|
|
|
const InboxPage = lazy(() => import('./pages/InboxPage'));
|
|
const InboxDetailPage = lazy(() => import('./pages/InboxDetailPage'));
|
|
const PosteingangPage = lazy(() => import('./pages/PosteingangPage'));
|
|
const ManuellBearbeitenPage = lazy(() => import('./pages/ManuellBearbeitenPage'));
|
|
const MailpostfachPage = lazy(() => import('./pages/MailpostfachPage'));
|
|
const MailDetailPage = lazy(() => import('./pages/MailDetailPage'));
|
|
const SettingsPage = lazy(() => import('./pages/SettingsPage'));
|
|
const UserSettingsPage = lazy(() => import('./pages/UserSettingsPage'));
|
|
const LoginPage = lazy(() => import('./pages/LoginPage'));
|
|
const DashboardPage = lazy(() => import('./pages/DashboardPage'));
|
|
import { Permission } from './auth/permissions';
|
|
|
|
function UnauthorizedPage() {
|
|
const navigate = useNavigate();
|
|
return (
|
|
<Result
|
|
status="403"
|
|
title="403"
|
|
subTitle="Entschuldigung, Sie haben keine Berechtigung, auf diese Seite zuzugreifen."
|
|
extra={<Button type="primary" onClick={() => navigate('/')}>Zurück zur Startseite</Button>}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function ProtectedRoute({ children }: { children: ReactNode }) {
|
|
const { isAuthenticated, isLoading } = useAuth();
|
|
const location = useLocation();
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
|
<Spin size="large" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!isAuthenticated) {
|
|
saveReturnUrl(location.pathname + location.search);
|
|
return <Navigate to="/login" replace />;
|
|
}
|
|
|
|
return <>{children}</>;
|
|
}
|
|
|
|
function PermissionRoute({ permission, children }: { permission: Permission; children: ReactNode }) {
|
|
const { hasPermission } = useAuth();
|
|
|
|
if (!hasPermission(permission)) {
|
|
return <UnauthorizedPage />;
|
|
}
|
|
return <>{children}</>;
|
|
}
|
|
|
|
function ThemedApp() {
|
|
const { isDark } = useTheme();
|
|
|
|
return (
|
|
<ConfigProvider
|
|
locale={deDE}
|
|
theme={{
|
|
algorithm: isDark ? theme.darkAlgorithm : theme.defaultAlgorithm,
|
|
token: {
|
|
colorPrimary: '#1677ff',
|
|
borderRadius: 6,
|
|
...(isDark
|
|
? {}
|
|
: {
|
|
// Extra-helles Light Theme — minimale Spiegelungsbelastung
|
|
colorBgContainer: '#ffffff',
|
|
colorBgElevated: '#ffffff',
|
|
colorBgLayout: '#f8f9fc',
|
|
colorBgBase: '#ffffff',
|
|
colorText: '#1a1a2e',
|
|
colorTextSecondary: '#4a4a6a',
|
|
colorBorder: '#e2e4ea',
|
|
colorBorderSecondary: '#ebedf2',
|
|
}),
|
|
},
|
|
components: isDark
|
|
? {}
|
|
: {
|
|
Layout: {
|
|
siderBg: '#f0f2f7',
|
|
headerBg: '#ffffff',
|
|
bodyBg: '#f8f9fc',
|
|
triggerBg: '#e2e4ea',
|
|
},
|
|
Menu: {
|
|
itemBg: 'transparent',
|
|
itemColor: '#4a4a6a',
|
|
itemSelectedBg: '#e6f0ff',
|
|
itemSelectedColor: '#1677ff',
|
|
itemHoverBg: '#eef1f8',
|
|
itemHoverColor: '#1a1a2e',
|
|
},
|
|
},
|
|
}}
|
|
>
|
|
<AuthProvider>
|
|
<AntdApp>
|
|
<BrowserRouter>
|
|
<Suspense fallback={<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}><Spin size="large" /></div>}>
|
|
<Routes>
|
|
<Route path="/login" element={<LoginPage />} />
|
|
<Route path="/auth/callback" element={<AuthCallback />} />
|
|
<Route
|
|
element={
|
|
<ProtectedRoute>
|
|
<AppLayout />
|
|
</ProtectedRoute>
|
|
}
|
|
>
|
|
<Route index element={<DashboardPage />} />
|
|
<Route path="/dashboard" element={<DashboardPage />} />
|
|
<Route path="/inbox" element={<PermissionRoute permission={Permission.VIEW_SCANNER}><InboxPage /></PermissionRoute>} />
|
|
<Route path="/inbox/:id" element={<PermissionRoute permission={Permission.VIEW_SCANNER}><InboxDetailPage /></PermissionRoute>} />
|
|
<Route path="/posteingang" element={<PermissionRoute permission={Permission.VIEW_INBOX}><PosteingangPage /></PermissionRoute>} />
|
|
<Route path="/manuell" element={<PermissionRoute permission={Permission.PROCESS_MANUALLY}><ManuellBearbeitenPage /></PermissionRoute>} />
|
|
<Route path="/mailpostfach" element={<PermissionRoute permission={Permission.VIEW_MAIL}><MailpostfachPage /></PermissionRoute>} />
|
|
<Route path="/mailpostfach/:id" element={<PermissionRoute permission={Permission.VIEW_MAIL}><MailDetailPage /></PermissionRoute>} />
|
|
<Route path="/settings" element={<PermissionRoute permission={Permission.MANAGE_SETTINGS}><SettingsPage /></PermissionRoute>} />
|
|
<Route path="/user-settings" element={<UserSettingsPage />} />
|
|
</Route>
|
|
</Routes>
|
|
</Suspense>
|
|
</BrowserRouter>
|
|
</AntdApp>
|
|
</AuthProvider>
|
|
</ConfigProvider>
|
|
);
|
|
}
|
|
|
|
export default function App() {
|
|
return (
|
|
<ThemeProvider>
|
|
<ThemedApp />
|
|
</ThemeProvider>
|
|
);
|
|
}
|