/** * Authenticated layout variant * Full application layout with sidebar, navigation, support drawer, and payment banner * Used for all main application pages when user is authenticated */ import type { PropsWithChildren } from "react"; import Head from "next/head"; import { SidebarProvider, SidebarInset } from "@/src/components/ui/sidebar"; import { AppSidebar } from "@/src/components/nav/app-sidebar"; import { Toaster } from "@/src/components/ui/sonner"; import { PaymentBannerProvider } from "@/src/features/payment-banner"; import { ResizableContent } from "../components/ResizableContent"; import { ThemeToggle } from "@/src/features/theming/ThemeToggle"; import type { Session } from "next-auth"; import type { NavigationItem } from "@/src/components/layouts/utilities/routes"; import type { RouteGroup } from "@/src/components/layouts/routes"; import dynamic from "next/dynamic"; const CommandMenu = dynamic( () => import("@/src/features/command-k-menu/CommandMenu").then((mod) => ({ default: mod.CommandMenu, })), { ssr: false, }, ); const PaymentBanner = dynamic( () => import("@/src/features/payment-banner").then((mod) => ({ default: mod.PaymentBanner, })), { ssr: false, }, ); /** Grouped navigation structure returned by processNavigation */ type GroupedNavigation = { ungrouped: NavigationItem[]; grouped: Partial> | null; flattened: NavigationItem[]; }; type AuthenticatedLayoutProps = PropsWithChildren<{ session: Session; navigation: { mainNavigation: GroupedNavigation; secondaryNavigation: GroupedNavigation; navigation: NavigationItem[]; }; metadata: { title: string; faviconPath: string; favicon256Path: string; appleTouchIconPath: string; }; onSignOut: () => void; }>; /** * Full authenticated layout with all features: * - AppSidebar with navigation * - Payment banner (conditional) * - Support drawer * - Command menu (Cmd/Ctrl+K) * - Toast notifications * - Dynamic page metadata */ export function AuthenticatedLayout({ children, session, navigation, metadata, onSignOut, }: AuthenticatedLayoutProps) { // Safe assertion: AuthenticatedLayout is only rendered after auth checks pass // in AppLayout, which guarantees session.user exists at this point const user = session.user; if (!user) { // This should never happen due to guards in AppLayout, but TypeScript needs this return null; } // User navigation items for sidebar dropdown const userNavProps = { user: { name: user.name ?? "", email: user.email ?? "", avatar: user.image ?? "", }, items: [ { name: "Account Settings", href: "/account/settings" }, { name: "Theme", onClick: () => {}, content: }, { name: "Sign out", onClick: onSignOut }, ], }; return ( <> {metadata.title}
{children}
); }