94 lines
2.1 KiB
TypeScript

import type { ReactNode } from 'react'
import {
isRouteErrorResponse,
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from 'react-router'
import type { Route } from './+types/root'
import './app.css'
import { APP, META_TITLE_CONFIG } from './configs/meta'
export const links: Route.LinksFunction = () => [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossOrigin: 'anonymous',
},
]
export const meta = ({ location }: Route.MetaArgs) => {
const { pathname } = location
const segments = pathname.split('/')
const path = segments.length > 4 ? segments.slice(0, 4).join('/') : pathname
const pageTitle = META_TITLE_CONFIG.find((meta) => meta.path === path)?.title
const metaTitle = APP.title
const title = `${pageTitle ? `${pageTitle} - ` : ''}${metaTitle}`
return [
{
title,
},
]
}
export const Layout = ({ children }: { children: ReactNode }) => {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
)
}
export const ErrorBoundary = ({ error }: Route.ErrorBoundaryProps) => {
let message = 'Oops!'
let details = 'An unexpected error occurred.'
let stack: string | undefined
if (isRouteErrorResponse(error)) {
message = error.status === 404 ? '404' : 'Error'
details =
error.status === 404
? 'The requested page could not be found.'
: error.statusText || details
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message
stack = error.stack
}
return (
<main className="container mx-auto p-4">
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full p-4 whitespace-pre-wrap">
<code>{stack}</code>
</pre>
)}
</main>
)
}
const App = () => {
return <Outlet />
}
export default App