feat(sn): CS 기준 UI 통일 및 지도 팝업 표준화

This commit is contained in:
2026-08-20 14:57:20 +09:00
parent c9e3ff0d91
commit 0cbbc3b934
167 changed files with 21191 additions and 14161 deletions
+7 -7
View File
@@ -1,12 +1,12 @@
import type { MenuItem } from "@/src/entities/menu";
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)
);
const marker = BBS_NOTICE_MENU_MARKER;
return (
item.urlPath?.toLowerCase().includes(marker) ||
item.menuEngNm?.toLowerCase().includes(marker) ||
item.menuPath?.toLowerCase().includes(marker)
);
}
+56 -56
View File
@@ -1,84 +1,84 @@
import type { MenuItem } from "@/src/entities/menu";
import type { MenuItem } from "@/entities/menu";
export type ParsedStatisticsMenuUrl = {
categoryFromPath: string | null;
componentName: string | null;
rawUrlPath: string;
categoryFromPath: string | null;
componentName: string | null;
rawUrlPath: string;
};
/** 메뉴 `urlPath`에서 통계 화면 카테고리·컴포넌트명을 파싱합니다. */
export function parseStatisticsMenuUrlPath(
urlPath: string,
urlPath: string,
): ParsedStatisticsMenuUrl {
const trimmed = (urlPath ?? "").trim();
if (!trimmed) {
return { categoryFromPath: null, componentName: null, rawUrlPath: trimmed };
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;
}
}
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 };
return { categoryFromPath, componentName, rawUrlPath: trimmed };
}
/** 동적 import용 카테고리 폴더명 (`input`, `review` 등) */
export function resolveStatisticsCategory(
urlPath: string,
parentEngNm: string,
urlPath: string,
parentEngNm: string,
): string {
const { categoryFromPath } = parseStatisticsMenuUrlPath(urlPath);
return categoryFromPath || parentEngNm || "";
const { categoryFromPath } = parseStatisticsMenuUrlPath(urlPath);
return categoryFromPath || parentEngNm || "";
}
/** 탭 ID·URL `?tab=` 값 - 컴포넌트 파일명(확장자 제외) */
export function resolveStatisticsTabId(urlPath: string): string {
const { componentName, rawUrlPath } = parseStatisticsMenuUrlPath(urlPath);
return componentName || rawUrlPath;
const { componentName, rawUrlPath } = parseStatisticsMenuUrlPath(urlPath);
return componentName || rawUrlPath;
}
/** `@/src/components/statistics/{category}/{Component}` 또는 루트 컴포넌트 경로 */
export function buildStatisticsComponentImportPath(
urlPath: string,
parentEngNm: string,
urlPath: string,
parentEngNm: string,
): string {
const { componentName } = parseStatisticsMenuUrlPath(urlPath);
const category = resolveStatisticsCategory(urlPath, parentEngNm);
const name = componentName || urlPath;
if (!category) {
return `@/src/components/statistics/${name}`;
}
return `@/src/components/statistics/${category}/${name}`;
const { componentName } = parseStatisticsMenuUrlPath(urlPath);
const category = resolveStatisticsCategory(urlPath, parentEngNm);
const name = componentName || urlPath;
if (!category) {
return `@/src/components/statistics/${name}`;
}
return `@/src/components/statistics/${category}/${name}`;
}
export function menuMatchesStatisticsTabId(
menu: MenuItem,
tabId: string,
menu: MenuItem,
tabId: string,
): boolean {
if (!tabId) return false;
if (menu.urlPath === tabId) return true;
return resolveStatisticsTabId(menu.urlPath) === tabId;
if (!tabId) return false;
if (menu.urlPath === tabId) return true;
return resolveStatisticsTabId(menu.urlPath) === tabId;
}