import clsx from "clsx"; import { FC, HTMLAttributes } from "react"; import { createPortal } from "react-dom"; import { useMatch, useSearchParams } from "react-router-dom"; import { NavigationMenu } from "@dndbeyond/navigation-menu"; import { Footer } from "@dndbeyond/ttui/components/Footer"; import config from "~/config"; import useUser from "~/hooks/useUser"; import styles from "./styles.module.css"; const BASE_PATHNAME = config.basePathname; const NOTIFICATIONS_CACHE_KEY = "dndbNotificationsCache"; const seedNotificationsCache = () => { try { const existing = localStorage.getItem(NOTIFICATIONS_CACHE_KEY); const parsed = existing ? JSON.parse(existing) : null; const isValid = parsed && typeof parsed.expiresAtMs === "number" && Date.now() < parsed.expiresAtMs; if (!isValid) { localStorage.setItem( NOTIFICATIONS_CACHE_KEY, JSON.stringify({ expiresAtMs: Date.now() + 60 * 60 * 1000, counts: { unreadNotifications: null, unreadMessages: null, unreadReports: null, unreadAppeals: null, }, }) ); } } catch { // localStorage unavailable } }; interface LayoutProps extends HTMLAttributes {} export const Layout: FC = ({ children, ...props }) => { const [searchParams] = useSearchParams(); const isVttView = searchParams.get("view") === "vtt"; const isDev = process.env.NODE_ENV === "development"; const user = useUser(); const matchSheet = useMatch(`${BASE_PATHNAME}/:characterId/`); // Don't show the navigation in production if (!isDev) return <>{children}; // Seed the notifications cache so NavigationMenu skips the JWT fetch in local // dev, where the auth service is not proxied. seedNotificationsCache(); const navigationUser = user && user.avatarUrl ? { displayName: user.displayName, avatarUrl: user.avatarUrl, subscriptionTier: user.subscriptionTier as "Master", roles: user.roles, } : undefined; return (
{!isVttView && createPortal( , document.getElementById("header-wrapper")! )}
{children}
{!isVttView && (!matchSheet || matchSheet.pathname === "/characters/builder" || matchSheet.pathname === "/characters/premade") && createPortal(
); };