w-funnel/src/components/admin/ErrorBoundary.tsx
dev.daminik00 92d70cf371 ref
2025-10-01 00:39:54 +02:00

124 lines
3.4 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Component, ReactNode } from 'react';
interface Props {
children: ReactNode;
fallback?: ReactNode;
onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
}
interface State {
hasError: boolean;
error: Error | null;
}
/**
* Error Boundary component to catch and handle React errors
* Prevents entire app from crashing when a component throws
*
* @example
* <ErrorBoundary fallback={<ErrorFallback />}>
* <MyComponent />
* </ErrorBoundary>
*/
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
hasError: false,
error: null,
};
}
static getDerivedStateFromError(error: Error): State {
return {
hasError: true,
error,
};
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
// Log error to console in development
console.error('ErrorBoundary caught an error:', error, errorInfo);
// Call optional error handler
this.props.onError?.(error, errorInfo);
}
handleReset = () => {
this.setState({
hasError: false,
error: null,
});
};
render() {
if (this.state.hasError) {
// Render custom fallback or default error UI
if (this.props.fallback) {
return this.props.fallback;
}
return (
<div className="flex flex-col items-center justify-center p-8 bg-red-50 border border-red-200 rounded-lg">
<div className="text-red-600 font-semibold mb-2"> Что-то пошло не так</div>
<div className="text-sm text-red-500 mb-4">
{this.state.error?.message || 'Произошла неизвестная ошибка'}
</div>
<button
onClick={this.handleReset}
className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 transition-colors"
>
Попробовать снова
</button>
</div>
);
}
return this.props.children;
}
}
/**
* Specific Error Boundary for Builder components
*/
export function BuilderErrorBoundary({ children }: { children: ReactNode }) {
return (
<ErrorBoundary
fallback={
<div className="flex flex-col items-center justify-center p-8 bg-yellow-50 border border-yellow-200 rounded-lg">
<div className="text-yellow-700 font-semibold mb-2"> Ошибка в билдере</div>
<div className="text-sm text-yellow-600 mb-4">
Не удалось загрузить компонент. Попробуйте перезагрузить страницу.
</div>
</div>
}
onError={(error) => {
// Could send to error tracking service here
console.error('[Builder Error]:', error);
}}
>
{children}
</ErrorBoundary>
);
}
/**
* Specific Error Boundary for Preview component
*/
export function PreviewErrorBoundary({ children }: { children: ReactNode }) {
return (
<ErrorBoundary
fallback={
<div className="flex flex-col items-center justify-center h-full p-8 bg-gray-50">
<div className="text-gray-600 font-semibold mb-2"> Ошибка превью</div>
<div className="text-sm text-gray-500">
Не удалось отобразить превью экрана
</div>
</div>
}
>
{children}
</ErrorBoundary>
);
}