[st] feat: 메뉴 경로에 '/cms' 포함 시 탭 로직 예외 처리
This commit is contained in:
@@ -1,54 +1,27 @@
|
||||
"use client";
|
||||
|
||||
|
||||
|
||||
import { Suspense, useCallback, useEffect, useMemo, useState } from "react";
|
||||
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
|
||||
|
||||
import {
|
||||
|
||||
getTabStoreState as getGridTabStoreState,
|
||||
|
||||
useTabStore as gridTabStore,
|
||||
|
||||
} from "@rsone/components";
|
||||
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
|
||||
|
||||
import { ENDPOINT } from "@/shared/config";
|
||||
|
||||
import { getCookie, useAlertStore, useMenuStore } from "@/shared/lib";
|
||||
|
||||
import { useStatisticsTabUrlSync } from "@/shared/lib/use-statistics-tab-url-sync";
|
||||
|
||||
import { isVerificationSelectionReportMenu } from "@/shared/lib/verification-selection-report";
|
||||
|
||||
import { StatisticsPageLayout } from "@/shared/ui/statistics-page-layout";
|
||||
|
||||
import { tokenManager } from "@/entities/auth";
|
||||
|
||||
import type { MenuItem } from "@/entities/menu";
|
||||
|
||||
import { MenuApi } from "@/entities/menu";
|
||||
|
||||
import { BaseLayout } from "@common/components";
|
||||
|
||||
import { getConfig } from "@common/config";
|
||||
|
||||
|
||||
|
||||
import { getTabStoreState, useTabStore } from "@/store/tab-store";
|
||||
|
||||
|
||||
|
||||
import VerificationSelectionReport from "@/components/statistics/VerificationSelectionReport";
|
||||
|
||||
|
||||
import { getTabStoreState, useTabStore } from "@/store/tab-store";
|
||||
|
||||
const appConfig = getConfig();
|
||||
|
||||
@@ -58,42 +31,22 @@ const appSiteId = getCookie("site-id-key") ?? "";
|
||||
|
||||
const isLoggedIn = !!userId;
|
||||
|
||||
|
||||
|
||||
function WithBaseLayoutInner({
|
||||
|
||||
children,
|
||||
|
||||
}: {
|
||||
|
||||
children: React.ReactNode;
|
||||
|
||||
}) {
|
||||
|
||||
function WithBaseLayoutInner({ children }: { children: React.ReactNode }) {
|
||||
const pathname = usePathname();
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
||||
|
||||
/** 탭 추가 없이 메뉴만 눌렀을 때 패널 유지 (다른 메뉴 클릭해도 유지) */
|
||||
|
||||
const [isVerificationSelectionReportPanelOpen, setReportPanelOpen] =
|
||||
|
||||
useState(false);
|
||||
|
||||
|
||||
|
||||
const setCurrentMenuInfo = useMenuStore(
|
||||
|
||||
(state) => state.setCurrentMenuInfo,
|
||||
|
||||
);
|
||||
|
||||
const currentMenuInfo = useMenuStore((state) => state.currentMenuInfo);
|
||||
|
||||
|
||||
|
||||
const addTab = useTabStore((state) => state.addTab);
|
||||
|
||||
const setActiveTab = useTabStore((state) => state.setActiveTab);
|
||||
@@ -108,16 +61,11 @@ function WithBaseLayoutInner({
|
||||
|
||||
const addTabForGrid = gridTabStore((state) => state.addTab);
|
||||
|
||||
const setActiveTabForGrid = gridTabStore((state) => state.setActiveTab);
|
||||
|
||||
const setMenuListForGrid = gridTabStore((state) => state.setMenuList);
|
||||
|
||||
const alert = useAlertStore((state) => state.setMessage);
|
||||
|
||||
|
||||
|
||||
const { syncTabToUrl } = useStatisticsTabUrlSync({
|
||||
|
||||
pathname,
|
||||
|
||||
menuList,
|
||||
@@ -129,41 +77,27 @@ function WithBaseLayoutInner({
|
||||
addTabForGrid,
|
||||
|
||||
setCurrentMenuInfo,
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
const { data: menuListData } = useQuery({
|
||||
|
||||
queryKey: [ENDPOINT.CMS_SERVICE.MENU_ROLES],
|
||||
|
||||
queryFn: () => MenuApi.getMenuRoles(appSiteId),
|
||||
|
||||
enabled: isLoggedIn,
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (menuListData) {
|
||||
|
||||
setMenuList(menuListData);
|
||||
|
||||
setMenuListForGrid(menuListData);
|
||||
|
||||
}
|
||||
|
||||
}, [menuListData, setMenuList, setMenuListForGrid]);
|
||||
|
||||
|
||||
|
||||
// 새로고침 후 persist로 앱 탭만 복원된 경우 rsone 그리드 스토어에 탭을 맞춤
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (!menuList) return;
|
||||
|
||||
const appTabs = getTabStoreState().tabs;
|
||||
@@ -172,20 +106,13 @@ function WithBaseLayoutInner({
|
||||
|
||||
if (getGridTabStoreState().tabs.length > 0) return;
|
||||
|
||||
|
||||
|
||||
for (const tab of appTabs) {
|
||||
|
||||
getGridTabStoreState().addTab(tab.menuItem);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const activeId = getTabStoreState().activeTabId;
|
||||
|
||||
if (activeId) {
|
||||
|
||||
setActiveTab(activeId);
|
||||
|
||||
const activeTab = appTabs.find((t) => t.id === activeId);
|
||||
@@ -193,155 +120,97 @@ function WithBaseLayoutInner({
|
||||
const gridActiveId = activeTab?.menuItem.menuEngNm;
|
||||
|
||||
if (gridActiveId) {
|
||||
|
||||
getGridTabStoreState().setActiveTab(gridActiveId);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}, [menuList, tabs, setActiveTab]);
|
||||
|
||||
|
||||
|
||||
// 활성 탭의 메뉴를 찾아서 urlPath를 가져옴. 탭이 전부 닫히면 ''를 넘겨 LNB에서 메뉴 강조 제거
|
||||
|
||||
const currentPath = useMemo(() => {
|
||||
|
||||
if (tabs.length === 0) return "";
|
||||
|
||||
|
||||
|
||||
if (activeTabId && menuList) {
|
||||
|
||||
// menuList에서 활성 탭의 메뉴 찾기
|
||||
|
||||
const findMenuByEngNm = (items: MenuItem[]): MenuItem | null => {
|
||||
|
||||
for (const item of items) {
|
||||
|
||||
if (item.urlPath === activeTabId) {
|
||||
|
||||
return item;
|
||||
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
|
||||
const found = findMenuByEngNm(item.children);
|
||||
|
||||
if (found) return found;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
const activeMenu = findMenuByEngNm(menuList);
|
||||
|
||||
|
||||
|
||||
if (activeMenu?.urlPath) {
|
||||
|
||||
return activeMenu.urlPath;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 탭에서 직접 찾기
|
||||
|
||||
if (activeTabId) {
|
||||
|
||||
const currentTabs = getTabStoreState().tabs;
|
||||
|
||||
const activeTab = currentTabs.find((t) => t.id === activeTabId);
|
||||
|
||||
if (activeTab?.menuItem?.urlPath) {
|
||||
|
||||
return activeTab.menuItem.urlPath;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// currentMenuInfo에서 가져오기
|
||||
|
||||
if (currentMenuInfo?.urlPath) {
|
||||
|
||||
return currentMenuInfo.urlPath;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 기본값으로 pathname 사용
|
||||
|
||||
return pathname ?? "";
|
||||
|
||||
}, [tabs.length, activeTabId, menuList, currentMenuInfo, pathname]);
|
||||
|
||||
|
||||
|
||||
const handleMenuClick = useCallback(
|
||||
|
||||
(item: MenuItem) => {
|
||||
if (item.urlPath.includes("/cms/")) return;
|
||||
|
||||
setCurrentMenuInfo(item);
|
||||
|
||||
|
||||
|
||||
if (isVerificationSelectionReportMenu(item)) {
|
||||
|
||||
setReportPanelOpen(true);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
const addTabResult: boolean = addTab(item);
|
||||
|
||||
|
||||
|
||||
// packages/rsone의 스토어에도 동기화
|
||||
|
||||
if (addTabResult) {
|
||||
|
||||
addTabForGrid(item);
|
||||
|
||||
if (item.urlPath) {
|
||||
|
||||
syncTabToUrl(item.urlPath);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (!addTabResult) {
|
||||
|
||||
alert(`최대 추가 할 수 있는 화면 수(10개)를 \n초과 하였습니다.
|
||||
|
||||
기존 화면을 닫은 후 이용해주세요.`);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
[
|
||||
|
||||
setCurrentMenuInfo,
|
||||
|
||||
addTab,
|
||||
@@ -353,71 +222,37 @@ function WithBaseLayoutInner({
|
||||
setReportPanelOpen,
|
||||
|
||||
syncTabToUrl,
|
||||
|
||||
],
|
||||
|
||||
);
|
||||
|
||||
|
||||
|
||||
return (
|
||||
|
||||
<BaseLayout
|
||||
|
||||
queryClient={queryClient}
|
||||
|
||||
tokenManager={tokenManager}
|
||||
|
||||
currentPath={currentPath}
|
||||
|
||||
handleMenuClick={handleMenuClick}
|
||||
|
||||
>
|
||||
|
||||
<div className="flex flex-1 h-full">
|
||||
|
||||
<div className="flex h-full flex-1">
|
||||
{isVerificationSelectionReportPanelOpen && (
|
||||
|
||||
<VerificationSelectionReport
|
||||
|
||||
onClose={() => setReportPanelOpen(false)}
|
||||
|
||||
/>
|
||||
|
||||
)}
|
||||
|
||||
<StatisticsPageLayout>{children}</StatisticsPageLayout>
|
||||
|
||||
</div>
|
||||
|
||||
</BaseLayout>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
export default function WithBaseLayout({
|
||||
|
||||
children,
|
||||
|
||||
}: {
|
||||
|
||||
children: React.ReactNode;
|
||||
|
||||
}) {
|
||||
|
||||
return (
|
||||
|
||||
<Suspense fallback={null}>
|
||||
|
||||
<WithBaseLayoutInner>{children}</WithBaseLayoutInner>
|
||||
|
||||
</Suspense>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user