) {
+ const dotSizeClasses = {
+ sm: 'w-1 h-1',
+ md: 'w-2 h-2',
+ lg: 'w-3 h-3',
+ xl: 'w-4 h-4'
+ };
+
+ const variantClasses = {
+ primary: 'bg-primary-500',
+ secondary: 'bg-secondary-500',
+ accent: 'bg-gold-500',
+ muted: 'bg-text-muted'
+ };
+
+ return (
+
+ {[0, 1, 2].map((index) => (
+
+ ))}
+
+ );
+}
+
+export default LoadingSpinner;
\ No newline at end of file
diff --git a/reactrebuild0825/src/components/loading/RouteSuspense.tsx b/reactrebuild0825/src/components/loading/RouteSuspense.tsx
new file mode 100644
index 0000000..da6c955
--- /dev/null
+++ b/reactrebuild0825/src/components/loading/RouteSuspense.tsx
@@ -0,0 +1,210 @@
+import React, { Suspense, useEffect, useState } from 'react';
+
+import { clsx } from 'clsx';
+
+import { Button } from '../ui/Button';
+import { Card } from '../ui/Card';
+
+import { LoadingSpinner } from './LoadingSpinner';
+import { Skeleton } from './Skeleton';
+
+export interface RouteSuspenseProps {
+ children: React.ReactNode;
+ fallback?: React.ReactNode;
+ timeout?: number;
+ skeletonType?: 'page' | 'card' | 'list' | 'table' | 'custom';
+ loadingText?: string;
+ className?: string;
+ onTimeout?: () => void;
+ enableRetry?: boolean;
+}
+
+/**
+ * Enhanced Suspense wrapper for route-level code splitting with timeout handling
+ * Provides progressive loading states and graceful error handling
+ */
+export function RouteSuspense({
+ children,
+ fallback,
+ timeout = 10000, // 10 seconds default timeout
+ skeletonType = 'page',
+ loadingText = 'Loading...',
+ className,
+ onTimeout,
+ enableRetry = true
+}: RouteSuspenseProps) {
+ const [hasTimedOut, setHasTimedOut] = useState(false);
+ const [retryKey, setRetryKey] = useState(0);
+
+ useEffect(() => {
+ if (timeout <= 0) {return;}
+
+ const timeoutId = setTimeout(() => {
+ setHasTimedOut(true);
+ onTimeout?.();
+ }, timeout);
+
+ return () => clearTimeout(timeoutId);
+ }, [timeout, onTimeout, retryKey]);
+
+ const handleRetry = () => {
+ setHasTimedOut(false);
+ setRetryKey(prev => prev + 1);
+ };
+
+ // Show timeout error if loading takes too long
+ if (hasTimedOut) {
+ return (
+
+
+
+ {/* Timeout Icon */}
+
+
+
+ Loading Timeout
+
+
+
+ The page is taking longer than expected to load. This might be due to a slow connection or server issues.
+
+
+
+ {enableRetry && (
+
+ )}
+
+
+
+
+
+
+ If this problem persists, please check your internet connection or{' '}
+
+ contact support
+
+
+
+
+
+
+ );
+ }
+
+ // Create default fallback based on skeleton type
+ const createDefaultFallback = () => {
+ switch (skeletonType) {
+ case 'page':
+ return ;
+ case 'card':
+ return ;
+ case 'list':
+ return ;
+ case 'table':
+ return ;
+ case 'custom':
+ default:
+ return (
+
+
+
+ );
+ }
+ };
+
+ const defaultFallback = fallback || createDefaultFallback();
+
+ return (
+
+
+ {children}
+
+
+ );
+}
+
+/**
+ * Higher-order component for wrapping routes with suspense
+ */
+export function withRouteSuspense(
+ Component: React.ComponentType
,
+ suspenseProps?: Omit
+) {
+ const WrappedComponent = (props: P) => (
+
+
+
+ );
+
+ WrappedComponent.displayName = `withRouteSuspense(${Component.displayName || Component.name})`;
+
+ return WrappedComponent;
+}
+
+/**
+ * Hook for programmatic timeout handling
+ */
+export function useLoadingTimeout(
+ timeout: number = 10000,
+ onTimeout?: () => void
+) {
+ const [hasTimedOut, setHasTimedOut] = useState(false);
+
+ useEffect(() => {
+ if (timeout <= 0) {return;}
+
+ const timeoutId = setTimeout(() => {
+ setHasTimedOut(true);
+ onTimeout?.();
+ }, timeout);
+
+ return () => clearTimeout(timeoutId);
+ }, [timeout, onTimeout]);
+
+ const resetTimeout = () => setHasTimedOut(false);
+
+ return { hasTimedOut, resetTimeout };
+}
+
+export default RouteSuspense;
\ No newline at end of file
diff --git a/reactrebuild0825/src/components/loading/Skeleton.tsx b/reactrebuild0825/src/components/loading/Skeleton.tsx
new file mode 100644
index 0000000..2384539
--- /dev/null
+++ b/reactrebuild0825/src/components/loading/Skeleton.tsx
@@ -0,0 +1,423 @@
+import { clsx } from 'clsx';
+
+import { Card } from '../ui/Card';
+
+import { LoadingSpinner } from './LoadingSpinner';
+
+export interface SkeletonProps {
+ className?: string;
+ rounded?: boolean;
+ animate?: boolean;
+}
+
+export interface SkeletonLayoutProps {
+ loadingText?: string;
+ className?: string;
+}
+
+/**
+ * Base skeleton component with glassmorphism styling
+ */
+export function BaseSkeleton({
+ className,
+ rounded = true,
+ animate = true
+}: SkeletonProps) {
+ return (
+
+ );
+}
+
+/**
+ * Skeleton for text content
+ */
+export function TextSkeleton({
+ lines = 1,
+ className,
+ animate = true
+}: {
+ lines?: number;
+ className?: string;
+ animate?: boolean;
+}) {
+ return (
+
+ {Array.from({ length: lines }).map((_, index) => (
+
+ ))}
+
+ );
+}
+
+/**
+ * Skeleton for avatars and circular elements
+ */
+export function AvatarSkeleton({
+ size = 'md',
+ className
+}: {
+ size?: 'sm' | 'md' | 'lg' | 'xl';
+ className?: string;
+}) {
+ const sizeClasses = {
+ sm: 'w-8 h-8',
+ md: 'w-12 h-12',
+ lg: 'w-16 h-16',
+ xl: 'w-24 h-24'
+ };
+
+ return (
+
+ );
+}
+
+/**
+ * Skeleton for buttons
+ */
+export function ButtonSkeleton({
+ size = 'md',
+ className
+}: {
+ size?: 'sm' | 'md' | 'lg';
+ className?: string;
+}) {
+ const sizeClasses = {
+ sm: 'h-8 w-20',
+ md: 'h-10 w-24',
+ lg: 'h-12 w-32'
+ };
+
+ return (
+
+ );
+}
+
+/**
+ * Skeleton for cards
+ */
+function CardSkeleton({ loadingText, className }: SkeletonLayoutProps) {
+ return (
+
+ {/* Loading indicator */}
+ {loadingText && (
+
+
+
+ )}
+
+ {/* Card skeletons */}
+
+ {Array.from({ length: 6 }).map((_, index) => (
+
+
+ {/* Header */}
+
+
+ {/* Content */}
+
+
+
+
+
+
+ {/* Footer */}
+
+
+
+
+
+
+ ))}
+
+
+ );
+}
+
+/**
+ * Skeleton for list items
+ */
+function ListSkeleton({ loadingText, className }: SkeletonLayoutProps) {
+ return (
+
+ {/* Loading indicator */}
+ {loadingText && (
+
+
+
+ )}
+
+ {/* List items */}
+ {Array.from({ length: 8 }).map((_, index) => (
+
+ ))}
+
+ );
+}
+
+/**
+ * Skeleton for tables
+ */
+function TableSkeleton({ loadingText, className }: SkeletonLayoutProps) {
+ return (
+
+ {/* Loading indicator */}
+ {loadingText && (
+
+
+
+ )}
+
+
+ {/* Table header */}
+
+
+ {Array.from({ length: 5 }).map((_, index) => (
+
+ ))}
+
+
+
+ {/* Table rows */}
+
+ {Array.from({ length: 10 }).map((_, rowIndex) => (
+
+
+ {Array.from({ length: 5 }).map((_, colIndex) => {
+ if (colIndex === 0) {
+ return (
+
+ );
+ }
+ if (colIndex === 4) {
+ return (
+
+
+
+ );
+ }
+ return
;
+ })}
+
+
+ ))}
+
+
+
+ );
+}
+
+/**
+ * Skeleton for full page layouts
+ */
+function PageSkeleton({ loadingText, className }: SkeletonLayoutProps) {
+ return (
+
+ {/* Header skeleton */}
+
+
+
+
+
+ {Array.from({ length: 4 }).map((_, index) => (
+
+ ))}
+
+
+
+
+
+
+ {/* Main content area */}
+
+ {/* Loading indicator */}
+ {loadingText && (
+
+
+
+ )}
+
+ {/* Page title and actions */}
+
+
+ {/* Stats cards */}
+
+ {Array.from({ length: 4 }).map((_, index) => (
+
+
+
+
+
+
+
+ ))}
+
+
+ {/* Main content */}
+
+ {/* Primary content */}
+
+
+
+
+
+
+
+
+ {Array.from({ length: 6 }).map((_, index) => (
+
+ ))}
+
+
+
+
+
+ {/* Sidebar */}
+
+
+
+
+
+ {Array.from({ length: 4 }).map((_, index) => (
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+/**
+ * Skeleton for form layouts
+ */
+function FormSkeleton({ loadingText, className }: SkeletonLayoutProps) {
+ return (
+
+ {/* Loading indicator */}
+ {loadingText && (
+
+
+
+ )}
+
+
+
+ {/* Form title */}
+
+
+ {/* Form fields */}
+
+ {Array.from({ length: 6 }).map((_, index) => (
+
+
+
+
+ ))}
+
+
+ {/* Text area */}
+
+
+
+
+
+ {/* Form actions */}
+
+
+
+
+
+
+
+ );
+}
+
+// Export all skeleton components
+export const Skeleton = {
+ Base: BaseSkeleton,
+ Text: TextSkeleton,
+ Avatar: AvatarSkeleton,
+ Button: ButtonSkeleton,
+ Card: CardSkeleton,
+ List: ListSkeleton,
+ Table: TableSkeleton,
+ Page: PageSkeleton,
+ Form: FormSkeleton
+};
+
+export default Skeleton;
\ No newline at end of file
diff --git a/reactrebuild0825/src/components/loading/index.ts b/reactrebuild0825/src/components/loading/index.ts
new file mode 100644
index 0000000..47cb15b
--- /dev/null
+++ b/reactrebuild0825/src/components/loading/index.ts
@@ -0,0 +1,24 @@
+/**
+ * Loading Components
+ *
+ * Comprehensive collection of loading states and skeleton components
+ * with glassmorphism styling and accessibility features.
+ */
+
+// Main loading components
+export { LoadingSpinner, PulseLoader, ShimmerLoader, DotsLoader } from './LoadingSpinner';
+export type { LoadingSpinnerProps } from './LoadingSpinner';
+
+// Suspense and route loading
+export { RouteSuspense, withRouteSuspense, useLoadingTimeout } from './RouteSuspense';
+export type { RouteSuspenseProps } from './RouteSuspense';
+
+// Skeleton components
+export {
+ BaseSkeleton,
+ TextSkeleton,
+ AvatarSkeleton,
+ ButtonSkeleton,
+ Skeleton
+} from './Skeleton';
+export type { SkeletonProps, SkeletonLayoutProps } from './Skeleton';
\ No newline at end of file
diff --git a/reactrebuild0825/src/pages/ErrorPage.tsx b/reactrebuild0825/src/pages/ErrorPage.tsx
new file mode 100644
index 0000000..5048af9
--- /dev/null
+++ b/reactrebuild0825/src/pages/ErrorPage.tsx
@@ -0,0 +1,357 @@
+import React from 'react';
+
+import { useNavigate, useLocation } from 'react-router-dom';
+
+import { clsx } from 'clsx';
+
+import { AppLayout } from '../components/layout/AppLayout';
+import { Alert } from '../components/ui/Alert';
+import { Button } from '../components/ui/Button';
+import { Card } from '../components/ui/Card';
+
+export type ErrorPageType = '404' | '403' | '500' | 'network' | 'timeout' | 'maintenance';
+
+export interface ErrorPageProps {
+ type?: ErrorPageType;
+ title?: string;
+ message?: string;
+ details?: string;
+ showRetry?: boolean;
+ showHome?: boolean;
+ showBack?: boolean;
+ customActions?: React.ReactNode;
+ className?: string;
+}
+
+/**
+ * Get error configuration based on error type
+ */
+interface ErrorConfig {
+ title: string;
+ message: string;
+ icon: React.ReactNode;
+ showRetry?: boolean;
+ showHome?: boolean;
+ showBack?: boolean;
+}
+
+function getErrorConfig(type: ErrorPageType): ErrorConfig {
+ const configs: Record = {
+ '404': {
+ title: 'Page Not Found',
+ message: 'The page you\'re looking for doesn\'t exist or has been moved.',
+ icon: (
+
+ ),
+ showHome: true,
+ showBack: true
+ },
+ '403': {
+ title: 'Access Denied',
+ message: 'You don\'t have permission to access this resource.',
+ icon: (
+
+ ),
+ showHome: true,
+ showBack: true
+ },
+ '500': {
+ title: 'Server Error',
+ message: 'Something went wrong on our end. We\'re working to fix it.',
+ icon: (
+
+ ),
+ showRetry: true,
+ showHome: true
+ },
+ 'network': {
+ title: 'Connection Error',
+ message: 'Unable to connect to the server. Please check your internet connection.',
+ icon: (
+
+ ),
+ showRetry: true,
+ showHome: true
+ },
+ 'timeout': {
+ title: 'Request Timeout',
+ message: 'The request took too long to complete. Please try again.',
+ icon: (
+
+ ),
+ showRetry: true,
+ showHome: true
+ },
+ 'maintenance': {
+ title: 'Under Maintenance',
+ message: 'We\'re currently performing scheduled maintenance. Please check back soon.',
+ icon: (
+
+ ),
+ showHome: false
+ }
+ };
+
+ return configs[type] || configs['500'];
+}
+
+/**
+ * Comprehensive error page component with glassmorphism styling
+ */
+export function ErrorPage({
+ type = '500',
+ title,
+ message,
+ details,
+ showRetry,
+ showHome,
+ showBack,
+ customActions,
+ className
+}: ErrorPageProps) {
+ const navigate = useNavigate();
+ const location = useLocation();
+
+ const config = getErrorConfig(type);
+ const errorTitle = title || config.title;
+ const errorMessage = message || config.message;
+ const shouldShowRetry = showRetry !== undefined ? showRetry : config.showRetry;
+ const shouldShowHome = showHome !== undefined ? showHome : config.showHome;
+ const shouldShowBack = showBack !== undefined ? showBack : config.showBack;
+
+ const handleRetry = () => {
+ window.location.reload();
+ };
+
+ const handleGoHome = () => {
+ navigate('/');
+ };
+
+ const handleGoBack = () => {
+ if (window.history.length > 1) {
+ navigate(-1);
+ } else {
+ navigate('/');
+ }
+ };
+
+ const getErrorColor = (errorType: ErrorPageType) => {
+ switch (errorType) {
+ case '404':
+ return 'text-info-accent';
+ case '403':
+ return 'text-warning-accent';
+ case '500':
+ case 'network':
+ case 'timeout':
+ return 'text-error-accent';
+ case 'maintenance':
+ return 'text-gold-500';
+ default:
+ return 'text-error-accent';
+ }
+ };
+
+ const getErrorBg = (errorType: ErrorPageType) => {
+ switch (errorType) {
+ case '404':
+ return 'bg-info-bg border-info-border';
+ case '403':
+ return 'bg-warning-bg border-warning-border';
+ case '500':
+ case 'network':
+ case 'timeout':
+ return 'bg-error-bg border-error-border';
+ case 'maintenance':
+ return 'bg-gold-bg border-gold-border';
+ default:
+ return 'bg-error-bg border-error-border';
+ }
+ };
+
+ return (
+
+
+
+
+ {/* Error Icon */}
+
+
+
+
+ {/* Error Code */}
+ {(type === '404' || type === '403' || type === '500') && (
+
+ {type}
+
+ )}
+
+ {/* Error Title */}
+
+ {errorTitle}
+
+
+ {/* Error Message */}
+
+ {errorMessage}
+
+
+ {/* Error Details */}
+ {details && (
+
+ {details}
+
+ )}
+
+ {/* Development Details */}
+ {process.env.NODE_ENV === 'development' && (
+
+
+ Development Details
+
+
+
+ Current URL: {location.pathname + location.search}
+
+
+ Error Type: {type}
+
+
+ Timestamp: {new Date().toISOString()}
+
+
+
+ )}
+
+ {/* Action Buttons */}
+
+ {shouldShowRetry && (
+
+ )}
+
+ {shouldShowHome && (
+
+ )}
+
+ {shouldShowBack && (
+
+ )}
+
+ {customActions}
+
+
+ {/* Support Information */}
+
+
+
+
+
+ );
+}
+
+/**
+ * Specific error page components for common scenarios
+ */
+export function NotFoundPage(props: Omit) {
+ return ;
+}
+
+export function UnauthorizedPage(props: Omit) {
+ return ;
+}
+
+export function ServerErrorPage(props: Omit) {
+ return ;
+}
+
+export function NetworkErrorPage(props: Omit) {
+ return ;
+}
+
+export function TimeoutErrorPage(props: Omit) {
+ return ;
+}
+
+export function MaintenancePage(props: Omit) {
+ return ;
+}
+
+export default ErrorPage;
\ No newline at end of file
diff --git a/reactrebuild0825/src/types/errors.ts b/reactrebuild0825/src/types/errors.ts
new file mode 100644
index 0000000..d4a3e21
--- /dev/null
+++ b/reactrebuild0825/src/types/errors.ts
@@ -0,0 +1,98 @@
+/**
+ * Error types and interfaces for comprehensive error handling
+ */
+
+export type ErrorType = 'network' | 'auth' | 'permission' | 'validation' | 'generic' | 'timeout' | 'rate_limit';
+
+export interface ErrorInfo {
+ type: ErrorType;
+ message: string;
+ code?: string;
+ details?: string;
+ recoverable: boolean;
+ retryAction?: () => void;
+ timestamp?: Date;
+ componentStack?: string;
+ errorBoundary?: string;
+}
+
+export interface NetworkError extends ErrorInfo {
+ type: 'network';
+ status?: number;
+ endpoint?: string;
+}
+
+export interface AuthError extends ErrorInfo {
+ type: 'auth';
+ redirectTo?: string;
+}
+
+export interface PermissionError extends ErrorInfo {
+ type: 'permission';
+ requiredPermission?: string;
+ currentPermissions?: string[];
+}
+
+export interface ValidationError extends ErrorInfo {
+ type: 'validation';
+ field?: string;
+ value?: unknown;
+}
+
+export interface TimeoutError extends ErrorInfo {
+ type: 'timeout';
+ operation?: string;
+ timeoutMs?: number;
+}
+
+export interface RateLimitError extends ErrorInfo {
+ type: 'rate_limit';
+ retryAfter?: number;
+ limit?: number;
+}
+
+export type AppError = NetworkError | AuthError | PermissionError | ValidationError | TimeoutError | RateLimitError | ErrorInfo;
+
+/**
+ * Error severity levels for different handling strategies
+ */
+export type ErrorSeverity = 'low' | 'medium' | 'high' | 'critical';
+
+/**
+ * Enhanced error interface for error boundaries
+ */
+export interface BoundaryError {
+ error: Error;
+ errorInfo: React.ErrorInfo;
+ errorType: ErrorType;
+ severity: ErrorSeverity;
+ timestamp: Date;
+ userAgent?: string;
+ url?: string;
+ userId?: string;
+}
+
+/**
+ * Error recovery strategies
+ */
+export type RecoveryStrategy = 'retry' | 'reload' | 'redirect' | 'fallback' | 'none';
+
+export interface ErrorRecovery {
+ strategy: RecoveryStrategy;
+ action?: () => void;
+ fallbackComponent?: React.ComponentType;
+ maxRetries?: number;
+ retryDelay?: number;
+}
+
+/**
+ * Error reporting configuration
+ */
+export interface ErrorReportConfig {
+ enabled: boolean;
+ includeUserAgent: boolean;
+ includeUrl: boolean;
+ includeUserId: boolean;
+ includeBreadcrumbs: boolean;
+ endpoint?: string;
+}
\ No newline at end of file