Merge remote-tracking branch 'origin/iipbs/st/dev' into feature/sein
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
import type { MenuItem } from "@/entities/menu";
|
||||
|
||||
export const BBS_NOTICE_MENU_MARKER = "bbsnotice";
|
||||
|
||||
export function isBbsNoticeMenu(item: MenuItem): boolean {
|
||||
const marker = BBS_NOTICE_MENU_MARKER;
|
||||
return (
|
||||
item.urlPath?.toLowerCase().includes(marker) ||
|
||||
item.menuEngNm?.toLowerCase().includes(marker) ||
|
||||
item.menuPath?.toLowerCase().includes(marker)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { MenuItem } from "@/entities/menu";
|
||||
|
||||
export type ParsedStatisticsMenuUrl = {
|
||||
categoryFromPath: string | null;
|
||||
componentName: string | null;
|
||||
rawUrlPath: string;
|
||||
};
|
||||
|
||||
/** 메뉴 `urlPath`에서 통계 화면 카테고리·컴포넌트명을 파싱합니다. */
|
||||
export function parseStatisticsMenuUrlPath(urlPath: string): ParsedStatisticsMenuUrl {
|
||||
const trimmed = (urlPath ?? "").trim();
|
||||
if (!trimmed) {
|
||||
return { categoryFromPath: null, componentName: null, rawUrlPath: trimmed };
|
||||
}
|
||||
|
||||
let pathPart = trimmed;
|
||||
let queryString = "";
|
||||
const queryIndex = trimmed.indexOf("?");
|
||||
if (queryIndex >= 0) {
|
||||
pathPart = trimmed.slice(0, queryIndex);
|
||||
queryString = trimmed.slice(queryIndex + 1);
|
||||
}
|
||||
|
||||
const tabParam = new URLSearchParams(queryString).get("tab")?.trim() || null;
|
||||
const segments = pathPart.replace(/^\/+/, "").split("/").filter(Boolean);
|
||||
|
||||
let categoryFromPath: string | null = null;
|
||||
if (segments[0] === "statistics" && segments.length >= 2) {
|
||||
categoryFromPath = segments[1] ?? null;
|
||||
}
|
||||
|
||||
let componentName = tabParam;
|
||||
if (!componentName) {
|
||||
if (!pathPart.includes("/") && !queryString) {
|
||||
componentName = trimmed;
|
||||
} else if (segments.length === 1 && segments[0] !== "statistics") {
|
||||
componentName = segments[0] ?? null;
|
||||
} else if (segments[0] === "statistics" && segments.length >= 3) {
|
||||
componentName = segments[segments.length - 1] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
return { categoryFromPath, componentName, rawUrlPath: trimmed };
|
||||
}
|
||||
|
||||
/** 동적 import용 카테고리 폴더명 (`input`, `review` 등) */
|
||||
export function resolveStatisticsCategory(urlPath: string, parentEngNm: string): string {
|
||||
const { categoryFromPath } = parseStatisticsMenuUrlPath(urlPath);
|
||||
return categoryFromPath || parentEngNm || "";
|
||||
}
|
||||
|
||||
/** 탭 ID·URL `?tab=` 값 — 컴포넌트 파일명(확장자 제외) */
|
||||
export function resolveStatisticsTabId(urlPath: string): string {
|
||||
const { componentName, rawUrlPath } = parseStatisticsMenuUrlPath(urlPath);
|
||||
return componentName || rawUrlPath;
|
||||
}
|
||||
|
||||
/** `@/components/statistics/{category}/{Component}` 경로 */
|
||||
export function buildStatisticsComponentImportPath(
|
||||
urlPath: string,
|
||||
parentEngNm: string,
|
||||
): string {
|
||||
const { componentName } = parseStatisticsMenuUrlPath(urlPath);
|
||||
const category = resolveStatisticsCategory(urlPath, parentEngNm);
|
||||
const name = componentName || urlPath;
|
||||
return `@/components/statistics/${category}/${name}`;
|
||||
}
|
||||
|
||||
export function menuMatchesStatisticsTabId(menu: MenuItem, tabId: string): boolean {
|
||||
if (!tabId) return false;
|
||||
if (menu.urlPath === tabId) return true;
|
||||
return resolveStatisticsTabId(menu.urlPath) === tabId;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { MenuItem } from "@/entities/menu";
|
||||
import type { SearchFormValues } from "@/components/type/SearchForm.type";
|
||||
import { doNameList } from "@/components/util/column/input/DoList";
|
||||
import { menuMatchesStatisticsTabId } from "@/shared/lib/statistics-menu-url";
|
||||
import {
|
||||
SEWAGE_PIPE_INP_TAB_KEYS,
|
||||
SEWAGE_PIPE_MAINTAIN_INP_TAB_KEYS,
|
||||
@@ -97,7 +98,7 @@ export function findMenuItemByUrlPath(
|
||||
urlPath: string,
|
||||
): MenuItem | null {
|
||||
for (const item of menus) {
|
||||
if (item.urlPath === urlPath) return item;
|
||||
if (menuMatchesStatisticsTabId(item, urlPath)) return item;
|
||||
if (item.children?.length) {
|
||||
const found = findMenuItemByUrlPath(item.children, urlPath);
|
||||
if (found) return found;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useEffect, useRef } from "react";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
|
||||
import type { MenuItem } from "@/entities/menu";
|
||||
import { isBbsNoticeMenu } from "@/shared/lib/bbs-notice-menu";
|
||||
import { findMenuItemByUrlPath } from "@/shared/lib/stats-cd-input-navigation";
|
||||
import { getTabStoreState } from "@/store/tab-store";
|
||||
|
||||
@@ -61,7 +62,7 @@ export function useStatisticsTabUrlSync({
|
||||
if (getTabStoreState().activeTabId === tabParam) return;
|
||||
|
||||
const menu = findMenuItemByUrlPath(menuList, tabParam);
|
||||
if (!menu) return;
|
||||
if (!menu || isBbsNoticeMenu(menu)) return;
|
||||
|
||||
setCurrentMenuInfo(menu);
|
||||
const ok = addTab(menu);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { TabBar } from "./tab-bar";
|
||||
function StatisticsPageLayout({ children }: { children: React.ReactNode }) {
|
||||
const { activeTabId, tabs } = useTabStore();
|
||||
|
||||
const pageTitle = tabs.find((t) => t.menuItem.urlPath === activeTabId);
|
||||
const pageTitle = tabs.find((t) => t.id === activeTabId);
|
||||
|
||||
const menuPaths = pageTitle?.path?.split(">").map((path) => path.trim());
|
||||
|
||||
|
||||
Reference in New Issue
Block a user