Skip to content

Commit 623f4c5

Browse files
committed
feat: create generic error page
1 parent 4987525 commit 623f4c5

File tree

6 files changed

+143
-3
lines changed

6 files changed

+143
-3
lines changed

src/app/catalog/actions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export async function getServers(): Promise<V0ServerJson[]> {
1111

1212
if (resp.error) {
1313
console.error("[catalog] Failed to fetch servers:", resp.error);
14-
return [];
14+
throw new Error("Failed to fetch servers");
1515
}
1616

1717
if (!resp.data) {

src/app/catalog/error.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
import { ErrorPage } from "@/components/error-page";
5+
import { Button } from "@/components/ui/button";
6+
7+
interface ErrorProps {
8+
error: Error & { digest?: string };
9+
reset: () => void;
10+
}
11+
12+
export default function CatalogErrorPage({ error, reset }: ErrorProps) {
13+
useEffect(() => {
14+
console.error(error);
15+
}, [error]);
16+
17+
return (
18+
<ErrorPage
19+
title="Something went wrong"
20+
actions={
21+
<Button onClick={reset} variant="default">
22+
Try again
23+
</Button>
24+
}
25+
>
26+
An unexpected error occurred. Please try again.
27+
</ErrorPage>
28+
);
29+
}

src/app/error.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
"use client";
2+
3+
import { useEffect } from "react";
4+
import { ErrorPage } from "@/components/error-page";
5+
import { NavbarLogo } from "@/components/navbar-logo";
6+
import { Button } from "@/components/ui/button";
7+
8+
interface ErrorProps {
9+
error: Error & { digest?: string };
10+
reset: () => void;
11+
}
12+
13+
export default function RootErrorPage({ error, reset }: ErrorProps) {
14+
useEffect(() => {
15+
console.error(error);
16+
}, [error]);
17+
18+
return (
19+
<div className="flex flex-col h-screen">
20+
<header className="w-full border-b bg-muted/50 flex items-center justify-between pl-8 pr-4 h-16">
21+
<NavbarLogo />
22+
</header>
23+
<main className="flex flex-col flex-1 overflow-hidden px-4 py-5">
24+
<ErrorPage
25+
title="Something went wrong"
26+
actions={
27+
<Button onClick={reset} variant="default">
28+
Try again
29+
</Button>
30+
}
31+
>
32+
An unexpected error occurred. Please try again.
33+
</ErrorPage>
34+
</main>
35+
</div>
36+
);
37+
}

src/components/error-page/error-page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ReactNode } from "react";
2-
import { IllustrationNoLocation } from "@/components/illustrations/illustration-no-location";
2+
import { IllustrationError } from "@/components/illustrations/illustration-error";
33

44
interface ErrorPageProps {
55
title: string;
@@ -11,7 +11,7 @@ export function ErrorPage({ title, children, actions }: ErrorPageProps) {
1111
return (
1212
<div className="flex items-center justify-center min-h-[80vh]">
1313
<div className="flex flex-col items-center text-center gap-4 max-w-md">
14-
<IllustrationNoLocation className="size-40" />
14+
<IllustrationError className="size-40" />
1515

1616
<div className="space-y-2">
1717
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import type { SVGProps } from "react";
2+
3+
export const IllustrationError = (props: SVGProps<SVGSVGElement>) => (
4+
<svg
5+
xmlns="http://www.w3.org/2000/svg"
6+
viewBox="0 0 136 136"
7+
fill="none"
8+
aria-hidden="true"
9+
{...props}
10+
>
11+
<path
12+
fill="var(--color-background)"
13+
fillRule="evenodd"
14+
d="M28.5 116c-12.15 0-22-9.626-22-21.5S16.35 73 28.5 73c.517 0 1.03.017 1.537.052A34.205 34.205 0 0 1 29.5 67c0-18.778 15.222-34 34-34 14.991 0 27.716 9.702 32.239 23.17C96.81 56.056 97.899 56 99 56c16.845 0 30.5 13.431 30.5 30 0 15.741-12.325 28.727-28 29.978V116h-73zm11.996 0h-6.965 6.965z"
15+
clipRule="evenodd"
16+
/>
17+
<path
18+
stroke="var(--color-muted-foreground)"
19+
strokeLinecap="round"
20+
strokeWidth={2.5}
21+
d="M40.496 116h-6.965m-5.031 0c-12.15 0-22-9.626-22-21.5S16.35 73 28.5 73c.517 0 1.03.017 1.537.052A34.205 34.205 0 0 1 29.5 67c0-18.778 15.222-34 34-34 14.991 0 27.716 9.702 32.239 23.17C96.81 56.056 97.899 56 99 56c16.845 0 30.5 13.431 30.5 30 0 15.741-12.325 28.727-28 29.978V116h-73z"
22+
/>
23+
<path
24+
fill="transparent"
25+
fillRule="evenodd"
26+
d="M53.112 40.343c0 32.223 29.02 58.775 66.388 62.36-4.683 5.758-11.914 9.665-20.153 10.278V113H32.243c-8.142 0-21.743-3.43-21.743-18.452 0-15.021 10.574-18.451 21.743-18.451.475 0 .946.015 1.413.044-.324-1.685-.381-3.423-.494-5.194-.758-11.963 4.46-27.04 19.968-31.947-.012.447-.018.894-.018 1.343zm10.504 50.415c-3.038 0-5.502 2.434-5.502 5.437s2.464 5.437 5.502 5.437c3.039 0 5.502-2.434 5.502-5.437s-2.463-5.437-5.502-5.437z"
27+
clipRule="evenodd"
28+
/>
29+
<path
30+
stroke="var(--color-muted-foreground)"
31+
strokeWidth={2.5}
32+
d="M64 102a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11z"
33+
/>
34+
<path
35+
stroke="var(--color-muted-foreground)"
36+
strokeLinecap="round"
37+
strokeLinejoin="round"
38+
strokeWidth={2.5}
39+
d="m48.5 85 7-5.493-7-5.23M79.5 85l-7-5.493 7-5.23"
40+
/>
41+
<path
42+
stroke="var(--color-muted-foreground)"
43+
strokeLinecap="round"
44+
strokeWidth={2.5}
45+
d="M73.5 43a19.036 19.036 0 0 1 13.44 13.293"
46+
/>
47+
<path
48+
stroke="var(--color-muted-foreground)"
49+
strokeWidth={2}
50+
d="M94.5 26a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"
51+
/>
52+
<path
53+
fill="var(--color-muted-foreground)"
54+
d="M125.5 42a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"
55+
/>
56+
<path
57+
stroke="var(--color-muted-foreground)"
58+
strokeLinecap="round"
59+
strokeLinejoin="round"
60+
strokeWidth={2.5}
61+
d="m102.257 33.757 8.359 8.359m.127-8.359-8.359 8.359 8.359-8.359zM7.904 51.596l6 6m0-6-6 6 6-6z"
62+
/>
63+
<path
64+
fill="var(--color-muted-foreground)"
65+
d="M21.5 45a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"
66+
/>
67+
</svg>
68+
);

src/mocks/handlers.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ const scenarioHandlers = [
99
mockScenario("empty-servers").get("*/registry/v0.1/servers", () => {
1010
return HttpResponse.json({ servers: [], metadata: { count: 0 } });
1111
}),
12+
mockScenario("server-error").get("*/registry/v0.1/servers", () => {
13+
return HttpResponse.json(
14+
{ error: "Internal Server Error" },
15+
{ status: 500 },
16+
);
17+
}),
1218
];
1319

1420
export const handlers: RequestHandler[] = [

0 commit comments

Comments
 (0)