Files
panel/resources/scripts/components/elements/ScreenBlock.tsx
2022-11-05 02:51:09 +00:00

91 lines
2.3 KiB
TypeScript

import PageContentBlock from '@/components/elements/PageContentBlock'
import { Button } from '@mantine/core'
import { ComponentType } from 'react'
import { ExclaimationCircleIcon, LinkIcon } from '@heroicons/react/24/outline'
export interface IconProps {
className?: string
}
interface BaseProps {
title: string
icon?: ComponentType<IconProps>
message: string
full?: boolean
center?: boolean
onRetry?: () => void
onBack?: () => void
}
interface PropsWithRetry extends BaseProps {
onRetry?: () => void
onBack?: never
}
interface PropsWithBack extends BaseProps {
onBack?: () => void
onRetry?: never
}
export type ScreenBlockProps = PropsWithBack | PropsWithRetry
const ScreenBlock = ({
title,
icon: Icon,
message,
center,
onBack,
onRetry,
full,
}: ScreenBlockProps) => {
return (
<PageContentBlock
className={`${full && 'grid place-items-center min-h-screen -mt-10'}`}
title={title}
>
<div className={`w-full sm:max-w-md p-12 md:p-20 bg-white dark:bg-black rounded-md shadow-md text-center ${center && 'mx-auto'}`}>
{Icon && <Icon className='w-16 h-16 border dark:border-stone-600 rounded-md p-3 text-black dark:text-stone-400 mx-auto' />}
<h2 className='text-stone-900 dark:text-white font-bold text-4xl mt-6'>{title}</h2>
<p className='description-small mt-3'>{message}</p>
{(onBack || onRetry) && (
<div className='flex justify-center mt-3'>
<Button
onClick={() => (onRetry ? onRetry() : onBack ? onBack() : null)}
>
{onBack ? 'Go Back' : 'Retry'}
</Button>
</div>
)}
</div>
</PageContentBlock>
)
}
type ServerErrorProps = (Omit<PropsWithBack, 'icon' | 'title'> | Omit<PropsWithRetry, 'icon' | 'title'>) & {
title?: string;
};
export const ServerError = ({ title, ...props }: ServerErrorProps) => (
<ScreenBlock title={title || 'Something went wrong'} center icon={ExclaimationCircleIcon} {...props} />
);
export const NotFound = ({
title,
message,
onBack,
full,
}: Partial<Pick<BaseProps, 'title' | 'message' | 'onBack' | 'full'>>) => (
<ScreenBlock
title={title || '404'}
message={
message || "The link is either broken or doesn't exist on the server."
}
icon={LinkIcon}
full={full}
onBack={onBack}
/>
)
export default ScreenBlock