import React, { ReactNode } from 'react'; import { ApiError } from '@/lib/api/base/ApiError'; import { LoadingWrapper } from './LoadingWrapper'; import { ErrorDisplay } from './ErrorDisplay'; import { EmptyState } from './EmptyState'; import { Inbox, List, LucideIcon } from 'lucide-react'; // ==================== PAGEWRAPPER TYPES ==================== export interface PageWrapperLoadingConfig { variant?: 'skeleton' | 'full-screen'; message?: string; } export interface PageWrapperErrorConfig { variant?: 'full-screen' | 'card'; card?: { title?: string; description?: string; }; } export interface PageWrapperEmptyConfig { icon?: LucideIcon; title?: string; description?: string; action?: { label: string; onClick: () => void; }; } export interface PageWrapperProps { /** Data to be rendered */ data: TData | undefined; /** Loading state (default: false) */ isLoading?: boolean; /** Error state (default: null) */ error?: Error | null; /** Retry function for errors */ retry?: () => void; /** Template component that receives the data */ Template: React.ComponentType<{ data: TData }>; /** Loading configuration */ loading?: PageWrapperLoadingConfig; /** Error configuration */ errorConfig?: PageWrapperErrorConfig; /** Empty configuration */ empty?: PageWrapperEmptyConfig; /** Children for flexible content rendering */ children?: ReactNode; /** Additional CSS classes */ className?: string; } /** * PageWrapper Component * * A comprehensive wrapper component that handles all page states: * - Loading states (skeleton or full-screen) * - Error states (full-screen or card) * - Empty states (with icon, title, description, and action) * - Success state (renders Template component with data) * - Flexible children support for custom content * * Usage Example: * ```typescript * * * * ``` */ export function PageWrapper({ data, isLoading = false, error = null, retry, Template, loading, errorConfig, empty, children, className = '', }: PageWrapperProps) { // Priority order: Loading > Error > Empty > Success // 1. Loading State if (isLoading) { const loadingVariant = loading?.variant || 'skeleton'; const loadingMessage = loading?.message || 'Loading...'; if (loadingVariant === 'full-screen') { return ( ); } // Default to skeleton return (
{children}
); } // 2. Error State if (error) { const errorVariant = errorConfig?.variant || 'full-screen'; if (errorVariant === 'card') { const cardTitle = errorConfig?.card?.title || 'Error'; const cardDescription = errorConfig?.card?.description || 'Something went wrong'; return (
{children}
); } // Default to full-screen return ( ); } // 3. Empty State if (!data || (Array.isArray(data) && data.length === 0)) { if (empty) { const Icon = empty.icon; const hasAction = empty.action && retry; return (
{children}
); } // If no empty config provided but data is empty, show nothing return (
{children}
); } // 4. Success State - Render Template with data return (