diff --git a/apps/cs/src/pages/menu/api/menu-service.ts b/apps/cs/src/pages/menu/api/menu-service.ts index 6d22dcc58..cdb64b521 100644 --- a/apps/cs/src/pages/menu/api/menu-service.ts +++ b/apps/cs/src/pages/menu/api/menu-service.ts @@ -5,9 +5,17 @@ import type { 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}`, @@ -27,14 +35,14 @@ export class MenuApiService implements MenuService { return response.data; } - public async getTreeMenuList(siteId: string): Promise { - const response = await client.get( + public async getTreeMenuList(siteId: string): Promise { + const response = await client.get( `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree`, ); return response.data; } - public async modifyTreeMenu(siteId: string, data: TreeMenu[]): Promise { + public async modifyTreeMenu(siteId: string, data: TreeNode[]): Promise { const response = await client.put( `${ENDPOINT.CMS_SERVICE.MENUS}/${siteId}/tree`, data, diff --git a/apps/cs/src/pages/menu/lib/utils.ts b/apps/cs/src/pages/menu/lib/utils.ts index 333ebad94..a567cf96f 100644 --- a/apps/cs/src/pages/menu/lib/utils.ts +++ b/apps/cs/src/pages/menu/lib/utils.ts @@ -1,9 +1,9 @@ import type { DropOptions, NodeModel } from "@minoru/react-dnd-treeview"; -import type { Menu, TreeMenu } from "../model/menu-interface"; +import type { TreeMenu, TreeNode } from "../model/menu-interface"; -export const generateTreeData = (data: Menu[]): NodeModel[] => { - return data.reduce[]>((acc, menu) => { - const node: NodeModel = { +export const generateTreeData = (data: TreeMenu[]): NodeModel[] => { + return data.reduce[]>((acc, menu) => { + const node: NodeModel = { id: menu.menuCd ?? 0, parent: menu.parentId ?? 0, text: menu.menuKornNm, @@ -22,9 +22,9 @@ export const generateTreeData = (data: Menu[]): NodeModel[] => { }; export const generateNewTreeData = ( - treeData: NodeModel[], - options: DropOptions, -): TreeMenu | null => { + treeData: NodeModel[], + options: DropOptions, +): TreeNode | null => { const { dragSourceId, dragSource, dropTargetId, dropTarget } = options; if (!dragSource?.data) return null; @@ -38,7 +38,7 @@ export const generateNewTreeData = ( (node) => node.parent === dragSourceId && node.data, ); - const baseNode = (node: NodeModel): TreeMenu => { + const baseNode = (node: NodeModel): TreeNode => { if (!node.data) return {}; return { menuCd: node.data?.menuCd, @@ -47,20 +47,20 @@ export const generateNewTreeData = ( }; }; - const treeMenu: TreeMenu = { + const treeNode: TreeNode = { ...baseNode(dragSource), parentId: dropTargetId === 0 ? null : (dropTargetId as number), sortSeq: newSortSeq, levelNo: (dropTarget?.data?.levelNo ?? 0) + 1, }; - const result: TreeMenu = { - ...treeMenu, + const result: TreeNode = { + ...treeNode, children: childNodes.map((child) => ({ ...baseNode(child), parentId: child.data?.parentId === 0 ? null : (dropTargetId as number), sortSeq: child.data?.sortSeq, - levelNo: (treeMenu?.levelNo ?? 0) + 1, + levelNo: (treeNode?.levelNo ?? 0) + 1, })), }; @@ -68,21 +68,22 @@ export const generateNewTreeData = ( }; export const handleSelectNode = - (callback: (node: NodeModel) => void) => (node: NodeModel) => { + (callback: (node: NodeModel) => void) => + (node: NodeModel) => { callback(node); }; export const handleDropNode = - (callback: (newTree: TreeMenu) => void) => - (newTree: NodeModel[], options: DropOptions) => { + (callback: (newTree: TreeNode) => void) => + (newTree: NodeModel[], options: DropOptions) => { const newTreeData = generateNewTreeData(newTree, options); if (!newTreeData) return; callback(newTreeData); }; export const handleNodeTextChange = - (treeData: NodeModel[]) => - (callback: (newTree: NodeModel[]) => void) => + (treeData: NodeModel[]) => + (callback: (newTree: NodeModel[]) => void) => (id: NodeModel["id"], value: string) => { const newTree = treeData.map((node) => { if (node.id === id) { diff --git a/apps/cs/src/pages/menu/model/menu-interface.ts b/apps/cs/src/pages/menu/model/menu-interface.ts index 99c132bd6..31f319c82 100644 --- a/apps/cs/src/pages/menu/model/menu-interface.ts +++ b/apps/cs/src/pages/menu/model/menu-interface.ts @@ -1,31 +1,31 @@ import { z } from "zod"; export const MENU_TYPE = { - EMPTY: "EMPTY", - CONTENTS: "CONTENTS", - BOARD: "BOARD", - INSIDE: "INSIDE", - OUTSIDE: "OUTSIDE", - BOTTOM: "BOTTOM", + 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 TreeMenu { +export interface TreeNode { menuCd?: number; name?: string; sortSeq?: number; parentId?: number | null; levelNo?: number; icon?: string; - children?: TreeMenu[]; + children?: TreeNode[]; } -export interface Menu extends Omit { +export interface TreeMenu extends Omit { menuKornNm: string; menuEngNm: string; iconNm: string; - children: Menu[]; + children: TreeMenu[]; urlPath: string; menuLnkgTypeCd: string; menuLnkgSn: number; @@ -53,12 +53,12 @@ export const menuFormSchema = z.object({ MENU_TYPE.BOTTOM, ]), menuLnkgSn: z.number().nullish(), - otptYn: z.string().default("Y").nullish(), + otptYn: z.string().default("Y"), prntMenuCd: z.number().nullish(), sortSeq: z.number(), - evlUseYn: z.string().default("Y").nullish(), + evlUseYn: z.string().default("Y"), qrcd: z.string().nullish(), - useYn: z.string().default("Y").nullish(), + useYn: z.string().default("Y"), menuLnkgSnNm: z.string().nullish(), menuPicUserUnqId: z.string().nullish(), menuPicUserUnqIdNm: z.string().nullish(), @@ -66,14 +66,16 @@ export const menuFormSchema = z.object({ }); export type MenuFormData = z.infer; +export type Menu = MenuFormData & { menuCd: number }; export interface MenuService { + getMenuInfo: (menuCd: number) => Promise; createMenu: (data: MenuFormData) => Promise; modifyMenu: ( menuCd: number, data: Omit, ) => Promise; - getTreeMenuList: (siteId: string) => Promise; - modifyTreeMenu: (siteId: string, data: TreeMenu[]) => Promise; + getTreeMenuList: (siteId: string) => Promise; + modifyTreeMenu: (siteId: string, data: TreeNode[]) => Promise; modifyMenuName: (menuCd: number, name: string) => Promise; } diff --git a/apps/cs/src/pages/menu/ui/menu-form.tsx b/apps/cs/src/pages/menu/ui/menu-form.tsx index e85204e17..f42e3d725 100644 --- a/apps/cs/src/pages/menu/ui/menu-form.tsx +++ b/apps/cs/src/pages/menu/ui/menu-form.tsx @@ -48,22 +48,22 @@ function MenuForm({ const onSubmit = async (data: MenuFormData) => { if (isModifyMode) { - onModify(data); + await onModify(data); } else { - onCreate(data); + await onCreate(data); } }; - const onCreate = (data: MenuFormData) => { - handleConfirm(async () => { + const onCreate = async (data: MenuFormData) => { + await handleConfirm(async () => { if (await confirm("저장하시겠습니까?")) { handleCreate(data); } }); }; - const onModify = (data: MenuFormData) => { - handleConfirm(async () => { + const onModify = async (data: MenuFormData) => { + await handleConfirm(async () => { if (await confirm("수정하시겠습니까?")) { handleModify({ menuCd: menuCd!, data }); } diff --git a/apps/cs/src/pages/menu/ui/menu-node.tsx b/apps/cs/src/pages/menu/ui/menu-node.tsx index 827e480d4..d938f0df0 100644 --- a/apps/cs/src/pages/menu/ui/menu-node.tsx +++ b/apps/cs/src/pages/menu/ui/menu-node.tsx @@ -5,15 +5,15 @@ import { Button, Input } from "@common/components/ui"; import { cn } from "@common/components/lib"; import { ENDPOINT } from "@/shared/config"; import { MenuApi } from "../api/menu-service"; -import type { Menu } from "../model/menu-interface"; +import type { TreeMenu } from "../model/menu-interface"; type MenuNodeProps = { - node: NodeModel; + node: NodeModel; depth: number; isOpen: boolean; isSelected: boolean; onToggle: (id: NodeModel["id"]) => void; - onSelect: (node: NodeModel) => void; + onSelect: (node: NodeModel) => void; }; function MenuNode({ diff --git a/apps/cs/src/pages/menu/ui/menu-page.tsx b/apps/cs/src/pages/menu/ui/menu-page.tsx index edd1910fd..57fdec1f1 100644 --- a/apps/cs/src/pages/menu/ui/menu-page.tsx +++ b/apps/cs/src/pages/menu/ui/menu-page.tsx @@ -17,7 +17,7 @@ import { SiteApi } from "@/entities/site"; import { ENDPOINT } from "@/shared/config"; import { PageLayout } from "@/shared/ui/page-layout"; import { useAlertStore } from "@/shared/lib/use-alert-store"; -import type { Menu, MenuType } from "../model/menu-interface"; +import type { TreeMenu } from "../model/menu-interface"; import { MenuApi } from "../api/menu-service"; import { MENU_TYPE, @@ -33,7 +33,13 @@ function MenuPage() { const { setMessage: alert } = useAlertStore((state) => state); const [siteId, setSiteId] = useState(""); - const [selectedMenu, setSelectedMenu] = useState(null); + const [selectedMenu, setSelectedMenu] = useState(null); + + const { data: menuInfo } = useQuery({ + queryKey: [ENDPOINT.CMS_SERVICE.MENUS, selectedMenu?.menuCd], + queryFn: () => MenuApi.getMenuInfo(selectedMenu?.menuCd ?? 0), + enabled: !!selectedMenu?.menuCd, + }); const { data: treeData } = useQuery({ queryKey: [ENDPOINT.CMS_SERVICE.MENUS, siteId], @@ -91,13 +97,15 @@ function MenuPage() { menuLnkgTypeCd: MENU_TYPE.EMPTY, }, values: { - ...selectedMenu, + ...menuInfo, siteId, - sortSeq: selectedMenu?.sortSeq ?? 1, - levelNo: selectedMenu?.levelNo ?? 1, - menuKornNm: selectedMenu?.menuKornNm ?? "", - menuLnkgTypeCd: - (selectedMenu?.menuLnkgTypeCd as MenuType) ?? MENU_TYPE.EMPTY, + sortSeq: menuInfo?.sortSeq ?? 1, + levelNo: menuInfo?.levelNo ?? 1, + menuKornNm: menuInfo?.menuKornNm ?? "", + menuLnkgTypeCd: menuInfo?.menuLnkgTypeCd ?? MENU_TYPE.EMPTY, + otptYn: menuInfo?.otptYn ?? "Y", + evlUseYn: menuInfo?.evlUseYn ?? "Y", + useYn: menuInfo?.useYn ?? "Y", }, }); @@ -106,7 +114,7 @@ function MenuPage() { form.setValue("siteId", value); }; - const handleNodeSelect = (node: NodeModel) => { + const handleNodeSelect = (node: NodeModel) => { if (!node.data) return; setSelectedMenu(node.data); }; diff --git a/apps/cs/src/pages/menu/ui/menu-tree.tsx b/apps/cs/src/pages/menu/ui/menu-tree.tsx index 02f7ffbba..a7d6b0fd3 100644 --- a/apps/cs/src/pages/menu/ui/menu-tree.tsx +++ b/apps/cs/src/pages/menu/ui/menu-tree.tsx @@ -10,15 +10,15 @@ import { } from "@minoru/react-dnd-treeview"; import { ENDPOINT } from "@/shared/config"; import { MenuApi } from "../api/menu-service"; -import type { Menu, TreeMenu } from "../model/menu-interface"; +import type { TreeMenu, TreeNode } from "../model/menu-interface"; import { handleDropNode, handleSelectNode } from "../lib/utils"; import { MenuNode } from "./menu-node"; type MenuTreeProps = { - treeData: NodeModel[]; + treeData: NodeModel[]; siteId: string; - selectedMenu: Menu | null; - onSelectNode: (node: NodeModel) => void; + selectedMenu: TreeMenu | null; + onSelectNode: (node: NodeModel) => void; }; function MenuTree({ @@ -30,7 +30,7 @@ function MenuTree({ const queryClient = useQueryClient(); const { mutate: modifyTreeMenu } = useMutation({ - mutationFn: (newTree: TreeMenu) => + mutationFn: (newTree: TreeNode) => MenuApi.modifyTreeMenu(siteId, [newTree]), onSuccess: () => { queryClient.invalidateQueries({ @@ -44,7 +44,7 @@ function MenuTree({ , { depth, isOpen, onToggle }) => ( + render={(node: NodeModel, { depth, isOpen, onToggle }) => (