75 lines
2.8 KiB
TypeScript
75 lines
2.8 KiB
TypeScript
import { useEffect, useState } from "react";
|
|
import { Outlet, useLocation } from "react-router-dom";
|
|
import { Sidebar } from "./Sidebar";
|
|
import { TopBar } from "./TopBar";
|
|
import { FloatingQAChat } from "@/components/ai-steward/FloatingQAChat";
|
|
import { MobileProjectBottomNav, PMFlowOsHeader, ResponsiveAICopilot } from "@/features/pmflow-os/components/PMFlowOsFrame";
|
|
|
|
export default function Layout() {
|
|
const location = useLocation();
|
|
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
|
|
const isProjectLaunchSurface = location.pathname === "/project-launch";
|
|
const isPMFlowOsSurface = [
|
|
"/command-center",
|
|
"/structured-extraction",
|
|
"/change-review",
|
|
"/memory-writeback-result",
|
|
"/work-graph",
|
|
"/execution-bridge",
|
|
"/release-growth",
|
|
"/team-layer",
|
|
"/project-memory",
|
|
].includes(location.pathname);
|
|
|
|
useEffect(() => {
|
|
setMobileSidebarOpen(false);
|
|
window.scrollTo({ top: 0, left: 0, behavior: "auto" });
|
|
const main = document.querySelector("main");
|
|
if (main instanceof HTMLElement) {
|
|
main.scrollTop = 0;
|
|
}
|
|
}, [location.pathname, location.search]);
|
|
|
|
return (
|
|
<div className="relative flex h-screen overflow-hidden bg-[#f6f8fc] dark:bg-slate-950">
|
|
<Sidebar open={mobileSidebarOpen} onClose={() => setMobileSidebarOpen(false)} />
|
|
{mobileSidebarOpen && (
|
|
<button
|
|
type="button"
|
|
aria-label="关闭菜单遮罩"
|
|
className="fixed inset-0 z-40 bg-slate-900/45 md:hidden"
|
|
onClick={() => setMobileSidebarOpen(false)}
|
|
/>
|
|
)}
|
|
<div className="flex min-w-0 flex-1 flex-col overflow-hidden">
|
|
{isProjectLaunchSurface ? (
|
|
<main className="min-h-0 flex-1 overflow-hidden bg-white">
|
|
<Outlet />
|
|
</main>
|
|
) : isPMFlowOsSurface ? (
|
|
<>
|
|
<PMFlowOsHeader onMenuToggle={() => setMobileSidebarOpen((open) => !open)} />
|
|
<div className="min-h-0 flex-1 overflow-hidden bg-[linear-gradient(180deg,_#fbfdff,_#f6f9ff_40%,_#f8fafc)] px-3 pb-3 pt-3 sm:px-4 sm:pb-4 md:px-5 md:pb-5">
|
|
<div className="mx-auto flex h-full w-full max-w-[1880px] flex-col gap-3">
|
|
<ResponsiveAICopilot />
|
|
<main className="min-w-0 flex-1 overflow-auto lg:pr-20 min-[1440px]:pr-0">
|
|
<Outlet />
|
|
</main>
|
|
</div>
|
|
</div>
|
|
<MobileProjectBottomNav />
|
|
</>
|
|
) : (
|
|
<>
|
|
<TopBar onMenuToggle={() => setMobileSidebarOpen((open) => !open)} />
|
|
<main className="flex-1 overflow-auto bg-[#f6f8fc] p-3 dark:bg-slate-950 sm:p-4 md:p-6">
|
|
<Outlet />
|
|
</main>
|
|
</>
|
|
)}
|
|
</div>
|
|
{!isProjectLaunchSurface && !isPMFlowOsSurface ? <FloatingQAChat /> : null}
|
|
</div>
|
|
);
|
|
}
|