@bwg-ui/core 1.1.24 → 1.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/AuthContext-BQ3gHLbr.cjs +2 -0
- package/dist/chunks/AuthContext-BQ3gHLbr.cjs.map +1 -0
- package/dist/chunks/{AuthContext-Ei2P-z4d.js → AuthContext-CVizgYxY.js} +14 -10
- package/dist/chunks/AuthContext-CVizgYxY.js.map +1 -0
- package/dist/chunks/{BwgSpace-CnLM4qcg.js → BwgSpace-BPJARdOc.js} +4 -4
- package/dist/chunks/{BwgSpace-CnLM4qcg.js.map → BwgSpace-BPJARdOc.js.map} +1 -1
- package/dist/chunks/BwgSpace-Cw27d-XU.cjs +2 -0
- package/dist/chunks/{BwgSpace-b0hmM1Ht.cjs.map → BwgSpace-Cw27d-XU.cjs.map} +1 -1
- package/dist/chunks/BwgSwitch-BLtVdW44.cjs +2 -0
- package/dist/chunks/BwgSwitch-BLtVdW44.cjs.map +1 -0
- package/dist/chunks/{BwgSwitch-B79pseQM.js → BwgSwitch-DdHo4gYR.js} +66 -66
- package/dist/chunks/BwgSwitch-DdHo4gYR.js.map +1 -0
- package/dist/chunks/{BwgUploader-BcVlE61B.js → BwgUploader-BUmFmeuS.js} +639 -639
- package/dist/chunks/BwgUploader-BUmFmeuS.js.map +1 -0
- package/dist/chunks/BwgUploader-Djhl4lIt.cjs +3 -0
- package/dist/chunks/BwgUploader-Djhl4lIt.cjs.map +1 -0
- package/dist/chunks/LoadingOverlay-Uf6xy04v.js +19 -0
- package/dist/chunks/LoadingOverlay-Uf6xy04v.js.map +1 -0
- package/dist/chunks/LoadingOverlay-jdMzdB-z.cjs +2 -0
- package/dist/chunks/LoadingOverlay-jdMzdB-z.cjs.map +1 -0
- package/dist/chunks/{SSOHandler-CkPcSHIm.js → SSOHandler-CR0nR3rJ.js} +8132 -8085
- package/dist/chunks/SSOHandler-CR0nR3rJ.js.map +1 -0
- package/dist/chunks/{SSOHandler-DiW4Ft9i.cjs → SSOHandler-DQG0Jp4V.cjs} +53 -53
- package/dist/chunks/SSOHandler-DQG0Jp4V.cjs.map +1 -0
- package/dist/chunks/ScreenProtectContext-BMsPPcTX.js +154 -0
- package/dist/chunks/ScreenProtectContext-BMsPPcTX.js.map +1 -0
- package/dist/chunks/ScreenProtectContext-DrCGlcTs.cjs +2 -0
- package/dist/chunks/ScreenProtectContext-DrCGlcTs.cjs.map +1 -0
- package/dist/chunks/SearchBoxContext-DY6lES-W.cjs +2 -0
- package/dist/chunks/SearchBoxContext-DY6lES-W.cjs.map +1 -0
- package/dist/chunks/{SearchBoxContext-BCvEYyFk.js → SearchBoxContext-Dtzo_rJd.js} +25 -27
- package/dist/chunks/SearchBoxContext-Dtzo_rJd.js.map +1 -0
- package/dist/chunks/ViewContainer-BfiTFvLP.cjs +36 -0
- package/dist/chunks/ViewContainer-BfiTFvLP.cjs.map +1 -0
- package/dist/chunks/{ViewContainer-CjpJqoGG.js → ViewContainer-CTl3_56W.js} +128 -116
- package/dist/chunks/ViewContainer-CTl3_56W.js.map +1 -0
- package/dist/chunks/apiUtils-D9Vn1gwZ.cjs +3 -0
- package/dist/chunks/apiUtils-D9Vn1gwZ.cjs.map +1 -0
- package/dist/chunks/{apiUtils-DxzLqPhU.js → apiUtils-DPUgfmKk.js} +57 -48
- package/dist/chunks/apiUtils-DPUgfmKk.js.map +1 -0
- package/dist/chunks/{codeStore-CfI4Wh5M.js → codeStore-BrCfe9K3.js} +2 -2
- package/dist/chunks/{codeStore-CfI4Wh5M.js.map → codeStore-BrCfe9K3.js.map} +1 -1
- package/dist/chunks/{codeStore-il4-kZPe.cjs → codeStore-_b2fDZtD.cjs} +2 -2
- package/dist/chunks/{codeStore-il4-kZPe.cjs.map → codeStore-_b2fDZtD.cjs.map} +1 -1
- package/dist/chunks/{core-bHd8azE6.js → core-BBMCFpHx.js} +2 -2
- package/dist/chunks/{core-bHd8azE6.js.map → core-BBMCFpHx.js.map} +1 -1
- package/dist/chunks/{core-BHejg5iS.cjs → core-CM9MsJRf.cjs} +2 -2
- package/dist/chunks/{core-BHejg5iS.cjs.map → core-CM9MsJRf.cjs.map} +1 -1
- package/dist/chunks/{enc-base64-BQYwLKgk.js → enc-base64-DAsYWbA2.js} +3 -3
- package/dist/chunks/{enc-base64-BQYwLKgk.js.map → enc-base64-DAsYWbA2.js.map} +1 -1
- package/dist/chunks/{enc-base64-BkBtNBQV.cjs → enc-base64-DbK5VBfD.cjs} +2 -2
- package/dist/chunks/{enc-base64-BkBtNBQV.cjs.map → enc-base64-DbK5VBfD.cjs.map} +1 -1
- package/dist/chunks/{favoriteStore-CcKg_nEH.cjs → favoriteStore-BnQ2u-sa.cjs} +2 -2
- package/dist/chunks/{favoriteStore-CcKg_nEH.cjs.map → favoriteStore-BnQ2u-sa.cjs.map} +1 -1
- package/dist/chunks/{favoriteStore-Cemc-26t.js → favoriteStore-SyAjqLG8.js} +2 -2
- package/dist/chunks/{favoriteStore-Cemc-26t.js.map → favoriteStore-SyAjqLG8.js.map} +1 -1
- package/dist/chunks/{popupStore-Bi6o78lP.js → popupStore-BrKcPw7K.js} +2 -2
- package/dist/chunks/{popupStore-Bi6o78lP.js.map → popupStore-BrKcPw7K.js.map} +1 -1
- package/dist/chunks/{popupStore-DUApUBF2.cjs → popupStore-ChbYTqy1.cjs} +2 -2
- package/dist/chunks/{popupStore-DUApUBF2.cjs.map → popupStore-ChbYTqy1.cjs.map} +1 -1
- package/dist/chunks/{sha256-DiIRoCQ8.cjs → sha256-BnWVPP1K.cjs} +2 -2
- package/dist/chunks/{sha256-DiIRoCQ8.cjs.map → sha256-BnWVPP1K.cjs.map} +1 -1
- package/dist/chunks/{sha256-BZfJs28k.js → sha256-D80RpYO2.js} +3 -3
- package/dist/chunks/{sha256-BZfJs28k.js.map → sha256-D80RpYO2.js.map} +1 -1
- package/dist/chunks/{usePopup-BSqsnSz7.js → usePopup-DnfKRiYs.js} +27 -27
- package/dist/chunks/usePopup-DnfKRiYs.js.map +1 -0
- package/dist/chunks/usePopup-Domnpg55.cjs +2 -0
- package/dist/chunks/usePopup-Domnpg55.cjs.map +1 -0
- package/dist/components/common/BookmarkMngModal.d.ts +1 -1
- package/dist/components/common/BookmarkMngModal.d.ts.map +1 -1
- package/dist/components/common/BookmarkPopver.d.ts +2 -2
- package/dist/components/common/BookmarkPopver.d.ts.map +1 -1
- package/dist/components/common/BwgButtonGroup.d.ts +5 -5
- package/dist/components/common/BwgButtonGroup.d.ts.map +1 -1
- package/dist/components/common/BwgCmptArea.d.ts +7 -7
- package/dist/components/common/BwgCmptArea.d.ts.map +1 -1
- package/dist/components/common/BwgCol.d.ts +2 -1
- package/dist/components/common/BwgCol.d.ts.map +1 -1
- package/dist/components/common/BwgConfigProvider.d.ts +2 -2
- package/dist/components/common/BwgConfigProvider.d.ts.map +1 -1
- package/dist/components/common/BwgDetail.d.ts +2 -1
- package/dist/components/common/BwgDetail.d.ts.map +1 -1
- package/dist/components/common/BwgDraggable.d.ts +5 -5
- package/dist/components/common/BwgDraggable.d.ts.map +1 -1
- package/dist/components/common/BwgDrawer.d.ts +2 -1
- package/dist/components/common/BwgDrawer.d.ts.map +1 -1
- package/dist/components/common/BwgEditor.d.ts +5 -5
- package/dist/components/common/BwgEditor.d.ts.map +1 -1
- package/dist/components/common/BwgGrid.d.ts +8 -8
- package/dist/components/common/BwgGrid.d.ts.map +1 -1
- package/dist/components/common/BwgInfoArea.d.ts +4 -4
- package/dist/components/common/BwgInfoArea.d.ts.map +1 -1
- package/dist/components/common/BwgPopup.d.ts +3 -3
- package/dist/components/common/BwgPopup.d.ts.map +1 -1
- package/dist/components/common/BwgRow.d.ts +2 -1
- package/dist/components/common/BwgRow.d.ts.map +1 -1
- package/dist/components/common/BwgTitleBox.d.ts +5 -4
- package/dist/components/common/BwgTitleBox.d.ts.map +1 -1
- package/dist/components/common/BwgView.d.ts +4 -4
- package/dist/components/common/BwgView.d.ts.map +1 -1
- package/dist/components/common/ContentBox.d.ts +3 -3
- package/dist/components/common/ContentBox.d.ts.map +1 -1
- package/dist/components/common/ContentLayOut.d.ts +6 -5
- package/dist/components/common/ContentLayOut.d.ts.map +1 -1
- package/dist/components/common/GlobalConfigProvider.d.ts +2 -2
- package/dist/components/common/GlobalConfigProvider.d.ts.map +1 -1
- package/dist/components/common/QuickServiceToggle.d.ts +4 -4
- package/dist/components/common/QuickServiceToggle.d.ts.map +1 -1
- package/dist/components/common/SSOHandler.d.ts +2 -1
- package/dist/components/common/SSOHandler.d.ts.map +1 -1
- package/dist/components/common/SearchBox.d.ts +5 -4
- package/dist/components/common/SearchBox.d.ts.map +1 -1
- package/dist/components/common/index.cjs +1 -1
- package/dist/components/common/index.js +2 -2
- package/dist/components/core/BwgButton.d.ts +3 -2
- package/dist/components/core/BwgButton.d.ts.map +1 -1
- package/dist/components/core/BwgDatePicker.d.ts +3 -3
- package/dist/components/core/BwgDatePicker.d.ts.map +1 -1
- package/dist/components/core/BwgDownload.d.ts +2 -2
- package/dist/components/core/BwgDownload.d.ts.map +1 -1
- package/dist/components/core/BwgForm.d.ts +2 -1
- package/dist/components/core/BwgForm.d.ts.map +1 -1
- package/dist/components/core/BwgFormItem.d.ts +4 -4
- package/dist/components/core/BwgFormItem.d.ts.map +1 -1
- package/dist/components/core/BwgInput.d.ts +2 -2
- package/dist/components/core/BwgInput.d.ts.map +1 -1
- package/dist/components/core/BwgLargeUploader.d.ts +2 -2
- package/dist/components/core/BwgLargeUploader.d.ts.map +1 -1
- package/dist/components/core/BwgMaskedInput.d.ts +2 -2
- package/dist/components/core/BwgMaskedInput.d.ts.map +1 -1
- package/dist/components/core/BwgMaskedPicker.d.ts +2 -2
- package/dist/components/core/BwgMaskedPicker.d.ts.map +1 -1
- package/dist/components/core/BwgRangePicker.d.ts +3 -3
- package/dist/components/core/BwgRangePicker.d.ts.map +1 -1
- package/dist/components/core/BwgSearch.d.ts +1 -1
- package/dist/components/core/BwgSearch.d.ts.map +1 -1
- package/dist/components/core/BwgUploader.d.ts +2 -2
- package/dist/components/core/BwgUploader.d.ts.map +1 -1
- package/dist/components/core/index.cjs +1 -1
- package/dist/components/core/index.js +2 -2
- package/dist/components/guide/index.cjs +1 -1
- package/dist/components/guide/index.cjs.map +1 -1
- package/dist/components/guide/index.js +3 -3
- package/dist/components/guide/index.js.map +1 -1
- package/dist/components/layout/ErrorBound.d.ts +3 -3
- package/dist/components/layout/ErrorBound.d.ts.map +1 -1
- package/dist/components/layout/LoadingOverlay.d.ts +3 -2
- package/dist/components/layout/LoadingOverlay.d.ts.map +1 -1
- package/dist/components/layout/PrivateProtectedOverlay.d.ts +3 -2
- package/dist/components/layout/PrivateProtectedOverlay.d.ts.map +1 -1
- package/dist/components/layout/ProgressOverlay.d.ts +2 -2
- package/dist/components/layout/ProgressOverlay.d.ts.map +1 -1
- package/dist/components/layout/ViewContainer.d.ts +3 -3
- package/dist/components/layout/ViewContainer.d.ts.map +1 -1
- package/dist/components/layout/index.cjs +1 -1
- package/dist/components/layout/index.js +2 -2
- package/dist/components/popup/MenuReport.d.ts +2 -2
- package/dist/components/popup/MenuReport.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +14 -14
- package/dist/provider/contexts/AuthContext.d.ts +3 -2
- package/dist/provider/contexts/AuthContext.d.ts.map +1 -1
- package/dist/provider/contexts/CommonCodeContext.d.ts +2 -2
- package/dist/provider/contexts/CommonCodeContext.d.ts.map +1 -1
- package/dist/provider/contexts/ScreenProtectContext.d.ts +5 -5
- package/dist/provider/contexts/ScreenProtectContext.d.ts.map +1 -1
- package/dist/provider/contexts/SearchBoxContext.d.ts +3 -3
- package/dist/provider/contexts/SearchBoxContext.d.ts.map +1 -1
- package/dist/provider/contexts/ServiceCodeContext.d.ts +2 -2
- package/dist/provider/contexts/ServiceCodeContext.d.ts.map +1 -1
- package/dist/provider/index.cjs +1 -1
- package/dist/provider/index.js +4 -4
- package/dist/stores/index.cjs +1 -1
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +6 -6
- package/dist/stores/menuViewStore.d.ts +6 -5
- package/dist/stores/menuViewStore.d.ts.map +1 -1
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.js +2 -2
- package/package.json +2 -3
- package/dist/chunks/AuthContext-CXng9fj0.cjs +0 -2
- package/dist/chunks/AuthContext-CXng9fj0.cjs.map +0 -1
- package/dist/chunks/AuthContext-Ei2P-z4d.js.map +0 -1
- package/dist/chunks/BwgSpace-b0hmM1Ht.cjs +0 -2
- package/dist/chunks/BwgSwitch-B79pseQM.js.map +0 -1
- package/dist/chunks/BwgSwitch-CAI-kEaM.cjs +0 -2
- package/dist/chunks/BwgSwitch-CAI-kEaM.cjs.map +0 -1
- package/dist/chunks/BwgUploader-BcVlE61B.js.map +0 -1
- package/dist/chunks/BwgUploader-DaNV2URT.cjs +0 -3
- package/dist/chunks/BwgUploader-DaNV2URT.cjs.map +0 -1
- package/dist/chunks/LoadingOverlay-DAZJF5wg.js +0 -19
- package/dist/chunks/LoadingOverlay-DAZJF5wg.js.map +0 -1
- package/dist/chunks/LoadingOverlay-DcmKvoZA.cjs +0 -2
- package/dist/chunks/LoadingOverlay-DcmKvoZA.cjs.map +0 -1
- package/dist/chunks/SSOHandler-CkPcSHIm.js.map +0 -1
- package/dist/chunks/SSOHandler-DiW4Ft9i.cjs.map +0 -1
- package/dist/chunks/ScreenProtectContext-3my4PHFa.js +0 -154
- package/dist/chunks/ScreenProtectContext-3my4PHFa.js.map +0 -1
- package/dist/chunks/ScreenProtectContext-CVuXrJm6.cjs +0 -2
- package/dist/chunks/ScreenProtectContext-CVuXrJm6.cjs.map +0 -1
- package/dist/chunks/SearchBoxContext-BCvEYyFk.js.map +0 -1
- package/dist/chunks/SearchBoxContext-DwFDOyYG.cjs +0 -2
- package/dist/chunks/SearchBoxContext-DwFDOyYG.cjs.map +0 -1
- package/dist/chunks/ViewContainer-Bhq22_B3.cjs +0 -36
- package/dist/chunks/ViewContainer-Bhq22_B3.cjs.map +0 -1
- package/dist/chunks/ViewContainer-CjpJqoGG.js.map +0 -1
- package/dist/chunks/apiUtils-BZ6s0_NI.cjs +0 -3
- package/dist/chunks/apiUtils-BZ6s0_NI.cjs.map +0 -1
- package/dist/chunks/apiUtils-DxzLqPhU.js.map +0 -1
- package/dist/chunks/jsx-runtime-CeSfJrVB.cjs +0 -31
- package/dist/chunks/jsx-runtime-CeSfJrVB.cjs.map +0 -1
- package/dist/chunks/jsx-runtime-Dpn_P65e.js +0 -634
- package/dist/chunks/jsx-runtime-Dpn_P65e.js.map +0 -1
- package/dist/chunks/usePopup-BSqsnSz7.js.map +0 -1
- package/dist/chunks/usePopup-D2JEuDrO.cjs +0 -2
- package/dist/chunks/usePopup-D2JEuDrO.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"favoriteStore-CcKg_nEH.cjs","sources":["../../src/stores/favoriteStore.ts"],"sourcesContent":["// -------------------------------------------------------\r\n// 즐겨찾기(폴더형) Zustand Store (단일 테이블 CM_BKMK_MSTR 기반)\r\n// 공통 CRUD로 통합: addNode / moveNode / removeNode / editNode\r\n// 기존 API(폴더/메뉴 전용)는 호환용으로 래핑만 유지\r\n// - 정규화(nodes + rootIds)\r\n// - 낙관적 업데이트 + 임시ID(tmp_* → 서버ID) 스왑\r\n// - 필수 기능: 로드, 생성, 이동, 삭제, 수정 + 셀렉터/뷰 변환\r\n// -------------------------------------------------------\r\n\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getUserId } from \"../utils/userUtils\";\r\nimport { DataNode } from \"antd/es/tree\";\r\nimport { create, StateCreator } from \"zustand\";\r\n\r\n// 🔧 공통 ID 타입\r\nexport type Id = string;\r\n\r\n/** 공통 베이스 (CM_BKMK_MSTR 매핑) */\r\nexport type BkmkBase = {\r\n type: \"F\" | \"M\"; // TYPE\r\n bkmkId: Id; // BKMK_ID\r\n prntBkmkId: Id | \"-\"; // PRNT_BKMK_ID ('-'=루트)\r\n sortOrdr: number; // SORT_ORDR\r\n sysCd?: string; // SYS_CD (옵션)\r\n userId?: string | null; // USER_ID (옵션)\r\n fullPath?: string; // 프론트 보조(옵션)\r\n};\r\n\r\n/** 폴더 노드 (BKMK_NM 사용) */\r\nexport type FolderNode = BkmkBase & {\r\n bkmkNm: string; // BKMK_NM (폴더 전용)\r\n children: Id[]; // 폴더/아이템 혼재(정규화용)\r\n};\r\n\r\n/** 아이템 노드 (메뉴 전용 메타) */\r\nexport type ItemNode = BkmkBase & {\r\n menuId: string; // MENU_ID\r\n menuNm?: string; // 프론트 보조(메뉴명)\r\n};\r\n\r\nexport type FavNode = FolderNode | ItemNode;\r\n\r\nexport type MovePayload = {\r\n bkmkId: Id;\r\n newPrntBkmkId: Id | \"-\";\r\n sortOrdr: number; // 새 부모 내 0-based\r\n userId: string | null;\r\n};\r\n\r\nexport type AddNodePayload = {\r\n type: \"F\" | \"M\";\r\n prntBkmkId: Id | \"-\";\r\n sysCd: string;\r\n userId: string | null;\r\n bkmkNm?: string; // F 전용\r\n menuId?: string; // M 전용\r\n menuNm?: string; // 프론트 보조\r\n sortOrdr?: number; // 선택: 지정 없으면 tailIndex 사용\r\n};\r\n\r\nexport type EditNodePayload = {\r\n bkmkId: Id;\r\n userId: string;\r\n bkmkNm?: string; // F일 때만 의미\r\n prntBkmkId?: Id | \"-\"; // 선택(이동은 moveNode 권장)\r\n sortOrdr?: number; // 선택\r\n};\r\n\r\nexport type Normalized = { nodes: Record<Id, FavNode>; rootIds: Id[] };\r\n\r\nexport type State = {\r\n // ========== 데이터(정규화) ==========\r\n nodes: Record<Id, FavNode>;\r\n rootIds: Id[];\r\n treeNodes: FavNode[]; // 단순 트리(뷰용)\r\n\r\n // ========== 메타 ==========\r\n loadedFor?: string;\r\n loading: boolean;\r\n error?: string;\r\n\r\n // ========== 셀렉터 ==========\r\n isMenuBookmarked: (menuId: string) => boolean;\r\n getPrntBkmkIdByMenuId: (menuId: string) => Id | \"-\";\r\n getNodeByMenuId: (menuId: string) => ItemNode | null;\r\n getFolderTree: (q?: string) => DataNode[]; // 폴더만 Tree (검색 필터)\r\n\r\n // ========== 로더 ==========\r\n loadFavorites: (userId: string, force?: boolean) => Promise<void>;\r\n loadFavoritesIfNeeded: (userId: string) => Promise<void>;\r\n\r\n // ========== 공통 CRUD ==========\r\n addNode: (p: AddNodePayload) => Promise<Id>;\r\n moveNode: (p: MovePayload) => Promise<void>;\r\n removeNode: (bkmkId: Id) => Promise<void>;\r\n editNode: (p: EditNodePayload) => Promise<void>;\r\n\r\n // ========== 호환용(기존 API 유지, 내부에서 공통 호출) ==========\r\n addFolder: (\r\n bkmkNm: string,\r\n prntBkmkId: Id | \"-\",\r\n sysCd: string,\r\n userId: string | null\r\n ) => Promise<Id>;\r\n addMenuToFolder: (\r\n folderBkmkId: Id,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<Id | string>;\r\n toggleMenuFavorite: (\r\n userId: string | null,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<void>;\r\n removeMenu: (bkmkId: Id) => Promise<void>;\r\n removeMenuByMenuId: (menuId: string) => Promise<void>;\r\n removeFolder: (folderBkmkId: Id) => Promise<void>;\r\n editFolder: (\r\n folderBkmkId: Id,\r\n userId: string | null,\r\n newBkmkNm?: string,\r\n prntBkmkId?: Id | \"-\",\r\n sortOrdr?: number\r\n ) => Promise<void>;\r\n convertToAntTreeData: (\r\n nodesMap: Record<string, FavNode>,\r\n rootIds: string[],\r\n q: string,\r\n onlyFolder?: boolean\r\n ) => any[];\r\n};\r\n\r\nconst creator: StateCreator<State> = (set, get) => ({\r\n nodes: {},\r\n rootIds: [],\r\n loadedFor: undefined,\r\n loading: false,\r\n error: undefined,\r\n treeNodes: [],\r\n\r\n // ====== 셀렉터 ======\r\n isMenuBookmarked: (menuId) =>\r\n Object.values(get().nodes).some(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menuId\r\n ),\r\n getPrntBkmkIdByMenuId: (menuId) => {\r\n const id = findItemByMenuId(get().nodes, menuId);\r\n return id ? get().nodes[id]?.prntBkmkId ?? \"-\" : \"-\";\r\n },\r\n\r\n getNodeByMenuId: (menuId) => {\r\n const nodeId = findItemByMenuId(get().nodes, menuId);\r\n if (!nodeId) return null;\r\n const node = get().nodes[nodeId];\r\n return node?.type === \"M\" ? (node as ItemNode) : null;\r\n },\r\n\r\n getFolderTree: (q) => {\r\n const { nodes, rootIds } = get();\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const make = (id: Id): DataNode | null => {\r\n const n = nodes[id];\r\n if (!n || n.type !== \"F\") return null;\r\n const folder = n as FolderNode;\r\n\r\n const kids = (folder.children || [])\r\n .map((cid) => nodes[cid])\r\n .filter((c): c is FolderNode => !!c && c.type === \"F\")\r\n .map((f) => make(f.bkmkId))\r\n .filter(Boolean) as DataNode[];\r\n\r\n const visible = match(folder.bkmkNm) || kids.length > 0;\r\n if (!visible) return null;\r\n\r\n return {\r\n key: folder.bkmkId,\r\n title: `📁 ${folder.bkmkNm}`,\r\n children: kids.length ? kids : undefined,\r\n };\r\n };\r\n\r\n return rootIds.map((rid) => make(rid)).filter(Boolean) as DataNode[];\r\n },\r\n\r\n // ====== 로더 ======\r\n loadFavorites: async (userId, force = false) => {\r\n console.log(\"loadFavorites ::::: \", userId, force);\r\n const s = get();\r\n if (!force && s.loadedFor === userId && Object.keys(s.nodes).length) return;\r\n\r\n set({ loading: true, error: undefined });\r\n try {\r\n // 기대 응답 예시: { sub: rawTree[] }\r\n const res = await callService(\"SCMBKMK00101\", { userId });\r\n const raw: any[] = Array.isArray(res?.sub) ? res.sub : [];\r\n const normalized = normalize(raw);\r\n\r\n const treeNodes = toSimpleTreeFromMap(\r\n normalized.nodes,\r\n normalized.rootIds\r\n );\r\n\r\n set({\r\n ...normalized,\r\n treeNodes,\r\n loadedFor: userId,\r\n loading: false,\r\n });\r\n } catch (e: any) {\r\n set({ loading: false, error: e?.message || \"즐겨찾기 로드 실패\" });\r\n throw e;\r\n }\r\n },\r\n\r\n loadFavoritesIfNeeded: async (userId) => {\r\n const s = get();\r\n const notLoaded =\r\n s.loadedFor !== userId || Object.keys(s.nodes).length === 0;\r\n if (notLoaded) {\r\n await get().loadFavorites(userId);\r\n }\r\n },\r\n\r\n // ====== 공통: 생성 ======\r\n addNode: async (p) => {\r\n const prev = snapshot(get());\r\n const tmp = tempId();\r\n\r\n // 1) 낙관적 반영\r\n set((s) => {\r\n const sort = p.sortOrdr ?? tailIndex(s, p.prntBkmkId);\r\n const next: State = {\r\n ...s,\r\n nodes: {\r\n ...s.nodes,\r\n [tmp]:\r\n p.type === \"F\"\r\n ? ({\r\n bkmkId: tmp,\r\n type: \"F\",\r\n prntBkmkId: p.prntBkmkId || \"-\",\r\n sortOrdr: sort,\r\n bkmkNm: p.bkmkNm ?? \"새 폴더\",\r\n children: [],\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as FolderNode)\r\n : ({\r\n bkmkId: tmp,\r\n type: \"M\",\r\n prntBkmkId: p.prntBkmkId,\r\n sortOrdr: sort,\r\n menuId: p.menuId ?? \"\",\r\n menuNm: p.menuNm,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as ItemNode),\r\n },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n attach(next, tmp, p.prntBkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n // 2) 서버 호출\r\n // 백엔드는 통합 IUD가 아닐 수 있으므로, 호환 분기 적용\r\n let real: string = tmp;\r\n const sortForServer = tailIndex(get(), p.prntBkmkId);\r\n const res = await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"I\",\r\n type: p.type,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n bkmkId: tmp, // 서버 새 ID 반환 시 매칭용\r\n bkmkNm: p.bkmkNm,\r\n prntBkmkId: p.prntBkmkId,\r\n menuId: p.menuId,\r\n sortOrdr: sortForServer,\r\n chngId: getUserId(),\r\n });\r\n real = String(res?.bkmkId ?? res?.itemId ?? tmp);\r\n\r\n // 3) tmp → real 스왑\r\n set((s) => {\r\n const swapped = idSwapImmutable(s, tmp, real);\r\n return {\r\n ...swapped,\r\n treeNodes: toSimpleTreeFromMap(swapped.nodes, swapped.rootIds),\r\n };\r\n });\r\n return real;\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 이동 ======\r\n moveNode: async ({ bkmkId, newPrntBkmkId, sortOrdr, userId }) => {\r\n const prev = get(); // 함수 포함 스냅샷(rollback 용으로 set(prev) 사용)\r\n\r\n const nodes = structuredClone(prev.nodes);\r\n const rootIds = [...prev.rootIds];\r\n\r\n const node = nodes[bkmkId];\r\n if (!node) return;\r\n\r\n // 부모는 반드시 폴더만 허용\r\n if (newPrntBkmkId !== \"-\") {\r\n const parent = nodes[newPrntBkmkId];\r\n if (!parent || parent.type !== \"F\")\r\n throw new Error(\"부모는 폴더만 가능합니다.\");\r\n }\r\n\r\n const oldParentId = node.prntBkmkId ?? \"-\";\r\n\r\n const removeFrom =\r\n oldParentId === \"-\"\r\n ? rootIds\r\n : ((nodes[oldParentId] as FolderNode).children ||= []);\r\n {\r\n const idx = removeFrom.indexOf(bkmkId);\r\n if (idx >= 0) removeFrom.splice(idx, 1);\r\n }\r\n\r\n const insertTo =\r\n newPrntBkmkId === \"-\"\r\n ? rootIds\r\n : ((nodes[newPrntBkmkId] as FolderNode).children ||= []);\r\n insertTo.splice(\r\n Math.max(0, Math.min(sortOrdr, insertTo.length)),\r\n 0,\r\n bkmkId\r\n );\r\n\r\n node.prntBkmkId = newPrntBkmkId as Id;\r\n set({ nodes, rootIds });\r\n _resequence(nodes, rootIds, newPrntBkmkId);\r\n _resequence(nodes, rootIds, oldParentId);\r\n\r\n try {\r\n await callService(\"SCMBKMK00104\", {\r\n // 백엔드 명칭 호환\r\n bkmkId,\r\n prntBkmkId: newPrntBkmkId,\r\n sortOrdr,\r\n chngId: userId,\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 삭제 ======\r\n removeNode: async (bkmkId) => {\r\n const prev = snapshot(get());\r\n\r\n set((s) => {\r\n if (!s.nodes[bkmkId]) return s as State;\r\n const next: State = {\r\n ...s,\r\n nodes: { ...s.nodes },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n removeRecursively(next, bkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00103\", { bkmkId });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 수정 ======\r\n editNode: async ({ bkmkId, userId, bkmkNm, prntBkmkId, sortOrdr }) => {\r\n const prev = snapshot(get());\r\n\r\n // 폴더명 변경만 프런트 즉시 반영(옵션)\r\n set((s) => {\r\n const next = { ...s, nodes: { ...s.nodes } } as State;\r\n const target = next.nodes[bkmkId] as FavNode | undefined;\r\n if (target?.type === \"F\" && typeof bkmkNm === \"string\") {\r\n next.nodes[bkmkId] = {\r\n ...(target as FolderNode),\r\n bkmkNm,\r\n } as FolderNode;\r\n }\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"U\",\r\n userId,\r\n bkmkId,\r\n bkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n chngId: getUserId(),\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 호환용 래퍼 ======\r\n addFolder: async (bkmkNm, prntBkmkId, sysCd, userId) => {\r\n return await get().addNode({\r\n type: \"F\",\r\n bkmkNm,\r\n prntBkmkId,\r\n sysCd,\r\n userId,\r\n });\r\n },\r\n\r\n addMenuToFolder: async (folderBkmkId, menu) => {\r\n // 전역 중복 방지\r\n const dup = findItemByMenuId(get().nodes, menu.menuId);\r\n if (dup) return \"이미 북마크에 저장된 메뉴입니다.\";\r\n return await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderBkmkId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n },\r\n\r\n toggleMenuFavorite: async (userId, menu) => {\r\n const s = get();\r\n const exists = Object.values(s.nodes).find(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menu.menuId\r\n );\r\n if (exists) {\r\n await get().removeNode(exists.bkmkId);\r\n return;\r\n }\r\n\r\n let folderId = pickDefaultFolderId(s);\r\n if (!folderId) {\r\n await get().loadFavorites(userId, true);\r\n folderId = pickDefaultFolderId(get());\r\n }\r\n if (folderId) {\r\n await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n }\r\n },\r\n\r\n removeMenuByMenuId: async (menuId) => {\r\n const s = get();\r\n const bkmkId = findItemByMenuId(s.nodes, menuId);\r\n if (bkmkId) await get().removeNode(bkmkId);\r\n },\r\n\r\n removeMenu: async (bkmkId) => {\r\n await get().removeNode(bkmkId);\r\n },\r\n\r\n removeFolder: async (folderBkmkId) => {\r\n await get().removeNode(folderBkmkId);\r\n },\r\n\r\n editFolder: async (folderBkmkId, userId, newBkmkNm, prntBkmkId, sortOrdr) => {\r\n await get().editNode({\r\n bkmkId: folderBkmkId,\r\n userId,\r\n bkmkNm: newBkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n });\r\n },\r\n\r\n /** Ant Tree 데이터 변환 (검색 포함) */\r\n convertToAntTreeData: (nodesMap, rootIds, q, onlyFolder = false) => {\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const build = (id: string): any | null => {\r\n const n = nodesMap[id];\r\n if (!n) return null;\r\n\r\n if (onlyFolder && n.type !== \"F\") return null;\r\n\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const children = (f.children || [])\r\n .map((cid) => build(cid))\r\n .filter(Boolean);\r\n const visible = match(f.bkmkNm) || children.length > 0;\r\n if (!visible) return null;\r\n return {\r\n key: f.bkmkId,\r\n type: \"F\",\r\n title: `📁 ${f.bkmkNm}`,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n sortOrdr: f.sortOrdr,\r\n fullPath: f.fullPath,\r\n children: children.length ? children : undefined,\r\n };\r\n } else {\r\n const i = n as ItemNode;\r\n const label = i.menuNm ? `${i.menuNm} (${i.menuId})` : i.menuId;\r\n const visible = match(label);\r\n if (!visible) return null;\r\n return {\r\n key: i.bkmkId,\r\n type: \"M\",\r\n title: `📄 ${label}`,\r\n prntBkmkId: i.prntBkmkId,\r\n sortOrdr: i.sortOrdr,\r\n fullPath: i.fullPath,\r\n isLeaf: true,\r\n };\r\n }\r\n };\r\n\r\n return rootIds.map(build).filter(Boolean);\r\n },\r\n});\r\n\r\nexport const useFavoriteStore = create<State>(creator);\r\n\r\n// ===================================================================\r\n// Helpers\r\n// ===================================================================\r\n\r\nfunction normalize(raw: any[]): Normalized {\r\n const nodes: Record<Id, FavNode> = {};\r\n const roots: Id[] = [];\r\n\r\n const walk = (arr: any[]) => {\r\n arr.forEach((r: any) => {\r\n // 서버 raw 필드: TYPE, BKMK_ID, PRNT_BKMK_ID, SORT_ORDR, BKMK_NM, MENU_ID, FULL_PATH?\r\n const base: BkmkBase = {\r\n type: r.type,\r\n bkmkId: r.bkmkId ?? r.BKMK_ID ?? r.id,\r\n prntBkmkId: r.prntBkmkId ?? r.PRNT_BKMK_ID ?? \"-\",\r\n sortOrdr: Number(r.sortOrdr ?? r.SORT_ORDR ?? 0),\r\n sysCd: r.sysCd ?? r.SYS_CD,\r\n userId: r.userId ?? r.USER_ID,\r\n fullPath: r.fullPath ?? r.FULL_PATH,\r\n };\r\n\r\n if (r.type === \"F\") {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n bkmkNm: r.bkmkNm ?? r.BKMK_NM ?? r.name ?? base.bkmkId,\r\n children: [],\r\n } as FolderNode;\r\n\r\n const children = Array.isArray(r.children) ? r.children : [];\r\n walk(children);\r\n } else {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n menuId: r.menuId ?? r.MENU_ID ?? \"\",\r\n menuNm: r.menuNm ?? r.MENU_NM,\r\n } as ItemNode;\r\n }\r\n });\r\n };\r\n\r\n walk(raw);\r\n\r\n // children / rootIds 구성\r\n Object.values(nodes).forEach((n) => {\r\n if (n.prntBkmkId && n.prntBkmkId !== \"-\") {\r\n const p = nodes[n.prntBkmkId] as FolderNode;\r\n if (p?.type === \"F\") p.children.push(n.bkmkId);\r\n } else if (n.type === \"F\") {\r\n roots.push(n.bkmkId);\r\n }\r\n });\r\n\r\n // 정렬 인덱스 보정(안전)\r\n roots.sort((a, b) => (nodes[a].sortOrdr ?? 0) - (nodes[b].sortOrdr ?? 0));\r\n Object.values(nodes).forEach((n) => {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n f.children.sort(\r\n (A, B) => (nodes[A].sortOrdr ?? 0) - (nodes[B].sortOrdr ?? 0)\r\n );\r\n }\r\n });\r\n\r\n return { nodes, rootIds: roots };\r\n}\r\n\r\nfunction snapshot(s: State): State {\r\n return {\r\n ...s,\r\n nodes: JSON.parse(JSON.stringify(s.nodes)),\r\n rootIds: s.rootIds.slice(),\r\n };\r\n}\r\n\r\nfunction tempId(): Id {\r\n return `tmp_${Math.random().toString(36).slice(2, 10)}`;\r\n}\r\n\r\nfunction tailIndex(s: Pick<State, \"nodes\" | \"rootIds\">, parentId: Id | \"-\") {\r\n if (!parentId || parentId === \"-\") return s.rootIds.length;\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n return p ? p.children.length : 0;\r\n}\r\n\r\nfunction attach(s: State, bkmkId: Id, parentId: Id | \"-\") {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n\r\n if (parentId && parentId !== \"-\") {\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n if (!p || p.type !== \"F\") return;\r\n n.prntBkmkId = parentId;\r\n p.children = [...p.children, bkmkId];\r\n } else {\r\n n.prntBkmkId = \"-\";\r\n s.rootIds = [...s.rootIds, bkmkId];\r\n }\r\n}\r\n\r\nfunction detach(s: State, bkmkId: Id) {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n const pid = n.prntBkmkId;\r\n\r\n if (pid && pid !== \"-\") {\r\n const p = s.nodes[pid] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n p.children = p.children.filter((c) => c !== bkmkId);\r\n }\r\n } else {\r\n s.rootIds = s.rootIds.filter((r) => r !== bkmkId);\r\n }\r\n}\r\n\r\nfunction removeRecursively(s: State, bkmkId: Id) {\r\n const node = s.nodes[bkmkId];\r\n if (!node) return;\r\n if (node.type === \"F\") {\r\n const children = (node as FolderNode).children.slice();\r\n children.forEach((cid) => removeRecursively(s, cid));\r\n }\r\n detach(s, bkmkId);\r\n const { [bkmkId]: _omit, ...rest } = s.nodes as Record<string, FavNode>;\r\n s.nodes = rest;\r\n}\r\n\r\n/** 임시ID → 실제ID 스왑 (불변성 유지) */\r\nfunction idSwapImmutable(s: State, tmp: Id, real: Id): State {\r\n if (tmp === real) return s;\r\n const node = s.nodes[tmp];\r\n if (!node) return s;\r\n\r\n const newNode: FavNode = JSON.parse(JSON.stringify(node));\r\n newNode.bkmkId = real;\r\n\r\n const newNodes: Record<Id, FavNode> = { ...s.nodes, [real]: newNode };\r\n delete newNodes[tmp];\r\n\r\n let newRootIds = s.rootIds;\r\n if (newNode.prntBkmkId && newNode.prntBkmkId !== \"-\") {\r\n const p = newNodes[newNode.prntBkmkId] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n newNodes[newNode.prntBkmkId] = {\r\n ...p,\r\n children: p.children.map((c) => (c === tmp ? real : c)),\r\n } as FolderNode;\r\n }\r\n } else {\r\n newRootIds = s.rootIds.map((r) => (r === tmp ? real : r));\r\n }\r\n\r\n return { ...s, nodes: newNodes, rootIds: newRootIds };\r\n}\r\n\r\nfunction pickDefaultFolderId(s: Pick<State, \"nodes\" | \"rootIds\">): Id | null {\r\n return s.rootIds.find((id) => s.nodes[id]?.type === \"F\") ?? null;\r\n}\r\n\r\nfunction toSimpleTreeFromMap(nodes: Record<Id, FavNode>, rootIds: Id[]) {\r\n const childrenByParent: Record<string, string[]> = {};\r\n Object.values(nodes).forEach((n) => {\r\n const id = n.bkmkId;\r\n const pid = n.prntBkmkId;\r\n if (!id || !pid || pid === \"-\" || pid === id) return;\r\n (childrenByParent[pid] ??= []).push(id);\r\n });\r\n\r\n const visiting = new Set<string>();\r\n\r\n const build = (id: Id): any => {\r\n if (visiting.has(id)) return null;\r\n const n = nodes[id];\r\n if (!n) return null;\r\n\r\n visiting.add(id);\r\n try {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const childIds = childrenByParent[id] ?? [];\r\n return {\r\n type: \"F\",\r\n bkmkId: id,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n children: childIds.map(build).filter(Boolean),\r\n };\r\n }\r\n const i = n as ItemNode;\r\n\r\n return {\r\n type: \"M\",\r\n bkmkId: id,\r\n bkmkNm: i.menuNm,\r\n menuId: i.menuId,\r\n menuNm: i.menuNm,\r\n prntBkmkId: i.prntBkmkId,\r\n };\r\n } finally {\r\n visiting.delete(id);\r\n }\r\n };\r\n\r\n const rootMenuIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"M\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootFolderIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"F\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootKeys = Array.from(\r\n new Set([...rootIds, ...rootMenuIds, ...rootFolderIds])\r\n );\r\n return rootKeys.map(build).filter(Boolean);\r\n}\r\n\r\nfunction findItemByMenuId(\r\n nodes: Record<Id, FavNode>,\r\n menuId: string\r\n): Id | null {\r\n for (const n of Object.values(nodes)) {\r\n if (n.type === \"M\" && (n as ItemNode).menuId === menuId) return n.bkmkId;\r\n }\r\n return null;\r\n}\r\n\r\nfunction _resequence(\r\n nodes: Record<Id, FavNode>,\r\n rootIds: Id[],\r\n parentId: Id | \"-\"\r\n) {\r\n const siblings: Id[] =\r\n !parentId || parentId === \"-\"\r\n ? rootIds\r\n : (nodes[parentId] as FolderNode).children || [];\r\n siblings.forEach((sid, idx) => {\r\n const n = nodes[sid];\r\n if (!n) return;\r\n n.sortOrdr = idx;\r\n });\r\n}\r\n"],"names":["creator","set","get","menuId","n","id","findItemByMenuId","nodeId","node","q","nodes","rootIds","match","make","folder","kids","cid","c","f","rid","userId","force","s","res","callService","raw","normalized","normalize","treeNodes","toSimpleTreeFromMap","e","p","prev","snapshot","tmp","tempId","sort","tailIndex","next","attach","real","sortForServer","getUserId","swapped","idSwapImmutable","bkmkId","newPrntBkmkId","sortOrdr","parent","oldParentId","removeFrom","idx","insertTo","_resequence","removeRecursively","bkmkNm","prntBkmkId","target","sysCd","folderBkmkId","menu","exists","folderId","pickDefaultFolderId","newBkmkNm","nodesMap","onlyFolder","build","children","i","label","useFavoriteStore","create","roots","walk","arr","r","base","a","b","A","B","parentId","detach","pid","_omit","rest","newNode","newNodes","newRootIds","childrenByParent","visiting","childIds","rootMenuIds","rootFolderIds","sid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"favoriteStore-BnQ2u-sa.cjs","sources":["../../src/stores/favoriteStore.ts"],"sourcesContent":["// -------------------------------------------------------\r\n// 즐겨찾기(폴더형) Zustand Store (단일 테이블 CM_BKMK_MSTR 기반)\r\n// 공통 CRUD로 통합: addNode / moveNode / removeNode / editNode\r\n// 기존 API(폴더/메뉴 전용)는 호환용으로 래핑만 유지\r\n// - 정규화(nodes + rootIds)\r\n// - 낙관적 업데이트 + 임시ID(tmp_* → 서버ID) 스왑\r\n// - 필수 기능: 로드, 생성, 이동, 삭제, 수정 + 셀렉터/뷰 변환\r\n// -------------------------------------------------------\r\n\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getUserId } from \"../utils/userUtils\";\r\nimport { DataNode } from \"antd/es/tree\";\r\nimport { create, StateCreator } from \"zustand\";\r\n\r\n// 🔧 공통 ID 타입\r\nexport type Id = string;\r\n\r\n/** 공통 베이스 (CM_BKMK_MSTR 매핑) */\r\nexport type BkmkBase = {\r\n type: \"F\" | \"M\"; // TYPE\r\n bkmkId: Id; // BKMK_ID\r\n prntBkmkId: Id | \"-\"; // PRNT_BKMK_ID ('-'=루트)\r\n sortOrdr: number; // SORT_ORDR\r\n sysCd?: string; // SYS_CD (옵션)\r\n userId?: string | null; // USER_ID (옵션)\r\n fullPath?: string; // 프론트 보조(옵션)\r\n};\r\n\r\n/** 폴더 노드 (BKMK_NM 사용) */\r\nexport type FolderNode = BkmkBase & {\r\n bkmkNm: string; // BKMK_NM (폴더 전용)\r\n children: Id[]; // 폴더/아이템 혼재(정규화용)\r\n};\r\n\r\n/** 아이템 노드 (메뉴 전용 메타) */\r\nexport type ItemNode = BkmkBase & {\r\n menuId: string; // MENU_ID\r\n menuNm?: string; // 프론트 보조(메뉴명)\r\n};\r\n\r\nexport type FavNode = FolderNode | ItemNode;\r\n\r\nexport type MovePayload = {\r\n bkmkId: Id;\r\n newPrntBkmkId: Id | \"-\";\r\n sortOrdr: number; // 새 부모 내 0-based\r\n userId: string | null;\r\n};\r\n\r\nexport type AddNodePayload = {\r\n type: \"F\" | \"M\";\r\n prntBkmkId: Id | \"-\";\r\n sysCd: string;\r\n userId: string | null;\r\n bkmkNm?: string; // F 전용\r\n menuId?: string; // M 전용\r\n menuNm?: string; // 프론트 보조\r\n sortOrdr?: number; // 선택: 지정 없으면 tailIndex 사용\r\n};\r\n\r\nexport type EditNodePayload = {\r\n bkmkId: Id;\r\n userId: string;\r\n bkmkNm?: string; // F일 때만 의미\r\n prntBkmkId?: Id | \"-\"; // 선택(이동은 moveNode 권장)\r\n sortOrdr?: number; // 선택\r\n};\r\n\r\nexport type Normalized = { nodes: Record<Id, FavNode>; rootIds: Id[] };\r\n\r\nexport type State = {\r\n // ========== 데이터(정규화) ==========\r\n nodes: Record<Id, FavNode>;\r\n rootIds: Id[];\r\n treeNodes: FavNode[]; // 단순 트리(뷰용)\r\n\r\n // ========== 메타 ==========\r\n loadedFor?: string;\r\n loading: boolean;\r\n error?: string;\r\n\r\n // ========== 셀렉터 ==========\r\n isMenuBookmarked: (menuId: string) => boolean;\r\n getPrntBkmkIdByMenuId: (menuId: string) => Id | \"-\";\r\n getNodeByMenuId: (menuId: string) => ItemNode | null;\r\n getFolderTree: (q?: string) => DataNode[]; // 폴더만 Tree (검색 필터)\r\n\r\n // ========== 로더 ==========\r\n loadFavorites: (userId: string, force?: boolean) => Promise<void>;\r\n loadFavoritesIfNeeded: (userId: string) => Promise<void>;\r\n\r\n // ========== 공통 CRUD ==========\r\n addNode: (p: AddNodePayload) => Promise<Id>;\r\n moveNode: (p: MovePayload) => Promise<void>;\r\n removeNode: (bkmkId: Id) => Promise<void>;\r\n editNode: (p: EditNodePayload) => Promise<void>;\r\n\r\n // ========== 호환용(기존 API 유지, 내부에서 공통 호출) ==========\r\n addFolder: (\r\n bkmkNm: string,\r\n prntBkmkId: Id | \"-\",\r\n sysCd: string,\r\n userId: string | null\r\n ) => Promise<Id>;\r\n addMenuToFolder: (\r\n folderBkmkId: Id,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<Id | string>;\r\n toggleMenuFavorite: (\r\n userId: string | null,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<void>;\r\n removeMenu: (bkmkId: Id) => Promise<void>;\r\n removeMenuByMenuId: (menuId: string) => Promise<void>;\r\n removeFolder: (folderBkmkId: Id) => Promise<void>;\r\n editFolder: (\r\n folderBkmkId: Id,\r\n userId: string | null,\r\n newBkmkNm?: string,\r\n prntBkmkId?: Id | \"-\",\r\n sortOrdr?: number\r\n ) => Promise<void>;\r\n convertToAntTreeData: (\r\n nodesMap: Record<string, FavNode>,\r\n rootIds: string[],\r\n q: string,\r\n onlyFolder?: boolean\r\n ) => any[];\r\n};\r\n\r\nconst creator: StateCreator<State> = (set, get) => ({\r\n nodes: {},\r\n rootIds: [],\r\n loadedFor: undefined,\r\n loading: false,\r\n error: undefined,\r\n treeNodes: [],\r\n\r\n // ====== 셀렉터 ======\r\n isMenuBookmarked: (menuId) =>\r\n Object.values(get().nodes).some(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menuId\r\n ),\r\n getPrntBkmkIdByMenuId: (menuId) => {\r\n const id = findItemByMenuId(get().nodes, menuId);\r\n return id ? get().nodes[id]?.prntBkmkId ?? \"-\" : \"-\";\r\n },\r\n\r\n getNodeByMenuId: (menuId) => {\r\n const nodeId = findItemByMenuId(get().nodes, menuId);\r\n if (!nodeId) return null;\r\n const node = get().nodes[nodeId];\r\n return node?.type === \"M\" ? (node as ItemNode) : null;\r\n },\r\n\r\n getFolderTree: (q) => {\r\n const { nodes, rootIds } = get();\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const make = (id: Id): DataNode | null => {\r\n const n = nodes[id];\r\n if (!n || n.type !== \"F\") return null;\r\n const folder = n as FolderNode;\r\n\r\n const kids = (folder.children || [])\r\n .map((cid) => nodes[cid])\r\n .filter((c): c is FolderNode => !!c && c.type === \"F\")\r\n .map((f) => make(f.bkmkId))\r\n .filter(Boolean) as DataNode[];\r\n\r\n const visible = match(folder.bkmkNm) || kids.length > 0;\r\n if (!visible) return null;\r\n\r\n return {\r\n key: folder.bkmkId,\r\n title: `📁 ${folder.bkmkNm}`,\r\n children: kids.length ? kids : undefined,\r\n };\r\n };\r\n\r\n return rootIds.map((rid) => make(rid)).filter(Boolean) as DataNode[];\r\n },\r\n\r\n // ====== 로더 ======\r\n loadFavorites: async (userId, force = false) => {\r\n console.log(\"loadFavorites ::::: \", userId, force);\r\n const s = get();\r\n if (!force && s.loadedFor === userId && Object.keys(s.nodes).length) return;\r\n\r\n set({ loading: true, error: undefined });\r\n try {\r\n // 기대 응답 예시: { sub: rawTree[] }\r\n const res = await callService(\"SCMBKMK00101\", { userId });\r\n const raw: any[] = Array.isArray(res?.sub) ? res.sub : [];\r\n const normalized = normalize(raw);\r\n\r\n const treeNodes = toSimpleTreeFromMap(\r\n normalized.nodes,\r\n normalized.rootIds\r\n );\r\n\r\n set({\r\n ...normalized,\r\n treeNodes,\r\n loadedFor: userId,\r\n loading: false,\r\n });\r\n } catch (e: any) {\r\n set({ loading: false, error: e?.message || \"즐겨찾기 로드 실패\" });\r\n throw e;\r\n }\r\n },\r\n\r\n loadFavoritesIfNeeded: async (userId) => {\r\n const s = get();\r\n const notLoaded =\r\n s.loadedFor !== userId || Object.keys(s.nodes).length === 0;\r\n if (notLoaded) {\r\n await get().loadFavorites(userId);\r\n }\r\n },\r\n\r\n // ====== 공통: 생성 ======\r\n addNode: async (p) => {\r\n const prev = snapshot(get());\r\n const tmp = tempId();\r\n\r\n // 1) 낙관적 반영\r\n set((s) => {\r\n const sort = p.sortOrdr ?? tailIndex(s, p.prntBkmkId);\r\n const next: State = {\r\n ...s,\r\n nodes: {\r\n ...s.nodes,\r\n [tmp]:\r\n p.type === \"F\"\r\n ? ({\r\n bkmkId: tmp,\r\n type: \"F\",\r\n prntBkmkId: p.prntBkmkId || \"-\",\r\n sortOrdr: sort,\r\n bkmkNm: p.bkmkNm ?? \"새 폴더\",\r\n children: [],\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as FolderNode)\r\n : ({\r\n bkmkId: tmp,\r\n type: \"M\",\r\n prntBkmkId: p.prntBkmkId,\r\n sortOrdr: sort,\r\n menuId: p.menuId ?? \"\",\r\n menuNm: p.menuNm,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as ItemNode),\r\n },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n attach(next, tmp, p.prntBkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n // 2) 서버 호출\r\n // 백엔드는 통합 IUD가 아닐 수 있으므로, 호환 분기 적용\r\n let real: string = tmp;\r\n const sortForServer = tailIndex(get(), p.prntBkmkId);\r\n const res = await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"I\",\r\n type: p.type,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n bkmkId: tmp, // 서버 새 ID 반환 시 매칭용\r\n bkmkNm: p.bkmkNm,\r\n prntBkmkId: p.prntBkmkId,\r\n menuId: p.menuId,\r\n sortOrdr: sortForServer,\r\n chngId: getUserId(),\r\n });\r\n real = String(res?.bkmkId ?? res?.itemId ?? tmp);\r\n\r\n // 3) tmp → real 스왑\r\n set((s) => {\r\n const swapped = idSwapImmutable(s, tmp, real);\r\n return {\r\n ...swapped,\r\n treeNodes: toSimpleTreeFromMap(swapped.nodes, swapped.rootIds),\r\n };\r\n });\r\n return real;\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 이동 ======\r\n moveNode: async ({ bkmkId, newPrntBkmkId, sortOrdr, userId }) => {\r\n const prev = get(); // 함수 포함 스냅샷(rollback 용으로 set(prev) 사용)\r\n\r\n const nodes = structuredClone(prev.nodes);\r\n const rootIds = [...prev.rootIds];\r\n\r\n const node = nodes[bkmkId];\r\n if (!node) return;\r\n\r\n // 부모는 반드시 폴더만 허용\r\n if (newPrntBkmkId !== \"-\") {\r\n const parent = nodes[newPrntBkmkId];\r\n if (!parent || parent.type !== \"F\")\r\n throw new Error(\"부모는 폴더만 가능합니다.\");\r\n }\r\n\r\n const oldParentId = node.prntBkmkId ?? \"-\";\r\n\r\n const removeFrom =\r\n oldParentId === \"-\"\r\n ? rootIds\r\n : ((nodes[oldParentId] as FolderNode).children ||= []);\r\n {\r\n const idx = removeFrom.indexOf(bkmkId);\r\n if (idx >= 0) removeFrom.splice(idx, 1);\r\n }\r\n\r\n const insertTo =\r\n newPrntBkmkId === \"-\"\r\n ? rootIds\r\n : ((nodes[newPrntBkmkId] as FolderNode).children ||= []);\r\n insertTo.splice(\r\n Math.max(0, Math.min(sortOrdr, insertTo.length)),\r\n 0,\r\n bkmkId\r\n );\r\n\r\n node.prntBkmkId = newPrntBkmkId as Id;\r\n set({ nodes, rootIds });\r\n _resequence(nodes, rootIds, newPrntBkmkId);\r\n _resequence(nodes, rootIds, oldParentId);\r\n\r\n try {\r\n await callService(\"SCMBKMK00104\", {\r\n // 백엔드 명칭 호환\r\n bkmkId,\r\n prntBkmkId: newPrntBkmkId,\r\n sortOrdr,\r\n chngId: userId,\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 삭제 ======\r\n removeNode: async (bkmkId) => {\r\n const prev = snapshot(get());\r\n\r\n set((s) => {\r\n if (!s.nodes[bkmkId]) return s as State;\r\n const next: State = {\r\n ...s,\r\n nodes: { ...s.nodes },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n removeRecursively(next, bkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00103\", { bkmkId });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 수정 ======\r\n editNode: async ({ bkmkId, userId, bkmkNm, prntBkmkId, sortOrdr }) => {\r\n const prev = snapshot(get());\r\n\r\n // 폴더명 변경만 프런트 즉시 반영(옵션)\r\n set((s) => {\r\n const next = { ...s, nodes: { ...s.nodes } } as State;\r\n const target = next.nodes[bkmkId] as FavNode | undefined;\r\n if (target?.type === \"F\" && typeof bkmkNm === \"string\") {\r\n next.nodes[bkmkId] = {\r\n ...(target as FolderNode),\r\n bkmkNm,\r\n } as FolderNode;\r\n }\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"U\",\r\n userId,\r\n bkmkId,\r\n bkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n chngId: getUserId(),\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 호환용 래퍼 ======\r\n addFolder: async (bkmkNm, prntBkmkId, sysCd, userId) => {\r\n return await get().addNode({\r\n type: \"F\",\r\n bkmkNm,\r\n prntBkmkId,\r\n sysCd,\r\n userId,\r\n });\r\n },\r\n\r\n addMenuToFolder: async (folderBkmkId, menu) => {\r\n // 전역 중복 방지\r\n const dup = findItemByMenuId(get().nodes, menu.menuId);\r\n if (dup) return \"이미 북마크에 저장된 메뉴입니다.\";\r\n return await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderBkmkId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n },\r\n\r\n toggleMenuFavorite: async (userId, menu) => {\r\n const s = get();\r\n const exists = Object.values(s.nodes).find(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menu.menuId\r\n );\r\n if (exists) {\r\n await get().removeNode(exists.bkmkId);\r\n return;\r\n }\r\n\r\n let folderId = pickDefaultFolderId(s);\r\n if (!folderId) {\r\n await get().loadFavorites(userId, true);\r\n folderId = pickDefaultFolderId(get());\r\n }\r\n if (folderId) {\r\n await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n }\r\n },\r\n\r\n removeMenuByMenuId: async (menuId) => {\r\n const s = get();\r\n const bkmkId = findItemByMenuId(s.nodes, menuId);\r\n if (bkmkId) await get().removeNode(bkmkId);\r\n },\r\n\r\n removeMenu: async (bkmkId) => {\r\n await get().removeNode(bkmkId);\r\n },\r\n\r\n removeFolder: async (folderBkmkId) => {\r\n await get().removeNode(folderBkmkId);\r\n },\r\n\r\n editFolder: async (folderBkmkId, userId, newBkmkNm, prntBkmkId, sortOrdr) => {\r\n await get().editNode({\r\n bkmkId: folderBkmkId,\r\n userId,\r\n bkmkNm: newBkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n });\r\n },\r\n\r\n /** Ant Tree 데이터 변환 (검색 포함) */\r\n convertToAntTreeData: (nodesMap, rootIds, q, onlyFolder = false) => {\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const build = (id: string): any | null => {\r\n const n = nodesMap[id];\r\n if (!n) return null;\r\n\r\n if (onlyFolder && n.type !== \"F\") return null;\r\n\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const children = (f.children || [])\r\n .map((cid) => build(cid))\r\n .filter(Boolean);\r\n const visible = match(f.bkmkNm) || children.length > 0;\r\n if (!visible) return null;\r\n return {\r\n key: f.bkmkId,\r\n type: \"F\",\r\n title: `📁 ${f.bkmkNm}`,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n sortOrdr: f.sortOrdr,\r\n fullPath: f.fullPath,\r\n children: children.length ? children : undefined,\r\n };\r\n } else {\r\n const i = n as ItemNode;\r\n const label = i.menuNm ? `${i.menuNm} (${i.menuId})` : i.menuId;\r\n const visible = match(label);\r\n if (!visible) return null;\r\n return {\r\n key: i.bkmkId,\r\n type: \"M\",\r\n title: `📄 ${label}`,\r\n prntBkmkId: i.prntBkmkId,\r\n sortOrdr: i.sortOrdr,\r\n fullPath: i.fullPath,\r\n isLeaf: true,\r\n };\r\n }\r\n };\r\n\r\n return rootIds.map(build).filter(Boolean);\r\n },\r\n});\r\n\r\nexport const useFavoriteStore = create<State>(creator);\r\n\r\n// ===================================================================\r\n// Helpers\r\n// ===================================================================\r\n\r\nfunction normalize(raw: any[]): Normalized {\r\n const nodes: Record<Id, FavNode> = {};\r\n const roots: Id[] = [];\r\n\r\n const walk = (arr: any[]) => {\r\n arr.forEach((r: any) => {\r\n // 서버 raw 필드: TYPE, BKMK_ID, PRNT_BKMK_ID, SORT_ORDR, BKMK_NM, MENU_ID, FULL_PATH?\r\n const base: BkmkBase = {\r\n type: r.type,\r\n bkmkId: r.bkmkId ?? r.BKMK_ID ?? r.id,\r\n prntBkmkId: r.prntBkmkId ?? r.PRNT_BKMK_ID ?? \"-\",\r\n sortOrdr: Number(r.sortOrdr ?? r.SORT_ORDR ?? 0),\r\n sysCd: r.sysCd ?? r.SYS_CD,\r\n userId: r.userId ?? r.USER_ID,\r\n fullPath: r.fullPath ?? r.FULL_PATH,\r\n };\r\n\r\n if (r.type === \"F\") {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n bkmkNm: r.bkmkNm ?? r.BKMK_NM ?? r.name ?? base.bkmkId,\r\n children: [],\r\n } as FolderNode;\r\n\r\n const children = Array.isArray(r.children) ? r.children : [];\r\n walk(children);\r\n } else {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n menuId: r.menuId ?? r.MENU_ID ?? \"\",\r\n menuNm: r.menuNm ?? r.MENU_NM,\r\n } as ItemNode;\r\n }\r\n });\r\n };\r\n\r\n walk(raw);\r\n\r\n // children / rootIds 구성\r\n Object.values(nodes).forEach((n) => {\r\n if (n.prntBkmkId && n.prntBkmkId !== \"-\") {\r\n const p = nodes[n.prntBkmkId] as FolderNode;\r\n if (p?.type === \"F\") p.children.push(n.bkmkId);\r\n } else if (n.type === \"F\") {\r\n roots.push(n.bkmkId);\r\n }\r\n });\r\n\r\n // 정렬 인덱스 보정(안전)\r\n roots.sort((a, b) => (nodes[a].sortOrdr ?? 0) - (nodes[b].sortOrdr ?? 0));\r\n Object.values(nodes).forEach((n) => {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n f.children.sort(\r\n (A, B) => (nodes[A].sortOrdr ?? 0) - (nodes[B].sortOrdr ?? 0)\r\n );\r\n }\r\n });\r\n\r\n return { nodes, rootIds: roots };\r\n}\r\n\r\nfunction snapshot(s: State): State {\r\n return {\r\n ...s,\r\n nodes: JSON.parse(JSON.stringify(s.nodes)),\r\n rootIds: s.rootIds.slice(),\r\n };\r\n}\r\n\r\nfunction tempId(): Id {\r\n return `tmp_${Math.random().toString(36).slice(2, 10)}`;\r\n}\r\n\r\nfunction tailIndex(s: Pick<State, \"nodes\" | \"rootIds\">, parentId: Id | \"-\") {\r\n if (!parentId || parentId === \"-\") return s.rootIds.length;\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n return p ? p.children.length : 0;\r\n}\r\n\r\nfunction attach(s: State, bkmkId: Id, parentId: Id | \"-\") {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n\r\n if (parentId && parentId !== \"-\") {\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n if (!p || p.type !== \"F\") return;\r\n n.prntBkmkId = parentId;\r\n p.children = [...p.children, bkmkId];\r\n } else {\r\n n.prntBkmkId = \"-\";\r\n s.rootIds = [...s.rootIds, bkmkId];\r\n }\r\n}\r\n\r\nfunction detach(s: State, bkmkId: Id) {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n const pid = n.prntBkmkId;\r\n\r\n if (pid && pid !== \"-\") {\r\n const p = s.nodes[pid] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n p.children = p.children.filter((c) => c !== bkmkId);\r\n }\r\n } else {\r\n s.rootIds = s.rootIds.filter((r) => r !== bkmkId);\r\n }\r\n}\r\n\r\nfunction removeRecursively(s: State, bkmkId: Id) {\r\n const node = s.nodes[bkmkId];\r\n if (!node) return;\r\n if (node.type === \"F\") {\r\n const children = (node as FolderNode).children.slice();\r\n children.forEach((cid) => removeRecursively(s, cid));\r\n }\r\n detach(s, bkmkId);\r\n const { [bkmkId]: _omit, ...rest } = s.nodes as Record<string, FavNode>;\r\n s.nodes = rest;\r\n}\r\n\r\n/** 임시ID → 실제ID 스왑 (불변성 유지) */\r\nfunction idSwapImmutable(s: State, tmp: Id, real: Id): State {\r\n if (tmp === real) return s;\r\n const node = s.nodes[tmp];\r\n if (!node) return s;\r\n\r\n const newNode: FavNode = JSON.parse(JSON.stringify(node));\r\n newNode.bkmkId = real;\r\n\r\n const newNodes: Record<Id, FavNode> = { ...s.nodes, [real]: newNode };\r\n delete newNodes[tmp];\r\n\r\n let newRootIds = s.rootIds;\r\n if (newNode.prntBkmkId && newNode.prntBkmkId !== \"-\") {\r\n const p = newNodes[newNode.prntBkmkId] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n newNodes[newNode.prntBkmkId] = {\r\n ...p,\r\n children: p.children.map((c) => (c === tmp ? real : c)),\r\n } as FolderNode;\r\n }\r\n } else {\r\n newRootIds = s.rootIds.map((r) => (r === tmp ? real : r));\r\n }\r\n\r\n return { ...s, nodes: newNodes, rootIds: newRootIds };\r\n}\r\n\r\nfunction pickDefaultFolderId(s: Pick<State, \"nodes\" | \"rootIds\">): Id | null {\r\n return s.rootIds.find((id) => s.nodes[id]?.type === \"F\") ?? null;\r\n}\r\n\r\nfunction toSimpleTreeFromMap(nodes: Record<Id, FavNode>, rootIds: Id[]) {\r\n const childrenByParent: Record<string, string[]> = {};\r\n Object.values(nodes).forEach((n) => {\r\n const id = n.bkmkId;\r\n const pid = n.prntBkmkId;\r\n if (!id || !pid || pid === \"-\" || pid === id) return;\r\n (childrenByParent[pid] ??= []).push(id);\r\n });\r\n\r\n const visiting = new Set<string>();\r\n\r\n const build = (id: Id): any => {\r\n if (visiting.has(id)) return null;\r\n const n = nodes[id];\r\n if (!n) return null;\r\n\r\n visiting.add(id);\r\n try {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const childIds = childrenByParent[id] ?? [];\r\n return {\r\n type: \"F\",\r\n bkmkId: id,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n children: childIds.map(build).filter(Boolean),\r\n };\r\n }\r\n const i = n as ItemNode;\r\n\r\n return {\r\n type: \"M\",\r\n bkmkId: id,\r\n bkmkNm: i.menuNm,\r\n menuId: i.menuId,\r\n menuNm: i.menuNm,\r\n prntBkmkId: i.prntBkmkId,\r\n };\r\n } finally {\r\n visiting.delete(id);\r\n }\r\n };\r\n\r\n const rootMenuIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"M\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootFolderIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"F\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootKeys = Array.from(\r\n new Set([...rootIds, ...rootMenuIds, ...rootFolderIds])\r\n );\r\n return rootKeys.map(build).filter(Boolean);\r\n}\r\n\r\nfunction findItemByMenuId(\r\n nodes: Record<Id, FavNode>,\r\n menuId: string\r\n): Id | null {\r\n for (const n of Object.values(nodes)) {\r\n if (n.type === \"M\" && (n as ItemNode).menuId === menuId) return n.bkmkId;\r\n }\r\n return null;\r\n}\r\n\r\nfunction _resequence(\r\n nodes: Record<Id, FavNode>,\r\n rootIds: Id[],\r\n parentId: Id | \"-\"\r\n) {\r\n const siblings: Id[] =\r\n !parentId || parentId === \"-\"\r\n ? rootIds\r\n : (nodes[parentId] as FolderNode).children || [];\r\n siblings.forEach((sid, idx) => {\r\n const n = nodes[sid];\r\n if (!n) return;\r\n n.sortOrdr = idx;\r\n });\r\n}\r\n"],"names":["creator","set","get","menuId","n","id","findItemByMenuId","nodeId","node","q","nodes","rootIds","match","make","folder","kids","cid","c","f","rid","userId","force","s","res","callService","raw","normalized","normalize","treeNodes","toSimpleTreeFromMap","e","p","prev","snapshot","tmp","tempId","sort","tailIndex","next","attach","real","sortForServer","getUserId","swapped","idSwapImmutable","bkmkId","newPrntBkmkId","sortOrdr","parent","oldParentId","removeFrom","idx","insertTo","_resequence","removeRecursively","bkmkNm","prntBkmkId","target","sysCd","folderBkmkId","menu","exists","folderId","pickDefaultFolderId","newBkmkNm","nodesMap","onlyFolder","build","children","i","label","useFavoriteStore","create","roots","walk","arr","r","base","a","b","A","B","parentId","detach","pid","_omit","rest","newNode","newNodes","newRootIds","childrenByParent","visiting","childIds","rootMenuIds","rootFolderIds","sid"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ap as f, c as I } from "./apiUtils-
|
|
1
|
+
import { ap as f, c as I } from "./apiUtils-DPUgfmKk.js";
|
|
2
2
|
import { create as F } from "zustand";
|
|
3
3
|
const M = (d, o) => ({
|
|
4
4
|
nodes: {},
|
|
@@ -436,4 +436,4 @@ function b(d, o, e) {
|
|
|
436
436
|
export {
|
|
437
437
|
E as u
|
|
438
438
|
};
|
|
439
|
-
//# sourceMappingURL=favoriteStore-
|
|
439
|
+
//# sourceMappingURL=favoriteStore-SyAjqLG8.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"favoriteStore-Cemc-26t.js","sources":["../../src/stores/favoriteStore.ts"],"sourcesContent":["// -------------------------------------------------------\r\n// 즐겨찾기(폴더형) Zustand Store (단일 테이블 CM_BKMK_MSTR 기반)\r\n// 공통 CRUD로 통합: addNode / moveNode / removeNode / editNode\r\n// 기존 API(폴더/메뉴 전용)는 호환용으로 래핑만 유지\r\n// - 정규화(nodes + rootIds)\r\n// - 낙관적 업데이트 + 임시ID(tmp_* → 서버ID) 스왑\r\n// - 필수 기능: 로드, 생성, 이동, 삭제, 수정 + 셀렉터/뷰 변환\r\n// -------------------------------------------------------\r\n\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getUserId } from \"../utils/userUtils\";\r\nimport { DataNode } from \"antd/es/tree\";\r\nimport { create, StateCreator } from \"zustand\";\r\n\r\n// 🔧 공통 ID 타입\r\nexport type Id = string;\r\n\r\n/** 공통 베이스 (CM_BKMK_MSTR 매핑) */\r\nexport type BkmkBase = {\r\n type: \"F\" | \"M\"; // TYPE\r\n bkmkId: Id; // BKMK_ID\r\n prntBkmkId: Id | \"-\"; // PRNT_BKMK_ID ('-'=루트)\r\n sortOrdr: number; // SORT_ORDR\r\n sysCd?: string; // SYS_CD (옵션)\r\n userId?: string | null; // USER_ID (옵션)\r\n fullPath?: string; // 프론트 보조(옵션)\r\n};\r\n\r\n/** 폴더 노드 (BKMK_NM 사용) */\r\nexport type FolderNode = BkmkBase & {\r\n bkmkNm: string; // BKMK_NM (폴더 전용)\r\n children: Id[]; // 폴더/아이템 혼재(정규화용)\r\n};\r\n\r\n/** 아이템 노드 (메뉴 전용 메타) */\r\nexport type ItemNode = BkmkBase & {\r\n menuId: string; // MENU_ID\r\n menuNm?: string; // 프론트 보조(메뉴명)\r\n};\r\n\r\nexport type FavNode = FolderNode | ItemNode;\r\n\r\nexport type MovePayload = {\r\n bkmkId: Id;\r\n newPrntBkmkId: Id | \"-\";\r\n sortOrdr: number; // 새 부모 내 0-based\r\n userId: string | null;\r\n};\r\n\r\nexport type AddNodePayload = {\r\n type: \"F\" | \"M\";\r\n prntBkmkId: Id | \"-\";\r\n sysCd: string;\r\n userId: string | null;\r\n bkmkNm?: string; // F 전용\r\n menuId?: string; // M 전용\r\n menuNm?: string; // 프론트 보조\r\n sortOrdr?: number; // 선택: 지정 없으면 tailIndex 사용\r\n};\r\n\r\nexport type EditNodePayload = {\r\n bkmkId: Id;\r\n userId: string;\r\n bkmkNm?: string; // F일 때만 의미\r\n prntBkmkId?: Id | \"-\"; // 선택(이동은 moveNode 권장)\r\n sortOrdr?: number; // 선택\r\n};\r\n\r\nexport type Normalized = { nodes: Record<Id, FavNode>; rootIds: Id[] };\r\n\r\nexport type State = {\r\n // ========== 데이터(정규화) ==========\r\n nodes: Record<Id, FavNode>;\r\n rootIds: Id[];\r\n treeNodes: FavNode[]; // 단순 트리(뷰용)\r\n\r\n // ========== 메타 ==========\r\n loadedFor?: string;\r\n loading: boolean;\r\n error?: string;\r\n\r\n // ========== 셀렉터 ==========\r\n isMenuBookmarked: (menuId: string) => boolean;\r\n getPrntBkmkIdByMenuId: (menuId: string) => Id | \"-\";\r\n getNodeByMenuId: (menuId: string) => ItemNode | null;\r\n getFolderTree: (q?: string) => DataNode[]; // 폴더만 Tree (검색 필터)\r\n\r\n // ========== 로더 ==========\r\n loadFavorites: (userId: string, force?: boolean) => Promise<void>;\r\n loadFavoritesIfNeeded: (userId: string) => Promise<void>;\r\n\r\n // ========== 공통 CRUD ==========\r\n addNode: (p: AddNodePayload) => Promise<Id>;\r\n moveNode: (p: MovePayload) => Promise<void>;\r\n removeNode: (bkmkId: Id) => Promise<void>;\r\n editNode: (p: EditNodePayload) => Promise<void>;\r\n\r\n // ========== 호환용(기존 API 유지, 내부에서 공통 호출) ==========\r\n addFolder: (\r\n bkmkNm: string,\r\n prntBkmkId: Id | \"-\",\r\n sysCd: string,\r\n userId: string | null\r\n ) => Promise<Id>;\r\n addMenuToFolder: (\r\n folderBkmkId: Id,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<Id | string>;\r\n toggleMenuFavorite: (\r\n userId: string | null,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<void>;\r\n removeMenu: (bkmkId: Id) => Promise<void>;\r\n removeMenuByMenuId: (menuId: string) => Promise<void>;\r\n removeFolder: (folderBkmkId: Id) => Promise<void>;\r\n editFolder: (\r\n folderBkmkId: Id,\r\n userId: string | null,\r\n newBkmkNm?: string,\r\n prntBkmkId?: Id | \"-\",\r\n sortOrdr?: number\r\n ) => Promise<void>;\r\n convertToAntTreeData: (\r\n nodesMap: Record<string, FavNode>,\r\n rootIds: string[],\r\n q: string,\r\n onlyFolder?: boolean\r\n ) => any[];\r\n};\r\n\r\nconst creator: StateCreator<State> = (set, get) => ({\r\n nodes: {},\r\n rootIds: [],\r\n loadedFor: undefined,\r\n loading: false,\r\n error: undefined,\r\n treeNodes: [],\r\n\r\n // ====== 셀렉터 ======\r\n isMenuBookmarked: (menuId) =>\r\n Object.values(get().nodes).some(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menuId\r\n ),\r\n getPrntBkmkIdByMenuId: (menuId) => {\r\n const id = findItemByMenuId(get().nodes, menuId);\r\n return id ? get().nodes[id]?.prntBkmkId ?? \"-\" : \"-\";\r\n },\r\n\r\n getNodeByMenuId: (menuId) => {\r\n const nodeId = findItemByMenuId(get().nodes, menuId);\r\n if (!nodeId) return null;\r\n const node = get().nodes[nodeId];\r\n return node?.type === \"M\" ? (node as ItemNode) : null;\r\n },\r\n\r\n getFolderTree: (q) => {\r\n const { nodes, rootIds } = get();\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const make = (id: Id): DataNode | null => {\r\n const n = nodes[id];\r\n if (!n || n.type !== \"F\") return null;\r\n const folder = n as FolderNode;\r\n\r\n const kids = (folder.children || [])\r\n .map((cid) => nodes[cid])\r\n .filter((c): c is FolderNode => !!c && c.type === \"F\")\r\n .map((f) => make(f.bkmkId))\r\n .filter(Boolean) as DataNode[];\r\n\r\n const visible = match(folder.bkmkNm) || kids.length > 0;\r\n if (!visible) return null;\r\n\r\n return {\r\n key: folder.bkmkId,\r\n title: `📁 ${folder.bkmkNm}`,\r\n children: kids.length ? kids : undefined,\r\n };\r\n };\r\n\r\n return rootIds.map((rid) => make(rid)).filter(Boolean) as DataNode[];\r\n },\r\n\r\n // ====== 로더 ======\r\n loadFavorites: async (userId, force = false) => {\r\n console.log(\"loadFavorites ::::: \", userId, force);\r\n const s = get();\r\n if (!force && s.loadedFor === userId && Object.keys(s.nodes).length) return;\r\n\r\n set({ loading: true, error: undefined });\r\n try {\r\n // 기대 응답 예시: { sub: rawTree[] }\r\n const res = await callService(\"SCMBKMK00101\", { userId });\r\n const raw: any[] = Array.isArray(res?.sub) ? res.sub : [];\r\n const normalized = normalize(raw);\r\n\r\n const treeNodes = toSimpleTreeFromMap(\r\n normalized.nodes,\r\n normalized.rootIds\r\n );\r\n\r\n set({\r\n ...normalized,\r\n treeNodes,\r\n loadedFor: userId,\r\n loading: false,\r\n });\r\n } catch (e: any) {\r\n set({ loading: false, error: e?.message || \"즐겨찾기 로드 실패\" });\r\n throw e;\r\n }\r\n },\r\n\r\n loadFavoritesIfNeeded: async (userId) => {\r\n const s = get();\r\n const notLoaded =\r\n s.loadedFor !== userId || Object.keys(s.nodes).length === 0;\r\n if (notLoaded) {\r\n await get().loadFavorites(userId);\r\n }\r\n },\r\n\r\n // ====== 공통: 생성 ======\r\n addNode: async (p) => {\r\n const prev = snapshot(get());\r\n const tmp = tempId();\r\n\r\n // 1) 낙관적 반영\r\n set((s) => {\r\n const sort = p.sortOrdr ?? tailIndex(s, p.prntBkmkId);\r\n const next: State = {\r\n ...s,\r\n nodes: {\r\n ...s.nodes,\r\n [tmp]:\r\n p.type === \"F\"\r\n ? ({\r\n bkmkId: tmp,\r\n type: \"F\",\r\n prntBkmkId: p.prntBkmkId || \"-\",\r\n sortOrdr: sort,\r\n bkmkNm: p.bkmkNm ?? \"새 폴더\",\r\n children: [],\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as FolderNode)\r\n : ({\r\n bkmkId: tmp,\r\n type: \"M\",\r\n prntBkmkId: p.prntBkmkId,\r\n sortOrdr: sort,\r\n menuId: p.menuId ?? \"\",\r\n menuNm: p.menuNm,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as ItemNode),\r\n },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n attach(next, tmp, p.prntBkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n // 2) 서버 호출\r\n // 백엔드는 통합 IUD가 아닐 수 있으므로, 호환 분기 적용\r\n let real: string = tmp;\r\n const sortForServer = tailIndex(get(), p.prntBkmkId);\r\n const res = await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"I\",\r\n type: p.type,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n bkmkId: tmp, // 서버 새 ID 반환 시 매칭용\r\n bkmkNm: p.bkmkNm,\r\n prntBkmkId: p.prntBkmkId,\r\n menuId: p.menuId,\r\n sortOrdr: sortForServer,\r\n chngId: getUserId(),\r\n });\r\n real = String(res?.bkmkId ?? res?.itemId ?? tmp);\r\n\r\n // 3) tmp → real 스왑\r\n set((s) => {\r\n const swapped = idSwapImmutable(s, tmp, real);\r\n return {\r\n ...swapped,\r\n treeNodes: toSimpleTreeFromMap(swapped.nodes, swapped.rootIds),\r\n };\r\n });\r\n return real;\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 이동 ======\r\n moveNode: async ({ bkmkId, newPrntBkmkId, sortOrdr, userId }) => {\r\n const prev = get(); // 함수 포함 스냅샷(rollback 용으로 set(prev) 사용)\r\n\r\n const nodes = structuredClone(prev.nodes);\r\n const rootIds = [...prev.rootIds];\r\n\r\n const node = nodes[bkmkId];\r\n if (!node) return;\r\n\r\n // 부모는 반드시 폴더만 허용\r\n if (newPrntBkmkId !== \"-\") {\r\n const parent = nodes[newPrntBkmkId];\r\n if (!parent || parent.type !== \"F\")\r\n throw new Error(\"부모는 폴더만 가능합니다.\");\r\n }\r\n\r\n const oldParentId = node.prntBkmkId ?? \"-\";\r\n\r\n const removeFrom =\r\n oldParentId === \"-\"\r\n ? rootIds\r\n : ((nodes[oldParentId] as FolderNode).children ||= []);\r\n {\r\n const idx = removeFrom.indexOf(bkmkId);\r\n if (idx >= 0) removeFrom.splice(idx, 1);\r\n }\r\n\r\n const insertTo =\r\n newPrntBkmkId === \"-\"\r\n ? rootIds\r\n : ((nodes[newPrntBkmkId] as FolderNode).children ||= []);\r\n insertTo.splice(\r\n Math.max(0, Math.min(sortOrdr, insertTo.length)),\r\n 0,\r\n bkmkId\r\n );\r\n\r\n node.prntBkmkId = newPrntBkmkId as Id;\r\n set({ nodes, rootIds });\r\n _resequence(nodes, rootIds, newPrntBkmkId);\r\n _resequence(nodes, rootIds, oldParentId);\r\n\r\n try {\r\n await callService(\"SCMBKMK00104\", {\r\n // 백엔드 명칭 호환\r\n bkmkId,\r\n prntBkmkId: newPrntBkmkId,\r\n sortOrdr,\r\n chngId: userId,\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 삭제 ======\r\n removeNode: async (bkmkId) => {\r\n const prev = snapshot(get());\r\n\r\n set((s) => {\r\n if (!s.nodes[bkmkId]) return s as State;\r\n const next: State = {\r\n ...s,\r\n nodes: { ...s.nodes },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n removeRecursively(next, bkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00103\", { bkmkId });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 수정 ======\r\n editNode: async ({ bkmkId, userId, bkmkNm, prntBkmkId, sortOrdr }) => {\r\n const prev = snapshot(get());\r\n\r\n // 폴더명 변경만 프런트 즉시 반영(옵션)\r\n set((s) => {\r\n const next = { ...s, nodes: { ...s.nodes } } as State;\r\n const target = next.nodes[bkmkId] as FavNode | undefined;\r\n if (target?.type === \"F\" && typeof bkmkNm === \"string\") {\r\n next.nodes[bkmkId] = {\r\n ...(target as FolderNode),\r\n bkmkNm,\r\n } as FolderNode;\r\n }\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"U\",\r\n userId,\r\n bkmkId,\r\n bkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n chngId: getUserId(),\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 호환용 래퍼 ======\r\n addFolder: async (bkmkNm, prntBkmkId, sysCd, userId) => {\r\n return await get().addNode({\r\n type: \"F\",\r\n bkmkNm,\r\n prntBkmkId,\r\n sysCd,\r\n userId,\r\n });\r\n },\r\n\r\n addMenuToFolder: async (folderBkmkId, menu) => {\r\n // 전역 중복 방지\r\n const dup = findItemByMenuId(get().nodes, menu.menuId);\r\n if (dup) return \"이미 북마크에 저장된 메뉴입니다.\";\r\n return await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderBkmkId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n },\r\n\r\n toggleMenuFavorite: async (userId, menu) => {\r\n const s = get();\r\n const exists = Object.values(s.nodes).find(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menu.menuId\r\n );\r\n if (exists) {\r\n await get().removeNode(exists.bkmkId);\r\n return;\r\n }\r\n\r\n let folderId = pickDefaultFolderId(s);\r\n if (!folderId) {\r\n await get().loadFavorites(userId, true);\r\n folderId = pickDefaultFolderId(get());\r\n }\r\n if (folderId) {\r\n await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n }\r\n },\r\n\r\n removeMenuByMenuId: async (menuId) => {\r\n const s = get();\r\n const bkmkId = findItemByMenuId(s.nodes, menuId);\r\n if (bkmkId) await get().removeNode(bkmkId);\r\n },\r\n\r\n removeMenu: async (bkmkId) => {\r\n await get().removeNode(bkmkId);\r\n },\r\n\r\n removeFolder: async (folderBkmkId) => {\r\n await get().removeNode(folderBkmkId);\r\n },\r\n\r\n editFolder: async (folderBkmkId, userId, newBkmkNm, prntBkmkId, sortOrdr) => {\r\n await get().editNode({\r\n bkmkId: folderBkmkId,\r\n userId,\r\n bkmkNm: newBkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n });\r\n },\r\n\r\n /** Ant Tree 데이터 변환 (검색 포함) */\r\n convertToAntTreeData: (nodesMap, rootIds, q, onlyFolder = false) => {\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const build = (id: string): any | null => {\r\n const n = nodesMap[id];\r\n if (!n) return null;\r\n\r\n if (onlyFolder && n.type !== \"F\") return null;\r\n\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const children = (f.children || [])\r\n .map((cid) => build(cid))\r\n .filter(Boolean);\r\n const visible = match(f.bkmkNm) || children.length > 0;\r\n if (!visible) return null;\r\n return {\r\n key: f.bkmkId,\r\n type: \"F\",\r\n title: `📁 ${f.bkmkNm}`,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n sortOrdr: f.sortOrdr,\r\n fullPath: f.fullPath,\r\n children: children.length ? children : undefined,\r\n };\r\n } else {\r\n const i = n as ItemNode;\r\n const label = i.menuNm ? `${i.menuNm} (${i.menuId})` : i.menuId;\r\n const visible = match(label);\r\n if (!visible) return null;\r\n return {\r\n key: i.bkmkId,\r\n type: \"M\",\r\n title: `📄 ${label}`,\r\n prntBkmkId: i.prntBkmkId,\r\n sortOrdr: i.sortOrdr,\r\n fullPath: i.fullPath,\r\n isLeaf: true,\r\n };\r\n }\r\n };\r\n\r\n return rootIds.map(build).filter(Boolean);\r\n },\r\n});\r\n\r\nexport const useFavoriteStore = create<State>(creator);\r\n\r\n// ===================================================================\r\n// Helpers\r\n// ===================================================================\r\n\r\nfunction normalize(raw: any[]): Normalized {\r\n const nodes: Record<Id, FavNode> = {};\r\n const roots: Id[] = [];\r\n\r\n const walk = (arr: any[]) => {\r\n arr.forEach((r: any) => {\r\n // 서버 raw 필드: TYPE, BKMK_ID, PRNT_BKMK_ID, SORT_ORDR, BKMK_NM, MENU_ID, FULL_PATH?\r\n const base: BkmkBase = {\r\n type: r.type,\r\n bkmkId: r.bkmkId ?? r.BKMK_ID ?? r.id,\r\n prntBkmkId: r.prntBkmkId ?? r.PRNT_BKMK_ID ?? \"-\",\r\n sortOrdr: Number(r.sortOrdr ?? r.SORT_ORDR ?? 0),\r\n sysCd: r.sysCd ?? r.SYS_CD,\r\n userId: r.userId ?? r.USER_ID,\r\n fullPath: r.fullPath ?? r.FULL_PATH,\r\n };\r\n\r\n if (r.type === \"F\") {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n bkmkNm: r.bkmkNm ?? r.BKMK_NM ?? r.name ?? base.bkmkId,\r\n children: [],\r\n } as FolderNode;\r\n\r\n const children = Array.isArray(r.children) ? r.children : [];\r\n walk(children);\r\n } else {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n menuId: r.menuId ?? r.MENU_ID ?? \"\",\r\n menuNm: r.menuNm ?? r.MENU_NM,\r\n } as ItemNode;\r\n }\r\n });\r\n };\r\n\r\n walk(raw);\r\n\r\n // children / rootIds 구성\r\n Object.values(nodes).forEach((n) => {\r\n if (n.prntBkmkId && n.prntBkmkId !== \"-\") {\r\n const p = nodes[n.prntBkmkId] as FolderNode;\r\n if (p?.type === \"F\") p.children.push(n.bkmkId);\r\n } else if (n.type === \"F\") {\r\n roots.push(n.bkmkId);\r\n }\r\n });\r\n\r\n // 정렬 인덱스 보정(안전)\r\n roots.sort((a, b) => (nodes[a].sortOrdr ?? 0) - (nodes[b].sortOrdr ?? 0));\r\n Object.values(nodes).forEach((n) => {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n f.children.sort(\r\n (A, B) => (nodes[A].sortOrdr ?? 0) - (nodes[B].sortOrdr ?? 0)\r\n );\r\n }\r\n });\r\n\r\n return { nodes, rootIds: roots };\r\n}\r\n\r\nfunction snapshot(s: State): State {\r\n return {\r\n ...s,\r\n nodes: JSON.parse(JSON.stringify(s.nodes)),\r\n rootIds: s.rootIds.slice(),\r\n };\r\n}\r\n\r\nfunction tempId(): Id {\r\n return `tmp_${Math.random().toString(36).slice(2, 10)}`;\r\n}\r\n\r\nfunction tailIndex(s: Pick<State, \"nodes\" | \"rootIds\">, parentId: Id | \"-\") {\r\n if (!parentId || parentId === \"-\") return s.rootIds.length;\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n return p ? p.children.length : 0;\r\n}\r\n\r\nfunction attach(s: State, bkmkId: Id, parentId: Id | \"-\") {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n\r\n if (parentId && parentId !== \"-\") {\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n if (!p || p.type !== \"F\") return;\r\n n.prntBkmkId = parentId;\r\n p.children = [...p.children, bkmkId];\r\n } else {\r\n n.prntBkmkId = \"-\";\r\n s.rootIds = [...s.rootIds, bkmkId];\r\n }\r\n}\r\n\r\nfunction detach(s: State, bkmkId: Id) {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n const pid = n.prntBkmkId;\r\n\r\n if (pid && pid !== \"-\") {\r\n const p = s.nodes[pid] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n p.children = p.children.filter((c) => c !== bkmkId);\r\n }\r\n } else {\r\n s.rootIds = s.rootIds.filter((r) => r !== bkmkId);\r\n }\r\n}\r\n\r\nfunction removeRecursively(s: State, bkmkId: Id) {\r\n const node = s.nodes[bkmkId];\r\n if (!node) return;\r\n if (node.type === \"F\") {\r\n const children = (node as FolderNode).children.slice();\r\n children.forEach((cid) => removeRecursively(s, cid));\r\n }\r\n detach(s, bkmkId);\r\n const { [bkmkId]: _omit, ...rest } = s.nodes as Record<string, FavNode>;\r\n s.nodes = rest;\r\n}\r\n\r\n/** 임시ID → 실제ID 스왑 (불변성 유지) */\r\nfunction idSwapImmutable(s: State, tmp: Id, real: Id): State {\r\n if (tmp === real) return s;\r\n const node = s.nodes[tmp];\r\n if (!node) return s;\r\n\r\n const newNode: FavNode = JSON.parse(JSON.stringify(node));\r\n newNode.bkmkId = real;\r\n\r\n const newNodes: Record<Id, FavNode> = { ...s.nodes, [real]: newNode };\r\n delete newNodes[tmp];\r\n\r\n let newRootIds = s.rootIds;\r\n if (newNode.prntBkmkId && newNode.prntBkmkId !== \"-\") {\r\n const p = newNodes[newNode.prntBkmkId] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n newNodes[newNode.prntBkmkId] = {\r\n ...p,\r\n children: p.children.map((c) => (c === tmp ? real : c)),\r\n } as FolderNode;\r\n }\r\n } else {\r\n newRootIds = s.rootIds.map((r) => (r === tmp ? real : r));\r\n }\r\n\r\n return { ...s, nodes: newNodes, rootIds: newRootIds };\r\n}\r\n\r\nfunction pickDefaultFolderId(s: Pick<State, \"nodes\" | \"rootIds\">): Id | null {\r\n return s.rootIds.find((id) => s.nodes[id]?.type === \"F\") ?? null;\r\n}\r\n\r\nfunction toSimpleTreeFromMap(nodes: Record<Id, FavNode>, rootIds: Id[]) {\r\n const childrenByParent: Record<string, string[]> = {};\r\n Object.values(nodes).forEach((n) => {\r\n const id = n.bkmkId;\r\n const pid = n.prntBkmkId;\r\n if (!id || !pid || pid === \"-\" || pid === id) return;\r\n (childrenByParent[pid] ??= []).push(id);\r\n });\r\n\r\n const visiting = new Set<string>();\r\n\r\n const build = (id: Id): any => {\r\n if (visiting.has(id)) return null;\r\n const n = nodes[id];\r\n if (!n) return null;\r\n\r\n visiting.add(id);\r\n try {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const childIds = childrenByParent[id] ?? [];\r\n return {\r\n type: \"F\",\r\n bkmkId: id,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n children: childIds.map(build).filter(Boolean),\r\n };\r\n }\r\n const i = n as ItemNode;\r\n\r\n return {\r\n type: \"M\",\r\n bkmkId: id,\r\n bkmkNm: i.menuNm,\r\n menuId: i.menuId,\r\n menuNm: i.menuNm,\r\n prntBkmkId: i.prntBkmkId,\r\n };\r\n } finally {\r\n visiting.delete(id);\r\n }\r\n };\r\n\r\n const rootMenuIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"M\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootFolderIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"F\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootKeys = Array.from(\r\n new Set([...rootIds, ...rootMenuIds, ...rootFolderIds])\r\n );\r\n return rootKeys.map(build).filter(Boolean);\r\n}\r\n\r\nfunction findItemByMenuId(\r\n nodes: Record<Id, FavNode>,\r\n menuId: string\r\n): Id | null {\r\n for (const n of Object.values(nodes)) {\r\n if (n.type === \"M\" && (n as ItemNode).menuId === menuId) return n.bkmkId;\r\n }\r\n return null;\r\n}\r\n\r\nfunction _resequence(\r\n nodes: Record<Id, FavNode>,\r\n rootIds: Id[],\r\n parentId: Id | \"-\"\r\n) {\r\n const siblings: Id[] =\r\n !parentId || parentId === \"-\"\r\n ? rootIds\r\n : (nodes[parentId] as FolderNode).children || [];\r\n siblings.forEach((sid, idx) => {\r\n const n = nodes[sid];\r\n if (!n) return;\r\n n.sortOrdr = idx;\r\n });\r\n}\r\n"],"names":["creator","set","get","menuId","n","id","findItemByMenuId","nodeId","node","q","nodes","rootIds","match","make","folder","kids","cid","c","f","rid","userId","force","s","res","callService","raw","normalized","normalize","treeNodes","toSimpleTreeFromMap","e","p","prev","snapshot","tmp","tempId","sort","tailIndex","next","attach","real","sortForServer","getUserId","swapped","idSwapImmutable","bkmkId","newPrntBkmkId","sortOrdr","parent","oldParentId","removeFrom","idx","insertTo","_resequence","removeRecursively","bkmkNm","prntBkmkId","target","sysCd","folderBkmkId","menu","exists","folderId","pickDefaultFolderId","newBkmkNm","nodesMap","onlyFolder","build","children","i","label","useFavoriteStore","create","roots","walk","arr","r","base","a","b","A","B","parentId","detach","pid","_omit","rest","newNode","newNodes","newRootIds","childrenByParent","visiting","childIds","rootMenuIds","rootFolderIds","sid"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"favoriteStore-SyAjqLG8.js","sources":["../../src/stores/favoriteStore.ts"],"sourcesContent":["// -------------------------------------------------------\r\n// 즐겨찾기(폴더형) Zustand Store (단일 테이블 CM_BKMK_MSTR 기반)\r\n// 공통 CRUD로 통합: addNode / moveNode / removeNode / editNode\r\n// 기존 API(폴더/메뉴 전용)는 호환용으로 래핑만 유지\r\n// - 정규화(nodes + rootIds)\r\n// - 낙관적 업데이트 + 임시ID(tmp_* → 서버ID) 스왑\r\n// - 필수 기능: 로드, 생성, 이동, 삭제, 수정 + 셀렉터/뷰 변환\r\n// -------------------------------------------------------\r\n\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getUserId } from \"../utils/userUtils\";\r\nimport { DataNode } from \"antd/es/tree\";\r\nimport { create, StateCreator } from \"zustand\";\r\n\r\n// 🔧 공통 ID 타입\r\nexport type Id = string;\r\n\r\n/** 공통 베이스 (CM_BKMK_MSTR 매핑) */\r\nexport type BkmkBase = {\r\n type: \"F\" | \"M\"; // TYPE\r\n bkmkId: Id; // BKMK_ID\r\n prntBkmkId: Id | \"-\"; // PRNT_BKMK_ID ('-'=루트)\r\n sortOrdr: number; // SORT_ORDR\r\n sysCd?: string; // SYS_CD (옵션)\r\n userId?: string | null; // USER_ID (옵션)\r\n fullPath?: string; // 프론트 보조(옵션)\r\n};\r\n\r\n/** 폴더 노드 (BKMK_NM 사용) */\r\nexport type FolderNode = BkmkBase & {\r\n bkmkNm: string; // BKMK_NM (폴더 전용)\r\n children: Id[]; // 폴더/아이템 혼재(정규화용)\r\n};\r\n\r\n/** 아이템 노드 (메뉴 전용 메타) */\r\nexport type ItemNode = BkmkBase & {\r\n menuId: string; // MENU_ID\r\n menuNm?: string; // 프론트 보조(메뉴명)\r\n};\r\n\r\nexport type FavNode = FolderNode | ItemNode;\r\n\r\nexport type MovePayload = {\r\n bkmkId: Id;\r\n newPrntBkmkId: Id | \"-\";\r\n sortOrdr: number; // 새 부모 내 0-based\r\n userId: string | null;\r\n};\r\n\r\nexport type AddNodePayload = {\r\n type: \"F\" | \"M\";\r\n prntBkmkId: Id | \"-\";\r\n sysCd: string;\r\n userId: string | null;\r\n bkmkNm?: string; // F 전용\r\n menuId?: string; // M 전용\r\n menuNm?: string; // 프론트 보조\r\n sortOrdr?: number; // 선택: 지정 없으면 tailIndex 사용\r\n};\r\n\r\nexport type EditNodePayload = {\r\n bkmkId: Id;\r\n userId: string;\r\n bkmkNm?: string; // F일 때만 의미\r\n prntBkmkId?: Id | \"-\"; // 선택(이동은 moveNode 권장)\r\n sortOrdr?: number; // 선택\r\n};\r\n\r\nexport type Normalized = { nodes: Record<Id, FavNode>; rootIds: Id[] };\r\n\r\nexport type State = {\r\n // ========== 데이터(정규화) ==========\r\n nodes: Record<Id, FavNode>;\r\n rootIds: Id[];\r\n treeNodes: FavNode[]; // 단순 트리(뷰용)\r\n\r\n // ========== 메타 ==========\r\n loadedFor?: string;\r\n loading: boolean;\r\n error?: string;\r\n\r\n // ========== 셀렉터 ==========\r\n isMenuBookmarked: (menuId: string) => boolean;\r\n getPrntBkmkIdByMenuId: (menuId: string) => Id | \"-\";\r\n getNodeByMenuId: (menuId: string) => ItemNode | null;\r\n getFolderTree: (q?: string) => DataNode[]; // 폴더만 Tree (검색 필터)\r\n\r\n // ========== 로더 ==========\r\n loadFavorites: (userId: string, force?: boolean) => Promise<void>;\r\n loadFavoritesIfNeeded: (userId: string) => Promise<void>;\r\n\r\n // ========== 공통 CRUD ==========\r\n addNode: (p: AddNodePayload) => Promise<Id>;\r\n moveNode: (p: MovePayload) => Promise<void>;\r\n removeNode: (bkmkId: Id) => Promise<void>;\r\n editNode: (p: EditNodePayload) => Promise<void>;\r\n\r\n // ========== 호환용(기존 API 유지, 내부에서 공통 호출) ==========\r\n addFolder: (\r\n bkmkNm: string,\r\n prntBkmkId: Id | \"-\",\r\n sysCd: string,\r\n userId: string | null\r\n ) => Promise<Id>;\r\n addMenuToFolder: (\r\n folderBkmkId: Id,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<Id | string>;\r\n toggleMenuFavorite: (\r\n userId: string | null,\r\n menu: { menuId: string; menuNm: string }\r\n ) => Promise<void>;\r\n removeMenu: (bkmkId: Id) => Promise<void>;\r\n removeMenuByMenuId: (menuId: string) => Promise<void>;\r\n removeFolder: (folderBkmkId: Id) => Promise<void>;\r\n editFolder: (\r\n folderBkmkId: Id,\r\n userId: string | null,\r\n newBkmkNm?: string,\r\n prntBkmkId?: Id | \"-\",\r\n sortOrdr?: number\r\n ) => Promise<void>;\r\n convertToAntTreeData: (\r\n nodesMap: Record<string, FavNode>,\r\n rootIds: string[],\r\n q: string,\r\n onlyFolder?: boolean\r\n ) => any[];\r\n};\r\n\r\nconst creator: StateCreator<State> = (set, get) => ({\r\n nodes: {},\r\n rootIds: [],\r\n loadedFor: undefined,\r\n loading: false,\r\n error: undefined,\r\n treeNodes: [],\r\n\r\n // ====== 셀렉터 ======\r\n isMenuBookmarked: (menuId) =>\r\n Object.values(get().nodes).some(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menuId\r\n ),\r\n getPrntBkmkIdByMenuId: (menuId) => {\r\n const id = findItemByMenuId(get().nodes, menuId);\r\n return id ? get().nodes[id]?.prntBkmkId ?? \"-\" : \"-\";\r\n },\r\n\r\n getNodeByMenuId: (menuId) => {\r\n const nodeId = findItemByMenuId(get().nodes, menuId);\r\n if (!nodeId) return null;\r\n const node = get().nodes[nodeId];\r\n return node?.type === \"M\" ? (node as ItemNode) : null;\r\n },\r\n\r\n getFolderTree: (q) => {\r\n const { nodes, rootIds } = get();\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const make = (id: Id): DataNode | null => {\r\n const n = nodes[id];\r\n if (!n || n.type !== \"F\") return null;\r\n const folder = n as FolderNode;\r\n\r\n const kids = (folder.children || [])\r\n .map((cid) => nodes[cid])\r\n .filter((c): c is FolderNode => !!c && c.type === \"F\")\r\n .map((f) => make(f.bkmkId))\r\n .filter(Boolean) as DataNode[];\r\n\r\n const visible = match(folder.bkmkNm) || kids.length > 0;\r\n if (!visible) return null;\r\n\r\n return {\r\n key: folder.bkmkId,\r\n title: `📁 ${folder.bkmkNm}`,\r\n children: kids.length ? kids : undefined,\r\n };\r\n };\r\n\r\n return rootIds.map((rid) => make(rid)).filter(Boolean) as DataNode[];\r\n },\r\n\r\n // ====== 로더 ======\r\n loadFavorites: async (userId, force = false) => {\r\n console.log(\"loadFavorites ::::: \", userId, force);\r\n const s = get();\r\n if (!force && s.loadedFor === userId && Object.keys(s.nodes).length) return;\r\n\r\n set({ loading: true, error: undefined });\r\n try {\r\n // 기대 응답 예시: { sub: rawTree[] }\r\n const res = await callService(\"SCMBKMK00101\", { userId });\r\n const raw: any[] = Array.isArray(res?.sub) ? res.sub : [];\r\n const normalized = normalize(raw);\r\n\r\n const treeNodes = toSimpleTreeFromMap(\r\n normalized.nodes,\r\n normalized.rootIds\r\n );\r\n\r\n set({\r\n ...normalized,\r\n treeNodes,\r\n loadedFor: userId,\r\n loading: false,\r\n });\r\n } catch (e: any) {\r\n set({ loading: false, error: e?.message || \"즐겨찾기 로드 실패\" });\r\n throw e;\r\n }\r\n },\r\n\r\n loadFavoritesIfNeeded: async (userId) => {\r\n const s = get();\r\n const notLoaded =\r\n s.loadedFor !== userId || Object.keys(s.nodes).length === 0;\r\n if (notLoaded) {\r\n await get().loadFavorites(userId);\r\n }\r\n },\r\n\r\n // ====== 공통: 생성 ======\r\n addNode: async (p) => {\r\n const prev = snapshot(get());\r\n const tmp = tempId();\r\n\r\n // 1) 낙관적 반영\r\n set((s) => {\r\n const sort = p.sortOrdr ?? tailIndex(s, p.prntBkmkId);\r\n const next: State = {\r\n ...s,\r\n nodes: {\r\n ...s.nodes,\r\n [tmp]:\r\n p.type === \"F\"\r\n ? ({\r\n bkmkId: tmp,\r\n type: \"F\",\r\n prntBkmkId: p.prntBkmkId || \"-\",\r\n sortOrdr: sort,\r\n bkmkNm: p.bkmkNm ?? \"새 폴더\",\r\n children: [],\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as FolderNode)\r\n : ({\r\n bkmkId: tmp,\r\n type: \"M\",\r\n prntBkmkId: p.prntBkmkId,\r\n sortOrdr: sort,\r\n menuId: p.menuId ?? \"\",\r\n menuNm: p.menuNm,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n } as ItemNode),\r\n },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n attach(next, tmp, p.prntBkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n // 2) 서버 호출\r\n // 백엔드는 통합 IUD가 아닐 수 있으므로, 호환 분기 적용\r\n let real: string = tmp;\r\n const sortForServer = tailIndex(get(), p.prntBkmkId);\r\n const res = await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"I\",\r\n type: p.type,\r\n sysCd: p.sysCd,\r\n userId: p.userId,\r\n bkmkId: tmp, // 서버 새 ID 반환 시 매칭용\r\n bkmkNm: p.bkmkNm,\r\n prntBkmkId: p.prntBkmkId,\r\n menuId: p.menuId,\r\n sortOrdr: sortForServer,\r\n chngId: getUserId(),\r\n });\r\n real = String(res?.bkmkId ?? res?.itemId ?? tmp);\r\n\r\n // 3) tmp → real 스왑\r\n set((s) => {\r\n const swapped = idSwapImmutable(s, tmp, real);\r\n return {\r\n ...swapped,\r\n treeNodes: toSimpleTreeFromMap(swapped.nodes, swapped.rootIds),\r\n };\r\n });\r\n return real;\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 이동 ======\r\n moveNode: async ({ bkmkId, newPrntBkmkId, sortOrdr, userId }) => {\r\n const prev = get(); // 함수 포함 스냅샷(rollback 용으로 set(prev) 사용)\r\n\r\n const nodes = structuredClone(prev.nodes);\r\n const rootIds = [...prev.rootIds];\r\n\r\n const node = nodes[bkmkId];\r\n if (!node) return;\r\n\r\n // 부모는 반드시 폴더만 허용\r\n if (newPrntBkmkId !== \"-\") {\r\n const parent = nodes[newPrntBkmkId];\r\n if (!parent || parent.type !== \"F\")\r\n throw new Error(\"부모는 폴더만 가능합니다.\");\r\n }\r\n\r\n const oldParentId = node.prntBkmkId ?? \"-\";\r\n\r\n const removeFrom =\r\n oldParentId === \"-\"\r\n ? rootIds\r\n : ((nodes[oldParentId] as FolderNode).children ||= []);\r\n {\r\n const idx = removeFrom.indexOf(bkmkId);\r\n if (idx >= 0) removeFrom.splice(idx, 1);\r\n }\r\n\r\n const insertTo =\r\n newPrntBkmkId === \"-\"\r\n ? rootIds\r\n : ((nodes[newPrntBkmkId] as FolderNode).children ||= []);\r\n insertTo.splice(\r\n Math.max(0, Math.min(sortOrdr, insertTo.length)),\r\n 0,\r\n bkmkId\r\n );\r\n\r\n node.prntBkmkId = newPrntBkmkId as Id;\r\n set({ nodes, rootIds });\r\n _resequence(nodes, rootIds, newPrntBkmkId);\r\n _resequence(nodes, rootIds, oldParentId);\r\n\r\n try {\r\n await callService(\"SCMBKMK00104\", {\r\n // 백엔드 명칭 호환\r\n bkmkId,\r\n prntBkmkId: newPrntBkmkId,\r\n sortOrdr,\r\n chngId: userId,\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 삭제 ======\r\n removeNode: async (bkmkId) => {\r\n const prev = snapshot(get());\r\n\r\n set((s) => {\r\n if (!s.nodes[bkmkId]) return s as State;\r\n const next: State = {\r\n ...s,\r\n nodes: { ...s.nodes },\r\n rootIds: s.rootIds.slice(),\r\n treeNodes: s.treeNodes,\r\n };\r\n removeRecursively(next, bkmkId);\r\n next.treeNodes = toSimpleTreeFromMap(next.nodes, next.rootIds);\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00103\", { bkmkId });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 공통: 수정 ======\r\n editNode: async ({ bkmkId, userId, bkmkNm, prntBkmkId, sortOrdr }) => {\r\n const prev = snapshot(get());\r\n\r\n // 폴더명 변경만 프런트 즉시 반영(옵션)\r\n set((s) => {\r\n const next = { ...s, nodes: { ...s.nodes } } as State;\r\n const target = next.nodes[bkmkId] as FavNode | undefined;\r\n if (target?.type === \"F\" && typeof bkmkNm === \"string\") {\r\n next.nodes[bkmkId] = {\r\n ...(target as FolderNode),\r\n bkmkNm,\r\n } as FolderNode;\r\n }\r\n return next;\r\n });\r\n\r\n try {\r\n await callService(\"SCMBKMK00102\", {\r\n iudFlag: \"U\",\r\n userId,\r\n bkmkId,\r\n bkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n chngId: getUserId(),\r\n });\r\n } catch (e) {\r\n set(prev);\r\n throw e;\r\n }\r\n },\r\n\r\n // ====== 호환용 래퍼 ======\r\n addFolder: async (bkmkNm, prntBkmkId, sysCd, userId) => {\r\n return await get().addNode({\r\n type: \"F\",\r\n bkmkNm,\r\n prntBkmkId,\r\n sysCd,\r\n userId,\r\n });\r\n },\r\n\r\n addMenuToFolder: async (folderBkmkId, menu) => {\r\n // 전역 중복 방지\r\n const dup = findItemByMenuId(get().nodes, menu.menuId);\r\n if (dup) return \"이미 북마크에 저장된 메뉴입니다.\";\r\n return await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderBkmkId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n },\r\n\r\n toggleMenuFavorite: async (userId, menu) => {\r\n const s = get();\r\n const exists = Object.values(s.nodes).find(\r\n (n) => n.type === \"M\" && (n as ItemNode).menuId === menu.menuId\r\n );\r\n if (exists) {\r\n await get().removeNode(exists.bkmkId);\r\n return;\r\n }\r\n\r\n let folderId = pickDefaultFolderId(s);\r\n if (!folderId) {\r\n await get().loadFavorites(userId, true);\r\n folderId = pickDefaultFolderId(get());\r\n }\r\n if (folderId) {\r\n await get().addNode({\r\n type: \"M\",\r\n prntBkmkId: folderId,\r\n sysCd: \"KH\",\r\n userId: getUserId(),\r\n menuId: menu.menuId,\r\n menuNm: menu.menuNm,\r\n });\r\n }\r\n },\r\n\r\n removeMenuByMenuId: async (menuId) => {\r\n const s = get();\r\n const bkmkId = findItemByMenuId(s.nodes, menuId);\r\n if (bkmkId) await get().removeNode(bkmkId);\r\n },\r\n\r\n removeMenu: async (bkmkId) => {\r\n await get().removeNode(bkmkId);\r\n },\r\n\r\n removeFolder: async (folderBkmkId) => {\r\n await get().removeNode(folderBkmkId);\r\n },\r\n\r\n editFolder: async (folderBkmkId, userId, newBkmkNm, prntBkmkId, sortOrdr) => {\r\n await get().editNode({\r\n bkmkId: folderBkmkId,\r\n userId,\r\n bkmkNm: newBkmkNm,\r\n prntBkmkId,\r\n sortOrdr,\r\n });\r\n },\r\n\r\n /** Ant Tree 데이터 변환 (검색 포함) */\r\n convertToAntTreeData: (nodesMap, rootIds, q, onlyFolder = false) => {\r\n const match = (s: string) =>\r\n q ? s.toLowerCase().includes(q.toLowerCase()) : true;\r\n\r\n const build = (id: string): any | null => {\r\n const n = nodesMap[id];\r\n if (!n) return null;\r\n\r\n if (onlyFolder && n.type !== \"F\") return null;\r\n\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const children = (f.children || [])\r\n .map((cid) => build(cid))\r\n .filter(Boolean);\r\n const visible = match(f.bkmkNm) || children.length > 0;\r\n if (!visible) return null;\r\n return {\r\n key: f.bkmkId,\r\n type: \"F\",\r\n title: `📁 ${f.bkmkNm}`,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n sortOrdr: f.sortOrdr,\r\n fullPath: f.fullPath,\r\n children: children.length ? children : undefined,\r\n };\r\n } else {\r\n const i = n as ItemNode;\r\n const label = i.menuNm ? `${i.menuNm} (${i.menuId})` : i.menuId;\r\n const visible = match(label);\r\n if (!visible) return null;\r\n return {\r\n key: i.bkmkId,\r\n type: \"M\",\r\n title: `📄 ${label}`,\r\n prntBkmkId: i.prntBkmkId,\r\n sortOrdr: i.sortOrdr,\r\n fullPath: i.fullPath,\r\n isLeaf: true,\r\n };\r\n }\r\n };\r\n\r\n return rootIds.map(build).filter(Boolean);\r\n },\r\n});\r\n\r\nexport const useFavoriteStore = create<State>(creator);\r\n\r\n// ===================================================================\r\n// Helpers\r\n// ===================================================================\r\n\r\nfunction normalize(raw: any[]): Normalized {\r\n const nodes: Record<Id, FavNode> = {};\r\n const roots: Id[] = [];\r\n\r\n const walk = (arr: any[]) => {\r\n arr.forEach((r: any) => {\r\n // 서버 raw 필드: TYPE, BKMK_ID, PRNT_BKMK_ID, SORT_ORDR, BKMK_NM, MENU_ID, FULL_PATH?\r\n const base: BkmkBase = {\r\n type: r.type,\r\n bkmkId: r.bkmkId ?? r.BKMK_ID ?? r.id,\r\n prntBkmkId: r.prntBkmkId ?? r.PRNT_BKMK_ID ?? \"-\",\r\n sortOrdr: Number(r.sortOrdr ?? r.SORT_ORDR ?? 0),\r\n sysCd: r.sysCd ?? r.SYS_CD,\r\n userId: r.userId ?? r.USER_ID,\r\n fullPath: r.fullPath ?? r.FULL_PATH,\r\n };\r\n\r\n if (r.type === \"F\") {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n bkmkNm: r.bkmkNm ?? r.BKMK_NM ?? r.name ?? base.bkmkId,\r\n children: [],\r\n } as FolderNode;\r\n\r\n const children = Array.isArray(r.children) ? r.children : [];\r\n walk(children);\r\n } else {\r\n nodes[base.bkmkId] = {\r\n ...base,\r\n menuId: r.menuId ?? r.MENU_ID ?? \"\",\r\n menuNm: r.menuNm ?? r.MENU_NM,\r\n } as ItemNode;\r\n }\r\n });\r\n };\r\n\r\n walk(raw);\r\n\r\n // children / rootIds 구성\r\n Object.values(nodes).forEach((n) => {\r\n if (n.prntBkmkId && n.prntBkmkId !== \"-\") {\r\n const p = nodes[n.prntBkmkId] as FolderNode;\r\n if (p?.type === \"F\") p.children.push(n.bkmkId);\r\n } else if (n.type === \"F\") {\r\n roots.push(n.bkmkId);\r\n }\r\n });\r\n\r\n // 정렬 인덱스 보정(안전)\r\n roots.sort((a, b) => (nodes[a].sortOrdr ?? 0) - (nodes[b].sortOrdr ?? 0));\r\n Object.values(nodes).forEach((n) => {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n f.children.sort(\r\n (A, B) => (nodes[A].sortOrdr ?? 0) - (nodes[B].sortOrdr ?? 0)\r\n );\r\n }\r\n });\r\n\r\n return { nodes, rootIds: roots };\r\n}\r\n\r\nfunction snapshot(s: State): State {\r\n return {\r\n ...s,\r\n nodes: JSON.parse(JSON.stringify(s.nodes)),\r\n rootIds: s.rootIds.slice(),\r\n };\r\n}\r\n\r\nfunction tempId(): Id {\r\n return `tmp_${Math.random().toString(36).slice(2, 10)}`;\r\n}\r\n\r\nfunction tailIndex(s: Pick<State, \"nodes\" | \"rootIds\">, parentId: Id | \"-\") {\r\n if (!parentId || parentId === \"-\") return s.rootIds.length;\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n return p ? p.children.length : 0;\r\n}\r\n\r\nfunction attach(s: State, bkmkId: Id, parentId: Id | \"-\") {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n\r\n if (parentId && parentId !== \"-\") {\r\n const p = s.nodes[parentId] as FolderNode | undefined;\r\n if (!p || p.type !== \"F\") return;\r\n n.prntBkmkId = parentId;\r\n p.children = [...p.children, bkmkId];\r\n } else {\r\n n.prntBkmkId = \"-\";\r\n s.rootIds = [...s.rootIds, bkmkId];\r\n }\r\n}\r\n\r\nfunction detach(s: State, bkmkId: Id) {\r\n const n = s.nodes[bkmkId];\r\n if (!n) return;\r\n const pid = n.prntBkmkId;\r\n\r\n if (pid && pid !== \"-\") {\r\n const p = s.nodes[pid] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n p.children = p.children.filter((c) => c !== bkmkId);\r\n }\r\n } else {\r\n s.rootIds = s.rootIds.filter((r) => r !== bkmkId);\r\n }\r\n}\r\n\r\nfunction removeRecursively(s: State, bkmkId: Id) {\r\n const node = s.nodes[bkmkId];\r\n if (!node) return;\r\n if (node.type === \"F\") {\r\n const children = (node as FolderNode).children.slice();\r\n children.forEach((cid) => removeRecursively(s, cid));\r\n }\r\n detach(s, bkmkId);\r\n const { [bkmkId]: _omit, ...rest } = s.nodes as Record<string, FavNode>;\r\n s.nodes = rest;\r\n}\r\n\r\n/** 임시ID → 실제ID 스왑 (불변성 유지) */\r\nfunction idSwapImmutable(s: State, tmp: Id, real: Id): State {\r\n if (tmp === real) return s;\r\n const node = s.nodes[tmp];\r\n if (!node) return s;\r\n\r\n const newNode: FavNode = JSON.parse(JSON.stringify(node));\r\n newNode.bkmkId = real;\r\n\r\n const newNodes: Record<Id, FavNode> = { ...s.nodes, [real]: newNode };\r\n delete newNodes[tmp];\r\n\r\n let newRootIds = s.rootIds;\r\n if (newNode.prntBkmkId && newNode.prntBkmkId !== \"-\") {\r\n const p = newNodes[newNode.prntBkmkId] as FolderNode | undefined;\r\n if (p?.type === \"F\") {\r\n newNodes[newNode.prntBkmkId] = {\r\n ...p,\r\n children: p.children.map((c) => (c === tmp ? real : c)),\r\n } as FolderNode;\r\n }\r\n } else {\r\n newRootIds = s.rootIds.map((r) => (r === tmp ? real : r));\r\n }\r\n\r\n return { ...s, nodes: newNodes, rootIds: newRootIds };\r\n}\r\n\r\nfunction pickDefaultFolderId(s: Pick<State, \"nodes\" | \"rootIds\">): Id | null {\r\n return s.rootIds.find((id) => s.nodes[id]?.type === \"F\") ?? null;\r\n}\r\n\r\nfunction toSimpleTreeFromMap(nodes: Record<Id, FavNode>, rootIds: Id[]) {\r\n const childrenByParent: Record<string, string[]> = {};\r\n Object.values(nodes).forEach((n) => {\r\n const id = n.bkmkId;\r\n const pid = n.prntBkmkId;\r\n if (!id || !pid || pid === \"-\" || pid === id) return;\r\n (childrenByParent[pid] ??= []).push(id);\r\n });\r\n\r\n const visiting = new Set<string>();\r\n\r\n const build = (id: Id): any => {\r\n if (visiting.has(id)) return null;\r\n const n = nodes[id];\r\n if (!n) return null;\r\n\r\n visiting.add(id);\r\n try {\r\n if (n.type === \"F\") {\r\n const f = n as FolderNode;\r\n const childIds = childrenByParent[id] ?? [];\r\n return {\r\n type: \"F\",\r\n bkmkId: id,\r\n bkmkNm: f.bkmkNm,\r\n prntBkmkId: f.prntBkmkId,\r\n children: childIds.map(build).filter(Boolean),\r\n };\r\n }\r\n const i = n as ItemNode;\r\n\r\n return {\r\n type: \"M\",\r\n bkmkId: id,\r\n bkmkNm: i.menuNm,\r\n menuId: i.menuId,\r\n menuNm: i.menuNm,\r\n prntBkmkId: i.prntBkmkId,\r\n };\r\n } finally {\r\n visiting.delete(id);\r\n }\r\n };\r\n\r\n const rootMenuIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"M\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootFolderIds = Object.values(nodes)\r\n .filter((n) => n.prntBkmkId === \"-\" && n.type === \"F\")\r\n .map((n) => n.bkmkId);\r\n\r\n const rootKeys = Array.from(\r\n new Set([...rootIds, ...rootMenuIds, ...rootFolderIds])\r\n );\r\n return rootKeys.map(build).filter(Boolean);\r\n}\r\n\r\nfunction findItemByMenuId(\r\n nodes: Record<Id, FavNode>,\r\n menuId: string\r\n): Id | null {\r\n for (const n of Object.values(nodes)) {\r\n if (n.type === \"M\" && (n as ItemNode).menuId === menuId) return n.bkmkId;\r\n }\r\n return null;\r\n}\r\n\r\nfunction _resequence(\r\n nodes: Record<Id, FavNode>,\r\n rootIds: Id[],\r\n parentId: Id | \"-\"\r\n) {\r\n const siblings: Id[] =\r\n !parentId || parentId === \"-\"\r\n ? rootIds\r\n : (nodes[parentId] as FolderNode).children || [];\r\n siblings.forEach((sid, idx) => {\r\n const n = nodes[sid];\r\n if (!n) return;\r\n n.sortOrdr = idx;\r\n });\r\n}\r\n"],"names":["creator","set","get","menuId","n","id","findItemByMenuId","nodeId","node","q","nodes","rootIds","match","make","folder","kids","cid","c","f","rid","userId","force","s","res","callService","raw","normalized","normalize","treeNodes","toSimpleTreeFromMap","e","p","prev","snapshot","tmp","tempId","sort","tailIndex","next","attach","real","sortForServer","getUserId","swapped","idSwapImmutable","bkmkId","newPrntBkmkId","sortOrdr","parent","oldParentId","removeFrom","idx","insertTo","_resequence","removeRecursively","bkmkNm","prntBkmkId","target","sysCd","folderBkmkId","menu","exists","folderId","pickDefaultFolderId","newBkmkNm","nodesMap","onlyFolder","build","children","i","label","useFavoriteStore","create","roots","walk","arr","r","base","a","b","A","B","parentId","detach","pid","_omit","rest","newNode","newNodes","newRootIds","childrenByParent","visiting","childIds","rootMenuIds","rootFolderIds","sid"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as d, al as P, aA as I } from "./apiUtils-
|
|
1
|
+
import { c as d, al as P, aA as I } from "./apiUtils-DPUgfmKk.js";
|
|
2
2
|
import { create as g } from "zustand";
|
|
3
3
|
const h = g((u, n) => ({
|
|
4
4
|
popups: [],
|
|
@@ -89,4 +89,4 @@ const h = g((u, n) => ({
|
|
|
89
89
|
export {
|
|
90
90
|
h as u
|
|
91
91
|
};
|
|
92
|
-
//# sourceMappingURL=popupStore-
|
|
92
|
+
//# sourceMappingURL=popupStore-BrKcPw7K.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popupStore-
|
|
1
|
+
{"version":3,"file":"popupStore-BrKcPw7K.js","sources":["../../src/stores/popupStore.ts"],"sourcesContent":["import { getUserInfo } from \"@/utils/userUtils\";\r\nimport { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\n\r\n// 팝업 아이템 타입 정의\r\nexport interface PopupItem {\r\n popupId: string; // 팝업 ID\r\n popupCode: string; // 팝업 코드\r\n popupTitle: string; // 팝업 제목\r\n popupUrl: string; // 팝업 프로그램 URL\r\n popupParams?: any; // 팝업 파라미터\r\n buttonList?: any[]; // 버튼 목록\r\n width?: number; // 팝업 너비\r\n height?: number; // 팝업 높이\r\n resizable?: boolean; // 크기 조절 가능 여부\r\n draggable?: boolean; // 드래그 가능 여부\r\n config?: PopupConfig; // 팝업 설정\r\n close?: () => void; // 팝업 닫기 함수\r\n}\r\n\r\n// 팝업 스토어 타입 정의\r\nexport interface PopupStore {\r\n popups: PopupItem[]; // 열린 팝업 목록\r\n activePopupId: string | null; // 현재 활성 팝업 ID\r\n isLoading: boolean; // 로딩 상태\r\n error: string | null; // 에러 상태\r\n\r\n // 팝업 관련 액션들\r\n openPopup: (\r\n popupCode: string,\r\n data?: any,\r\n config?: PopupConfig\r\n ) => Promise<void>;\r\n closePopup: (popupId: string) => void;\r\n closeAllPopups: () => void;\r\n setActivePopup: (popupId: string) => void;\r\n\r\n updatePopupConfig: (popupId: string, config: Partial<PopupConfig>) => void;\r\n}\r\n\r\nexport interface PopupButton {\r\n key: string; // 버튼 고유 키\r\n text: string; // 버튼 텍스트\r\n type?: \"primary\" | \"default\" | \"dashed\" | \"link\" | \"text\"; // 버튼 타입\r\n danger?: boolean; // 위험 버튼 여부\r\n disabled?: boolean; // 비활성화 여부\r\n icon?: string; // 아이콘 (Ant Design 아이콘명)\r\n onClick?: (popupData?: any) => void | Promise<void>; // 클릭 이벤트\r\n}\r\n\r\n/**\r\n * 팝업 설정 타입 정의\r\n */\r\nexport interface PopupConfig {\r\n width?: number; // 팝업 너비\r\n height?: number; // 팝업 높이\r\n title?: string; // 팝업 제목\r\n buttons?: PopupButton[]; // 팝업 버튼들\r\n resizable?: boolean; // 크기 조절 가능 여부\r\n draggable?: boolean; // 드래그 가능 여부\r\n closable?: boolean; // 닫기 버튼 표시 여부\r\n maskClosable?: boolean; // 마스크 클릭 시 닫기 여부\r\n destroyOnClose?: boolean; // 닫을 때 컴포넌트 파괴 여부\r\n searchBox?: {\r\n reqArea: any;\r\n subArea?: any;\r\n style?: any;\r\n };\r\n /**\r\n * 팝업 콜백\r\n * 팝업 콜백은 팝업이 닫힐 때 호출되는 함수입니다.\r\n */\r\n callback?: (callbackParams?: any) => void;\r\n}\r\n\r\n/**\r\n * 팝업 내부 뷰 컴포넌트 타입\r\n */\r\nexport interface PopupViewProps {\r\n /**\r\n * 팝업정보\r\n */\r\n popup?: PopupItem;\r\n /** 팝업 이벤트 전달 프로퍼티 */\r\n popupEvent?: any;\r\n /** 팝업 닫기 이벤트 전달 프로퍼티 */\r\n onClose?: () => void;\r\n}\r\n\r\n// 팝업 스토어 생성\r\nexport const usePopupStore = create<PopupStore>((set, get) => ({\r\n popups: [],\r\n activePopupId: null,\r\n isLoading: false,\r\n error: null,\r\n\r\n // 팝업 열기\r\n openPopup: async (popupCode: string, data?: any, config?: PopupConfig) => {\r\n //console.log(\"팝업 열기 요청:\", { popupCode, data, config });\r\n set({ isLoading: true, error: null });\r\n\r\n try {\r\n //console.log(\"팝업 열기 시작:\", popupCode);\r\n\r\n // 개발 환경에서는 모의 데이터 사용\r\n let popupInfo: any = null;\r\n\r\n const response = await callService(getServiceCode(\"SRCH_POPU\"), {\r\n crprCd: getUserInfo()?.crprCd,\r\n popuCd: popupCode,\r\n });\r\n //console.log(\"팝업 정보 조회 결과:\", response);\r\n\r\n // 응답 구조 파싱: { mstr: {...}, dtls: [...] }\r\n popupInfo = response?.mstr;\r\n const buttonList = response?.dtls || [];\r\n\r\n //console.info(\"popupInfo:\", popupInfo);\r\n\r\n if (!popupInfo || !popupInfo.popuUrl) {\r\n const errorMsg = `팝업 정보를 찾을 수 없습니다: ${popupCode}`;\r\n console.error(errorMsg);\r\n throw new Error(errorMsg);\r\n }\r\n\r\n //console.log(\"파싱된 팝업 정보:\", popupInfo);\r\n //console.log(\"버튼 목록:\", buttonList);\r\n\r\n // 팝업 URL 경로 변환: 서버 경로 -> 클라이언트 경로\r\n const convertPopupUrl = (serverUrl: string): string => {\r\n // 서버에서 받은 경로: \"cm/CMAuthMstrP01\"\r\n // 클라이언트에서 사용할 경로: \"/src/pages/views/popup/cm/CMAuthMstrP01\"\r\n return `/src/pages/views/popup/${serverUrl}`;\r\n };\r\n\r\n const convertedPopupUrl = convertPopupUrl(popupInfo.popuUrl);\r\n //console.log(\"변환된 팝업 URL:\", convertedPopupUrl);\r\n\r\n // 팝업 아이템 생성\r\n const popupItem: PopupItem = {\r\n popupId: `popup_${Date.now()}_${Math.random()\r\n .toString(36)\r\n .substr(2, 9)}`,\r\n popupCode: popupCode,\r\n //config.title을 통해 팝업 제목 변경 가능\r\n popupTitle: config?.title || popupInfo.popuNm || \"팝업\",\r\n popupUrl: convertedPopupUrl,\r\n popupParams: data,\r\n width: popupInfo.popuWdth || 800,\r\n height: popupInfo.popuHght || 600,\r\n resizable: true,\r\n draggable: true,\r\n buttonList: buttonList, // 버튼 목록 추가\r\n config: config,\r\n };\r\n\r\n //console.log(\"생성된 팝업 아이템:\", popupItem);\r\n\r\n // 이미 같은 팝업이 열려있는지 확인\r\n const existingPopup = get().popups.find((p) => p.popupCode === popupCode);\r\n if (existingPopup) {\r\n //console.log(\"기존 팝업 업데이트:\", existingPopup.popupId);\r\n // 기존 팝업을 활성화하고 데이터 업데이트\r\n set({\r\n activePopupId: existingPopup.popupId,\r\n popups: get().popups.map((p) =>\r\n p.popupId === existingPopup.popupId ? { ...p, config: config } : p\r\n ),\r\n isLoading: false,\r\n });\r\n return;\r\n }\r\n\r\n // 새 팝업 추가\r\n //console.log(\"새 팝업 추가:\", popupItem.popupId);\r\n set((state) => ({\r\n popups: [...state.popups, popupItem],\r\n activePopupId: popupItem.popupId,\r\n isLoading: false,\r\n }));\r\n\r\n //console.log(\"팝업 열기 완료:\", popupItem);\r\n } catch (error) {\r\n // console.error(\"팝업 열기 실패:\", error);\r\n set({\r\n error: error instanceof Error ? error.message : \"팝업 열기 실패\",\r\n isLoading: false,\r\n });\r\n }\r\n },\r\n\r\n // 팝업 닫기\r\n closePopup: (popupId: string) => {\r\n const { popups, activePopupId } = get();\r\n const newPopups = popups.filter((p) => p.popupId !== popupId);\r\n\r\n // 닫힌 팝업이 현재 활성 팝업이었다면 다른 팝업을 활성화\r\n let newActivePopupId = activePopupId;\r\n if (activePopupId === popupId) {\r\n newActivePopupId =\r\n newPopups.length > 0 ? newPopups[newPopups.length - 1].popupId : null;\r\n }\r\n\r\n set({\r\n popups: newPopups,\r\n activePopupId: newActivePopupId,\r\n });\r\n },\r\n\r\n // 모든 팝업 닫기\r\n closeAllPopups: () => {\r\n set({\r\n popups: [],\r\n activePopupId: null,\r\n });\r\n },\r\n\r\n // 활성 팝업 설정\r\n setActivePopup: (popupId: string) => {\r\n set({ activePopupId: popupId });\r\n },\r\n\r\n // 팝업 설정 업데이트\r\n updatePopupConfig: (popupId: string, config: Partial<PopupConfig>) => {\r\n set((state) => ({\r\n popups: state.popups.map((p) =>\r\n p.popupId === popupId ? { ...p, config: { ...p.config, ...config } } : p\r\n ),\r\n }));\r\n },\r\n}));\r\n"],"names":["usePopupStore","create","set","get","popupCode","data","config","popupInfo","response","callService","getServiceCode","getUserInfo","buttonList","errorMsg","convertedPopupUrl","serverUrl","popupItem","existingPopup","p","state","error","popupId","popups","activePopupId","newPopups","newActivePopupId"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const c=require("./apiUtils-
|
|
2
|
-
//# sourceMappingURL=popupStore-
|
|
1
|
+
"use strict";const c=require("./apiUtils-D9Vn1gwZ.cjs"),P=require("zustand"),I=P.create((r,n)=>({popups:[],activePopupId:null,isLoading:!1,error:null,openPopup:async(u,t,e)=>{r({isLoading:!0,error:null});try{let p=null;const s=await c.callService(c.getServiceCode("SRCH_POPU"),{crprCd:c.getUserInfo()?.crprCd,popuCd:u});p=s?.mstr;const i=s?.dtls||[];if(!p||!p.popuUrl){const o=`팝업 정보를 찾을 수 없습니다: ${u}`;throw console.error(o),new Error(o)}const d=(o=>`/src/pages/views/popup/${o}`)(p.popuUrl),a={popupId:`popup_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,popupCode:u,popupTitle:e?.title||p.popuNm||"팝업",popupUrl:d,popupParams:t,width:p.popuWdth||800,height:p.popuHght||600,resizable:!0,draggable:!0,buttonList:i,config:e},l=n().popups.find(o=>o.popupCode===u);if(l){r({activePopupId:l.popupId,popups:n().popups.map(o=>o.popupId===l.popupId?{...o,config:e}:o),isLoading:!1});return}r(o=>({popups:[...o.popups,a],activePopupId:a.popupId,isLoading:!1}))}catch(p){r({error:p instanceof Error?p.message:"팝업 열기 실패",isLoading:!1})}},closePopup:u=>{const{popups:t,activePopupId:e}=n(),p=t.filter(i=>i.popupId!==u);let s=e;e===u&&(s=p.length>0?p[p.length-1].popupId:null),r({popups:p,activePopupId:s})},closeAllPopups:()=>{r({popups:[],activePopupId:null})},setActivePopup:u=>{r({activePopupId:u})},updatePopupConfig:(u,t)=>{r(e=>({popups:e.popups.map(p=>p.popupId===u?{...p,config:{...p.config,...t}}:p)}))}}));exports.usePopupStore=I;
|
|
2
|
+
//# sourceMappingURL=popupStore-ChbYTqy1.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popupStore-
|
|
1
|
+
{"version":3,"file":"popupStore-ChbYTqy1.cjs","sources":["../../src/stores/popupStore.ts"],"sourcesContent":["import { getUserInfo } from \"@/utils/userUtils\";\r\nimport { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\n\r\n// 팝업 아이템 타입 정의\r\nexport interface PopupItem {\r\n popupId: string; // 팝업 ID\r\n popupCode: string; // 팝업 코드\r\n popupTitle: string; // 팝업 제목\r\n popupUrl: string; // 팝업 프로그램 URL\r\n popupParams?: any; // 팝업 파라미터\r\n buttonList?: any[]; // 버튼 목록\r\n width?: number; // 팝업 너비\r\n height?: number; // 팝업 높이\r\n resizable?: boolean; // 크기 조절 가능 여부\r\n draggable?: boolean; // 드래그 가능 여부\r\n config?: PopupConfig; // 팝업 설정\r\n close?: () => void; // 팝업 닫기 함수\r\n}\r\n\r\n// 팝업 스토어 타입 정의\r\nexport interface PopupStore {\r\n popups: PopupItem[]; // 열린 팝업 목록\r\n activePopupId: string | null; // 현재 활성 팝업 ID\r\n isLoading: boolean; // 로딩 상태\r\n error: string | null; // 에러 상태\r\n\r\n // 팝업 관련 액션들\r\n openPopup: (\r\n popupCode: string,\r\n data?: any,\r\n config?: PopupConfig\r\n ) => Promise<void>;\r\n closePopup: (popupId: string) => void;\r\n closeAllPopups: () => void;\r\n setActivePopup: (popupId: string) => void;\r\n\r\n updatePopupConfig: (popupId: string, config: Partial<PopupConfig>) => void;\r\n}\r\n\r\nexport interface PopupButton {\r\n key: string; // 버튼 고유 키\r\n text: string; // 버튼 텍스트\r\n type?: \"primary\" | \"default\" | \"dashed\" | \"link\" | \"text\"; // 버튼 타입\r\n danger?: boolean; // 위험 버튼 여부\r\n disabled?: boolean; // 비활성화 여부\r\n icon?: string; // 아이콘 (Ant Design 아이콘명)\r\n onClick?: (popupData?: any) => void | Promise<void>; // 클릭 이벤트\r\n}\r\n\r\n/**\r\n * 팝업 설정 타입 정의\r\n */\r\nexport interface PopupConfig {\r\n width?: number; // 팝업 너비\r\n height?: number; // 팝업 높이\r\n title?: string; // 팝업 제목\r\n buttons?: PopupButton[]; // 팝업 버튼들\r\n resizable?: boolean; // 크기 조절 가능 여부\r\n draggable?: boolean; // 드래그 가능 여부\r\n closable?: boolean; // 닫기 버튼 표시 여부\r\n maskClosable?: boolean; // 마스크 클릭 시 닫기 여부\r\n destroyOnClose?: boolean; // 닫을 때 컴포넌트 파괴 여부\r\n searchBox?: {\r\n reqArea: any;\r\n subArea?: any;\r\n style?: any;\r\n };\r\n /**\r\n * 팝업 콜백\r\n * 팝업 콜백은 팝업이 닫힐 때 호출되는 함수입니다.\r\n */\r\n callback?: (callbackParams?: any) => void;\r\n}\r\n\r\n/**\r\n * 팝업 내부 뷰 컴포넌트 타입\r\n */\r\nexport interface PopupViewProps {\r\n /**\r\n * 팝업정보\r\n */\r\n popup?: PopupItem;\r\n /** 팝업 이벤트 전달 프로퍼티 */\r\n popupEvent?: any;\r\n /** 팝업 닫기 이벤트 전달 프로퍼티 */\r\n onClose?: () => void;\r\n}\r\n\r\n// 팝업 스토어 생성\r\nexport const usePopupStore = create<PopupStore>((set, get) => ({\r\n popups: [],\r\n activePopupId: null,\r\n isLoading: false,\r\n error: null,\r\n\r\n // 팝업 열기\r\n openPopup: async (popupCode: string, data?: any, config?: PopupConfig) => {\r\n //console.log(\"팝업 열기 요청:\", { popupCode, data, config });\r\n set({ isLoading: true, error: null });\r\n\r\n try {\r\n //console.log(\"팝업 열기 시작:\", popupCode);\r\n\r\n // 개발 환경에서는 모의 데이터 사용\r\n let popupInfo: any = null;\r\n\r\n const response = await callService(getServiceCode(\"SRCH_POPU\"), {\r\n crprCd: getUserInfo()?.crprCd,\r\n popuCd: popupCode,\r\n });\r\n //console.log(\"팝업 정보 조회 결과:\", response);\r\n\r\n // 응답 구조 파싱: { mstr: {...}, dtls: [...] }\r\n popupInfo = response?.mstr;\r\n const buttonList = response?.dtls || [];\r\n\r\n //console.info(\"popupInfo:\", popupInfo);\r\n\r\n if (!popupInfo || !popupInfo.popuUrl) {\r\n const errorMsg = `팝업 정보를 찾을 수 없습니다: ${popupCode}`;\r\n console.error(errorMsg);\r\n throw new Error(errorMsg);\r\n }\r\n\r\n //console.log(\"파싱된 팝업 정보:\", popupInfo);\r\n //console.log(\"버튼 목록:\", buttonList);\r\n\r\n // 팝업 URL 경로 변환: 서버 경로 -> 클라이언트 경로\r\n const convertPopupUrl = (serverUrl: string): string => {\r\n // 서버에서 받은 경로: \"cm/CMAuthMstrP01\"\r\n // 클라이언트에서 사용할 경로: \"/src/pages/views/popup/cm/CMAuthMstrP01\"\r\n return `/src/pages/views/popup/${serverUrl}`;\r\n };\r\n\r\n const convertedPopupUrl = convertPopupUrl(popupInfo.popuUrl);\r\n //console.log(\"변환된 팝업 URL:\", convertedPopupUrl);\r\n\r\n // 팝업 아이템 생성\r\n const popupItem: PopupItem = {\r\n popupId: `popup_${Date.now()}_${Math.random()\r\n .toString(36)\r\n .substr(2, 9)}`,\r\n popupCode: popupCode,\r\n //config.title을 통해 팝업 제목 변경 가능\r\n popupTitle: config?.title || popupInfo.popuNm || \"팝업\",\r\n popupUrl: convertedPopupUrl,\r\n popupParams: data,\r\n width: popupInfo.popuWdth || 800,\r\n height: popupInfo.popuHght || 600,\r\n resizable: true,\r\n draggable: true,\r\n buttonList: buttonList, // 버튼 목록 추가\r\n config: config,\r\n };\r\n\r\n //console.log(\"생성된 팝업 아이템:\", popupItem);\r\n\r\n // 이미 같은 팝업이 열려있는지 확인\r\n const existingPopup = get().popups.find((p) => p.popupCode === popupCode);\r\n if (existingPopup) {\r\n //console.log(\"기존 팝업 업데이트:\", existingPopup.popupId);\r\n // 기존 팝업을 활성화하고 데이터 업데이트\r\n set({\r\n activePopupId: existingPopup.popupId,\r\n popups: get().popups.map((p) =>\r\n p.popupId === existingPopup.popupId ? { ...p, config: config } : p\r\n ),\r\n isLoading: false,\r\n });\r\n return;\r\n }\r\n\r\n // 새 팝업 추가\r\n //console.log(\"새 팝업 추가:\", popupItem.popupId);\r\n set((state) => ({\r\n popups: [...state.popups, popupItem],\r\n activePopupId: popupItem.popupId,\r\n isLoading: false,\r\n }));\r\n\r\n //console.log(\"팝업 열기 완료:\", popupItem);\r\n } catch (error) {\r\n // console.error(\"팝업 열기 실패:\", error);\r\n set({\r\n error: error instanceof Error ? error.message : \"팝업 열기 실패\",\r\n isLoading: false,\r\n });\r\n }\r\n },\r\n\r\n // 팝업 닫기\r\n closePopup: (popupId: string) => {\r\n const { popups, activePopupId } = get();\r\n const newPopups = popups.filter((p) => p.popupId !== popupId);\r\n\r\n // 닫힌 팝업이 현재 활성 팝업이었다면 다른 팝업을 활성화\r\n let newActivePopupId = activePopupId;\r\n if (activePopupId === popupId) {\r\n newActivePopupId =\r\n newPopups.length > 0 ? newPopups[newPopups.length - 1].popupId : null;\r\n }\r\n\r\n set({\r\n popups: newPopups,\r\n activePopupId: newActivePopupId,\r\n });\r\n },\r\n\r\n // 모든 팝업 닫기\r\n closeAllPopups: () => {\r\n set({\r\n popups: [],\r\n activePopupId: null,\r\n });\r\n },\r\n\r\n // 활성 팝업 설정\r\n setActivePopup: (popupId: string) => {\r\n set({ activePopupId: popupId });\r\n },\r\n\r\n // 팝업 설정 업데이트\r\n updatePopupConfig: (popupId: string, config: Partial<PopupConfig>) => {\r\n set((state) => ({\r\n popups: state.popups.map((p) =>\r\n p.popupId === popupId ? { ...p, config: { ...p.config, ...config } } : p\r\n ),\r\n }));\r\n },\r\n}));\r\n"],"names":["usePopupStore","create","set","get","popupCode","data","config","popupInfo","response","callService","getServiceCode","getUserInfo","buttonList","errorMsg","convertedPopupUrl","serverUrl","popupItem","existingPopup","p","state","error","popupId","popups","activePopupId","newPopups","newActivePopupId"],"mappings":"6EA2FaA,EAAgBC,EAAAA,OAAmB,CAACC,EAAKC,KAAS,CAC7D,OAAQ,CAAA,EACR,cAAe,KACf,UAAW,GACX,MAAO,KAGP,UAAW,MAAOC,EAAmBC,EAAYC,IAAyB,CAExEJ,EAAI,CAAE,UAAW,GAAM,MAAO,KAAM,EAEpC,GAAI,CAIF,IAAIK,EAAiB,KAErB,MAAMC,EAAW,MAAMC,EAAAA,YAAYC,EAAAA,eAAe,WAAW,EAAG,CAC9D,OAAQC,EAAAA,eAAe,OACvB,OAAQP,CAAA,CACT,EAIDG,EAAYC,GAAU,KACtB,MAAMI,EAAaJ,GAAU,MAAQ,CAAA,EAIrC,GAAI,CAACD,GAAa,CAACA,EAAU,QAAS,CACpC,MAAMM,EAAW,qBAAqBT,CAAS,GAC/C,cAAQ,MAAMS,CAAQ,EAChB,IAAI,MAAMA,CAAQ,CAC1B,CAYA,MAAMC,GANmBC,GAGhB,0BAA0BA,CAAS,IAGFR,EAAU,OAAO,EAIrDS,EAAuB,CAC3B,QAAS,SAAS,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAClC,SAAS,EAAE,EACX,OAAO,EAAG,CAAC,CAAC,GACf,UAAAZ,EAEA,WAAYE,GAAQ,OAASC,EAAU,QAAU,KACjD,SAAUO,EACV,YAAaT,EACb,MAAOE,EAAU,UAAY,IAC7B,OAAQA,EAAU,UAAY,IAC9B,UAAW,GACX,UAAW,GACX,WAAAK,EACA,OAAAN,CAAA,EAMIW,EAAgBd,IAAM,OAAO,KAAMe,GAAMA,EAAE,YAAcd,CAAS,EACxE,GAAIa,EAAe,CAGjBf,EAAI,CACF,cAAee,EAAc,QAC7B,OAAQd,IAAM,OAAO,IAAKe,GACxBA,EAAE,UAAYD,EAAc,QAAU,CAAE,GAAGC,EAAG,OAAAZ,GAAmBY,CAAA,EAEnE,UAAW,EAAA,CACZ,EACD,MACF,CAIAhB,EAAKiB,IAAW,CACd,OAAQ,CAAC,GAAGA,EAAM,OAAQH,CAAS,EACnC,cAAeA,EAAU,QACzB,UAAW,EAAA,EACX,CAGJ,OAASI,EAAO,CAEdlB,EAAI,CACF,MAAOkB,aAAiB,MAAQA,EAAM,QAAU,WAChD,UAAW,EAAA,CACZ,CACH,CACF,EAGA,WAAaC,GAAoB,CAC/B,KAAM,CAAE,OAAAC,EAAQ,cAAAC,CAAA,EAAkBpB,EAAA,EAC5BqB,EAAYF,EAAO,OAAQJ,GAAMA,EAAE,UAAYG,CAAO,EAG5D,IAAII,EAAmBF,EACnBA,IAAkBF,IACpBI,EACED,EAAU,OAAS,EAAIA,EAAUA,EAAU,OAAS,CAAC,EAAE,QAAU,MAGrEtB,EAAI,CACF,OAAQsB,EACR,cAAeC,CAAA,CAChB,CACH,EAGA,eAAgB,IAAM,CACpBvB,EAAI,CACF,OAAQ,CAAA,EACR,cAAe,IAAA,CAChB,CACH,EAGA,eAAiBmB,GAAoB,CACnCnB,EAAI,CAAE,cAAemB,EAAS,CAChC,EAGA,kBAAmB,CAACA,EAAiBf,IAAiC,CACpEJ,EAAKiB,IAAW,CACd,OAAQA,EAAM,OAAO,IAAK,GACxB,EAAE,UAAYE,EAAU,CAAE,GAAG,EAAG,OAAQ,CAAE,GAAG,EAAE,OAAQ,GAAGf,CAAA,GAAa,CAAA,CACzE,EACA,CACJ,CACF,EAAE"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const N=require("./apiUtils-
|
|
2
|
-
//# sourceMappingURL=sha256-
|
|
1
|
+
"use strict";const N=require("./apiUtils-D9Vn1gwZ.cjs"),R=require("./core-CM9MsJRf.cjs");function T(d,g){for(var c=0;c<g.length;c++){const t=g[c];if(typeof t!="string"&&!Array.isArray(t)){for(const n in t)if(n!=="default"&&!(n in d)){const h=Object.getOwnPropertyDescriptor(t,n);h&&Object.defineProperty(d,n,h.get?h:{enumerable:!0,get:()=>t[n]})}}}return Object.freeze(Object.defineProperty(d,Symbol.toStringTag,{value:"Module"}))}var A={exports:{}},K=A.exports,j;function L(){return j||(j=1,(function(d,g){(function(c,t){d.exports=t(R.requireCore())})(K,function(c){return(function(t){var n=c,h=n.lib,x=h.WordArray,H=h.Hasher,C=n.algo,q=[],w=[];(function(){function i(o){for(var f=t.sqrt(o),l=2;l<=f;l++)if(!(o%l))return!1;return!0}function v(o){return(o-(o|0))*4294967296|0}for(var r=2,e=0;e<64;)i(r)&&(e<8&&(q[e]=v(t.pow(r,1/2))),w[e]=v(t.pow(r,1/3)),e++),r++})();var u=[],B=C.SHA256=H.extend({_doReset:function(){this._hash=new x.init(q.slice(0))},_doProcessBlock:function(i,v){for(var r=this._hash.words,e=r[0],o=r[1],f=r[2],l=r[3],s=r[4],y=r[5],b=r[6],S=r[7],a=0;a<64;a++){if(a<16)u[a]=i[v+a]|0;else{var p=u[a-15],W=(p<<25|p>>>7)^(p<<14|p>>>18)^p>>>3,_=u[a-2],D=(_<<15|_>>>17)^(_<<13|_>>>19)^_>>>10;u[a]=W+u[a-7]+D+u[a-16]}var F=s&y^~s&b,$=e&o^e&f^o&f,k=(e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22),z=(s<<26|s>>>6)^(s<<21|s>>>11)^(s<<7|s>>>25),P=S+z+F+w[a]+u[a],E=k+$;S=b,b=y,y=s,s=l+P|0,l=f,f=o,o=e,e=P+E|0}r[0]=r[0]+e|0,r[1]=r[1]+o|0,r[2]=r[2]+f|0,r[3]=r[3]+l|0,r[4]=r[4]+s|0,r[5]=r[5]+y|0,r[6]=r[6]+b|0,r[7]=r[7]+S|0},_doFinalize:function(){var i=this._data,v=i.words,r=this._nDataBytes*8,e=i.sigBytes*8;return v[e>>>5]|=128<<24-e%32,v[(e+64>>>9<<4)+14]=t.floor(r/4294967296),v[(e+64>>>9<<4)+15]=r,i.sigBytes=v.length*4,this._process(),this._hash},clone:function(){var i=H.clone.call(this);return i._hash=this._hash.clone(),i}});n.SHA256=H._createHelper(B),n.HmacSHA256=H._createHmacHelper(B)})(Math),c.SHA256})})(A)),A.exports}var O=L();const U=N.getDefaultExportFromCjs(O),G=T({__proto__:null,default:U},[O]);exports.sha256=G;
|
|
2
|
+
//# sourceMappingURL=sha256-BnWVPP1K.cjs.map
|