import imgSrc from '@/assets/generic-error.png'; import { History } from '@mui/icons-material'; import { Box, Button, Container, Typography, useTheme } from '@mui/material'; import { TitleComponent, useTranslate } from 'ra-core'; import { Title, useResetErrorBoundaryOnLocationChange } from 'ra-ui-materialui'; import { ComponentType, ErrorInfo, HtmlHTMLAttributes, useCallback } from 'react'; import { FallbackProps } from 'react-error-boundary'; type ErrorBoundaryProps = InternalErrorProps & { errorComponent?: ComponentType; title?: TitleComponent; resetErrorBoundary?: null | (() => void); }; function goBack() { window.history.go(-1); } function Error(props: ErrorBoundaryProps) { const { error, errorComponent: ErrorComponent, errorInfo, resetErrorBoundary, title } = props; const translate = useTranslate(); const theme = useTheme(); const isProduction = process.env.NODE_ENV === 'production'; useResetErrorBoundaryOnLocationChange(resetErrorBoundary); const handleBack = useCallback(() => { goBack(); }, []); if (ErrorComponent) { return ; } return ( <Typography component="img" src={imgSrc} style={{ width: '100%', maxWidth: 350, marginTop: theme.spacing(3), marginBottom: theme.spacing(2) }} alt="oops!" /> <Typography variant="h2" justifyContent={'center'} align="center" sx={{ mb: 2 }}> {translate(isProduction ? 'ra.page.error' : error.message, { _: error.message })} </Typography> <Button variant="contained" startIcon={<History sx={{ fontSize: 22 }} />} onClick={handleBack}> {translate('ra.action.back')} </Button> </Box> </Container> ); } interface InternalErrorProps extends Omit<HtmlHTMLAttributes<HTMLDivElement>, 'title'>, FallbackProps, ErrorProps { className?: string; } interface ErrorProps extends Pick<FallbackProps, 'error'> { errorInfo?: ErrorInfo; title?: TitleComponent; } export { Error }; export type { ErrorBoundaryProps, ErrorProps, InternalErrorProps };