'use client'; import { Component, ErrorInfo, ReactNode } from 'react'; import { clientLogger } from '@/lib/utils/client-logger'; interface ErrorBoundaryProps { children: ReactNode; fallback?: (error: Error, errorInfo: ErrorInfo, reset: () => void) => ReactNode; } interface ErrorBoundaryState { hasError: boolean; error: Error | null; errorInfo: ErrorInfo | null; } /** * Error Boundary component that catches React errors and logs them * Provides a fallback UI when errors occur */ export class ErrorBoundary extends Component { constructor(props: ErrorBoundaryProps) { super(props); this.state = { hasError: false, error: null, errorInfo: null, }; } static getDerivedStateFromError(error: Error): Partial { return { hasError: true, error, }; } componentDidCatch(error: Error, errorInfo: ErrorInfo): void { // Log error to client logger clientLogger.error('React Error Boundary caught error', error, { componentStack: errorInfo.componentStack, errorBoundary: 'ErrorBoundary', }); // Store error info in state this.setState({ errorInfo, }); // Send error to server for logging (async, non-blocking) this.reportErrorToServer(error, errorInfo).catch((reportError) => { clientLogger.error('Failed to report error to server', reportError); }); } private async reportErrorToServer(error: Error, errorInfo: ErrorInfo): Promise { try { await fetch('/api/client-error', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: error.message, stack: error.stack, componentStack: errorInfo.componentStack, name: error.name, userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : 'unknown', url: typeof window !== 'undefined' ? window.location.href : 'unknown', timestamp: new Date().toISOString(), }), }); } catch (err) { // Silently fail - we don't want error reporting to cause more errors console.error('Error reporting failed:', err); } } private handleReset = (): void => { clientLogger.info('Error boundary reset requested'); this.setState({ hasError: false, error: null, errorInfo: null, }); }; render(): ReactNode { if (this.state.hasError && this.state.error) { // Use custom fallback if provided if (this.props.fallback) { return this.props.fallback( this.state.error, this.state.errorInfo!, this.handleReset ); } // Default fallback UI return (

Something went wrong

An unexpected error occurred. The error has been logged and we'll look into it.

{process.env.NODE_ENV === 'development' && this.state.error && (

{this.state.error.message}

{this.state.error.stack && (
Stack trace
                      {this.state.error.stack}
                    
)}
)}
); } return this.props.children; } }