feat: migrate ScoreOdonto CRM to Docker, PostgreSQL, and DragonflyDB
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
import React, { ErrorInfo, ReactNode } from 'react';
|
||||
import { AlertTriangle, RefreshCw, XCircle } from 'lucide-react';
|
||||
|
||||
interface Props {
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
interface State {
|
||||
hasError: boolean;
|
||||
error: Error | null;
|
||||
errorInfo: ErrorInfo | null;
|
||||
}
|
||||
|
||||
export class ErrorBoundary extends React.Component<Props, State> {
|
||||
// FIX: Switched to constructor-based state initialization to resolve issues
|
||||
// where the TypeScript toolchain might not correctly interpret public class fields,
|
||||
// causing `this.props` and `this.setState` to appear unavailable. This is a more
|
||||
// widely compatible approach.
|
||||
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: ErrorInfo) {
|
||||
console.error("Uncaught error:", error, errorInfo);
|
||||
this.setState({ errorInfo });
|
||||
}
|
||||
|
||||
handleReload = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return (
|
||||
<div className="min-h-screen bg-red-50 flex items-center justify-center p-6 font-sans">
|
||||
<div className="max-w-3xl w-full bg-white rounded-2xl shadow-2xl overflow-hidden border border-red-100">
|
||||
<div className="bg-red-600 p-6 flex items-center gap-4">
|
||||
<div className="bg-white/20 p-3 rounded-full text-white">
|
||||
<XCircle size={32} />
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-white uppercase">ERRO CRÍTICO NO SISTEMA</h1>
|
||||
<p className="text-red-100 text-xs font-bold uppercase mt-1">O APLICATIVO ENCONTROU UM PROBLEMA INESPERADO</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-8">
|
||||
<div className="mb-6">
|
||||
<p className="text-gray-700 font-bold uppercase mb-2">O QUE ACONTECEU?</p>
|
||||
<p className="text-gray-600 text-sm">
|
||||
Ocorreu uma falha durante a renderização da interface. Tente recarregar a página.
|
||||
Se o problema persistir, envie o log abaixo para o suporte técnico.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{this.state.error && (
|
||||
<div className="bg-gray-900 rounded-lg p-4 mb-6 overflow-x-auto border-l-4 border-red-500">
|
||||
<div className="flex items-center gap-2 text-red-400 font-bold text-xs uppercase mb-2">
|
||||
<AlertTriangle size={14} /> Stack Trace / Log Técnico
|
||||
</div>
|
||||
<pre className="text-green-400 font-mono text-xs leading-relaxed whitespace-pre-wrap break-words">
|
||||
{this.state.error.toString()}
|
||||
<br />
|
||||
{this.state.errorInfo?.componentStack}
|
||||
</pre>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex gap-4">
|
||||
<button
|
||||
onClick={this.handleReload}
|
||||
className="bg-red-600 hover:bg-red-700 text-white px-6 py-3 rounded-lg font-bold uppercase flex items-center gap-2 transition-colors shadow-lg"
|
||||
>
|
||||
<RefreshCw size={18} /> RECARREGAR SISTEMA
|
||||
</button>
|
||||
<button
|
||||
onClick={() => { localStorage.clear(); window.location.reload(); }}
|
||||
className="bg-gray-200 hover:bg-gray-300 text-gray-700 px-6 py-3 rounded-lg font-bold uppercase flex items-center gap-2 transition-colors"
|
||||
>
|
||||
LIMPAR CACHE E REINICIAR
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user