8b3873d676
TopBar: - Add Automation and Agenten to user dropdown menu Settings restructure: - Stammdaten: Firmendaten, Adressen (CRUD), Konten (CRUD), Sonstige Daten - Nutzerverwaltung: Benutzer, Rollen, Gruppen as tabs - System: Menü, Theme, Plugins as tabs - Reduce nav items from 15+ to 8 - Add end prop to all settings NavLinks
133 lines
8.6 KiB
TypeScript
133 lines
8.6 KiB
TypeScript
import React, { Suspense } from 'react';
|
|
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
|
|
import { AppShell } from '@/components/layout/AppShell';
|
|
import { ProtectedRoute } from './ProtectedRoute';
|
|
import { LoginPage } from '@/pages/Login';
|
|
import { PasswordResetRequestPage } from '@/pages/PasswordResetRequest';
|
|
import { PasswordResetConfirmPage } from '@/pages/PasswordResetConfirm';
|
|
import { Loader2 } from 'lucide-react';
|
|
import { PluginRouteRenderer } from '@/components/plugins/PluginRouteRenderer';
|
|
|
|
// Lazy-loaded pages (code-splitting)
|
|
const DashboardPage = React.lazy(() => import('@/pages/Dashboard').then(m => ({ default: m.DashboardPage })));
|
|
const ContactsListPage = React.lazy(() => import('@/pages/ContactsList').then(m => ({ default: m.ContactsListPage })));
|
|
const ContactDetailPage = React.lazy(() => import('@/pages/ContactDetailPage').then(m => ({ default: m.ContactDetailPage })));
|
|
const AuditLogPage = React.lazy(() => import('@/pages/AuditLog').then(m => ({ default: m.AuditLogPage })));
|
|
const GlobalSearchResultsPage = React.lazy(() => import('@/pages/GlobalSearchResults').then(m => ({ default: m.GlobalSearchResultsPage })));
|
|
const SettingsPage = React.lazy(() => import('@/pages/Settings').then(m => ({ default: m.SettingsPage })));
|
|
const SettingsProfilePage = React.lazy(() => import('@/pages/SettingsProfile').then(m => ({ default: m.SettingsProfilePage })));
|
|
const SettingsRolesPage = React.lazy(() => import('@/pages/SettingsRoles').then(m => ({ default: m.SettingsRolesPage })));
|
|
const SettingsUsersPage = React.lazy(() => import('@/pages/SettingsUsers').then(m => ({ default: m.SettingsUsersPage })));
|
|
const SettingsGroupsPage = React.lazy(() => import('@/pages/SettingsGroups').then(m => ({ default: m.SettingsGroupsPage })));
|
|
const SettingsPluginsPage = React.lazy(() => import('@/pages/SettingsPlugins').then(m => ({ default: m.SettingsPluginsPage })));
|
|
const SettingsSystemPage = React.lazy(() => import('@/pages/SettingsSystem').then(m => ({ default: m.SettingsSystemPage })));
|
|
const SettingsCurrenciesPage = React.lazy(() => import('@/pages/SettingsCurrencies').then(m => ({ default: m.SettingsCurrenciesPage })));
|
|
const SettingsTaxesPage = React.lazy(() => import('@/pages/SettingsTaxes').then(m => ({ default: m.SettingsTaxesPage })));
|
|
const SettingsSequencesPage = React.lazy(() => import('@/pages/SettingsSequences').then(m => ({ default: m.SettingsSequencesPage })));
|
|
const CalendarPage = React.lazy(() => import('@/pages/Calendar').then(m => ({ default: m.CalendarPage })));
|
|
const CalendarKanbanPage = React.lazy(() => import('@/pages/CalendarKanban').then(m => ({ default: m.CalendarKanbanPage })));
|
|
const DmsPage = React.lazy(() => import('@/pages/Dms').then(m => ({ default: m.DmsPage })));
|
|
const DmsTrashPage = React.lazy(() => import('@/pages/DmsTrash').then(m => ({ default: m.DmsTrashPage })));
|
|
const MailPage = React.lazy(() => import('@/pages/Mail').then(m => ({ default: m.MailPage })));
|
|
const MailSettingsPage = React.lazy(() => import('@/pages/MailSettings').then(m => ({ default: m.MailSettingsPage })));
|
|
const SettingsNotificationsPage = React.lazy(() => import('@/pages/SettingsNotifications').then(m => ({ default: m.SettingsNotificationsPage })));
|
|
const AIAssistantPage = React.lazy(() => import('@/pages/AIAssistant').then(m => ({ default: m.AIAssistantPage })));
|
|
const AISettingsPage = React.lazy(() => import('@/pages/AISettings').then(m => ({ default: m.AISettingsPage })));
|
|
const ProactiveAISettings = React.lazy(() => import('@/pages/ProactiveAISettings').then(m => ({ default: m.ProactiveAISettings })));
|
|
const SettingsThemePage = React.lazy(() => import('@/pages/SettingsTheme').then(m => ({ default: m.SettingsThemePage })));
|
|
const SettingsMcpPage = React.lazy(() => import('@/pages/SettingsMcp').then(m => ({ default: m.SettingsMcpPage })));
|
|
const SettingsMenuOrderPage = React.lazy(() => import('@/pages/SettingsMenuOrder').then(m => ({ default: m.SettingsMenuOrderPage })));
|
|
const SettingsStammdatenPage = React.lazy(() => import('@/pages/SettingsStammdaten').then(m => ({ default: m.SettingsStammdatenPage })));
|
|
const SettingsUserManagementPage = React.lazy(() => import('@/pages/SettingsUserManagement').then(m => ({ default: m.SettingsUserManagementPage })));
|
|
const AutomationDashboardPage = React.lazy(() => import('@/pages/AutomationDashboard').then(m => ({ default: m.AutomationDashboardPage })));
|
|
const AgentDashboardPage = React.lazy(() => import('@/pages/AgentDashboard').then(m => ({ default: m.AgentDashboardPage })));
|
|
const AutomationSettingsPage = React.lazy(() => import('@/pages/AutomationSettings').then(m => ({ default: m.AutomationSettingsPage })));
|
|
const ReportsPage = React.lazy(() => import('@/pages/Reports').then(m => ({ default: m.ReportsPage })));
|
|
const TasksPage = React.lazy(() => import('@/pages/Tasks').then(m => ({ default: m.TasksPage })));
|
|
|
|
/** Centered spinner fallback for lazy-loaded routes */
|
|
function PageLoader() {
|
|
return (
|
|
<div className="flex items-center justify-center min-h-[50vh]" role="status" aria-label="Seite wird geladen">
|
|
<Loader2 className="animate-spin h-8 w-8 text-primary-500" aria-hidden="true" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/** Wrap a lazy element in Suspense with PageLoader fallback */
|
|
function withSuspense(element: React.ReactElement) {
|
|
return <Suspense fallback={<PageLoader />}>{element}</Suspense>;
|
|
}
|
|
|
|
const router = createBrowserRouter([
|
|
{
|
|
path: '/login',
|
|
element: <LoginPage />,
|
|
},
|
|
{
|
|
path: '/password-reset',
|
|
element: <PasswordResetRequestPage />,
|
|
},
|
|
{
|
|
path: '/password-reset/confirm',
|
|
element: <PasswordResetConfirmPage />,
|
|
},
|
|
{
|
|
element: (
|
|
<ProtectedRoute>
|
|
<AppShell />
|
|
</ProtectedRoute>
|
|
),
|
|
children: [
|
|
{ path: '/', element: withSuspense(<DashboardPage />) },
|
|
{ path: '/dashboard', element: withSuspense(<DashboardPage />) },
|
|
{ path: '/contacts', element: withSuspense(<ContactsListPage />) },
|
|
{ path: '/contacts/:id', element: withSuspense(<ContactDetailPage />) },
|
|
{ path: '/audit-log', element: withSuspense(<AuditLogPage />) },
|
|
{ path: '/search', element: withSuspense(<GlobalSearchResultsPage />) },
|
|
{ path: '/calendar', element: withSuspense(<CalendarPage />) },
|
|
{ path: '/calendar/kanban', element: withSuspense(<CalendarKanbanPage />) },
|
|
{ path: '/dms', element: withSuspense(<DmsPage />) },
|
|
{ path: '/dms/trash', element: withSuspense(<DmsTrashPage />) },
|
|
{ path: '/mail', element: withSuspense(<MailPage />) },
|
|
{ path: '/mail/settings', element: withSuspense(<MailSettingsPage />) },
|
|
{ path: '/ai-assistant', element: withSuspense(<AIAssistantPage />) },
|
|
{ path: '/automation', element: withSuspense(<AutomationDashboardPage />) },
|
|
{ path: '/agents', element: withSuspense(<AgentDashboardPage />) },
|
|
{ path: '/reports', element: withSuspense(<ReportsPage />) },
|
|
{ path: '/tasks', element: withSuspense(<TasksPage />) },
|
|
{ path: '/profile', element: withSuspense(<SettingsProfilePage />) },
|
|
{
|
|
path: '/settings',
|
|
element: withSuspense(<SettingsPage />),
|
|
children: [
|
|
{ path: 'stammdaten', element: withSuspense(<SettingsStammdatenPage />) },
|
|
{ path: 'user-management', element: withSuspense(<SettingsUserManagementPage />) },
|
|
{ path: 'roles', element: withSuspense(<SettingsRolesPage />) },
|
|
{ path: 'users', element: withSuspense(<SettingsUsersPage />) },
|
|
{ path: 'groups', element: withSuspense(<SettingsGroupsPage />) },
|
|
{ path: 'plugins', element: withSuspense(<SettingsPluginsPage />) },
|
|
{ path: 'system', element: withSuspense(<SettingsSystemPage />) },
|
|
{ path: 'currencies', element: withSuspense(<SettingsCurrenciesPage />) },
|
|
{ path: 'taxes', element: withSuspense(<SettingsTaxesPage />) },
|
|
{ path: 'sequences', element: withSuspense(<SettingsSequencesPage />) },
|
|
{ path: 'mail', element: withSuspense(<MailSettingsPage />) },
|
|
{ path: 'notifications', element: withSuspense(<SettingsNotificationsPage />) },
|
|
{ path: 'ai', element: withSuspense(<AISettingsPage />) },
|
|
{ path: 'ai-proactive', element: withSuspense(<ProactiveAISettings />) },
|
|
{ path: 'theme', element: withSuspense(<SettingsThemePage />) },
|
|
{ path: 'automation', element: withSuspense(<AutomationSettingsPage />) },
|
|
{ path: 'mcp', element: withSuspense(<SettingsMcpPage />) },
|
|
{ path: 'menu', element: withSuspense(<SettingsMenuOrderPage />) },
|
|
{ path: '*', element: <PluginRouteRenderer /> },
|
|
],
|
|
},
|
|
{ path: '*', element: <PluginRouteRenderer /> },
|
|
],
|
|
},
|
|
]);
|
|
|
|
export function AppRouter() {
|
|
return <RouterProvider router={router} />;
|
|
}
|