Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
File size: 5,762 Bytes
7214c09 9ba12cb 7214c09 9ba12cb 7214c09 9ba12cb 7214c09 9ba12cb 7214c09 17fd0c4 9ba12cb 17fd0c4 9ba12cb 7214c09 0062aef 9ba12cb d45b4a0 0062aef 9ba12cb 0062aef 9ba12cb d45b4a0 9ba12cb d45b4a0 17fd0c4 9ba12cb 17fd0c4 9ba12cb 17fd0c4 d45b4a0 9ba12cb d45b4a0 9ba12cb d45b4a0 0062aef d45b4a0 7214c09 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | import React from 'react';
export class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null, showDetails: false };
}
static getDerivedStateFromError(error) {
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
console.error("Uncaught Error caught by ErrorBoundary:", error, errorInfo);
// If it's a chunk loading error (common after new deployments or SPA lazy route updates), auto-reload page once
const isChunkError = error && (
error.name === 'ChunkLoadError' ||
error.message?.includes('dynamically imported module') ||
error.message?.includes('Importing a module script failed') ||
error.message?.includes('Failed to fetch dynamically imported module') ||
error.message?.includes('Failed to load module script')
);
if (isChunkError) {
const hasReloaded = sessionStorage.getItem('chunk_reload_retry');
if (!hasReloaded) {
sessionStorage.setItem('chunk_reload_retry', 'true');
window.location.reload();
}
}
}
componentDidMount() {
sessionStorage.removeItem('chunk_reload_retry');
window.addEventListener('popstate', this.handlePopState);
}
componentWillUnmount() {
window.removeEventListener('popstate', this.handlePopState);
}
handlePopState = () => {
if (this.state.hasError) {
this.setState({ hasError: false, error: null, showDetails: false });
}
};
render() {
if (this.state.hasError) {
return (
<div className="min-h-screen flex flex-col items-center justify-center bg-[#f8fafc] p-6 text-center font-sans">
<div className="bg-white border border-slate-200/80 shadow-2xl rounded-3xl p-8 max-w-lg w-full animate-fade-in text-slate-900">
{/* Warning Icon Badge */}
<div className="w-16 h-16 rounded-2xl bg-amber-500/10 text-amber-600 border border-amber-500/20 flex items-center justify-center mx-auto mb-5 shadow-xs">
<span className="material-symbols-outlined text-4xl">warning</span>
</div>
<h2 className="text-2xl font-black text-slate-900 mb-2 tracking-tight">
Something Went Wrong
</h2>
<p className="text-sm text-slate-600 mb-6 leading-relaxed font-medium">
Sorry, due to a temporary technical issue or standard network update, this page could not be displayed properly. Please refresh the page or contact our support team.
</p>
{/* Optional Collapsible Technical Details */}
{this.state.error?.message && (
<div className="mb-6 text-left">
<button
onClick={() => this.setState(prev => ({ showDetails: !prev.showDetails }))}
className="text-[12px] font-bold text-slate-500 hover:text-primary transition-colors flex items-center gap-1 bg-transparent border-0 cursor-pointer p-0 mb-2 mx-auto"
>
<span className="material-symbols-outlined text-[16px]">
{this.state.showDetails ? 'expand_less' : 'expand_more'}
</span>
{this.state.showDetails ? 'Hide Error Details' : 'View Error Details'}
</button>
{this.state.showDetails && (
<div className="bg-slate-900 text-slate-200 p-3.5 rounded-xl font-mono text-[11px] overflow-x-auto max-h-36 border border-slate-800 break-all select-all leading-relaxed shadow-inner">
<span className="text-red-400 font-bold">Error:</span> {this.state.error.toString()}
</div>
)}
</div>
)}
{/* Action Buttons */}
<div className="flex flex-col gap-3">
<button
onClick={() => {
this.setState({ hasError: false, error: null, showDetails: false });
window.location.reload();
}}
className="w-full bg-primary hover:brightness-110 text-white font-bold py-3.5 px-6 rounded-xl transition-all shadow-md shadow-primary/20 border-0 cursor-pointer text-sm flex items-center justify-center gap-2 active:scale-[0.99]"
>
<span className="material-symbols-outlined text-[20px]">refresh</span>
Refresh Page
</button>
<a
href="mailto:support@larshield.io?subject=LarShield%20System%20Issue%20Report"
className="w-full bg-slate-100 hover:bg-slate-200 text-slate-700 font-bold py-3 px-6 rounded-xl transition-all border border-slate-200/80 cursor-pointer text-sm no-underline flex items-center justify-center gap-2 active:scale-[0.99]"
>
<span className="material-symbols-outlined text-[20px]">support_agent</span>
Contact Support Team
</a>
<button
onClick={() => {
sessionStorage.clear();
localStorage.removeItem('wss_token');
localStorage.removeItem('wss_refresh_token');
localStorage.removeItem('superAdminActiveTab');
localStorage.removeItem('supportEngineerActiveTab');
window.location.href = '/login';
}}
className="w-full text-slate-500 hover:text-red-600 text-xs font-bold py-1.5 transition-colors border-0 bg-transparent cursor-pointer mt-1"
>
Clear Session & Return to Login
</button>
</div>
</div>
</div>
);
}
return this.props.children;
}
}
|