Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
car-crushers-portal/app/root.tsx
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
203 lines (180 sloc)
5.64 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | |
LiveReload, | |
Meta, | |
Outlet, | |
Scripts, | |
useCatch, | |
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 CatchBoundary() { | |
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.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" ? "" : document.cookie | |
)} | |
theme={theme} | |
> | |
<div className="App"> | |
<Navigation {...loaderData} /> | |
{children} | |
<Scripts /> | |
<LiveReload /> | |
</div> | |
</ChakraProvider> | |
</StrictMode> | |
); | |
return ( | |
<html lang="en-US"> | |
<head> | |
<Links /> | |
{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="style-nonce" content={loaderData.nonce} /> | |
<meta name="theme-color" content="#00a8f8" /> | |
<meta | |
name="viewport" | |
content="width=device-width, initial-scale=1.0" | |
/> | |
<Meta /> | |
</head> | |
<body>{body}</body> | |
</html> | |
); | |
} | |
); | |
return <Document>{child}</Document>; | |
} | |
export default function () { | |
const loaderData = useLoaderData<typeof loader>(); | |
return getMarkup(loaderData, <Outlet />); | |
} |