99 lines
3.3 KiB
TypeScript
99 lines
3.3 KiB
TypeScript
/**
|
|
* @ai-summary React 19 Suspense wrapper components for different UI sections
|
|
* @ai-context Reusable Suspense boundaries with appropriate fallbacks
|
|
*/
|
|
|
|
import React, { Suspense } from 'react';
|
|
import { VehicleListSkeleton } from '../shared-minimal/components/skeletons/VehicleListSkeleton';
|
|
import { VehicleCardSkeleton } from '../shared-minimal/components/skeletons/VehicleCardSkeleton';
|
|
import { MobileVehiclesSkeleton } from '../shared-minimal/components/skeletons/MobileVehiclesSkeleton';
|
|
import { Box, Skeleton } from '@mui/material';
|
|
|
|
interface SuspenseWrapperProps {
|
|
children: React.ReactNode;
|
|
}
|
|
|
|
// Vehicle list suspense for desktop
|
|
export const VehicleListSuspense: React.FC<SuspenseWrapperProps> = ({ children }) => (
|
|
<Suspense fallback={<VehicleListSkeleton />}>
|
|
{children}
|
|
</Suspense>
|
|
);
|
|
|
|
// Individual vehicle card suspense
|
|
export const VehicleCardSuspense: React.FC<SuspenseWrapperProps> = ({ children }) => (
|
|
<Suspense fallback={<VehicleCardSkeleton />}>
|
|
{children}
|
|
</Suspense>
|
|
);
|
|
|
|
// Mobile vehicles screen suspense
|
|
export const MobileVehiclesSuspense: React.FC<SuspenseWrapperProps> = ({ children }) => (
|
|
<Suspense fallback={<MobileVehiclesSkeleton />}>
|
|
{children}
|
|
</Suspense>
|
|
);
|
|
|
|
// Authentication state suspense
|
|
export const AuthSuspense: React.FC<SuspenseWrapperProps> = ({ children }) => (
|
|
<Suspense fallback={
|
|
<Box sx={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
minHeight: '100vh'
|
|
}}>
|
|
<div className="text-center space-y-4">
|
|
<Skeleton variant="circular" width={60} height={60} sx={{ mx: 'auto' }} />
|
|
<Skeleton variant="text" width={200} height={24} sx={{ mx: 'auto' }} />
|
|
<Skeleton variant="text" width={150} height={20} sx={{ mx: 'auto' }} />
|
|
</div>
|
|
</Box>
|
|
}>
|
|
{children}
|
|
</Suspense>
|
|
);
|
|
|
|
// Route-level suspense for navigation transitions
|
|
export const RouteSuspense: React.FC<SuspenseWrapperProps> = ({ children }) => (
|
|
<Suspense fallback={
|
|
<Box sx={{
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
height: '400px'
|
|
}}>
|
|
<div className="text-center space-y-3">
|
|
<Skeleton variant="rectangular" width={300} height={40} sx={{ mx: 'auto', borderRadius: 1 }} />
|
|
<Skeleton variant="rectangular" width={400} height={200} sx={{ mx: 'auto', borderRadius: 1 }} />
|
|
<div className="flex justify-center space-x-2">
|
|
<Skeleton variant="rounded" width={80} height={32} />
|
|
<Skeleton variant="rounded" width={80} height={32} />
|
|
</div>
|
|
</div>
|
|
</Box>
|
|
}>
|
|
{children}
|
|
</Suspense>
|
|
);
|
|
|
|
// Form suspense for dynamic form loading
|
|
export const FormSuspense: React.FC<SuspenseWrapperProps> = ({ children }) => (
|
|
<Suspense fallback={
|
|
<Box sx={{ p: 3 }}>
|
|
<Skeleton variant="text" width="40%" height={28} sx={{ mb: 3 }} />
|
|
{Array.from({ length: 4 }).map((_, index) => (
|
|
<Box key={index} sx={{ mb: 2 }}>
|
|
<Skeleton variant="text" width="30%" height={20} sx={{ mb: 1 }} />
|
|
<Skeleton variant="rectangular" width="100%" height={40} sx={{ borderRadius: 1 }} />
|
|
</Box>
|
|
))}
|
|
<Box sx={{ display: 'flex', gap: 2, mt: 3 }}>
|
|
<Skeleton variant="rounded" width={100} height={36} />
|
|
<Skeleton variant="rounded" width={80} height={36} />
|
|
</Box>
|
|
</Box>
|
|
}>
|
|
{children}
|
|
</Suspense>
|
|
); |