|
1 | 1 | import { useEffect } from 'react'; |
2 | 2 |
|
| 3 | +import { Button } from '@douglasneuroinformatics/libui/components'; |
| 4 | +import { useDownload } from '@douglasneuroinformatics/libui/hooks'; |
| 5 | +import { isAxiosError } from 'axios'; |
| 6 | +import { getReasonPhrase } from 'http-status-codes'; |
| 7 | +import { serializeError } from 'serialize-error'; |
| 8 | + |
3 | 9 | export type ErrorPageProps = { |
4 | | - error: { |
5 | | - message: string; |
6 | | - }; |
| 10 | + error: unknown; |
7 | 11 | }; |
8 | 12 |
|
9 | 13 | export const ErrorPage = ({ error }: ErrorPageProps) => { |
| 14 | + const download = useDownload(); |
| 15 | + |
10 | 16 | useEffect(() => { |
11 | 17 | console.error(error); |
12 | 18 | }, [error]); |
13 | 19 |
|
| 20 | + let heading = 'Unknown Error'; |
| 21 | + if (isAxiosError(error) && error.status) { |
| 22 | + heading = `${error.status} - ${getReasonPhrase(error.status)}`; |
| 23 | + } |
| 24 | + |
14 | 25 | return ( |
15 | 26 | <div className="flex min-h-screen flex-col items-center justify-center gap-1 p-3 text-center"> |
16 | | - <h1 className="text-muted-foreground text-sm font-semibold uppercase tracking-wide">Unexpected Error</h1> |
17 | | - <h3 className="text-3xl font-extrabold tracking-tight sm:text-4xl md:text-5xl">Something Went Wrong</h3> |
| 27 | + <h1 className="text-muted-foreground text-sm font-semibold uppercase tracking-wide">Something Went Wrong</h1> |
| 28 | + <h3 className="text-3xl font-extrabold tracking-tight sm:text-4xl md:text-5xl">{heading}</h3> |
18 | 29 | <p className="text-muted-foreground mt-2 max-w-prose text-sm sm:text-base"> |
19 | | - We apologize for the inconvenience. Please contact us for further assistance. |
| 30 | + We apologize for the inconvenience. Please download the error report using the button below and send it to your |
| 31 | + platform administrator for further assistance. |
20 | 32 | </p> |
21 | | - <div className="mt-6"> |
22 | | - <button |
23 | | - className="text-sky-800 underline-offset-4 hover:text-sky-700 hover:underline dark:text-sky-200 dark:hover:text-sky-300" |
| 33 | + <div className="mt-6 flex gap-2"> |
| 34 | + <Button |
| 35 | + type="button" |
| 36 | + variant="outline" |
| 37 | + onClick={() => { |
| 38 | + void download('error.json', JSON.stringify(serializeError(error), null, 2)); |
| 39 | + }} |
| 40 | + > |
| 41 | + Error Report |
| 42 | + </Button> |
| 43 | + <Button |
24 | 44 | type="button" |
| 45 | + variant="primary" |
25 | 46 | onClick={() => { |
26 | 47 | window.location.assign(window.location.origin); |
27 | 48 | }} |
28 | 49 | > |
29 | | - Reload Page<span aria-hidden="true"> →</span> |
30 | | - </button> |
| 50 | + Reload Page |
| 51 | + </Button> |
31 | 52 | </div> |
32 | 53 | </div> |
33 | 54 | ); |
|
0 commit comments