107 lines
3.6 KiB
TypeScript
107 lines
3.6 KiB
TypeScript
import React, { Suspense } from 'react';
|
|
import { createRoot } from 'react-dom/client';
|
|
import { RouterProvider } from 'react-router-dom';
|
|
import { Toaster } from 'react-hot-toast';
|
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
import { TamaguiProvider, Theme } from '@tamagui/core';
|
|
import '@tamagui/core/reset.css';
|
|
import tamaguiConfig from '../../../tamagui.config';
|
|
import { AuthProvider } from './auth/context';
|
|
import { router } from './router';
|
|
import '../../css/app.css';
|
|
import './i18n';
|
|
import './dev-tools';
|
|
import { AppearanceProvider, useAppearance, initializeTheme } from '@/hooks/use-appearance';
|
|
import { EventProvider } from './context/EventContext';
|
|
import MatomoTracker from '@/components/analytics/MatomoTracker';
|
|
import { ConsentProvider } from '@/contexts/consent';
|
|
import CookieBanner from '@/components/consent/CookieBanner';
|
|
import { Sentry, initSentry } from '@/lib/sentry';
|
|
import { prefetchMobileRoutes } from './mobile/prefetch';
|
|
|
|
const DevTenantSwitcher = React.lazy(() => import('./DevTenantSwitcher'));
|
|
|
|
const enableDevSwitcher = import.meta.env.DEV || import.meta.env.VITE_ENABLE_TENANT_SWITCHER === 'true';
|
|
|
|
initializeTheme();
|
|
initSentry('admin');
|
|
const rootEl = document.getElementById('root')!;
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
staleTime: 1000 * 60, // 1 minute
|
|
refetchOnWindowFocus: false,
|
|
refetchOnReconnect: false,
|
|
retry: 1,
|
|
},
|
|
mutations: {
|
|
retry: 1,
|
|
},
|
|
},
|
|
});
|
|
|
|
if ('serviceWorker' in navigator) {
|
|
window.addEventListener('load', () => {
|
|
navigator.serviceWorker.register('/admin-sw.js').catch(() => {});
|
|
});
|
|
}
|
|
|
|
const AdminFallback: React.FC<{ message: string }> = ({ message }) => (
|
|
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
|
|
{message}
|
|
</div>
|
|
);
|
|
|
|
createRoot(rootEl).render(
|
|
<React.StrictMode>
|
|
<Sentry.ErrorBoundary fallback={<AdminFallback message="Oberfläche konnte nicht geladen werden." />}>
|
|
<AppearanceProvider>
|
|
<AdminApp />
|
|
</AppearanceProvider>
|
|
</Sentry.ErrorBoundary>
|
|
</React.StrictMode>
|
|
);
|
|
|
|
function AdminApp() {
|
|
const { resolved } = useAppearance();
|
|
const themeName = resolved ?? 'light';
|
|
|
|
React.useEffect(() => {
|
|
prefetchMobileRoutes();
|
|
}, []);
|
|
|
|
return (
|
|
<TamaguiProvider config={tamaguiConfig} defaultTheme={themeName} themeClassNameOnRoot>
|
|
<Theme name={themeName}>
|
|
<ConsentProvider>
|
|
<QueryClientProvider client={queryClient}>
|
|
<AuthProvider>
|
|
<EventProvider>
|
|
<MatomoTracker config={(window as any).__MATOMO_ADMIN__} />
|
|
<Suspense
|
|
fallback={(
|
|
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
|
|
Oberfläche wird geladen …
|
|
</div>
|
|
)}
|
|
>
|
|
<div className="bg-[#FFF1E8] font-[Manrope] text-[14px] font-normal leading-[1.6] text-[#0B132B] dark:bg-[#0B132B] dark:text-slate-100">
|
|
<RouterProvider router={router} />
|
|
</div>
|
|
</Suspense>
|
|
</EventProvider>
|
|
</AuthProvider>
|
|
<CookieBanner />
|
|
<Toaster position="top-right" toastOptions={{ duration: 4000 }} />
|
|
{enableDevSwitcher ? (
|
|
<Suspense fallback={null}>
|
|
<DevTenantSwitcher />
|
|
</Suspense>
|
|
) : null}
|
|
</QueryClientProvider>
|
|
</ConsentProvider>
|
|
</Theme>
|
|
</TamaguiProvider>
|
|
);
|
|
}
|