jeanma's picture
Omnilingual ASR transcription demo
ae238b3 verified
import React, { Component, ReactNode } from 'react';
interface Props {
children: ReactNode;
componentName?: string;
}
interface State {
hasError: boolean;
error: Error | null;
errorInfo: React.ErrorInfo | null;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null, errorInfo: null };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error, errorInfo: null };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
console.error('ErrorBoundary caught an error:', error, errorInfo);
this.setState({
error,
errorInfo
});
}
handleRetry = () => {
this.setState({ hasError: false, error: null, errorInfo: null });
};
handleCopyError = () => {
const { error, errorInfo } = this.state;
const { componentName } = this.props;
const errorText = `
Component: ${componentName || 'Unknown'}
Error: ${error?.message || 'Unknown error'}
Stack: ${error?.stack || 'No stack trace available'}
Component Stack: ${errorInfo?.componentStack || 'No component stack available'}
Timestamp: ${new Date().toISOString()}
`.trim();
navigator.clipboard.writeText(errorText).then(() => {
alert('Error details copied to clipboard!');
}).catch(() => {
// Fallback for older browsers
const textArea = document.createElement('textarea');
textArea.value = errorText;
document.body.appendChild(textArea);
textArea.select();
document.execCommand('copy');
document.body.removeChild(textArea);
alert('Error details copied to clipboard!');
});
};
render() {
if (this.state.hasError) {
const { componentName } = this.props;
const { error, errorInfo } = this.state;
return (
<div className="flex flex-col items-center justify-center p-8 bg-red-50 border border-red-200 rounded-lg m-4">
<div className="text-center mb-6">
<h2 className="text-xl font-semibold text-red-800 mb-2">
Sorry, something went wrong
</h2>
<p className="text-red-600 mb-4">
{componentName ? `An error occurred in the ${componentName} component.` : 'An unexpected error occurred.'}
</p>
<button
onClick={this.handleRetry}
className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors mr-2"
>
Try Again
</button>
<button
onClick={this.handleCopyError}
className="px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
>
Copy Error Details
</button>
</div>
<details className="w-full max-w-4xl">
<summary className="cursor-pointer text-red-700 font-medium mb-2 hover:text-red-800">
Show Error Details (for developers)
</summary>
<div className="bg-gray-100 p-4 rounded border text-sm font-mono overflow-auto max-h-96">
<div className="mb-4">
<strong className="text-red-700">Error Message:</strong>
<pre className="mt-1 whitespace-pre-wrap text-red-800">
{error?.message || 'Unknown error'}
</pre>
</div>
<div className="mb-4">
<strong className="text-red-700">Stack Trace:</strong>
<pre className="mt-1 whitespace-pre-wrap text-gray-800 text-xs">
{error?.stack || 'No stack trace available'}
</pre>
</div>
{errorInfo?.componentStack && (
<div className="mb-4">
<strong className="text-red-700">Component Stack:</strong>
<pre className="mt-1 whitespace-pre-wrap text-gray-800 text-xs">
{errorInfo.componentStack}
</pre>
</div>
)}
<div className="text-xs text-gray-600">
<strong>Timestamp:</strong> {new Date().toISOString()}
</div>
</div>
</details>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;