mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 16:31:12 -05:00
Refactor: Implement Code Splitting
This commit is contained in:
23
src/components/admin/MarkdownEditorLazy.tsx
Normal file
23
src/components/admin/MarkdownEditorLazy.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { EditorSkeleton } from '@/components/loading/PageSkeletons';
|
||||
|
||||
const MarkdownEditor = lazy(() =>
|
||||
import('./MarkdownEditor').then(module => ({ default: module.MarkdownEditor }))
|
||||
);
|
||||
|
||||
export interface MarkdownEditorProps {
|
||||
value: string;
|
||||
onChange: (value: string) => void;
|
||||
onSave?: (value: string) => Promise<void>;
|
||||
autoSave?: boolean;
|
||||
height?: number;
|
||||
placeholder?: string;
|
||||
}
|
||||
|
||||
export function MarkdownEditorLazy(props: MarkdownEditorProps) {
|
||||
return (
|
||||
<Suspense fallback={<EditorSkeleton />}>
|
||||
<MarkdownEditor {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
72
src/components/loading/PageSkeletons.tsx
Normal file
72
src/components/loading/PageSkeletons.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
|
||||
export const PageLoader = () => (
|
||||
<div className="min-h-screen flex items-center justify-center">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary mx-auto" />
|
||||
<p className="text-muted-foreground">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const ParkDetailSkeleton = () => (
|
||||
<div className="container mx-auto px-4 py-8 space-y-6">
|
||||
<Skeleton className="h-64 w-full rounded-lg" />
|
||||
<Skeleton className="h-10 w-2/3" />
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
{[...Array(4)].map((_, i) => (
|
||||
<Skeleton key={i} className="h-20" />
|
||||
))}
|
||||
</div>
|
||||
<Skeleton className="h-40 w-full" />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const RideCardGridSkeleton = () => (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{[...Array(6)].map((_, i) => (
|
||||
<Skeleton key={i} className="h-64 rounded-lg" />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
export const AdminFormSkeleton = () => (
|
||||
<div className="space-y-4 p-6">
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<Skeleton className="h-32 w-full" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<Skeleton className="h-10 w-24" />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const EditorSkeleton = () => (
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<Skeleton className="h-64 w-full" />
|
||||
</div>
|
||||
);
|
||||
|
||||
export const UploadPlaceholder = () => (
|
||||
<div className="border-2 border-dashed rounded-lg p-8 text-center">
|
||||
<div className="mx-auto h-12 w-12 rounded-full border-2 border-muted-foreground/20 flex items-center justify-center">
|
||||
<Skeleton className="h-6 w-6" />
|
||||
</div>
|
||||
<p className="mt-2 text-sm text-muted-foreground">Loading uploader...</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export const DialogSkeleton = () => (
|
||||
<Card>
|
||||
<CardContent className="p-6 space-y-4">
|
||||
<Skeleton className="h-8 w-48" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<Skeleton className="h-32 w-full" />
|
||||
<Skeleton className="h-10 w-full" />
|
||||
<div className="flex gap-2 justify-end">
|
||||
<Skeleton className="h-10 w-20" />
|
||||
<Skeleton className="h-10 w-20" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@@ -4,7 +4,7 @@ import { Label } from '@/components/ui/label';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Image as ImageIcon, ImagePlus, X } from 'lucide-react';
|
||||
import { UppyPhotoUpload } from './UppyPhotoUpload';
|
||||
import { UppyPhotoUploadLazy } from './UppyPhotoUploadLazy';
|
||||
import { getCloudflareImageUrl } from '@/lib/cloudflareImageUtils';
|
||||
|
||||
export type ImageType = 'logo' | 'banner' | 'card';
|
||||
@@ -125,7 +125,7 @@ export function EntityImageUploader({
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-sm text-muted-foreground">{spec.description}</p>
|
||||
<UppyPhotoUpload
|
||||
<UppyPhotoUploadLazy
|
||||
onUploadComplete={(urls) => handleUploadComplete(type, urls)}
|
||||
maxFiles={1}
|
||||
variant="compact"
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { Progress } from '@/components/ui/progress';
|
||||
import { UppyPhotoUpload } from './UppyPhotoUpload';
|
||||
import { UppyPhotoUploadLazy } from './UppyPhotoUploadLazy';
|
||||
import { PhotoCaptionEditor, PhotoWithCaption } from './PhotoCaptionEditor';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { useAuth } from '@/hooks/useAuth';
|
||||
@@ -340,7 +340,7 @@ export function UppyPhotoSubmissionUpload({
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<UppyPhotoUpload
|
||||
<UppyPhotoUploadLazy
|
||||
onFilesSelected={handleFilesSelected}
|
||||
deferUpload={true}
|
||||
maxFiles={10}
|
||||
|
||||
15
src/components/upload/UppyPhotoSubmissionUploadLazy.tsx
Normal file
15
src/components/upload/UppyPhotoSubmissionUploadLazy.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { UploadPlaceholder } from '@/components/loading/PageSkeletons';
|
||||
import { UppyPhotoSubmissionUploadProps } from '@/types/submissions';
|
||||
|
||||
const UppyPhotoSubmissionUpload = lazy(() =>
|
||||
import('./UppyPhotoSubmissionUpload').then(module => ({ default: module.UppyPhotoSubmissionUpload }))
|
||||
);
|
||||
|
||||
export function UppyPhotoSubmissionUploadLazy(props: UppyPhotoSubmissionUploadProps) {
|
||||
return (
|
||||
<Suspense fallback={<UploadPlaceholder />}>
|
||||
<UppyPhotoSubmissionUpload {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
35
src/components/upload/UppyPhotoUploadLazy.tsx
Normal file
35
src/components/upload/UppyPhotoUploadLazy.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { lazy, Suspense } from 'react';
|
||||
import { UploadPlaceholder } from '@/components/loading/PageSkeletons';
|
||||
import React from 'react';
|
||||
|
||||
const UppyPhotoUpload = lazy(() =>
|
||||
import('./UppyPhotoUpload').then(module => ({ default: module.UppyPhotoUpload }))
|
||||
);
|
||||
|
||||
export interface UppyPhotoUploadLazyProps {
|
||||
onUploadComplete?: (urls: string[]) => void;
|
||||
onFilesSelected?: (files: File[]) => void;
|
||||
onUploadStart?: () => void;
|
||||
onUploadError?: (error: Error) => void;
|
||||
maxFiles?: number;
|
||||
maxSizeMB?: number;
|
||||
allowedFileTypes?: string[];
|
||||
metadata?: Record<string, any>;
|
||||
variant?: string;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
disabled?: boolean;
|
||||
showPreview?: boolean;
|
||||
size?: 'default' | 'compact' | 'large';
|
||||
enableDragDrop?: boolean;
|
||||
showUploadModal?: boolean;
|
||||
deferUpload?: boolean;
|
||||
}
|
||||
|
||||
export function UppyPhotoUploadLazy(props: UppyPhotoUploadLazyProps) {
|
||||
return (
|
||||
<Suspense fallback={<UploadPlaceholder />}>
|
||||
<UppyPhotoUpload {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user