Files
ALwrity/frontend/src/components/ErrorBoundary.tsx
2025-08-06 12:48:02 +05:30

148 lines
4.2 KiB
TypeScript

import React, { Component, ErrorInfo, ReactNode } from 'react';
import {
Box,
Typography,
Button,
Paper,
Alert,
AlertTitle
} from '@mui/material';
import { Refresh, BugReport, Home } from '@mui/icons-material';
interface Props {
children: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
errorInfo?: ErrorInfo;
}
class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
this.setState({ error, errorInfo });
// Log error to monitoring service (e.g., Sentry)
// logErrorToService(error, errorInfo);
}
handleRetry = () => {
this.setState({ hasError: false, error: undefined, errorInfo: undefined });
};
handleGoHome = () => {
window.location.href = '/';
};
render() {
if (this.state.hasError) {
return (
<Box
sx={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
p: 3,
}}
>
<Paper
elevation={24}
sx={{
maxWidth: 500,
p: 4,
borderRadius: 3,
background: 'rgba(255, 255, 255, 0.95)',
backdropFilter: 'blur(10px)',
border: '1px solid rgba(255, 255, 255, 0.2)',
}}
>
<Alert severity="error" sx={{ mb: 3 }}>
<AlertTitle>Something went wrong</AlertTitle>
We encountered an unexpected error. Please try again.
</Alert>
<Typography variant="h5" gutterBottom sx={{ fontWeight: 600 }}>
Oops! Something went wrong
</Typography>
<Typography variant="body1" color="text.secondary" sx={{ mb: 3 }}>
We're sorry, but something unexpected happened. Our team has been notified and is working to fix this issue.
</Typography>
{process.env.NODE_ENV === 'development' && this.state.error && (
<Box sx={{ mb: 3, p: 2, bgcolor: 'rgba(0,0,0,0.05)', borderRadius: 1 }}>
<Typography variant="body2" fontFamily="monospace" sx={{ fontSize: '0.75rem' }}>
{this.state.error.toString()}
</Typography>
</Box>
)}
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
<Button
variant="contained"
onClick={this.handleRetry}
startIcon={<Refresh />}
sx={{
borderRadius: 2,
textTransform: 'none',
fontWeight: 600,
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
'&:hover': {
background: 'linear-gradient(135deg, #5a6fd8 0%, #6a4190 100%)',
}
}}
>
Try Again
</Button>
<Button
variant="outlined"
onClick={this.handleGoHome}
startIcon={<Home />}
sx={{
borderRadius: 2,
textTransform: 'none',
fontWeight: 600,
}}
>
Go Home
</Button>
<Button
variant="text"
startIcon={<BugReport />}
onClick={() => {
// Open support ticket or contact form
window.open('mailto:support@alwrity.com?subject=Error Report', '_blank');
}}
sx={{
textTransform: 'none',
fontWeight: 600,
}}
>
Report Issue
</Button>
</Box>
</Paper>
</Box>
);
}
return this.props.children;
}
}
export default ErrorBoundary;