Skip to content

Commit 63655a0

Browse files
committed
feat(web): error-page
1 parent 49932e2 commit 63655a0

File tree

4 files changed

+214
-79
lines changed

4 files changed

+214
-79
lines changed

web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
"react": "^18.3.1",
107107
"react-chartjs-2": "^4.3.1",
108108
"react-dom": "^18.3.1",
109-
"react-error-boundary": "^3.1.4",
109+
"react-error-boundary": "^4.1.2",
110110
"react-identicons": "^1.2.5",
111111
"react-is": "^18.3.1",
112112
"react-loading-skeleton": "^3.5.0",

web/src/app.tsx

Lines changed: 78 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React, { lazy, Suspense } from "react";
22

3+
import { ErrorBoundary } from "react-error-boundary";
34
import { Route } from "react-router-dom";
45

56
import "react-loading-skeleton/dist/skeleton.css";
67
import "react-toastify/dist/ReactToastify.css";
8+
79
import AtlasProvider from "context/AtlasProvider";
810
import GraphqlBatcherProvider from "context/GraphqlBatcher";
911
import IsListProvider from "context/IsListProvider";
@@ -22,84 +24,87 @@ import Web3Provider from "context/Web3Provider";
2224
import Loader from "components/Loader";
2325
import Layout from "layout/index";
2426

27+
import ErrorFallback from "./components/ErrorFallback";
2528
import { SentryRoutes } from "./utils/sentry";
2629

2730
const App: React.FC = () => {
2831
return (
2932
<StyledComponentsProvider>
30-
<Web3Provider>
31-
<QueryClientProvider>
32-
<GraphqlBatcherProvider>
33-
<AtlasProvider>
34-
<IsListProvider>
35-
<NewDisputeProvider>
36-
<SentryRoutes>
37-
<Route path="/" element={<Layout />}>
38-
<Route
39-
index
40-
element={
41-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
42-
<Home />
43-
</Suspense>
44-
}
45-
/>
46-
<Route
47-
path="cases/*"
48-
element={
49-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
50-
<Cases />
51-
</Suspense>
52-
}
53-
/>
54-
<Route
55-
path="courts/*"
56-
element={
57-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
58-
<Courts />
59-
</Suspense>
60-
}
61-
/>
62-
<Route
63-
path="dashboard/:page/:order/:filter"
64-
element={
65-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
66-
<Dashboard />
67-
</Suspense>
68-
}
69-
/>
70-
<Route
71-
path="resolver/*"
72-
element={
73-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
74-
<DisputeResolver />
75-
</Suspense>
76-
}
77-
/>
78-
<Route
79-
path="get-pnk/*"
80-
element={
81-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
82-
<GetPnk />
83-
</Suspense>
84-
}
85-
/>
86-
<Route
87-
path="settings/*"
88-
element={
89-
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
90-
<Settings />
91-
</Suspense>
92-
}
93-
/>
94-
<Route path="*" element={<h1>Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯</h1>} />
95-
</Route>
96-
</SentryRoutes>
97-
</NewDisputeProvider>
98-
</IsListProvider>
99-
</AtlasProvider>
100-
</GraphqlBatcherProvider>
101-
</QueryClientProvider>
102-
</Web3Provider>
33+
<ErrorBoundary FallbackComponent={ErrorFallback}>
34+
<Web3Provider>
35+
<QueryClientProvider>
36+
<GraphqlBatcherProvider>
37+
<AtlasProvider>
38+
<IsListProvider>
39+
<NewDisputeProvider>
40+
<SentryRoutes>
41+
<Route path="/" element={<Layout />}>
42+
<Route
43+
index
44+
element={
45+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
46+
<Home />
47+
</Suspense>
48+
}
49+
/>
50+
<Route
51+
path="cases/*"
52+
element={
53+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
54+
<Cases />
55+
</Suspense>
56+
}
57+
/>
58+
<Route
59+
path="courts/*"
60+
element={
61+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
62+
<Courts />
63+
</Suspense>
64+
}
65+
/>
66+
<Route
67+
path="dashboard/:page/:order/:filter"
68+
element={
69+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
70+
<Dashboard />
71+
</Suspense>
72+
}
73+
/>
74+
<Route
75+
path="resolver/*"
76+
element={
77+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
78+
<DisputeResolver />
79+
</Suspense>
80+
}
81+
/>
82+
<Route
83+
path="get-pnk/*"
84+
element={
85+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
86+
<GetPnk />
87+
</Suspense>
88+
}
89+
/>
90+
<Route
91+
path="settings/*"
92+
element={
93+
<Suspense fallback={<Loader width={"48px"} height={"48px"} />}>
94+
<Settings />
95+
</Suspense>
96+
}
97+
/>
98+
<Route path="*" element={<h1>Justice not found here ¯\_( ͡° ͜ʖ ͡°)_/¯</h1>} />
99+
</Route>
100+
</SentryRoutes>
101+
</NewDisputeProvider>
102+
</IsListProvider>
103+
</AtlasProvider>
104+
</GraphqlBatcherProvider>
105+
</QueryClientProvider>
106+
</Web3Provider>
107+
</ErrorBoundary>
103108
</StyledComponentsProvider>
104109
);
105110
};

web/src/components/ErrorFallback.tsx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import React from "react";
2+
import styled, { css } from "styled-components";
3+
4+
import { FallbackProps } from "react-error-boundary";
5+
import { Link } from "react-router-dom";
6+
7+
import { Button } from "@kleros/ui-components-library";
8+
9+
import ErrorIcon from "svgs/icons/warning-outline.svg";
10+
11+
import { landscapeStyle } from "styles/landscapeStyle";
12+
import { responsiveSize } from "styles/responsiveSize";
13+
14+
import HeroImage from "./HeroImage";
15+
16+
const Container = styled.div`
17+
width: 100%;
18+
height: 100vh;
19+
background-color: ${({ theme }) => theme.lightBackground};
20+
padding: ${responsiveSize(32, 80)} ${responsiveSize(24, 136)} ${responsiveSize(76, 96)};
21+
max-width: 1780px;
22+
margin: 0 auto;
23+
`;
24+
25+
const ErrorContainer = styled.div`
26+
display: flex;
27+
width: 100%;
28+
gap: 48px 16px;
29+
flex-direction: column;
30+
justify-content: center;
31+
align-items: center;
32+
${landscapeStyle(
33+
() => css`
34+
flex-direction: row;
35+
justify-content: space-between;
36+
`
37+
)}
38+
`;
39+
40+
const InfoWrapper = styled.div`
41+
display: flex;
42+
flex-direction: column;
43+
gap: 32px;
44+
align-items: center;
45+
flex: 1;
46+
${landscapeStyle(
47+
() => css`
48+
align-items: start;
49+
`
50+
)}
51+
`;
52+
53+
const textCss = css`
54+
margin: 0;
55+
text-align: center;
56+
white-space: pre-line;
57+
58+
${landscapeStyle(
59+
() => css`
60+
text-align: left;
61+
`
62+
)}
63+
`;
64+
65+
const Header = styled.h1`
66+
${textCss}
67+
`;
68+
69+
const Subtitle = styled.h3`
70+
${textCss}
71+
max-width: 735px;
72+
`;
73+
74+
const HeaderIconContainer = styled.div`
75+
svg {
76+
width: 64px;
77+
height: 64px;
78+
path {
79+
fill: ${({ theme }) => theme.error};
80+
}
81+
}
82+
`;
83+
84+
const ButtonsContainer = styled.div`
85+
display: flex;
86+
gap: 16px;
87+
`;
88+
89+
const IconContainer = styled.div`
90+
svg {
91+
width: 250px;
92+
height: 250px;
93+
path {
94+
fill: ${({ theme }) => theme.whiteBackground};
95+
}
96+
}
97+
`;
98+
99+
const ErrorFallback: React.FC<FallbackProps> = ({ error, resetErrorBoundary }) => {
100+
// eslint-disable-next-line no-console
101+
console.log("Error:", { error });
102+
103+
return (
104+
<>
105+
<HeroImage />
106+
<Container>
107+
<ErrorContainer>
108+
<InfoWrapper>
109+
<HeaderIconContainer>
110+
<ErrorIcon />
111+
</HeaderIconContainer>
112+
<Header>Ooops, Something went wrong in Athens!</Header>
113+
<Subtitle>Please reload the page or contact us if the issue is not resolved.</Subtitle>
114+
<ButtonsContainer>
115+
<Button text={"Reload"} onClick={resetErrorBoundary} />
116+
<Link to={"https://t.me/kleros"}>
117+
<Button text={"Contact us"} />
118+
</Link>
119+
</ButtonsContainer>
120+
</InfoWrapper>
121+
<IconContainer>
122+
<ErrorIcon />
123+
</IconContainer>
124+
</ErrorContainer>
125+
</Container>
126+
</>
127+
);
128+
};
129+
130+
export default ErrorFallback;

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5248,7 +5248,7 @@ __metadata:
52485248
react: "npm:^18.3.1"
52495249
react-chartjs-2: "npm:^4.3.1"
52505250
react-dom: "npm:^18.3.1"
5251-
react-error-boundary: "npm:^3.1.4"
5251+
react-error-boundary: "npm:^4.1.2"
52525252
react-identicons: "npm:^1.2.5"
52535253
react-is: "npm:^18.3.1"
52545254
react-loading-skeleton: "npm:^3.5.0"
@@ -29441,14 +29441,14 @@ __metadata:
2944129441
languageName: node
2944229442
linkType: hard
2944329443

29444-
"react-error-boundary@npm:^3.1.4":
29445-
version: 3.1.4
29446-
resolution: "react-error-boundary@npm:3.1.4"
29444+
"react-error-boundary@npm:^4.1.2":
29445+
version: 4.1.2
29446+
resolution: "react-error-boundary@npm:4.1.2"
2944729447
dependencies:
2944829448
"@babel/runtime": "npm:^7.12.5"
2944929449
peerDependencies:
2945029450
react: ">=16.13.1"
29451-
checksum: 10/7418637bf352b88f35ff3798e6faa094ee046df9d422fc08f54c017892c3c0738dac661ba3d64d97209464e7a60e7fbbeffdbeaee5edc38f3aaf5f1f4a8bf610
29451+
checksum: 10/a8b59e5ef891bb6c48874d12c72bbd1a9292a56751adeee5666e228bd3a4913084329a9c21f7baafa0df68dc6d25e18883edb25946ce5763981885cbb93786eb
2945229452
languageName: node
2945329453
linkType: hard
2945429454

0 commit comments

Comments
 (0)