import { useEffect } from "react";
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { useAuth } from "../auth/AuthContext";
import { AppPwaUpdateNotice } from "../components/common/AppPwaUpdateNotice";
import { ErrorBoundary } from "../components/common/ErrorBoundary";
import { MobileBottomNav } from "../components/mobile/MobileBottomNav";
import { Sidebar } from "../components/navigation/Sidebar";
import { Topbar } from "../components/navigation/Topbar";
import { resolvePageMeta } from "../features/navigation/schema";
import { writeRecentVisit } from "../lib/recentVisits";
import { resolveMobileEquivalentPath, shouldPreferMobileWorkplace } from "../lib/runtimeContext";
export function AppShellLayout() {
const { permissions } = useAuth();
const location = useLocation();
const isMobileRoute = location.pathname.startsWith("/mobile");
const mobileSearchParams = new URLSearchParams(location.search);
const isMobileDeepRoute =
/^\/mobile\/(?:reimbursements|approvals|leave|purchase-requests)\/[^/]+$/.test(location.pathname) ||
(location.pathname === "/mobile/approvals" && mobileSearchParams.has("taskId"));
const showMobileBottomNav = isMobileRoute && !isMobileDeepRoute;
const mobileEquivalentPath = !isMobileRoute && shouldPreferMobileWorkplace()
? resolveMobileEquivalentPath(location.pathname, location.search)
: null;
useEffect(() => {
if (!isMobileRoute || typeof window === "undefined") {
return;
}
const updateViewportHeight = () => {
const height = Math.max(320, Math.floor(window.visualViewport?.height ?? window.innerHeight));
document.documentElement.style.setProperty("--mobile-viewport-height", `${height}px`);
};
updateViewportHeight();
const frameId = window.requestAnimationFrame(updateViewportHeight);
window.addEventListener("resize", updateViewportHeight);
window.addEventListener("orientationchange", updateViewportHeight);
window.visualViewport?.addEventListener("resize", updateViewportHeight);
window.visualViewport?.addEventListener("scroll", updateViewportHeight);
return () => {
window.cancelAnimationFrame(frameId);
window.removeEventListener("resize", updateViewportHeight);
window.removeEventListener("orientationchange", updateViewportHeight);
window.visualViewport?.removeEventListener("resize", updateViewportHeight);
window.visualViewport?.removeEventListener("scroll", updateViewportHeight);
};
}, [isMobileRoute]);
useEffect(() => {
const pathname = location.pathname;
if (!pathname || pathname === "/login" || pathname.startsWith("/mobile/")) {
return;
}
writeRecentVisit(pathname, resolvePageMeta(pathname, permissions).title, permissions);
}, [location.pathname, permissions]);
if (mobileEquivalentPath && mobileEquivalentPath !== `${location.pathname}${location.search}`) {
return