@@ -15,6 +15,7 @@ import ShareRoute from './ShareRoute';
15
15
import ChatRoute from './ChatRoute' ;
16
16
import Search from './Search' ;
17
17
import Root from './Root' ;
18
+ import { useRouteError } from 'react-router-dom' ;
18
19
19
20
const AuthLayout = ( ) => (
20
21
< AuthContextProvider >
@@ -23,14 +24,109 @@ const AuthLayout = () => (
23
24
</ AuthContextProvider >
24
25
) ;
25
26
27
+ function RouteErrorBoundary ( ) {
28
+ const typedError = useRouteError ( ) as {
29
+ message ?: string ;
30
+ stack ?: string ;
31
+ status ?: number ;
32
+ statusText ?: string ;
33
+ data ?: unknown ;
34
+ } ;
35
+
36
+ const errorDetails = {
37
+ message : typedError . message ?? 'An unexpected error occurred' ,
38
+ stack : typedError . stack ,
39
+ status : typedError . status ,
40
+ statusText : typedError . statusText ,
41
+ data : typedError . data ,
42
+ } ;
43
+
44
+ return (
45
+ < div
46
+ role = "alert"
47
+ className = "flex min-h-screen flex-col items-center justify-center bg-surface-primary bg-gradient-to-br"
48
+ >
49
+ < div className = "bg-surface-primary/60 mx-4 w-full max-w-4xl rounded-2xl border border-border-light p-8 shadow-2xl backdrop-blur-xl" >
50
+ < h2 className = "mb-6 text-center text-3xl font-medium tracking-tight text-text-primary" >
51
+ Oops! Something went wrong
52
+ </ h2 >
53
+
54
+ { /* Error Message */ }
55
+ < div className = "mb-4 rounded-xl border border-red-500/20 bg-red-500/5 p-4 text-sm text-gray-600 dark:text-gray-200" >
56
+ < h3 className = "mb-2 font-medium" > Error Message:</ h3 >
57
+ < pre className = "whitespace-pre-wrap text-sm font-light leading-relaxed text-text-primary" >
58
+ { errorDetails . message }
59
+ </ pre >
60
+ </ div >
61
+
62
+ { /* Status Information */ }
63
+ { ( typeof errorDetails . status === 'number' ||
64
+ typeof errorDetails . statusText === 'string' ) && (
65
+ < div className = "mb-4 rounded-xl border border-yellow-500/20 bg-yellow-500/5 p-4 text-sm text-text-primary" >
66
+ < h3 className = "mb-2 font-medium" > Status:</ h3 >
67
+ < p className = "text-text-primary" >
68
+ { typeof errorDetails . status === 'number' && `${ errorDetails . status } ` }
69
+ { typeof errorDetails . statusText === 'string' && errorDetails . statusText }
70
+ </ p >
71
+ </ div >
72
+ ) }
73
+
74
+ { /* Stack Trace - Collapsible */ }
75
+ { errorDetails . stack && (
76
+ < details className = "mb-4 rounded-xl border border-border-light p-4" >
77
+ < summary className = "mb-2 cursor-pointer text-sm font-medium text-text-primary" >
78
+ Stack Trace
79
+ </ summary >
80
+ < pre className = "overflow-x-auto whitespace-pre-wrap text-xs font-light leading-relaxed text-text-primary" >
81
+ { errorDetails . stack }
82
+ </ pre >
83
+ </ details >
84
+ ) }
85
+
86
+ { /* Additional Error Data */ }
87
+ { errorDetails . data && (
88
+ < details className = "mb-4 rounded-xl border border-border-light p-4" >
89
+ < summary className = "mb-2 cursor-pointer text-sm font-medium text-text-primary" >
90
+ Additional Details
91
+ </ summary >
92
+ < pre className = "whitespace-pre-wrap text-xs font-light leading-relaxed text-text-primary" >
93
+ { JSON . stringify ( errorDetails . data , null , 2 ) }
94
+ </ pre >
95
+ </ details >
96
+ ) }
97
+
98
+ < div className = "mt-6 flex flex-col gap-4" >
99
+ < p className = "text-sm font-light text-text-secondary" > Please try one of the following:</ p >
100
+ < ul className = "list-inside list-disc text-sm text-text-secondary" >
101
+ < li > Refresh the page</ li >
102
+ < li > Clear your browser cache</ li >
103
+ < li > Check your internet connection</ li >
104
+ < li > Contact the Admin if the issue persists</ li >
105
+ </ ul >
106
+ < div className = "mt-4 flex justify-center gap-4" >
107
+ < button
108
+ onClick = { ( ) => window . location . reload ( ) }
109
+ className = "rounded-lg bg-surface-submit px-4 py-2 text-white transition-colors hover:bg-surface-submit-hover"
110
+ >
111
+ Refresh Page
112
+ </ button >
113
+ </ div >
114
+ </ div >
115
+ </ div >
116
+ </ div >
117
+ ) ;
118
+ }
119
+
26
120
export const router = createBrowserRouter ( [
27
121
{
28
122
path : 'share/:shareId' ,
29
123
element : < ShareRoute /> ,
124
+ errorElement : < RouteErrorBoundary /> ,
30
125
} ,
31
126
{
32
127
path : '/' ,
33
128
element : < StartupLayout /> ,
129
+ errorElement : < RouteErrorBoundary /> ,
34
130
children : [
35
131
{
36
132
path : 'register' ,
@@ -49,9 +145,11 @@ export const router = createBrowserRouter([
49
145
{
50
146
path : 'verify' ,
51
147
element : < VerifyEmail /> ,
148
+ errorElement : < RouteErrorBoundary /> ,
52
149
} ,
53
150
{
54
151
element : < AuthLayout /> ,
152
+ errorElement : < RouteErrorBoundary /> ,
55
153
children : [
56
154
{
57
155
path : '/' ,
0 commit comments