71 lines
1.7 KiB
TypeScript
71 lines
1.7 KiB
TypeScript
import type { ReactNode } from 'react'
|
|
import { Button, Center, Stack, Text } from '@mantine/core'
|
|
import { RefreshCw } from 'lucide-react'
|
|
|
|
interface ServerErrorStateProps {
|
|
title?: string
|
|
description?: string
|
|
onRetry?: () => void
|
|
retrying?: boolean
|
|
retryLabel?: string
|
|
glyph?: ReactNode
|
|
}
|
|
|
|
export function ServerErrorState({
|
|
title = 'Something went wrong',
|
|
description = 'The server returned an error while loading this page.',
|
|
onRetry,
|
|
retrying = false,
|
|
retryLabel = 'Retry',
|
|
glyph,
|
|
}: ServerErrorStateProps) {
|
|
const normalizedDescription = typeof description === 'string' ? description.trim() : ''
|
|
const showDescription =
|
|
normalizedDescription.length > 0 &&
|
|
normalizedDescription !== 'HTTP 500' &&
|
|
normalizedDescription !== 'HTTP 500.'
|
|
|
|
return (
|
|
<Center flex={1}>
|
|
<Stack
|
|
align="center"
|
|
justify="center"
|
|
gap="xs"
|
|
py="xl"
|
|
style={{ minHeight: '60vh', width: '100%' }}
|
|
>
|
|
{glyph ?? (
|
|
<Text
|
|
style={{
|
|
fontSize: 72,
|
|
lineHeight: 1,
|
|
letterSpacing: '-0.06em',
|
|
fontWeight: 600,
|
|
}}
|
|
>
|
|
500
|
|
</Text>
|
|
)}
|
|
<Text size="xl" fw={600}>
|
|
{title}
|
|
</Text>
|
|
{showDescription ? (
|
|
<Text ta="center" maw={520} c="dimmed">
|
|
{normalizedDescription}
|
|
</Text>
|
|
) : null}
|
|
{onRetry ? (
|
|
<Button
|
|
onClick={onRetry}
|
|
loading={retrying}
|
|
leftSection={<RefreshCw size={16} />}
|
|
variant="default"
|
|
>
|
|
{retryLabel}
|
|
</Button>
|
|
) : null}
|
|
</Stack>
|
|
</Center>
|
|
)
|
|
}
|