import { ChakraProvider, Container, cookieStorageManagerSSR, Heading, Link, Text, } from "@chakra-ui/react"; import { ClientStyleContext, ServerStyleContext } from "./context.js"; import fontStyle from "@fontsource/plus-jakarta-sans/index.css"; import Forbidden from "../components/Forbidden.js"; import globalStyles from "../index.css"; import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, useLoaderData, useRouteError, } from "@remix-run/react"; import { type ErrorResponse } from "@remix-run/router"; import { LinksFunction } from "@remix-run/cloudflare"; import Login from "../components/Login.js"; import Navigation from "../components/Navigation.js"; import { type ReactNode, StrictMode, useContext, useEffect } from "react"; import theme from "../theme.js"; import { withEmotionCache } from "@emotion/react"; export function ErrorBoundary() { const error = useRouteError() as ErrorResponse; if (!isRouteErrorResponse(error)) return getMarkup( { hide: true }, <Container maxW="container.lg" pt="8vh" textAlign="left"> <Heading size="4xl">???</Heading> <br /> <Text fontSize="xl">Something bad happened!</Text> <br /> <br /> <br /> <Text>Details: {error}</Text> <br /> <br /> <Link color="#646cff" onClick={() => location.reload()}> Refresh </Link> </Container>, ); const { status } = error; switch (status) { case 303: return ""; case 401: return getMarkup({ hide: true }, <Login />); case 403: return getMarkup({ hide: true }, <Forbidden />); case 404: return getMarkup( { hide: true }, <Container maxW="container.lg" pt="8vh" textAlign="left"> <Heading size="4xl">404</Heading> <br /> <Text fontSize="xl">There is nothing to find here.</Text> <br /> <br /> <br /> <Link color="#646cff" onClick={() => history.go(-1)}> Go back </Link> </Container>, ); default: return getMarkup( { hide: true }, <Container maxW="container.lg" pt="8vh" textAlign="left"> <Heading size="4xl">500</Heading> <br /> <Text fontSize="xl">S̶̡͈̠̗̠͖͙̭o̶̶͕͚̥͍̪̤m̸̨͏͈͔̖͚̖̰̱͞e҉̵͖͚͇̀t̕͟͠͏͎̺̯̲̱̣̤̠̟͙̠̙̫̬ḩ̸̭͓̬͎̙̀į̞̮͉͖̰̥̹͚̫̙̪̗̜̳̕ͅn҉͔̯̪̗̝̝͖̲͇͍͎̲̲̤̖̫͈̪͡g̴̰̻̙̝͉̭͇̖̰̝̙͕̼͙͘͜ ̵̶̫̥̳̲̘̻̗͈͕̭̲͇̘̜̺̟̥̖̥b̴̙̭̹͕̞͠r̞͎̠̩͈̖̰̞̯̯͢͢͠ͅo̝̯̗̹̳͍̰͉͕̘̰̠̺̥̰͔̕ͅk̵̸̻̠͕̺̦̦͖̲̺̦̞̝̞͞͡e̶͏̤̼̼͔̘̰̰̭͈̀͞͡</Text> <br /> <br /> <br /> <Link color="#646cff" onClick={() => location.reload()}> Reload </Link> </Container>, ); } } export const links: LinksFunction = () => { return [ { href: "/favicon.ico", rel: "icon" }, { href: "/files/logo192.png", rel: "apple-touch-icon", type: "image/png" }, { href: fontStyle, rel: "stylesheet" }, { href: globalStyles, rel: "stylesheet" }, ]; }; export async function loader({ context, }: { context: RequestContext; }): Promise<{ [k: string]: any }> { let data: { [k: string]: string } = {}; if (context.data.current_user) data = { ...context.data.current_user }; if (context.env.DSN) data.dsn = context.env.DSN; if (context.data.nonce) data.nonce = context.data.nonce; if (context.data.theme) data.theme = context.data.theme; return data; } export function meta() { return [{ title: "Car Crushers" }]; } function getMarkup( loaderData: { [k: string]: any }, child: ReactNode, ): JSX.Element { const Document = withEmotionCache( ({ children }: { children: ReactNode }, emotionCache) => { const serverStyleData = useContext(ServerStyleContext); const clientStyleData = useContext(ClientStyleContext); useEffect(() => { emotionCache.sheet.container = document.head; const tags = emotionCache.sheet.tags; emotionCache.sheet.flush(); tags.forEach((tag) => { (emotionCache.sheet as any)._insertTag(tag); }); clientStyleData?.reset(); }, []); const body = ( <StrictMode> <ChakraProvider colorModeManager={cookieStorageManagerSSR( typeof document === "undefined" ? `chakra-ui-color-mode=${loaderData.theme}` : document.cookie, )} theme={theme} > <div className="App"> <Navigation {...loaderData} /> {children} <Scripts /> </div> </ChakraProvider> </StrictMode> ); return ( <html data-theme={loaderData.theme} lang="en-US"> <head> <Links /> <style> {` :root { color-scheme: ${loaderData.theme}; } `} </style> {serverStyleData?.map(({ key, ids, css }) => ( <style key={key} data-emotion={`${key} ${ids.join(" ")}`} dangerouslySetInnerHTML={{ __html: css }} /> ))} <meta charSet="UTF-8" /> {loaderData.dsn ? ( <meta name="dsn" content={loaderData.dsn} /> ) : null} <meta name="theme-color" content="#00a8f8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <Meta /> </head> <body {...(loaderData.theme && { className: `chakra-ui-${loaderData.theme}`, })} > {body} </body> </html> ); }, ); return <Document>{child}</Document>; } export default function () { const loaderData = useLoaderData<typeof loader>(); return getMarkup(loaderData, <Outlet />); }