Files
fotospiel-app/resources/js/app.tsx
2025-12-19 10:13:30 +01:00

96 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import '../css/app.css';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot } from 'react-dom/client';
import { AppearanceProvider, initializeTheme } from './hooks/use-appearance';
import AppLayout from './layouts/app/AppLayout';
import { I18nextProvider } from 'react-i18next';
import i18n from './i18n';
import { Toaster } from 'react-hot-toast';
import { ConsentProvider } from './contexts/consent';
import CookieBanner from '@/components/consent/CookieBanner';
import React from 'react';
import { usePage } from '@inertiajs/react';
import { useEffect } from 'react';
import { Sentry, initSentry } from './lib/sentry';
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
const InertiaFallback: React.FC = () => (
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
Oberfläche konnte nicht geladen werden.
</div>
);
initSentry('inertia');
const LocaleSync: React.FC<{ children: React.ReactNode }> = ({ children }) => {
// usePage is only available inside Inertia-provided tree; guard for SSR/raw mounts
try {
const { props } = usePage<{ locale?: string }>();
useEffect(() => {
if (props.locale && i18n.language !== props.locale) {
i18n.changeLanguage(props.locale);
}
}, [props.locale]);
} catch (error) {
// noop will be hydrated once Inertia provides context
}
return <>{children}</>;
};
createInertiaApp({
title: (title) => title ? `${title} - ${appName}` : appName,
resolve: (name) =>
resolvePageComponent(
`./pages/${name}.tsx`,
import.meta.glob('./pages/**/*.tsx')
).then((page) => {
const resolved = page as { default?: { layout?: (page: React.ReactNode) => React.ReactNode } };
if (resolved?.default) {
const Component = resolved.default;
if (!Component.layout) {
Component.layout = (node: React.ReactNode) => <AppLayout>{node}</AppLayout>;
}
}
return resolved;
}),
setup({ el, App, props }) {
const root = createRoot(el);
// Sync i18n with initial locale from props
if (
props.initialPage &&
props.initialPage.props &&
typeof props.initialPage.props.locale === 'string'
) {
i18n.changeLanguage(props.initialPage.props.locale);
}
root.render(
<Sentry.ErrorBoundary fallback={<InertiaFallback />}>
<AppearanceProvider>
<ConsentProvider>
<I18nextProvider i18n={i18n}>
<LocaleSync>
<App {...props} />
</LocaleSync>
<CookieBanner />
<Toaster position="top-right" toastOptions={{ duration: 4000 }} />
</I18nextProvider>
</ConsentProvider>
</AppearanceProvider>
</Sentry.ErrorBoundary>
);
},
progress: {
color: '#4B5563',
},
});
// This will set light / dark mode on load...
initializeTheme();