random imporvements
This commit is contained in:
@@ -1,53 +1,159 @@
|
||||
import {
|
||||
ErrorComponent,
|
||||
Link,
|
||||
rootRouteId,
|
||||
useMatch,
|
||||
useRouter,
|
||||
useNavigate,
|
||||
} from '@tanstack/react-router'
|
||||
import type { ErrorComponentProps } from '@tanstack/react-router'
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Text,
|
||||
Title,
|
||||
Stack,
|
||||
Group,
|
||||
Alert,
|
||||
Collapse,
|
||||
Code,
|
||||
ThemeIcon
|
||||
} from '@mantine/core'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { useEffect } from 'react'
|
||||
import toast from '@/lib/sonner'
|
||||
import { logger } from '@/lib/logger'
|
||||
import { ExclamationMarkIcon, XCircleIcon } from '@phosphor-icons/react'
|
||||
|
||||
export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
|
||||
const router = useRouter()
|
||||
const navigate = useNavigate()
|
||||
const isRoot = useMatch({
|
||||
strict: false,
|
||||
select: (state) => state.id === rootRouteId,
|
||||
})
|
||||
const [detailsOpened, { toggle: toggleDetails }] = useDisclosure(false)
|
||||
|
||||
console.error('DefaultCatchBoundary Error:', error)
|
||||
const errorMessage = error?.message || 'Unknown error'
|
||||
const errorStack = error?.stack || 'No stack trace available'
|
||||
|
||||
useEffect(() => {
|
||||
logger.error('DefaultCatchBoundary | ', error)
|
||||
|
||||
if (errorMessage.toLowerCase().includes('unauthenticated')) {
|
||||
toast.error('You\'ve been logged out')
|
||||
navigate({ to: '/login' })
|
||||
return
|
||||
}
|
||||
}, [error, errorMessage, navigate])
|
||||
|
||||
if (errorMessage.toLowerCase().includes('unauthorized')) {
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minHeight: '50vh',
|
||||
padding: 'var(--mantine-spacing-xl)',
|
||||
}}
|
||||
>
|
||||
<Stack align="center" gap="lg">
|
||||
<ThemeIcon color="red" size={80} radius="xl">
|
||||
<XCircleIcon size={48} />
|
||||
</ThemeIcon>
|
||||
<Title order={2} ta="center">Access Denied</Title>
|
||||
<Text size="lg" c="dimmed" ta="center">
|
||||
You don't have permission to access this.
|
||||
</Text>
|
||||
<Group>
|
||||
<Button
|
||||
variant="light"
|
||||
onClick={() => window.history.back()}
|
||||
>
|
||||
Go Back
|
||||
</Button>
|
||||
<Button
|
||||
component={Link}
|
||||
to="/"
|
||||
variant="filled"
|
||||
>
|
||||
Home
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-w-0 flex-1 p-4 flex flex-col items-center justify-center gap-6">
|
||||
<ErrorComponent error={error} />
|
||||
<div className="flex gap-2 items-center flex-wrap">
|
||||
<button
|
||||
onClick={() => {
|
||||
router.invalidate()
|
||||
}}
|
||||
className={`px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded text-white uppercase font-extrabold`}
|
||||
<Box
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minHeight: '50vh',
|
||||
padding: 'var(--mantine-spacing-xl)',
|
||||
}}
|
||||
>
|
||||
<Stack align="center" gap="lg" maw={600}>
|
||||
<ThemeIcon color="red" size={80} radius="xl">
|
||||
<ExclamationMarkIcon size={48} />
|
||||
</ThemeIcon>
|
||||
|
||||
<Title order={2} ta="center">Something went wrong</Title>
|
||||
|
||||
<Text size="lg" c="dimmed" ta="center">
|
||||
There was an unexpected error. Please try again later.
|
||||
</Text>
|
||||
|
||||
<Alert
|
||||
variant="light"
|
||||
color="red"
|
||||
title="Error Details"
|
||||
w="100%"
|
||||
>
|
||||
Try Again
|
||||
</button>
|
||||
{isRoot ? (
|
||||
<Link
|
||||
to="/"
|
||||
className={`px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded text-white uppercase font-extrabold`}
|
||||
<Text mb="sm">{errorMessage}</Text>
|
||||
<Button
|
||||
variant="subtle"
|
||||
size="compact-sm"
|
||||
onClick={toggleDetails}
|
||||
>
|
||||
Home
|
||||
</Link>
|
||||
) : (
|
||||
<Link
|
||||
to="/"
|
||||
className={`px-2 py-1 bg-gray-600 dark:bg-gray-700 rounded text-white uppercase font-extrabold`}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
window.history.back()
|
||||
}}
|
||||
{detailsOpened ? 'Hide' : 'Show'} technical details
|
||||
</Button>
|
||||
<Collapse in={detailsOpened}>
|
||||
<Code block mt="md" p="md">
|
||||
{errorStack}
|
||||
</Code>
|
||||
</Collapse>
|
||||
</Alert>
|
||||
|
||||
<Group>
|
||||
<Button
|
||||
variant="light"
|
||||
onClick={() => router.invalidate()}
|
||||
>
|
||||
Go Back
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
Try Again
|
||||
</Button>
|
||||
{isRoot ? (
|
||||
<Button
|
||||
component={Link}
|
||||
to="/"
|
||||
variant="filled"
|
||||
>
|
||||
Home
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant="filled"
|
||||
onClick={() => window.history.back()}
|
||||
>
|
||||
Go Back
|
||||
</Button>
|
||||
)}
|
||||
</Group>
|
||||
</Stack>
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user