"use client"; import { useEffect, useRef, type ReactNode } from "react"; import { usePathname } from "next/navigation"; import { Sidebar } from "../../components/shell/sidebar"; import { CommandPalette } from "../../components/shell/command-palette"; import { BottomNav } from "../../components/mobile/bottom-nav"; import { MobileTopBar } from "../../components/mobile/top-bar"; import { AuthProvider, useAuth } from "../../lib/auth-store"; import { AuthGate, SessionStatus } from "../../components/auth/auth-gate"; import { useApiResource } from "../../lib/use-api"; import type { DraftRecord } from "../../lib/api-types"; import { useIsMobile } from "../../hooks/use-is-mobile"; const titles: Record = { streams: "Home", search: "Search", inbox: "Inbox", approvals: "Approvals", more: "More", compose: "New post", calendar: "Calendar", video: "Video", analytics: "Analytics", connections: "Connections", team: "Team", audit: "Audit log", onboarding: "Welcome", settings: "Settings", archive: "Archive", files: "Files", }; const rootTabs = new Set(["/streams", "/search", "/inbox", "/more"]); const scrollPositions = new Map(); const identity = (drafts: DraftRecord[]): DraftRecord[] => drafts; const emptyDrafts: DraftRecord[] = []; function scrollableChildren(main: HTMLElement): HTMLElement[] { return Array.from(main.querySelectorAll("*")).filter((element) => element.scrollHeight > element.clientHeight && /auto|scroll/.test(getComputedStyle(element).overflowY)); } function Shell({ children }: { children: ReactNode }): React.ReactElement { const pathname = usePathname(); const mobile = useIsMobile(); const { can } = useAuth(); const drafts = useApiResource("/publishing/drafts", identity, emptyDrafts, { state: "in_review", limit: 100 }); // Badge comes from live approvals-in-review only — 0 while loading/sample/forbidden, never fixture counts. const approvals = can("approval.grant") && drafts.source === "live" ? drafts.data.length : 0; const mainRef = useRef(null); useEffect(() => { const main = mainRef.current; if (main === null || !mobile) return; const saved = scrollPositions.get(pathname); const restore = window.setTimeout(() => { main.scrollTop = saved?.main ?? 0; scrollableChildren(main).forEach((element, index) => { element.scrollTop = saved?.nested[index] ?? 0; }); }, 0); return () => { window.clearTimeout(restore); scrollPositions.set(pathname, { main: main.scrollTop, nested: scrollableChildren(main).map((element) => element.scrollTop) }); }; }, [pathname, mobile]); const title = titles[pathname.split("/")[1] ?? ""] ?? "Tactical Media Broadcast Hub"; return (
Press ⌘K for commands
{mobile && }
{children}
{mobile && }
{!mobile && }
); } export default function MainLayout({ children }: { children: ReactNode }): React.ReactNode { return {children}; }