import { useEffect } from "react"; import { Links, Meta, Outlet, Scripts, ScrollRestoration, isRouteErrorResponse, useLocation, Form, Link } from "react-router"; import type { LinksFunction } from "react-router"; import type { Route } from "./+types/root"; import * as Sentry from "@sentry/react"; import { useTranslation } from "react-i18next"; import { detectLocale } from "@trails-cool/i18n"; import { getSessionUser } from "~/lib/auth.server"; import { LocaleProvider } from "~/components/LocaleContext"; import stylesheet from "@trails-cool/ui/styles.css?url"; export const links: LinksFunction = () => [{ rel: "stylesheet", href: stylesheet }]; export function Layout({ children }: { children: React.ReactNode }) { const { i18n } = useTranslation(); return ( {children} ); } export async function loader({ request }: Route.LoaderArgs) { const user = await getSessionUser(request); const locale = detectLocale(request); return { user: user ? { id: user.id, username: user.username } : null, locale }; } function NavBar({ user }: { user: { id: string; username: string } | null }) { const { t } = useTranslation("journal"); const location = useLocation(); const isActive = (path: string) => location.pathname === path || location.pathname.startsWith(path + "/"); const linkClass = (path: string) => `text-sm font-medium ${ isActive(path) ? "text-blue-600" : "text-gray-600 hover:text-gray-900" }`; return ( ); } export default function App({ loaderData }: Route.ComponentProps) { const user = loaderData?.user; const locale = loaderData?.locale ?? "en"; useEffect(() => { if (user) { Sentry.setUser({ id: user.id, username: user.username }); } else { Sentry.setUser(null); } }, [user]); return ( ); } export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) { // Don't report expected HTTP errors (404, 403) to Sentry if (!(isRouteErrorResponse(error) && error.status < 500)) { Sentry.captureException(error); } const { t } = useTranslation(); if (isRouteErrorResponse(error)) { return (

{error.status}

{error.status === 404 && t("pageNotFound")} {error.status === 503 && t("serviceUnavailable")} {error.status !== 404 && error.status !== 503 && (error.statusText || t("error"))}

{t("goHome")}
); } return (

{t("error")}

{error instanceof Error ? error.message : t("error")}

{t("goHome")}
); }