Files
vexplor_dev/frontend/app/(main)/layout.tsx
2026-05-08 16:07:41 +09:00

57 lines
2.1 KiB
TypeScript

"use client";
import { useEffect } from "react";
import { usePathname } from "next/navigation";
import { AuthProvider } from "@/contexts/AuthContext";
import { MenuProvider } from "@/contexts/MenuContext";
import { MessengerProvider } from "@/contexts/MessengerContext";
import { AppLayout } from "@/components/layout/AppLayout";
import { ApprovalGlobalListener } from "@/components/approval/ApprovalGlobalListener";
import { ApprovalDetailModal } from "@/components/approval/ApprovalDetailModal";
import { MessengerFAB } from "@/components/messenger/MessengerFAB";
import { MessengerModal } from "@/components/messenger/MessengerModal";
export default function MainLayout({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const isPop = pathname.includes("/pop/");
// POP 영역은 라이트 모드 고정 — globals.css의 .dark override가 PopShell 인라인 색과 충돌해 부분만 변색되는 문제 방지.
// next-themes localStorage는 건드리지 않으므로 PC 모드 복귀 시 사용자 선호 그대로 유지.
useEffect(() => {
if (!isPop) return;
const root = document.documentElement;
const wasDark = root.classList.contains("dark");
if (wasDark) root.classList.remove("dark");
// next-themes ThemeProvider 가 부모 컴포넌트라 useEffect 가 우리보다 늦게 실행되면서
// dark 클래스를 다시 추가하는 케이스 차단. POP 동안만 활성.
const observer = new MutationObserver(() => {
if (root.classList.contains("dark")) {
root.classList.remove("dark");
}
});
observer.observe(root, { attributes: true, attributeFilter: ["class"] });
return () => {
observer.disconnect();
if (wasDark) root.classList.add("dark");
};
}, [isPop]);
if (isPop) {
return <>{children}</>;
}
return (
<AuthProvider>
<MenuProvider>
<MessengerProvider>
<AppLayout>{children}</AppLayout>
<ApprovalGlobalListener />
<ApprovalDetailModal />
<MessengerFAB />
<MessengerModal />
</MessengerProvider>
</MenuProvider>
</AuthProvider>
);
}