blob: 9fc663618c1f5cff70ca98c5a7867edb9ba452ce [file] [log] [blame]
sogln3131a462025-04-15 17:01:40 +08001import {
2 isRouteErrorResponse,
3 Links,
4 Meta,
5 Outlet,
6 Scripts,
7 ScrollRestoration,
8} from "react-router";
9
10import type { Route } from "./+types/root";
11import "./app.css";
12
13export const links: Route.LinksFunction = () => [
14 { rel: "preconnect", href: "https://fonts.googleapis.com" },
15 {
16 rel: "preconnect",
17 href: "https://fonts.gstatic.com",
18 crossOrigin: "anonymous",
19 },
20 {
21 rel: "stylesheet",
22 href: "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap",
23 },
24];
25
26export function Layout({ children }: { children: React.ReactNode }) {
27 return (
28 <html lang="en">
29 <head>
30 <meta charSet="utf-8" />
31 <meta name="viewport" content="width=device-width, initial-scale=1" />
32 <Meta />
33 <Links />
34 </head>
35 <body>
36 {children}
37 <ScrollRestoration />
38 <Scripts />
39 </body>
40 </html>
41 );
42}
43
44export default function App() {
45 return <Outlet />;
46}
47
48export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
49 let message = "Oops!";
50 let details = "An unexpected error occurred.";
51 let stack: string | undefined;
52
53 if (isRouteErrorResponse(error)) {
54 message = error.status === 404 ? "404" : "Error";
55 details =
56 error.status === 404
57 ? "The requested page could not be found."
58 : error.statusText || details;
59 } else if (import.meta.env.DEV && error && error instanceof Error) {
60 details = error.message;
61 stack = error.stack;
62 }
63
64 return (
65 <main className="pt-16 p-4 container mx-auto">
66 <h1>{message}</h1>
67 <p>{details}</p>
68 {stack && (
69 <pre className="w-full p-4 overflow-x-auto">
70 <code>{stack}</code>
71 </pre>
72 )}
73 </main>
74 );
75}