From 46c3f504329b3aaf7e9d112675bc4995bff5ef52 Mon Sep 17 00:00:00 2001 From: bicochan Date: Mon, 7 Jul 2025 13:58:29 +0900 Subject: [PATCH] =?UTF-8?q?[apps/cs]=20refactor:=20=EB=A9=94=EB=89=B4=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EB=B0=8F=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=97=94=ED=8B=B0=ED=8B=B0?= =?UTF-8?q?=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/cs/src/entities/menu/api/menu-service.ts | 37 +++++++- apps/cs/src/entities/menu/index.ts | 9 +- .../src/entities/menu/model/menu-interface.ts | 58 +++++++++++++ apps/cs/src/pages/menu/api/menu-service.ts | 65 -------------- .../src/pages/menu/api/tree-menu-service.ts | 33 +++++++ apps/cs/src/pages/menu/lib/utils.ts | 2 +- .../cs/src/pages/menu/model/menu-interface.ts | 86 ------------------- .../pages/menu/model/tree-menu-interface.ts | 29 +++++++ apps/cs/src/pages/menu/ui/base-menu-form.tsx | 2 +- apps/cs/src/pages/menu/ui/menu-form.tsx | 14 ++- apps/cs/src/pages/menu/ui/menu-node.tsx | 6 +- apps/cs/src/pages/menu/ui/menu-page.tsx | 17 ++-- apps/cs/src/pages/menu/ui/menu-tree.tsx | 7 +- apps/cs/src/pages/menu/ui/type-menu-form.tsx | 2 +- 14 files changed, 194 insertions(+), 173 deletions(-) delete mode 100644 apps/cs/src/pages/menu/api/menu-service.ts create mode 100644 apps/cs/src/pages/menu/api/tree-menu-service.ts delete mode 100644 apps/cs/src/pages/menu/model/menu-interface.ts create mode 100644 apps/cs/src/pages/menu/model/tree-menu-interface.ts diff --git a/apps/cs/src/entities/menu/api/menu-service.ts b/apps/cs/src/entities/menu/api/menu-service.ts index 4424f8d37..7dd0aecd9 100644 --- a/apps/cs/src/entities/menu/api/menu-service.ts +++ b/apps/cs/src/entities/menu/api/menu-service.ts @@ -1,6 +1,11 @@ import { client } from "@/shared/api"; import { ENDPOINT } from "@/shared/config"; -import type { MenuItem, MenuService } from "../model/menu-interface"; +import type { + MenuService, + Menu, + MenuItem, + MenuFormData, +} from "../model/menu-interface"; export class MenuApiService implements MenuService { async getMenuRoles(siteId: string): Promise { @@ -9,6 +14,36 @@ export class MenuApiService implements MenuService { ); return response.data; } + + public async getMenuInfo(menuCd: number): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`, + ); + return response.data; + } + + public async createMenu(data: MenuFormData): Promise { + const response = await client.post( + `${ENDPOINT.CMS_SERVICE.MENUS}`, + data, + ); + return response.data; + } + + public async updateMenu( + menuCd: number, + data: Omit, + ): Promise { + const response = await client.put( + `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`, + data, + ); + return response.data; + } + + public async deleteMenu(menuCd: number): Promise { + await client.delete(`${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`); + } } export const MenuApi = new MenuApiService(); diff --git a/apps/cs/src/entities/menu/index.ts b/apps/cs/src/entities/menu/index.ts index 04f63e38b..e4a9cec40 100644 --- a/apps/cs/src/entities/menu/index.ts +++ b/apps/cs/src/entities/menu/index.ts @@ -1,2 +1,9 @@ +export { MenuApi } from "./api/menu-service"; +export { + MENU_TYPE, + menuFormSchema, + type MenuType, + type MenuItem, + type MenuFormData, +} from "./model/menu-interface"; export { MenuWrapper } from "./lib/menu-wrapper"; -export type { MenuItem } from "./model/menu-interface"; diff --git a/apps/cs/src/entities/menu/model/menu-interface.ts b/apps/cs/src/entities/menu/model/menu-interface.ts index 12c7d007a..285c28b04 100644 --- a/apps/cs/src/entities/menu/model/menu-interface.ts +++ b/apps/cs/src/entities/menu/model/menu-interface.ts @@ -1,3 +1,16 @@ +import { z } from "zod"; + +export const MENU_TYPE = { + EMPTY: "EMPTY", + CONTENTS: "CONTENTS", + BOARD: "BOARD", + INSIDE: "INSIDE", + OUTSIDE: "OUTSIDE", + BOTTOM: "BOTTOM", +} as const; + +export type MenuType = (typeof MENU_TYPE)[keyof typeof MENU_TYPE]; + export interface MenuItem { menuCd: number; menuKornNm: string; @@ -18,6 +31,51 @@ export interface MenuItem { requiredUrlPath: boolean; } +export const menuFormSchema = z.object({ + siteId: z.string(), + menuKornNm: z.string(), + menuSubKornNm: z.string().nullish(), + menuEngNm: z.string().nullish(), + menuSubEngNm: z.string().nullish(), + levelNo: z.number(), + urlPath: z.string().nullish(), + iconNm: z.string().nullish(), + menuLnkgTypeCd: z.enum([ + MENU_TYPE.EMPTY, + MENU_TYPE.CONTENTS, + MENU_TYPE.BOARD, + MENU_TYPE.INSIDE, + MENU_TYPE.OUTSIDE, + MENU_TYPE.BOTTOM, + ]), + menuLnkgSn: z.number().nullish(), + otptYn: z.string().default("Y"), + prntMenuCd: z.number().nullish(), + sortSeq: z.number(), + evlUseYn: z.string().default("Y"), + qrcd: z.string().nullish(), + useYn: z.string().default("Y"), + newWndwYn: z.string().nullish(), + menuLnkgSnNm: z.string().nullish(), + menuPicUserUnqId: z.string().nullish(), + menuPicUserUnqIdNm: z.string().nullish(), + menuPicDsgnYmd: z.string().nullish(), +}); + +export type MenuFormData = z.infer; + +export type Menu = Omit & { + menuCd: number; + iconName?: string; +}; + export interface MenuService { getMenuRoles(siteId: string): Promise; + getMenuInfo: (menuCd: number) => Promise; + createMenu: (data: MenuFormData) => Promise; + updateMenu: ( + menuCd: number, + data: Omit, + ) => Promise; + deleteMenu: (menuCd: number) => Promise; } diff --git a/apps/cs/src/pages/menu/api/menu-service.ts b/apps/cs/src/pages/menu/api/menu-service.ts deleted file mode 100644 index dbb67cb3e..000000000 --- a/apps/cs/src/pages/menu/api/menu-service.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { client } from "@/shared/api"; -import { ENDPOINT } from "@/shared/config"; -import type { - Menu, - MenuFormData, - MenuService, - TreeMenu, - TreeNode, -} from "../model/menu-interface"; - -export class MenuApiService implements MenuService { - public async getMenuInfo(menuCd: number): Promise { - const response = await client.get( - `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`, - ); - return response.data; - } - - public async createMenu(data: MenuFormData): Promise { - const response = await client.post( - `${ENDPOINT.CMS_SERVICE.MENUS}`, - data, - ); - return response.data; - } - - public async updateMenu( - menuCd: number, - data: Omit, - ): Promise { - const response = await client.put( - `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`, - data, - ); - return response.data; - } - - public async deleteMenu(menuCd: number): Promise { - await client.delete(`${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}`); - } - - public async getTreeMenuList(siteId: string): Promise { - const response = await client.get( - `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree`, - ); - return response.data; - } - - public async updateTreeMenu(siteId: string, data: TreeNode[]): Promise { - const response = await client.put( - `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree`, - data, - ); - return response.data; - } - - public async updateMenuName(menuCd: number, name: string): Promise { - const response = await client.put( - `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}/${name}`, - ); - return response.data; - } -} - -export const MenuApi = new MenuApiService(); diff --git a/apps/cs/src/pages/menu/api/tree-menu-service.ts b/apps/cs/src/pages/menu/api/tree-menu-service.ts new file mode 100644 index 000000000..9f36f5383 --- /dev/null +++ b/apps/cs/src/pages/menu/api/tree-menu-service.ts @@ -0,0 +1,33 @@ +import { client } from "@/shared/api"; +import { ENDPOINT } from "@/shared/config"; +import type { + TreeMenuService, + TreeMenu, + TreeNode, +} from "../model/tree-menu-interface"; + +export class TreeMenuApiService implements TreeMenuService { + public async getTreeMenuList(siteId: string): Promise { + const response = await client.get( + `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree`, + ); + return response.data; + } + + public async updateTreeMenu(siteId: string, data: TreeNode[]): Promise { + const response = await client.put( + `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree`, + data, + ); + return response.data; + } + + public async updateMenuName(menuCd: number, name: string): Promise { + const response = await client.put( + `${ENDPOINT.CMS_SERVICE.MENUS}/${menuCd}/${name}`, + ); + return response.data; + } +} + +export const TreeMenuApi = new TreeMenuApiService(); diff --git a/apps/cs/src/pages/menu/lib/utils.ts b/apps/cs/src/pages/menu/lib/utils.ts index f6d13be33..0e219047d 100644 --- a/apps/cs/src/pages/menu/lib/utils.ts +++ b/apps/cs/src/pages/menu/lib/utils.ts @@ -3,7 +3,7 @@ import type { TreeUserOrganization, TreeUser, } from "@/entities/user-organization"; -import type { TreeMenu, TreeNode } from "../model/menu-interface"; +import type { TreeMenu, TreeNode } from "../model/tree-menu-interface"; export const generateMenuTreeData = ( data: TreeMenu[], diff --git a/apps/cs/src/pages/menu/model/menu-interface.ts b/apps/cs/src/pages/menu/model/menu-interface.ts deleted file mode 100644 index f9650e0e2..000000000 --- a/apps/cs/src/pages/menu/model/menu-interface.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { z } from "zod"; - -export const MENU_TYPE = { - EMPTY: "EMPTY", - CONTENTS: "CONTENTS", - BOARD: "BOARD", - INSIDE: "INSIDE", - OUTSIDE: "OUTSIDE", - BOTTOM: "BOTTOM", -} as const; - -export type MenuType = (typeof MENU_TYPE)[keyof typeof MENU_TYPE]; - -export interface TreeNode { - menuCd?: number; - name?: string; - sortSeq?: number; - parentId?: number | null; - levelNo?: number; - icon?: string; - children?: TreeNode[]; -} - -export interface TreeMenu extends Omit { - menuKornNm: string; - menuEngNm?: string; - iconNm?: string; - children?: TreeMenu[]; - urlPath?: string; - menuLnkgTypeCd: string; - menuLnkgSn?: number; - qrcd?: string; - useYn: string; - otptYn: string; - requiredUrlPath?: boolean; -} - -export const menuFormSchema = z.object({ - siteId: z.string(), - menuKornNm: z.string(), - menuSubKornNm: z.string().nullish(), - menuEngNm: z.string().nullish(), - menuSubEngNm: z.string().nullish(), - levelNo: z.number(), - urlPath: z.string().nullish(), - iconNm: z.string().nullish(), - menuLnkgTypeCd: z.enum([ - MENU_TYPE.EMPTY, - MENU_TYPE.CONTENTS, - MENU_TYPE.BOARD, - MENU_TYPE.INSIDE, - MENU_TYPE.OUTSIDE, - MENU_TYPE.BOTTOM, - ]), - menuLnkgSn: z.number().nullish(), - otptYn: z.string().default("Y"), - prntMenuCd: z.number().nullish(), - sortSeq: z.number(), - evlUseYn: z.string().default("Y"), - qrcd: z.string().nullish(), - useYn: z.string().default("Y"), - newWndwYn: z.string().nullish(), - menuLnkgSnNm: z.string().nullish(), - menuPicUserUnqId: z.string().nullish(), - menuPicUserUnqIdNm: z.string().nullish(), - menuPicDsgnYmd: z.string().nullish(), -}); - -export type MenuFormData = z.infer; -export type Menu = Omit & { - menuCd: number; - iconName?: string; -}; - -export interface MenuService { - getMenuInfo: (menuCd: number) => Promise; - createMenu: (data: MenuFormData) => Promise; - updateMenu: ( - menuCd: number, - data: Omit, - ) => Promise; - deleteMenu: (menuCd: number) => Promise; - getTreeMenuList: (siteId: string) => Promise; - updateTreeMenu: (siteId: string, data: TreeNode[]) => Promise; - updateMenuName: (menuCd: number, name: string) => Promise; -} diff --git a/apps/cs/src/pages/menu/model/tree-menu-interface.ts b/apps/cs/src/pages/menu/model/tree-menu-interface.ts new file mode 100644 index 000000000..39a6f92c9 --- /dev/null +++ b/apps/cs/src/pages/menu/model/tree-menu-interface.ts @@ -0,0 +1,29 @@ +export interface TreeNode { + menuCd?: number; + name?: string; + sortSeq?: number; + parentId?: number | null; + levelNo?: number; + icon?: string; + children?: TreeNode[]; +} + +export interface TreeMenu extends Omit { + menuKornNm: string; + menuEngNm?: string; + iconNm?: string; + children?: TreeMenu[]; + urlPath?: string; + menuLnkgTypeCd: string; + menuLnkgSn?: number; + qrcd?: string; + useYn: string; + otptYn: string; + requiredUrlPath?: boolean; +} + +export interface TreeMenuService { + getTreeMenuList: (siteId: string) => Promise; + updateTreeMenu: (siteId: string, data: TreeNode[]) => Promise; + updateMenuName: (menuCd: number, name: string) => Promise; +} diff --git a/apps/cs/src/pages/menu/ui/base-menu-form.tsx b/apps/cs/src/pages/menu/ui/base-menu-form.tsx index fceb66549..eeae63255 100644 --- a/apps/cs/src/pages/menu/ui/base-menu-form.tsx +++ b/apps/cs/src/pages/menu/ui/base-menu-form.tsx @@ -10,8 +10,8 @@ import { TableHead, TableRow, } from "@common/components"; +import { MENU_TYPE, type MenuFormData } from "@/entities/menu"; import { FormItem, FormControl, FormField } from "@/shared/ui/form"; -import { MENU_TYPE, type MenuFormData } from "../model/menu-interface"; import { InfoTooltip } from "@/shared/ui/info-tooltip"; interface BaseMenuFormProps { diff --git a/apps/cs/src/pages/menu/ui/menu-form.tsx b/apps/cs/src/pages/menu/ui/menu-form.tsx index 0a45214eb..1cba9ddf3 100644 --- a/apps/cs/src/pages/menu/ui/menu-form.tsx +++ b/apps/cs/src/pages/menu/ui/menu-form.tsx @@ -1,9 +1,9 @@ import type { UseFormReturn } from "react-hook-form"; import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { Button } from "@common/components"; -import { Form } from "@/shared/ui/form"; +import type { MenuFormData } from "@/entities/menu"; import { ManagementAuthorityDialog } from "@/entities/menu-authority"; -import type { MenuFormData } from "../model/menu-interface"; +import { Form } from "@/shared/ui/form"; import { BaseMenuForm } from "./base-menu-form"; import { TypeMenuForm } from "./type-menu-form"; @@ -69,7 +69,15 @@ function MenuForm({

{isModifyMode ? "메뉴 수정" : "메뉴 등록"}

- +
+ + + +
diff --git a/apps/cs/src/pages/menu/ui/menu-node.tsx b/apps/cs/src/pages/menu/ui/menu-node.tsx index 5cda4f522..4a2b3624f 100644 --- a/apps/cs/src/pages/menu/ui/menu-node.tsx +++ b/apps/cs/src/pages/menu/ui/menu-node.tsx @@ -4,8 +4,8 @@ import type { NodeModel, TreeMethods } from "@minoru/react-dnd-treeview"; import { Button, cn } from "@common/components"; import { useMutationWrapper } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; -import { MenuApi } from "../api/menu-service"; -import type { TreeMenu } from "../model/menu-interface"; +import { TreeMenuApi } from "../api/tree-menu-service"; +import type { TreeMenu } from "../model/tree-menu-interface"; import { EditableNode } from "./editable-node"; type MenuNodeProps = { @@ -37,7 +37,7 @@ function MenuNode({ const { mutateAsync: updateMenuName } = useMutationWrapper({ mutationFn: (nodeName: string) => { const encodedName = encodeURIComponent(nodeName); - return MenuApi.updateMenuName(id as number, encodedName); + return TreeMenuApi.updateMenuName(id as number, encodedName); }, onSuccess: () => { queryClient.invalidateQueries({ diff --git a/apps/cs/src/pages/menu/ui/menu-page.tsx b/apps/cs/src/pages/menu/ui/menu-page.tsx index d212dc970..2d3dedc16 100644 --- a/apps/cs/src/pages/menu/ui/menu-page.tsx +++ b/apps/cs/src/pages/menu/ui/menu-page.tsx @@ -14,19 +14,20 @@ import { SelectTrigger, SelectValue, } from "@common/components"; -import { SiteApi } from "@/entities/site"; -import { ENDPOINT } from "@/shared/config"; -import { useAlertStore, useMutationWrapper } from "@/shared/lib"; -import type { TreeMenu } from "../model/menu-interface"; -import { MenuApi } from "../api/menu-service"; import { + MenuApi, MENU_TYPE, menuFormSchema, type MenuFormData, -} from "../model/menu-interface"; +} from "@/entities/menu"; +import { SiteApi } from "@/entities/site"; +import { ENDPOINT } from "@/shared/config"; +import { useAlertStore, useMutationWrapper } from "@/shared/lib"; +import { generateMenuTreeData } from "../lib/utils"; +import { TreeMenuApi } from "../api/tree-menu-service"; +import type { TreeMenu } from "../model/tree-menu-interface"; import { MenuTree } from "./menu-tree"; import { MenuForm } from "./menu-form"; -import { generateMenuTreeData } from "../lib/utils"; function MenuPage() { const queryClient = useQueryClient(); @@ -46,7 +47,7 @@ function MenuPage() { const { data: menuTreeData } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.MENUS, siteId], - queryFn: () => MenuApi.getTreeMenuList(siteId), + queryFn: () => TreeMenuApi.getTreeMenuList(siteId), select: (data) => { const treeData = generateMenuTreeData(data); const defaultSortSeq = diff --git a/apps/cs/src/pages/menu/ui/menu-tree.tsx b/apps/cs/src/pages/menu/ui/menu-tree.tsx index a1fa4dacb..5ef15062c 100644 --- a/apps/cs/src/pages/menu/ui/menu-tree.tsx +++ b/apps/cs/src/pages/menu/ui/menu-tree.tsx @@ -11,8 +11,9 @@ import { import { Button } from "@common/components"; import { ENDPOINT } from "@/shared/config"; import { useMutationWrapper } from "@/shared/lib"; -import { MenuApi } from "../api/menu-service"; -import type { MenuFormData, TreeMenu, TreeNode } from "../model/menu-interface"; +import type { MenuFormData } from "@/entities/menu"; +import { TreeMenuApi } from "../api/tree-menu-service"; +import type { TreeMenu, TreeNode } from "../model/tree-menu-interface"; import { handleDropNode, handleSelectNode } from "../lib/utils"; import { MenuNode } from "./menu-node"; import { EditableNode } from "./editable-node"; @@ -41,7 +42,7 @@ function MenuTree({ const { mutate: updateTreeMenu } = useMutationWrapper({ mutationFn: (newTree: TreeNode) => - MenuApi.updateTreeMenu(siteId, [newTree]), + TreeMenuApi.updateTreeMenu(siteId, [newTree]), onSuccess: () => { queryClient.invalidateQueries({ queryKey: [ENDPOINT.CMS_SERVICE.MENUS], diff --git a/apps/cs/src/pages/menu/ui/type-menu-form.tsx b/apps/cs/src/pages/menu/ui/type-menu-form.tsx index ac62e2520..eeb50e805 100644 --- a/apps/cs/src/pages/menu/ui/type-menu-form.tsx +++ b/apps/cs/src/pages/menu/ui/type-menu-form.tsx @@ -16,8 +16,8 @@ import { import type { BoardPopup } from "@/entities/board"; import type { Contents } from "@/entities/content"; import type { TreeUser } from "@/entities/user-organization"; +import type { MenuFormData, MenuType } from "@/entities/menu"; import { FormItem, FormControl, FormField } from "@/shared/ui/form"; -import type { MenuFormData, MenuType } from "../model/menu-interface"; import { OrganizationSearchDialog } from "./organization-search-dialog"; import { ContentSearchDialog } from "./content-search-dialog"; import { BoardSearchDialog } from "./board-search-dialog";