noscript varianten eingebaut, matomo integration erweitert und als konfiguration aufgenommen.
This commit is contained in:
@@ -200,30 +200,6 @@ export function DashboardEventFocusCard({
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{limitWarnings.length > 0 && (
|
||||
<div className="grid gap-3 md:grid-cols-2">
|
||||
{limitWarnings.map((warning) => (
|
||||
<Alert
|
||||
key={warning.id}
|
||||
variant={warning.tone === 'danger' ? 'destructive' : 'default'}
|
||||
className={warning.tone === 'warning' ? 'border-amber-400/50 bg-amber-50 text-amber-900 dark:border-amber-300/40 dark:bg-amber-500/10 dark:text-amber-100' : undefined}
|
||||
>
|
||||
<AlertTitle className="flex items-center gap-2 text-sm font-semibold">
|
||||
<AlertTriangle className="h-4 w-4" />
|
||||
{t(`limitWarnings.${warning.scope}`, {
|
||||
defaultValue:
|
||||
warning.scope === 'photos'
|
||||
? 'Fotos'
|
||||
: warning.scope === 'guests'
|
||||
? 'Gäste'
|
||||
: 'Galerie',
|
||||
})}
|
||||
</AlertTitle>
|
||||
<AlertDescription className="text-sm">{warning.message}</AlertDescription>
|
||||
</Alert>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@
|
||||
},
|
||||
"limits": {
|
||||
"photosTitle": "Foto-Limit",
|
||||
"photosWarning": "Nur noch {remaining} von {limit} Foto-Uploads verfügbar.",
|
||||
"photosWarning": "Nur noch {{remaining}} von {{limit}} Foto-Uploads verfügbar.",
|
||||
"photosBlocked": "Foto-Uploads sind blockiert. Bitte Paket upgraden oder erweitern.",
|
||||
"guestsTitle": "Gäste-Limit",
|
||||
"guestsWarning": "Nur noch {remaining} von {limit} Gästelinks verfügbar.",
|
||||
"guestsWarning": "Nur noch {{remaining}} von {{limit}} Gästelinks verfügbar.",
|
||||
"guestsBlocked": "Alle Gästeplätze sind belegt. Upgrade euer Paket oder erweitert das Kontingent, um weitere Gäste zuzulassen.",
|
||||
"galleryTitle": "Galerie",
|
||||
"galleryWarningDay": "Galerie läuft in {days} Tag ab.",
|
||||
|
||||
@@ -71,10 +71,10 @@
|
||||
},
|
||||
"limits": {
|
||||
"photosTitle": "Photo limit",
|
||||
"photosWarning": "Only {remaining} of {limit} photo uploads remaining.",
|
||||
"photosWarning": "Only {{remaining}} of {{limit}} photo uploads remaining.",
|
||||
"photosBlocked": "Photo uploads are blocked. Please upgrade or extend your package.",
|
||||
"guestsTitle": "Guest limit",
|
||||
"guestsWarning": "Only {remaining} of {limit} guest invites remaining.",
|
||||
"guestsWarning": "Only {{remaining}} of {{limit}} guest invites remaining.",
|
||||
"guestsBlocked": "All guest slots are filled. Upgrade your package or extend the quota to welcome more guests.",
|
||||
"galleryTitle": "Gallery",
|
||||
"galleryWarningDay": "Gallery expires in {days} day.",
|
||||
|
||||
@@ -11,6 +11,9 @@ import './dev-tools';
|
||||
import { initializeTheme } from '@/hooks/use-appearance';
|
||||
import { OnboardingProgressProvider } from './onboarding';
|
||||
import { EventProvider } from './context/EventContext';
|
||||
import MatomoTracker from '@/components/analytics/MatomoTracker';
|
||||
import { ConsentProvider } from '@/contexts/consent';
|
||||
import CookieBanner from '@/components/consent/CookieBanner';
|
||||
|
||||
const DevTenantSwitcher = React.lazy(() => import('./components/DevTenantSwitcher'));
|
||||
|
||||
@@ -40,28 +43,32 @@ if ('serviceWorker' in navigator) {
|
||||
|
||||
createRoot(rootEl).render(
|
||||
<React.StrictMode>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
<EventProvider>
|
||||
<OnboardingProgressProvider>
|
||||
<Suspense
|
||||
fallback={(
|
||||
<div className="flex min-h-screen items-center justify-center text-sm text-muted-foreground">
|
||||
Oberfläche wird geladen …
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<RouterProvider router={router} />
|
||||
</Suspense>
|
||||
</OnboardingProgressProvider>
|
||||
</EventProvider>
|
||||
</AuthProvider>
|
||||
<Toaster position="top-right" toastOptions={{ duration: 4000 }} />
|
||||
{enableDevSwitcher ? (
|
||||
<Suspense fallback={null}>
|
||||
<DevTenantSwitcher />
|
||||
</Suspense>
|
||||
) : null}
|
||||
</QueryClientProvider>
|
||||
<ConsentProvider>
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<AuthProvider>
|
||||
<EventProvider>
|
||||
<OnboardingProgressProvider>
|
||||
<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>
|
||||
)}
|
||||
>
|
||||
<RouterProvider router={router} />
|
||||
</Suspense>
|
||||
</OnboardingProgressProvider>
|
||||
</EventProvider>
|
||||
</AuthProvider>
|
||||
<CookieBanner />
|
||||
<Toaster position="top-right" toastOptions={{ duration: 4000 }} />
|
||||
{enableDevSwitcher ? (
|
||||
<Suspense fallback={null}>
|
||||
<DevTenantSwitcher />
|
||||
</Suspense>
|
||||
) : null}
|
||||
</QueryClientProvider>
|
||||
</ConsentProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
@@ -13,8 +13,6 @@ import {
|
||||
ClipboardList,
|
||||
Package as PackageIcon,
|
||||
} from 'lucide-react';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@@ -254,20 +252,7 @@ export default function DashboardPage() {
|
||||
|
||||
const shownToastsRef = React.useRef<Set<string>>(new Set());
|
||||
|
||||
React.useEffect(() => {
|
||||
limitWarnings.forEach((warning) => {
|
||||
const toastKey = `${warning.id}-${warning.message}`;
|
||||
if (shownToastsRef.current.has(toastKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
shownToastsRef.current.add(toastKey);
|
||||
toast(warning.message, {
|
||||
icon: warning.tone === 'danger' ? '🚨' : '⚠️',
|
||||
id: toastKey,
|
||||
});
|
||||
});
|
||||
}, [limitWarnings]);
|
||||
// Limit warnings werden ausschließlich in der Limits-Karte angezeigt; keine Toasts mehr
|
||||
|
||||
const limitScopeLabels = React.useMemo(
|
||||
() => ({
|
||||
@@ -533,13 +518,6 @@ export default function DashboardPage() {
|
||||
|
||||
return (
|
||||
<AdminLayout title={adminTitle} subtitle={adminSubtitle}>
|
||||
{errorMessage && (
|
||||
<Alert variant="destructive">
|
||||
<AlertTitle>{t('dashboard.alerts.errorTitle')}</AlertTitle>
|
||||
<AlertDescription>{errorMessage}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{loading ? (
|
||||
<DashboardSkeleton />
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user