Phase 2: Code-Splitting + Virtual Scrolling (Tasks 2.1-2.7)
This commit is contained in:
@@ -1,35 +1,52 @@
|
||||
import React from 'react';
|
||||
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 { DashboardPage } from '@/pages/Dashboard';
|
||||
import { ContactsListPage } from '@/pages/ContactsList';
|
||||
import { AuditLogPage } from '@/pages/AuditLog';
|
||||
import { GlobalSearchResultsPage } from '@/pages/GlobalSearchResults';
|
||||
import { SettingsPage } from '@/pages/Settings';
|
||||
import { SettingsProfilePage } from '@/pages/SettingsProfile';
|
||||
import { SettingsRolesPage } from '@/pages/SettingsRoles';
|
||||
import { SettingsUsersPage } from '@/pages/SettingsUsers';
|
||||
import { SettingsGroupsPage } from '@/pages/SettingsGroups';
|
||||
import { SettingsPluginsPage } from '@/pages/SettingsPlugins';
|
||||
import { SettingsSystemPage } from '@/pages/SettingsSystem';
|
||||
import { SettingsCurrenciesPage } from '@/pages/SettingsCurrencies';
|
||||
import { SettingsTaxesPage } from '@/pages/SettingsTaxes';
|
||||
import { SettingsSequencesPage } from '@/pages/SettingsSequences';
|
||||
import { CalendarPage } from '@/pages/Calendar';
|
||||
import { CalendarKanbanPage } from '@/pages/CalendarKanban';
|
||||
import { DmsPage } from '@/pages/Dms';
|
||||
import { DmsTrashPage } from '@/pages/DmsTrash';
|
||||
import { MailPage } from '@/pages/Mail';
|
||||
import { MailSettingsPage } from '@/pages/MailSettings';
|
||||
import { SettingsNotificationsPage } from '@/pages/SettingsNotifications';
|
||||
import { AIAssistantPage } from '@/pages/AIAssistant';
|
||||
import { AISettingsPage } from '@/pages/AISettings';
|
||||
import { ProactiveAISettings } from '@/pages/ProactiveAISettings';
|
||||
import { SettingsThemePage } from '@/pages/SettingsTheme';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
// 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 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 })));
|
||||
|
||||
/** 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([
|
||||
{
|
||||
@@ -51,36 +68,36 @@ const router = createBrowserRouter([
|
||||
</ProtectedRoute>
|
||||
),
|
||||
children: [
|
||||
{ path: '/', element: <DashboardPage /> },
|
||||
{ path: '/dashboard', element: <DashboardPage /> },
|
||||
{ path: '/contacts', element: <ContactsListPage /> },
|
||||
{ path: '/audit-log', element: <AuditLogPage /> },
|
||||
{ path: '/search', element: <GlobalSearchResultsPage /> },
|
||||
{ path: '/calendar', element: <CalendarPage /> },
|
||||
{ path: '/calendar/kanban', element: <CalendarKanbanPage /> },
|
||||
{ path: '/dms', element: <DmsPage /> },
|
||||
{ path: '/dms/trash', element: <DmsTrashPage /> },
|
||||
{ path: '/mail', element: <MailPage /> },
|
||||
{ path: '/mail/settings', element: <MailSettingsPage /> },
|
||||
{ path: '/ai-assistant', element: <AIAssistantPage /> },
|
||||
{ path: '/profile', element: <SettingsProfilePage /> },
|
||||
{ path: '/', element: withSuspense(<DashboardPage />) },
|
||||
{ path: '/dashboard', element: withSuspense(<DashboardPage />) },
|
||||
{ path: '/contacts', element: withSuspense(<ContactsListPage />) },
|
||||
{ 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: '/profile', element: withSuspense(<SettingsProfilePage />) },
|
||||
{
|
||||
path: '/settings',
|
||||
element: <SettingsPage />,
|
||||
element: withSuspense(<SettingsPage />),
|
||||
children: [
|
||||
{ path: 'roles', element: <SettingsRolesPage /> },
|
||||
{ path: 'users', element: <SettingsUsersPage /> },
|
||||
{ path: 'groups', element: <SettingsGroupsPage /> },
|
||||
{ path: 'plugins', element: <SettingsPluginsPage /> },
|
||||
{ path: 'system', element: <SettingsSystemPage /> },
|
||||
{ path: 'currencies', element: <SettingsCurrenciesPage /> },
|
||||
{ path: 'taxes', element: <SettingsTaxesPage /> },
|
||||
{ path: 'sequences', element: <SettingsSequencesPage /> },
|
||||
{ path: 'mail', element: <MailSettingsPage /> },
|
||||
{ path: 'notifications', element: <SettingsNotificationsPage /> },
|
||||
{ path: 'ai', element: <AISettingsPage /> },
|
||||
{ path: 'ai-proactive', element: <ProactiveAISettings /> },
|
||||
{ path: 'theme', element: <SettingsThemePage /> },
|
||||
{ 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 />) },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user