feat(frontend): slightly better error page
This commit is contained in:
		
							parent
							
								
									0f51f01b34
								
							
						
					
					
						commit
						bb76c24017
					
				
					 4 changed files with 72 additions and 40 deletions
				
			
		
							
								
								
									
										22
									
								
								Foxnouns.Frontend/app/components/nav/BaseNavbar.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								Foxnouns.Frontend/app/components/nav/BaseNavbar.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | |||
| import { ReactNode } from "react"; | ||||
| import { Nav, Navbar } from "react-bootstrap"; | ||||
| import { Link } from "@remix-run/react"; | ||||
| import Logo from "~/components/nav/Logo"; | ||||
| 
 | ||||
| export default function BaseNavbar({ children, theme }: { children?: ReactNode; theme: string }) { | ||||
| 	return ( | ||||
| 		<Navbar expand="lg" className={`mb-4 mx-2 bg-${theme}`} color={theme} variant={theme}> | ||||
| 			<Navbar.Brand to="/" as={Link}> | ||||
| 				<Logo /> | ||||
| 			</Navbar.Brand> | ||||
| 			{children && ( | ||||
| 				<> | ||||
| 					<Navbar.Toggle aria-controls="main-navbar" /> | ||||
| 					<Navbar.Collapse id="main-navbar"> | ||||
| 						<Nav className="ms-auto">{children}</Nav> | ||||
| 					</Navbar.Collapse> | ||||
| 				</> | ||||
| 			)} | ||||
| 		</Navbar> | ||||
| 	); | ||||
| } | ||||
|  | @ -1,11 +1,11 @@ | |||
| import { Link, useFetcher } from "@remix-run/react"; | ||||
| import Meta from "~/lib/api/meta"; | ||||
| import { User, UserSettings } from "~/lib/api/user"; | ||||
| import Logo from "./Logo"; | ||||
| 
 | ||||
| import { Nav, Navbar, NavDropdown } from "react-bootstrap"; | ||||
| import { Nav, NavDropdown } from "react-bootstrap"; | ||||
| import { BrightnessHigh, BrightnessHighFill, MoonFill } from "react-bootstrap-icons"; | ||||
| import { useTranslation } from "react-i18next"; | ||||
| import BaseNavbar from "~/components/nav/BaseNavbar"; | ||||
| 
 | ||||
| export default function MainNavbar({ | ||||
| 	user, | ||||
|  | @ -49,36 +49,28 @@ export default function MainNavbar({ | |||
| 	const theme = settings.dark_mode ? "dark" : "light"; | ||||
| 
 | ||||
| 	return ( | ||||
| 		<Navbar expand="lg" className={`mb-4 mx-2 bg-${theme}`} color={theme} variant={theme}> | ||||
| 			<Navbar.Brand to="/" as={Link}> | ||||
| 				<Logo /> | ||||
| 			</Navbar.Brand> | ||||
| 			<Navbar.Toggle aria-controls="main-navbar" /> | ||||
| 			<Navbar.Collapse id="main-navbar"> | ||||
| 				<Nav className="ms-auto"> | ||||
| 					{userMenu} | ||||
| 					<fetcher.Form method="POST" action="/dark-mode"> | ||||
| 						<NavDropdown | ||||
| 							title={ | ||||
| 								<> | ||||
| 									<ThemeIcon /> {t("navbar.theme")} | ||||
| 								</> | ||||
| 							} | ||||
| 							align="end" | ||||
| 						> | ||||
| 							<NavDropdown.Item as="button" name="theme" value="auto" type="submit"> | ||||
| 								{t("navbar.theme-auto")} | ||||
| 							</NavDropdown.Item> | ||||
| 							<NavDropdown.Item as="button" name="theme" value="dark" type="submit"> | ||||
| 								{t("navbar.theme-dark")} | ||||
| 							</NavDropdown.Item> | ||||
| 							<NavDropdown.Item as="button" name="theme" value="light" type="submit"> | ||||
| 								{t("navbar.theme-light")} | ||||
| 							</NavDropdown.Item> | ||||
| 						</NavDropdown> | ||||
| 					</fetcher.Form> | ||||
| 				</Nav> | ||||
| 			</Navbar.Collapse> | ||||
| 		</Navbar> | ||||
| 		<BaseNavbar theme={theme}> | ||||
| 			{userMenu} | ||||
| 			<fetcher.Form method="POST" action="/dark-mode"> | ||||
| 				<NavDropdown | ||||
| 					title={ | ||||
| 						<> | ||||
| 							<ThemeIcon /> {t("navbar.theme")} | ||||
| 						</> | ||||
| 					} | ||||
| 					align="end" | ||||
| 				> | ||||
| 					<NavDropdown.Item as="button" name="theme" value="auto" type="submit"> | ||||
| 						{t("navbar.theme-auto")} | ||||
| 					</NavDropdown.Item> | ||||
| 					<NavDropdown.Item as="button" name="theme" value="dark" type="submit"> | ||||
| 						{t("navbar.theme-dark")} | ||||
| 					</NavDropdown.Item> | ||||
| 					<NavDropdown.Item as="button" name="theme" value="light" type="submit"> | ||||
| 						{t("navbar.theme-light")} | ||||
| 					</NavDropdown.Item> | ||||
| 				</NavDropdown> | ||||
| 			</fetcher.Form> | ||||
| 		</BaseNavbar> | ||||
| 	); | ||||
| } | ||||
|  |  | |||
|  | @ -24,6 +24,8 @@ import getLocalSettings from "./lib/settings.server"; | |||
| import { LANGUAGE } from "~/env.server"; | ||||
| import { errorCodeDesc } from "./components/ErrorAlert"; | ||||
| import { Container } from "react-bootstrap"; | ||||
| import { ReactNode } from "react"; | ||||
| import BaseNavbar from "~/components/nav/BaseNavbar"; | ||||
| 
 | ||||
| export const loader = async ({ request }: LoaderFunctionArgs) => { | ||||
| 	const meta = await serverRequest<Meta>("GET", "/meta"); | ||||
|  | @ -54,7 +56,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { | |||
| 	); | ||||
| }; | ||||
| 
 | ||||
| export function Layout({ children }: { children: React.ReactNode }) { | ||||
| export function Layout({ children }: { children: ReactNode }) { | ||||
| 	const { locale, settings } = useRouteLoaderData<typeof loader>("root") || { | ||||
| 		meta: { | ||||
| 			users: { | ||||
|  | @ -94,6 +96,8 @@ export function Layout({ children }: { children: React.ReactNode }) { | |||
| } | ||||
| 
 | ||||
| export function ErrorBoundary() { | ||||
| 	const data = useRouteLoaderData<typeof loader>("root"); | ||||
| 
 | ||||
| 	// eslint-disable-next-line @typescript-eslint/no-explicit-any
 | ||||
| 	const error: any = useRouteError(); | ||||
| 	const { t } = useTranslation(); | ||||
|  | @ -110,14 +114,17 @@ export function ErrorBoundary() { | |||
| 	return ( | ||||
| 		<html lang="en"> | ||||
| 			<head> | ||||
| 				<title> | ||||
| 					<>{t("error.title")} - pronouns.cc</> | ||||
| 				</title> | ||||
| 				<title>{t("error.title")}</title> | ||||
| 				<MetaComponent /> | ||||
| 				<Links /> | ||||
| 			</head> | ||||
| 			<body> | ||||
| 				{errorElem} | ||||
| 				{data?.meUser && data?.settings && data?.meta ? ( | ||||
| 					<Navbar meta={data.meta} user={data.meUser} settings={data.settings} /> | ||||
| 				) : ( | ||||
| 					<BaseNavbar theme="light" /> | ||||
| 				)} | ||||
| 				<Container>{errorElem}</Container> | ||||
| 				<Scripts /> | ||||
| 			</body> | ||||
| 		</html> | ||||
|  | @ -130,8 +137,14 @@ function ApiErrorElem({ error }: { error: ApiError }) { | |||
| 
 | ||||
| 	return ( | ||||
| 		<> | ||||
| 			<h4>{t("error.heading")}</h4> | ||||
| 			<h1>{t("error.heading")}</h1> | ||||
| 			<p>{errorDesc}</p> | ||||
| 			<details> | ||||
| 				<summary>{t("error.more-info")}</summary> | ||||
| 				<pre> | ||||
| 					<code>{JSON.stringify(error, null, "  ")}</code> | ||||
| 				</pre> | ||||
| 			</details> | ||||
| 		</> | ||||
| 	); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue