@bwg-ui/core 1.1.4 → 1.1.6

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.
@@ -0,0 +1,266 @@
1
+ import { create as f } from "zustand";
2
+ import { V as c, am as d } from "./serviceConfig-lAlRNVIw.js";
3
+ import { i as v } from "./envUtils-C9Gf5aek.js";
4
+ const y = f((a, i) => ({
5
+ favorites: [],
6
+ isLoading: !1,
7
+ error: null,
8
+ // 즐겨찾기 메뉴 가져오기
9
+ fetchFavorites: async ({ crprCd: r, userId: t }) => {
10
+ console.log("즐겨찾기 메뉴 요청:", { crprCd: r, userId: t }), a({ isLoading: !0, error: null });
11
+ try {
12
+ const n = await c(d("AUTH_BMRK"), {
13
+ crprCd: r,
14
+ userId: t
15
+ });
16
+ let e = [];
17
+ if (n?.favorites && Array.isArray(n.favorites) ? e = n.favorites : Array.isArray(n) ? e = n : (console.warn("즐겨찾기 데이터가 비어있거나 예상과 다른 구조입니다."), e = []), console.log("즐겨찾기 메뉴 로드 완료:", e), v && e.length === 0) {
18
+ const o = [
19
+ {
20
+ crprCd: "100",
21
+ menuGbCd: "CMPRGRP",
22
+ menuPrntId: "FAV001",
23
+ menuId: "FAV_TEST001",
24
+ menuNm: "API 테스트",
25
+ scrnId: "TEST001",
26
+ menuNo: 1,
27
+ scrnPath: "/dev/ApiTest",
28
+ menuLvl: 3,
29
+ rootMenu: "FAV001",
30
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
31
+ userId: t
32
+ },
33
+ {
34
+ crprCd: "100",
35
+ menuGbCd: "CMPRGRP",
36
+ menuPrntId: "FAV001",
37
+ menuId: "FAV_TEST002",
38
+ menuNm: "프로젝트 개요",
39
+ scrnId: "DOCS001",
40
+ menuNo: 2,
41
+ scrnPath: "/docs/ProjectOverview",
42
+ menuLvl: 3,
43
+ rootMenu: "FAV001",
44
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
45
+ userId: t
46
+ }
47
+ ];
48
+ a({ favorites: o, isLoading: !1, error: null }), console.log("개발 모드: 테스트용 즐겨찾기 데이터 추가");
49
+ } else
50
+ a({ favorites: e, isLoading: !1, error: null });
51
+ } catch (n) {
52
+ console.error("즐겨찾기 메뉴 로드 실패:", n), a({
53
+ error: n instanceof Error ? n.message : "즐겨찾기 로드 실패",
54
+ isLoading: !1
55
+ });
56
+ }
57
+ },
58
+ // 즐겨찾기 추가
59
+ addFavorite: async (r, t) => {
60
+ const { favorites: n } = i();
61
+ if (n.some((e) => e.menuId === r.menuId)) {
62
+ console.log("이미 즐겨찾기에 추가된 메뉴입니다:", r.menuNm);
63
+ return;
64
+ }
65
+ try {
66
+ await c(d("AUTH_BMRK"), {
67
+ action: "add",
68
+ crprCd: r.crprCd,
69
+ userId: t,
70
+ menuId: r.menuId,
71
+ menuNm: r.menuNm,
72
+ scrnPath: r.scrnPath
73
+ });
74
+ const e = {
75
+ ...r,
76
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
77
+ userId: t
78
+ };
79
+ a({ favorites: [...n, e] }), console.log("즐겨찾기 추가 완료:", r.menuNm);
80
+ } catch (e) {
81
+ throw console.error("즐겨찾기 추가 실패:", e), e;
82
+ }
83
+ },
84
+ // 즐겨찾기 제거
85
+ removeFavorite: async (r, t) => {
86
+ const { favorites: n } = i();
87
+ try {
88
+ await c(d("AUTH_BMRK"), {
89
+ action: "remove",
90
+ crprCd: "100",
91
+ // 기본값
92
+ userId: t,
93
+ menuId: r
94
+ });
95
+ const e = n.filter((o) => o.menuId !== r);
96
+ a({ favorites: e }), console.log("즐겨찾기 제거 완료:", r);
97
+ } catch (e) {
98
+ throw console.error("즐겨찾기 제거 실패:", e), e;
99
+ }
100
+ },
101
+ // 즐겨찾기 여부 확인
102
+ isFavorite: (r) => {
103
+ const { favorites: t } = i();
104
+ return t.some((n) => n.menuId === r);
105
+ },
106
+ // 즐겨찾기 초기화
107
+ clearFavorites: () => {
108
+ a({ favorites: [], isLoading: !1, error: null });
109
+ }
110
+ })), m = (a) => {
111
+ if (!a || !Array.isArray(a) || a.length === 0)
112
+ return [];
113
+ const i = /* @__PURE__ */ new Map(), r = [];
114
+ a.forEach((o) => {
115
+ o && o.menuId && i.set(o.menuId, { ...o, children: [] });
116
+ }), a.forEach((o) => {
117
+ if (!o || !o.menuId) return;
118
+ const s = i.get(o.menuId);
119
+ if (s)
120
+ if (o.menuPrntId && o.menuPrntId !== "" && o.menuPrntId !== "-") {
121
+ const l = i.get(o.menuPrntId);
122
+ l && l.children.push(s);
123
+ } else
124
+ r.push(s);
125
+ });
126
+ const t = (o) => o.sort((s, l) => s.menuNo - l.menuNo).map((s) => ({
127
+ ...s,
128
+ children: s.children && s.children.length > 0 ? t(s.children) : void 0
129
+ })), n = t(r), e = n.filter((o) => o.menuId.startsWith("DEV"));
130
+ return e.length > 0 && console.log("DEV 최종 결과:", e), n;
131
+ }, P = f((a, i) => ({
132
+ menuList: [],
133
+ isLoading: !1,
134
+ error: null,
135
+ activeMenu: "1",
136
+ currentProgram: null,
137
+ tabs: [],
138
+ activeTabKey: null,
139
+ sidebarCollapsed: !1,
140
+ // 사이드바 접기/펼치기 상태
141
+ viewStates: {},
142
+ // 뷰별 상태 저장
143
+ _lastFetchParams: null,
144
+ // 마지막 fetch 파라미터 저장
145
+ // 메뉴 데이터 가져오기
146
+ fetchMenu: async ({ crprCd: r, userId: t, prntGbcd: n }) => {
147
+ const e = { crprCd: r, userId: t, prntGbcd: n ?? 1 }, { _lastFetchParams: o } = i();
148
+ if (o && o.crprCd === e.crprCd && o.userId === e.userId && o.prntGbcd === e.prntGbcd) {
149
+ console.log("동일한 파라미터로 중복 요청 방지:", e);
150
+ return;
151
+ }
152
+ console.log("메뉴 데이터 요청 시작:", e), a({ isLoading: !0, error: null, _lastFetchParams: e });
153
+ try {
154
+ const s = await c(
155
+ d("AUTH_MENU"),
156
+ e
157
+ );
158
+ let l = [];
159
+ s?.menus && Array.isArray(s.menus) ? l = s.menus : Array.isArray(s) ? l = s : (console.warn(
160
+ "서버 응답이 비어있거나 예상과 다른 구조입니다. 개발자 메뉴만 표시합니다."
161
+ ), l = []);
162
+ const u = m(l);
163
+ console.log("메뉴 데이터 로드 완료 (계층 구조):", u), a({
164
+ menuList: u,
165
+ isLoading: !1,
166
+ error: null
167
+ });
168
+ } catch (s) {
169
+ console.error("메뉴 데이터 로드 실패:", s), a({
170
+ error: s instanceof Error ? s.message : "메뉴 로드 실패",
171
+ isLoading: !1
172
+ });
173
+ }
174
+ },
175
+ // 활성 메뉴 설정
176
+ setActiveMenu: (r) => {
177
+ a({ activeMenu: r });
178
+ },
179
+ // 현재 프로그램 설정
180
+ setCurrentProgram: (r) => {
181
+ console.log("setCurrentProgram 호출:", r), a({ currentProgram: r });
182
+ },
183
+ // 탭 추가
184
+ addTab: (r) => {
185
+ const { tabs: t } = i();
186
+ if (t.find((e) => e.key === r.menuId))
187
+ a({ activeTabKey: r.menuId });
188
+ else {
189
+ const e = {
190
+ key: r.menuId,
191
+ label: r.menuNm,
192
+ menuItem: r,
193
+ closable: !0
194
+ };
195
+ a({
196
+ tabs: [...t, e],
197
+ activeTabKey: r.menuId
198
+ });
199
+ }
200
+ },
201
+ // 탭 제거
202
+ removeTab: (r) => {
203
+ const { tabs: t, activeTabKey: n } = i(), e = t.filter((s) => s.key !== r);
204
+ let o = n;
205
+ if (n === r) {
206
+ const s = t.findIndex((l) => l.key === r);
207
+ e.length > 0 ? o = e[Math.min(s, e.length - 1)]?.key || null : o = null;
208
+ }
209
+ a({
210
+ tabs: e,
211
+ activeTabKey: o,
212
+ currentProgram: o && e.find((s) => s.key === o)?.menuItem || null
213
+ });
214
+ },
215
+ // 활성 탭 설정
216
+ setActiveTab: (r) => {
217
+ const { tabs: t } = i(), n = t.find((e) => e.key === r);
218
+ n && a({
219
+ activeTabKey: r,
220
+ currentProgram: n.menuItem
221
+ });
222
+ },
223
+ // 탭 초기화
224
+ clearTabs: () => {
225
+ a({
226
+ tabs: [],
227
+ activeTabKey: null,
228
+ currentProgram: null
229
+ });
230
+ },
231
+ // 메뉴 데이터 초기화
232
+ clearMenu: () => {
233
+ a({
234
+ menuList: [],
235
+ error: null,
236
+ activeMenu: "1",
237
+ currentProgram: null,
238
+ tabs: [],
239
+ activeTabKey: null,
240
+ _lastFetchParams: null
241
+ // 마지막 fetch 파라미터도 초기화
242
+ });
243
+ },
244
+ // 사이드바 접기/펼치기 토글
245
+ toggleSidebar: () => {
246
+ const { sidebarCollapsed: r } = i();
247
+ a({ sidebarCollapsed: !r });
248
+ },
249
+ // 뷰 상태 업데이트
250
+ updateViewState: (r, t, n) => {
251
+ a((e) => ({
252
+ viewStates: {
253
+ ...e.viewStates,
254
+ [r]: {
255
+ ...e.viewStates[r],
256
+ [t]: n
257
+ }
258
+ }
259
+ })), console.log(`뷰 상태 업데이트: ${r}.${t}`, n);
260
+ }
261
+ }));
262
+ export {
263
+ y as a,
264
+ P as u
265
+ };
266
+ //# sourceMappingURL=menuStore-2zsN-PRt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"menuStore-CvQrMo35.js","sources":["../../src/stores/favoriteStore.ts","../../src/stores/menuStore.ts"],"sourcesContent":["import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\nimport type { MenuItem } from \"./menuStore\";\r\nimport { isLocal } from \"@/utils\";\r\n\r\n// 즐겨찾기 메뉴 타입 정의\r\nexport interface FavoriteMenuItem extends MenuItem {\r\n addedAt: string; // 즐겨찾기 추가 시간\r\n userId: string; // 사용자 ID\r\n}\r\n\r\n// 즐겨찾기 스토어 타입 정의\r\nexport interface FavoriteStore {\r\n favorites: FavoriteMenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: (params: { crprCd: string; userId: string }) => Promise<void>;\r\n\r\n // 즐겨찾기 추가\r\n addFavorite: (menuItem: MenuItem, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: (menuId: string, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => boolean;\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => void;\r\n}\r\n\r\n// 즐겨찾기 스토어 생성\r\nexport const useFavoriteStore = create<FavoriteStore>((set, get) => ({\r\n favorites: [],\r\n isLoading: false,\r\n error: null,\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: async ({ crprCd, userId }) => {\r\n console.log(\"즐겨찾기 메뉴 요청:\", { crprCd, userId });\r\n set({ isLoading: true, error: null });\r\n\r\n try {\r\n // 서버에서 즐겨찾기 메뉴 가져오기\r\n const data = await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n crprCd,\r\n userId,\r\n });\r\n\r\n let favoritesList: FavoriteMenuItem[] = [];\r\n\r\n if (data?.favorites && Array.isArray(data.favorites)) {\r\n favoritesList = data.favorites;\r\n } else if (Array.isArray(data)) {\r\n favoritesList = data;\r\n } else {\r\n console.warn(\"즐겨찾기 데이터가 비어있거나 예상과 다른 구조입니다.\");\r\n favoritesList = [];\r\n }\r\n\r\n console.log(\"즐겨찾기 메뉴 로드 완료:\", favoritesList);\r\n\r\n // 개발 모드에서 테스트용 즐겨찾기 데이터 추가\r\n if (isLocal && favoritesList.length === 0) {\r\n const testFavorites: FavoriteMenuItem[] = [\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST001\",\r\n menuNm: \"API 테스트\",\r\n scrnId: \"TEST001\",\r\n menuNo: 1,\r\n scrnPath: \"/dev/ApiTest\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST002\",\r\n menuNm: \"프로젝트 개요\",\r\n scrnId: \"DOCS001\",\r\n menuNo: 2,\r\n scrnPath: \"/docs/ProjectOverview\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n ];\r\n set({ favorites: testFavorites, isLoading: false, error: null });\r\n console.log(\"개발 모드: 테스트용 즐겨찾기 데이터 추가\");\r\n } else {\r\n set({ favorites: favoritesList, isLoading: false, error: null });\r\n }\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 addFavorite: async (menuItem: MenuItem, userId: string) => {\r\n const { favorites } = get();\r\n\r\n // 이미 즐겨찾기에 있는지 확인\r\n if (favorites.some((fav) => fav.menuId === menuItem.menuId)) {\r\n console.log(\"이미 즐겨찾기에 추가된 메뉴입니다:\", menuItem.menuNm);\r\n return;\r\n }\r\n\r\n try {\r\n // 서버에 즐겨찾기 추가 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"add\",\r\n crprCd: menuItem.crprCd,\r\n userId,\r\n menuId: menuItem.menuId,\r\n menuNm: menuItem.menuNm,\r\n scrnPath: menuItem.scrnPath,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const newFavorite: FavoriteMenuItem = {\r\n ...menuItem,\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n };\r\n\r\n set({ favorites: [...favorites, newFavorite] });\r\n console.log(\"즐겨찾기 추가 완료:\", menuItem.menuNm);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 추가 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: async (menuId: string, userId: string) => {\r\n const { favorites } = get();\r\n\r\n try {\r\n // 서버에 즐겨찾기 제거 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"remove\",\r\n crprCd: \"100\", // 기본값\r\n userId,\r\n menuId,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const updatedFavorites = favorites.filter((fav) => fav.menuId !== menuId);\r\n set({ favorites: updatedFavorites });\r\n console.log(\"즐겨찾기 제거 완료:\", menuId);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 제거 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => {\r\n const { favorites } = get();\r\n return favorites.some((fav) => fav.menuId === menuId);\r\n },\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => {\r\n set({ favorites: [], isLoading: false, error: null });\r\n },\r\n}));\r\n","import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\n\r\n// 메뉴 아이템 타입 정의 (서버 응답 구조 기반)\r\nexport interface MenuItem {\r\n crprCd: string; // 회사 코드\r\n menuGbCd: string; // 메뉴 구분 코드 (CMPRGRM: 메인, CMPRGRS: 서브, CMPRGRP: 프로그램)\r\n menuPrntId: string; // 부모 메뉴 ID\r\n menuId: string; // 메뉴 ID\r\n menuNm: string; // 메뉴명\r\n scrnId: string; // 화면 ID\r\n menuNo: number; // 메뉴 순서\r\n scrnPath: string; // 화면 경로\r\n menuLvl: number; // 메뉴 레벨 (1: 메인, 2~3: 서브, 2~4: 프로그램)\r\n rootMenu: string; // 루트 메뉴\r\n iconCd?: string; // 아이콘 코드\r\n children?: MenuItem[]; // 하위 메뉴 (클라이언트에서 구성)\r\n}\r\n\r\n// 탭 아이템 타입 정의\r\nexport interface TabItem {\r\n key: string; // 탭 고유 키 (menuId)\r\n label: string; // 탭 표시명 (menuNm)\r\n menuItem: MenuItem; // 메뉴 아이템 정보\r\n closable: boolean; // 닫기 가능 여부\r\n}\r\n\r\n// 개발자 메뉴 데이터 (개발 모드에서만 표시)\r\nconst getDeveloperMenuData = (): MenuItem[] => {\r\n const isDevelopment =\r\n (typeof process !== \"undefined\" &&\r\n process.env.NODE_ENV === \"development\") ||\r\n (typeof window !== \"undefined\" && window.location.hostname === \"localhost\");\r\n //console.log('isDevelopment:', isDevelopment);\r\n\r\n if (!isDevelopment) return [];\r\n\r\n return [\r\n // 1뎁스: 개발자 도구\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRM\",\r\n menuPrntId: \"-\",\r\n menuId: \"DEV001\",\r\n menuNm: \"개발자 도구\",\r\n scrnId: \"\",\r\n menuNo: 0,\r\n scrnPath: \"\",\r\n menuLvl: 1,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 2뎁스: 컴포넌트 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00101\",\r\n menuNm: \"컴포넌트 가이드\",\r\n scrnId: \"\",\r\n menuNo: 1,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgComponentGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010101\",\r\n menuNm: \"기본 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM01\",\r\n menuNo: 9991,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010102\",\r\n menuNm: \"응용 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM02\",\r\n menuNo: 9992,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM02\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n // 2뎁스: 개발자 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00102\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"\",\r\n menuNo: 2,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgDeveloperGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010201\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"BwgDeveloperGuideM01\",\r\n menuNo: 9993,\r\n scrnPath: \"/cm/guide/BwgDeveloperGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010202\",\r\n menuNm: \"React 가이드\",\r\n scrnId: \"BwgReactGuideM01\",\r\n menuNo: 9994,\r\n scrnPath: \"/cm/guide/BwgReactGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010203\",\r\n menuNm: \"연습공간\",\r\n scrnId: \"BwgPracticeM01\",\r\n menuNo: 9995,\r\n scrnPath: \"/cm/guide/BwgPracticeM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n ];\r\n};\r\n\r\ntype fetchMenuParams = {\r\n crprCd: string;\r\n userId: string;\r\n prntGbcd: number;\r\n};\r\n\r\n// 메뉴 스토어 타입 정의\r\n// 뷰 상태 타입 정의\r\nexport interface ViewState {\r\n [key: string]: any;\r\n}\r\n\r\nexport interface MenuStore {\r\n menuList: MenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n activeMenu: string;\r\n currentProgram: MenuItem | null; // 현재 선택된 프로그램\r\n tabs: TabItem[]; // 열린 탭 목록\r\n activeTabKey: string | null; // 현재 활성 탭 키\r\n _lastFetchParams: fetchMenuParams | null; // 마지막 fetch 파라미터 (내부용)\r\n sidebarCollapsed: boolean; // 사이드바 접기/펼치기 상태\r\n viewStates: Record<string, ViewState>; // 뷰별 상태 저장\r\n fetchMenu: (params: fetchMenuParams) => Promise<void>;\r\n setActiveMenu: (menuId: string) => void;\r\n setCurrentProgram: (program: MenuItem | null) => void;\r\n addTab: (menuItem: MenuItem) => void;\r\n removeTab: (tabKey: string) => void;\r\n setActiveTab: (tabKey: string) => void;\r\n clearTabs: () => void;\r\n clearMenu: () => void;\r\n toggleSidebar: () => void; // 사이드바 접기/펼치기 토글\r\n // 뷰 상태 관리 함수들\r\n updateViewState: (viewKey: string, key: string, value: any) => void;\r\n}\r\n\r\n// 계층적 메뉴 구성 함수\r\nconst buildMenuHierarchy = (flatMenuList: MenuItem[]): MenuItem[] => {\r\n if (\r\n !flatMenuList ||\r\n !Array.isArray(flatMenuList) ||\r\n flatMenuList.length === 0\r\n ) {\r\n return [];\r\n }\r\n\r\n const menuMap = new Map<string, MenuItem>();\r\n const rootMenus: MenuItem[] = [];\r\n\r\n // 모든 메뉴를 Map에 저장\r\n flatMenuList.forEach((menu) => {\r\n if (menu && menu.menuId) {\r\n menuMap.set(menu.menuId, { ...menu, children: [] });\r\n }\r\n });\r\n\r\n // 계층 구조 구성\r\n flatMenuList.forEach((menu) => {\r\n if (!menu || !menu.menuId) return;\r\n\r\n const menuWithChildren = menuMap.get(menu.menuId);\r\n if (!menuWithChildren) return;\r\n\r\n // 개발자 메뉴만 로그 출력\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`DEV 메뉴 처리: ${menu.menuId} (${menu.menuNm}), 부모: ${menu.menuPrntId}`)\r\n //}\r\n\r\n if (menu.menuPrntId && menu.menuPrntId !== \"\" && menu.menuPrntId !== \"-\") {\r\n // 부모 메뉴가 있는 경우\r\n const parentMenu = menuMap.get(menu.menuPrntId);\r\n if (parentMenu) {\r\n parentMenu.children!.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 자식 메뉴 추가: ${menu.menuId} → ${menu.menuPrntId}`)\r\n //}\r\n } else {\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.warn(`❌ DEV 부모 메뉴를 찾을 수 없음: ${menu.menuPrntId}`)\r\n //}\r\n }\r\n } else {\r\n // 루트 메뉴인 경우 (부모가 없거나 '-'인 경우)\r\n rootMenus.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 루트 메뉴 추가: ${menu.menuId} (${menu.menuNm})`)\r\n //}\r\n }\r\n });\r\n\r\n // 개발자 메뉴만 확인\r\n //const devRootMenus = rootMenus.filter(m => m.menuId.startsWith('DEV'))\r\n //if (devRootMenus.length > 0) {\r\n //console.log('DEV 루트 메뉴들:', devRootMenus.map(m => `${m.menuId} (${m.menuNm})`))\r\n //} else {\r\n //console.warn('❌ DEV 루트 메뉴가 없습니다!')\r\n //}\r\n\r\n // menuNo로 정렬\r\n const sortMenus = (menus: MenuItem[]): MenuItem[] => {\r\n return menus\r\n .sort((a, b) => a.menuNo - b.menuNo)\r\n .map((menu) => ({\r\n ...menu,\r\n children:\r\n menu.children && menu.children.length > 0\r\n ? sortMenus(menu.children)\r\n : undefined,\r\n }));\r\n };\r\n\r\n const result = sortMenus(rootMenus);\r\n\r\n // 개발자 메뉴만 최종 결과 확인\r\n const devResult = result.filter((m) => m.menuId.startsWith(\"DEV\"));\r\n if (devResult.length > 0) {\r\n console.log(\"DEV 최종 결과:\", devResult);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n// 메뉴 스토어 생성\r\nexport const useMenuStore = create<MenuStore>((set, get) => ({\r\n menuList: [],\r\n isLoading: false,\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n sidebarCollapsed: false, // 사이드바 접기/펼치기 상태\r\n viewStates: {}, // 뷰별 상태 저장\r\n _lastFetchParams: null as fetchMenuParams | null, // 마지막 fetch 파라미터 저장\r\n\r\n // 메뉴 데이터 가져오기\r\n fetchMenu: async ({ crprCd, userId, prntGbcd }: fetchMenuParams) => {\r\n const currentParams = { crprCd, userId, prntGbcd: prntGbcd ?? 1 };\r\n const { _lastFetchParams } = get();\r\n\r\n // 동일한 파라미터로 중복 요청 방지\r\n if (\r\n _lastFetchParams &&\r\n _lastFetchParams.crprCd === currentParams.crprCd &&\r\n _lastFetchParams.userId === currentParams.userId &&\r\n _lastFetchParams.prntGbcd === currentParams.prntGbcd\r\n ) {\r\n console.log(\"동일한 파라미터로 중복 요청 방지:\", currentParams);\r\n return;\r\n }\r\n\r\n console.log(\"메뉴 데이터 요청 시작:\", currentParams);\r\n set({ isLoading: true, error: null, _lastFetchParams: currentParams });\r\n\r\n try {\r\n // 실제 서버에서 메뉴 데이터 가져오기\r\n const data = await callService(\r\n getServiceCode(\"AUTH_MENU\"),\r\n currentParams\r\n );\r\n\r\n // console.log('서버 응답 전체 데이터:', data)\r\n // console.log('서버 응답 타입:', typeof data)\r\n // console.log('data.menuList 존재 여부:', !!data?.menuList)\r\n // console.log('data.menuList 타입:', typeof data?.menuList)\r\n // console.log('data.menuList 길이:', data?.menuList?.length)\r\n\r\n // 서버 응답 구조 확인 및 데이터 추출\r\n let flatMenuList: MenuItem[] = [];\r\n\r\n if (data?.menus && Array.isArray(data.menus)) {\r\n flatMenuList = data.menus;\r\n } else if (Array.isArray(data)) {\r\n // 응답이 바로 배열인 경우\r\n flatMenuList = data;\r\n } else {\r\n console.warn(\r\n \"서버 응답이 비어있거나 예상과 다른 구조입니다. 개발자 메뉴만 표시합니다.\"\r\n );\r\n flatMenuList = [];\r\n }\r\n\r\n // 개발자 메뉴 추가 (개발 모드에서만)\r\n const developerMenus = getDeveloperMenuData();\r\n //console.log('개발자 메뉴 데이터:', developerMenus)\r\n if (developerMenus.length > 0) {\r\n flatMenuList = [...developerMenus, ...flatMenuList];\r\n //console.log('개발자 메뉴 추가 후 flatMenuList 길이:', flatMenuList.length)\r\n }\r\n\r\n // console.log('추출된 flatMenuList:', flatMenuList)\r\n\r\n const hierarchicalMenuList = buildMenuHierarchy(flatMenuList);\r\n\r\n console.log(\"메뉴 데이터 로드 완료 (계층 구조):\", hierarchicalMenuList);\r\n\r\n set({\r\n menuList: hierarchicalMenuList,\r\n isLoading: false,\r\n error: null,\r\n });\r\n } catch (error) {\r\n console.error(\"메뉴 데이터 로드 실패:\", error);\r\n\r\n // 서버 오류 시에도 개발자 메뉴는 표시\r\n const developerMenus = getDeveloperMenuData();\r\n if (developerMenus.length > 0) {\r\n console.log(\"서버 오류로 인해 개발자 메뉴만 표시합니다.\");\r\n const hierarchicalMenuList = buildMenuHierarchy(developerMenus);\r\n set({\r\n menuList: hierarchicalMenuList,\r\n isLoading: false,\r\n error: null,\r\n });\r\n } else {\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 // 활성 메뉴 설정\r\n setActiveMenu: (menuId: string) => {\r\n set({ activeMenu: menuId });\r\n },\r\n\r\n // 현재 프로그램 설정\r\n setCurrentProgram: (program: MenuItem | null) => {\r\n console.log(\"setCurrentProgram 호출:\", program);\r\n set({ currentProgram: program });\r\n },\r\n\r\n // 탭 추가\r\n addTab: (menuItem: MenuItem) => {\r\n const { tabs } = get();\r\n const existingTab = tabs.find((tab) => tab.key === menuItem.menuId);\r\n\r\n if (!existingTab) {\r\n const newTab: TabItem = {\r\n key: menuItem.menuId,\r\n label: menuItem.menuNm,\r\n menuItem,\r\n closable: true,\r\n };\r\n set({\r\n tabs: [...tabs, newTab],\r\n activeTabKey: menuItem.menuId,\r\n });\r\n } else {\r\n // 이미 존재하는 탭이면 활성화만\r\n set({ activeTabKey: menuItem.menuId });\r\n }\r\n },\r\n\r\n // 탭 제거\r\n removeTab: (tabKey: string) => {\r\n const { tabs, activeTabKey } = get();\r\n const newTabs = tabs.filter((tab) => tab.key !== tabKey);\r\n\r\n // 제거된 탭이 현재 활성 탭이었다면 다른 탭을 활성화\r\n let newActiveTabKey = activeTabKey;\r\n if (activeTabKey === tabKey) {\r\n const currentIndex = tabs.findIndex((tab) => tab.key === tabKey);\r\n if (newTabs.length > 0) {\r\n // 제거된 탭 다음 탭을 활성화, 마지막 탭이었다면 이전 탭을 활성화\r\n newActiveTabKey =\r\n newTabs[Math.min(currentIndex, newTabs.length - 1)]?.key || null;\r\n } else {\r\n newActiveTabKey = null;\r\n }\r\n }\r\n\r\n set({\r\n tabs: newTabs,\r\n activeTabKey: newActiveTabKey,\r\n currentProgram: newActiveTabKey\r\n ? newTabs.find((tab) => tab.key === newActiveTabKey)?.menuItem || null\r\n : null,\r\n });\r\n },\r\n\r\n // 활성 탭 설정\r\n setActiveTab: (tabKey: string) => {\r\n const { tabs } = get();\r\n const targetTab = tabs.find((tab) => tab.key === tabKey);\r\n if (targetTab) {\r\n set({\r\n activeTabKey: tabKey,\r\n currentProgram: targetTab.menuItem,\r\n });\r\n }\r\n },\r\n\r\n // 탭 초기화\r\n clearTabs: () => {\r\n set({\r\n tabs: [],\r\n activeTabKey: null,\r\n currentProgram: null,\r\n });\r\n },\r\n\r\n // 메뉴 데이터 초기화\r\n clearMenu: () => {\r\n set({\r\n menuList: [],\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n _lastFetchParams: null, // 마지막 fetch 파라미터도 초기화\r\n });\r\n },\r\n\r\n // 사이드바 접기/펼치기 토글\r\n toggleSidebar: () => {\r\n const { sidebarCollapsed } = get();\r\n set({ sidebarCollapsed: !sidebarCollapsed });\r\n },\r\n\r\n // 뷰 상태 업데이트\r\n updateViewState: (viewKey: string, key: string, value: any) => {\r\n set((prev) => ({\r\n viewStates: {\r\n ...prev.viewStates,\r\n [viewKey]: {\r\n ...prev.viewStates[viewKey],\r\n [key]: value,\r\n },\r\n },\r\n }));\r\n console.log(`뷰 상태 업데이트: ${viewKey}.${key}`, value);\r\n },\r\n}));\r\n"],"names":["useFavoriteStore","create","set","get","crprCd","userId","data","callService","getServiceCode","favoritesList","isLocal","testFavorites","error","menuItem","favorites","fav","newFavorite","menuId","updatedFavorites","getDeveloperMenuData","buildMenuHierarchy","flatMenuList","menuMap","rootMenus","menu","menuWithChildren","parentMenu","sortMenus","menus","a","b","result","devResult","m","useMenuStore","prntGbcd","currentParams","_lastFetchParams","developerMenus","hierarchicalMenuList","program","tabs","tab","newTab","tabKey","activeTabKey","newTabs","newActiveTabKey","currentIndex","targetTab","sidebarCollapsed","viewKey","key","value","prev"],"mappings":"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"}
1
+ {"version":3,"file":"menuStore-2zsN-PRt.js","sources":["../../src/stores/favoriteStore.ts","../../src/stores/menuStore.ts"],"sourcesContent":["import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\nimport type { MenuItem } from \"./menuStore\";\r\nimport { isLocal } from \"@/utils\";\r\n\r\n// 즐겨찾기 메뉴 타입 정의\r\nexport interface FavoriteMenuItem extends MenuItem {\r\n addedAt: string; // 즐겨찾기 추가 시간\r\n userId: string; // 사용자 ID\r\n}\r\n\r\n// 즐겨찾기 스토어 타입 정의\r\nexport interface FavoriteStore {\r\n favorites: FavoriteMenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: (params: { crprCd: string; userId: string }) => Promise<void>;\r\n\r\n // 즐겨찾기 추가\r\n addFavorite: (menuItem: MenuItem, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: (menuId: string, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => boolean;\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => void;\r\n}\r\n\r\n// 즐겨찾기 스토어 생성\r\nexport const useFavoriteStore = create<FavoriteStore>((set, get) => ({\r\n favorites: [],\r\n isLoading: false,\r\n error: null,\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: async ({ crprCd, userId }) => {\r\n console.log(\"즐겨찾기 메뉴 요청:\", { crprCd, userId });\r\n set({ isLoading: true, error: null });\r\n\r\n try {\r\n // 서버에서 즐겨찾기 메뉴 가져오기\r\n const data = await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n crprCd,\r\n userId,\r\n });\r\n\r\n let favoritesList: FavoriteMenuItem[] = [];\r\n\r\n if (data?.favorites && Array.isArray(data.favorites)) {\r\n favoritesList = data.favorites;\r\n } else if (Array.isArray(data)) {\r\n favoritesList = data;\r\n } else {\r\n console.warn(\"즐겨찾기 데이터가 비어있거나 예상과 다른 구조입니다.\");\r\n favoritesList = [];\r\n }\r\n\r\n console.log(\"즐겨찾기 메뉴 로드 완료:\", favoritesList);\r\n\r\n // 개발 모드에서 테스트용 즐겨찾기 데이터 추가\r\n if (isLocal && favoritesList.length === 0) {\r\n const testFavorites: FavoriteMenuItem[] = [\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST001\",\r\n menuNm: \"API 테스트\",\r\n scrnId: \"TEST001\",\r\n menuNo: 1,\r\n scrnPath: \"/dev/ApiTest\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST002\",\r\n menuNm: \"프로젝트 개요\",\r\n scrnId: \"DOCS001\",\r\n menuNo: 2,\r\n scrnPath: \"/docs/ProjectOverview\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n ];\r\n set({ favorites: testFavorites, isLoading: false, error: null });\r\n console.log(\"개발 모드: 테스트용 즐겨찾기 데이터 추가\");\r\n } else {\r\n set({ favorites: favoritesList, isLoading: false, error: null });\r\n }\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 addFavorite: async (menuItem: MenuItem, userId: string) => {\r\n const { favorites } = get();\r\n\r\n // 이미 즐겨찾기에 있는지 확인\r\n if (favorites.some((fav) => fav.menuId === menuItem.menuId)) {\r\n console.log(\"이미 즐겨찾기에 추가된 메뉴입니다:\", menuItem.menuNm);\r\n return;\r\n }\r\n\r\n try {\r\n // 서버에 즐겨찾기 추가 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"add\",\r\n crprCd: menuItem.crprCd,\r\n userId,\r\n menuId: menuItem.menuId,\r\n menuNm: menuItem.menuNm,\r\n scrnPath: menuItem.scrnPath,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const newFavorite: FavoriteMenuItem = {\r\n ...menuItem,\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n };\r\n\r\n set({ favorites: [...favorites, newFavorite] });\r\n console.log(\"즐겨찾기 추가 완료:\", menuItem.menuNm);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 추가 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: async (menuId: string, userId: string) => {\r\n const { favorites } = get();\r\n\r\n try {\r\n // 서버에 즐겨찾기 제거 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"remove\",\r\n crprCd: \"100\", // 기본값\r\n userId,\r\n menuId,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const updatedFavorites = favorites.filter((fav) => fav.menuId !== menuId);\r\n set({ favorites: updatedFavorites });\r\n console.log(\"즐겨찾기 제거 완료:\", menuId);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 제거 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => {\r\n const { favorites } = get();\r\n return favorites.some((fav) => fav.menuId === menuId);\r\n },\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => {\r\n set({ favorites: [], isLoading: false, error: null });\r\n },\r\n}));\r\n","import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\n\r\n// 메뉴 아이템 타입 정의 (서버 응답 구조 기반)\r\nexport interface MenuItem {\r\n crprCd: string; // 회사 코드\r\n menuGbCd: string; // 메뉴 구분 코드 (CMPRGRM: 메인, CMPRGRS: 서브, CMPRGRP: 프로그램)\r\n menuPrntId: string; // 부모 메뉴 ID\r\n menuId: string; // 메뉴 ID\r\n menuNm: string; // 메뉴명\r\n scrnId: string; // 화면 ID\r\n menuNo: number; // 메뉴 순서\r\n scrnPath: string; // 화면 경로\r\n menuLvl: number; // 메뉴 레벨 (1: 메인, 2~3: 서브, 2~4: 프로그램)\r\n rootMenu: string; // 루트 메뉴\r\n iconCd?: string; // 아이콘 코드\r\n children?: MenuItem[]; // 하위 메뉴 (클라이언트에서 구성)\r\n}\r\n\r\n// 탭 아이템 타입 정의\r\nexport interface TabItem {\r\n key: string; // 탭 고유 키 (menuId)\r\n label: string; // 탭 표시명 (menuNm)\r\n menuItem: MenuItem; // 메뉴 아이템 정보\r\n closable: boolean; // 닫기 가능 여부\r\n}\r\n\r\n// 개발자 메뉴 데이터 (개발 모드에서만 표시)\r\nconst getDeveloperMenuData = (): MenuItem[] => {\r\n const isDevelopment =\r\n (typeof process !== \"undefined\" &&\r\n process.env.NODE_ENV === \"development\") ||\r\n (typeof window !== \"undefined\" && window.location.hostname === \"localhost\");\r\n //console.log('isDevelopment:', isDevelopment);\r\n\r\n if (!isDevelopment) return [];\r\n\r\n return [\r\n // 1뎁스: 개발자 도구\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRM\",\r\n menuPrntId: \"-\",\r\n menuId: \"DEV001\",\r\n menuNm: \"개발자 도구\",\r\n scrnId: \"\",\r\n menuNo: 0,\r\n scrnPath: \"\",\r\n menuLvl: 1,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 2뎁스: 컴포넌트 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00101\",\r\n menuNm: \"컴포넌트 가이드\",\r\n scrnId: \"\",\r\n menuNo: 1,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgComponentGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010101\",\r\n menuNm: \"기본 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM01\",\r\n menuNo: 9991,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010102\",\r\n menuNm: \"응용 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM02\",\r\n menuNo: 9992,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM02\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n // 2뎁스: 개발자 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00102\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"\",\r\n menuNo: 2,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgDeveloperGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010201\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"BwgDeveloperGuideM01\",\r\n menuNo: 9993,\r\n scrnPath: \"/cm/guide/BwgDeveloperGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010202\",\r\n menuNm: \"React 가이드\",\r\n scrnId: \"BwgReactGuideM01\",\r\n menuNo: 9994,\r\n scrnPath: \"/cm/guide/BwgReactGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010203\",\r\n menuNm: \"연습공간\",\r\n scrnId: \"BwgPracticeM01\",\r\n menuNo: 9995,\r\n scrnPath: \"/cm/guide/BwgPracticeM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n ];\r\n};\r\n\r\ntype fetchMenuParams = {\r\n crprCd: string;\r\n userId: string;\r\n prntGbcd: number;\r\n};\r\n\r\n// 메뉴 스토어 타입 정의\r\n// 뷰 상태 타입 정의\r\nexport interface ViewState {\r\n [key: string]: any;\r\n}\r\n\r\nexport interface MenuStore {\r\n menuList: MenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n activeMenu: string;\r\n currentProgram: MenuItem | null; // 현재 선택된 프로그램\r\n tabs: TabItem[]; // 열린 탭 목록\r\n activeTabKey: string | null; // 현재 활성 탭 키\r\n _lastFetchParams: fetchMenuParams | null; // 마지막 fetch 파라미터 (내부용)\r\n sidebarCollapsed: boolean; // 사이드바 접기/펼치기 상태\r\n viewStates: Record<string, ViewState>; // 뷰별 상태 저장\r\n fetchMenu: (params: fetchMenuParams) => Promise<void>;\r\n setActiveMenu: (menuId: string) => void;\r\n setCurrentProgram: (program: MenuItem | null) => void;\r\n addTab: (menuItem: MenuItem) => void;\r\n removeTab: (tabKey: string) => void;\r\n setActiveTab: (tabKey: string) => void;\r\n clearTabs: () => void;\r\n clearMenu: () => void;\r\n toggleSidebar: () => void; // 사이드바 접기/펼치기 토글\r\n // 뷰 상태 관리 함수들\r\n updateViewState: (viewKey: string, key: string, value: any) => void;\r\n}\r\n\r\n// 계층적 메뉴 구성 함수\r\nconst buildMenuHierarchy = (flatMenuList: MenuItem[]): MenuItem[] => {\r\n if (\r\n !flatMenuList ||\r\n !Array.isArray(flatMenuList) ||\r\n flatMenuList.length === 0\r\n ) {\r\n return [];\r\n }\r\n\r\n const menuMap = new Map<string, MenuItem>();\r\n const rootMenus: MenuItem[] = [];\r\n\r\n // 모든 메뉴를 Map에 저장\r\n flatMenuList.forEach((menu) => {\r\n if (menu && menu.menuId) {\r\n menuMap.set(menu.menuId, { ...menu, children: [] });\r\n }\r\n });\r\n\r\n // 계층 구조 구성\r\n flatMenuList.forEach((menu) => {\r\n if (!menu || !menu.menuId) return;\r\n\r\n const menuWithChildren = menuMap.get(menu.menuId);\r\n if (!menuWithChildren) return;\r\n\r\n // 개발자 메뉴만 로그 출력\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`DEV 메뉴 처리: ${menu.menuId} (${menu.menuNm}), 부모: ${menu.menuPrntId}`)\r\n //}\r\n\r\n if (menu.menuPrntId && menu.menuPrntId !== \"\" && menu.menuPrntId !== \"-\") {\r\n // 부모 메뉴가 있는 경우\r\n const parentMenu = menuMap.get(menu.menuPrntId);\r\n if (parentMenu) {\r\n parentMenu.children!.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 자식 메뉴 추가: ${menu.menuId} → ${menu.menuPrntId}`)\r\n //}\r\n } else {\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.warn(`❌ DEV 부모 메뉴를 찾을 수 없음: ${menu.menuPrntId}`)\r\n //}\r\n }\r\n } else {\r\n // 루트 메뉴인 경우 (부모가 없거나 '-'인 경우)\r\n rootMenus.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 루트 메뉴 추가: ${menu.menuId} (${menu.menuNm})`)\r\n //}\r\n }\r\n });\r\n\r\n // 개발자 메뉴만 확인\r\n //const devRootMenus = rootMenus.filter(m => m.menuId.startsWith('DEV'))\r\n //if (devRootMenus.length > 0) {\r\n //console.log('DEV 루트 메뉴들:', devRootMenus.map(m => `${m.menuId} (${m.menuNm})`))\r\n //} else {\r\n //console.warn('❌ DEV 루트 메뉴가 없습니다!')\r\n //}\r\n\r\n // menuNo로 정렬\r\n const sortMenus = (menus: MenuItem[]): MenuItem[] => {\r\n return menus\r\n .sort((a, b) => a.menuNo - b.menuNo)\r\n .map((menu) => ({\r\n ...menu,\r\n children:\r\n menu.children && menu.children.length > 0\r\n ? sortMenus(menu.children)\r\n : undefined,\r\n }));\r\n };\r\n\r\n const result = sortMenus(rootMenus);\r\n\r\n // 개발자 메뉴만 최종 결과 확인\r\n const devResult = result.filter((m) => m.menuId.startsWith(\"DEV\"));\r\n if (devResult.length > 0) {\r\n console.log(\"DEV 최종 결과:\", devResult);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n// 메뉴 스토어 생성\r\nexport const useMenuStore = create<MenuStore>((set, get) => ({\r\n menuList: [],\r\n isLoading: false,\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n sidebarCollapsed: false, // 사이드바 접기/펼치기 상태\r\n viewStates: {}, // 뷰별 상태 저장\r\n _lastFetchParams: null as fetchMenuParams | null, // 마지막 fetch 파라미터 저장\r\n\r\n // 메뉴 데이터 가져오기\r\n fetchMenu: async ({ crprCd, userId, prntGbcd }: fetchMenuParams) => {\r\n const currentParams = { crprCd, userId, prntGbcd: prntGbcd ?? 1 };\r\n const { _lastFetchParams } = get();\r\n\r\n // 동일한 파라미터로 중복 요청 방지\r\n if (\r\n _lastFetchParams &&\r\n _lastFetchParams.crprCd === currentParams.crprCd &&\r\n _lastFetchParams.userId === currentParams.userId &&\r\n _lastFetchParams.prntGbcd === currentParams.prntGbcd\r\n ) {\r\n console.log(\"동일한 파라미터로 중복 요청 방지:\", currentParams);\r\n return;\r\n }\r\n\r\n console.log(\"메뉴 데이터 요청 시작:\", currentParams);\r\n set({ isLoading: true, error: null, _lastFetchParams: currentParams });\r\n\r\n try {\r\n // 실제 서버에서 메뉴 데이터 가져오기\r\n const data = await callService(\r\n getServiceCode(\"AUTH_MENU\"),\r\n currentParams\r\n );\r\n\r\n // console.log('서버 응답 전체 데이터:', data)\r\n // console.log('서버 응답 타입:', typeof data)\r\n // console.log('data.menuList 존재 여부:', !!data?.menuList)\r\n // console.log('data.menuList 타입:', typeof data?.menuList)\r\n // console.log('data.menuList 길이:', data?.menuList?.length)\r\n\r\n // 서버 응답 구조 확인 및 데이터 추출\r\n let flatMenuList: MenuItem[] = [];\r\n\r\n if (data?.menus && Array.isArray(data.menus)) {\r\n flatMenuList = data.menus;\r\n } else if (Array.isArray(data)) {\r\n // 응답이 바로 배열인 경우\r\n flatMenuList = data;\r\n } else {\r\n console.warn(\r\n \"서버 응답이 비어있거나 예상과 다른 구조입니다. 개발자 메뉴만 표시합니다.\"\r\n );\r\n flatMenuList = [];\r\n }\r\n\r\n // 개발자 메뉴 추가 (개발 모드에서만)\r\n // const developerMenus = getDeveloperMenuData();\r\n // if (developerMenus.length > 0) {\r\n // flatMenuList = [...developerMenus, ...flatMenuList];\r\n // }\r\n\r\n // console.log('추출된 flatMenuList:', flatMenuList)\r\n\r\n const hierarchicalMenuList = buildMenuHierarchy(flatMenuList);\r\n\r\n console.log(\"메뉴 데이터 로드 완료 (계층 구조):\", hierarchicalMenuList);\r\n\r\n set({\r\n menuList: hierarchicalMenuList,\r\n isLoading: false,\r\n error: null,\r\n });\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 setActiveMenu: (menuId: string) => {\r\n set({ activeMenu: menuId });\r\n },\r\n\r\n // 현재 프로그램 설정\r\n setCurrentProgram: (program: MenuItem | null) => {\r\n console.log(\"setCurrentProgram 호출:\", program);\r\n set({ currentProgram: program });\r\n },\r\n\r\n // 탭 추가\r\n addTab: (menuItem: MenuItem) => {\r\n const { tabs } = get();\r\n const existingTab = tabs.find((tab) => tab.key === menuItem.menuId);\r\n\r\n if (!existingTab) {\r\n const newTab: TabItem = {\r\n key: menuItem.menuId,\r\n label: menuItem.menuNm,\r\n menuItem,\r\n closable: true,\r\n };\r\n set({\r\n tabs: [...tabs, newTab],\r\n activeTabKey: menuItem.menuId,\r\n });\r\n } else {\r\n // 이미 존재하는 탭이면 활성화만\r\n set({ activeTabKey: menuItem.menuId });\r\n }\r\n },\r\n\r\n // 탭 제거\r\n removeTab: (tabKey: string) => {\r\n const { tabs, activeTabKey } = get();\r\n const newTabs = tabs.filter((tab) => tab.key !== tabKey);\r\n\r\n // 제거된 탭이 현재 활성 탭이었다면 다른 탭을 활성화\r\n let newActiveTabKey = activeTabKey;\r\n if (activeTabKey === tabKey) {\r\n const currentIndex = tabs.findIndex((tab) => tab.key === tabKey);\r\n if (newTabs.length > 0) {\r\n // 제거된 탭 다음 탭을 활성화, 마지막 탭이었다면 이전 탭을 활성화\r\n newActiveTabKey =\r\n newTabs[Math.min(currentIndex, newTabs.length - 1)]?.key || null;\r\n } else {\r\n newActiveTabKey = null;\r\n }\r\n }\r\n\r\n set({\r\n tabs: newTabs,\r\n activeTabKey: newActiveTabKey,\r\n currentProgram: newActiveTabKey\r\n ? newTabs.find((tab) => tab.key === newActiveTabKey)?.menuItem || null\r\n : null,\r\n });\r\n },\r\n\r\n // 활성 탭 설정\r\n setActiveTab: (tabKey: string) => {\r\n const { tabs } = get();\r\n const targetTab = tabs.find((tab) => tab.key === tabKey);\r\n if (targetTab) {\r\n set({\r\n activeTabKey: tabKey,\r\n currentProgram: targetTab.menuItem,\r\n });\r\n }\r\n },\r\n\r\n // 탭 초기화\r\n clearTabs: () => {\r\n set({\r\n tabs: [],\r\n activeTabKey: null,\r\n currentProgram: null,\r\n });\r\n },\r\n\r\n // 메뉴 데이터 초기화\r\n clearMenu: () => {\r\n set({\r\n menuList: [],\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n _lastFetchParams: null, // 마지막 fetch 파라미터도 초기화\r\n });\r\n },\r\n\r\n // 사이드바 접기/펼치기 토글\r\n toggleSidebar: () => {\r\n const { sidebarCollapsed } = get();\r\n set({ sidebarCollapsed: !sidebarCollapsed });\r\n },\r\n\r\n // 뷰 상태 업데이트\r\n updateViewState: (viewKey: string, key: string, value: any) => {\r\n set((prev) => ({\r\n viewStates: {\r\n ...prev.viewStates,\r\n [viewKey]: {\r\n ...prev.viewStates[viewKey],\r\n [key]: value,\r\n },\r\n },\r\n }));\r\n console.log(`뷰 상태 업데이트: ${viewKey}.${key}`, value);\r\n },\r\n}));\r\n"],"names":["useFavoriteStore","create","set","get","crprCd","userId","data","callService","getServiceCode","favoritesList","isLocal","testFavorites","error","menuItem","favorites","fav","newFavorite","menuId","updatedFavorites","buildMenuHierarchy","flatMenuList","menuMap","rootMenus","menu","menuWithChildren","parentMenu","sortMenus","menus","a","b","result","devResult","m","useMenuStore","prntGbcd","currentParams","_lastFetchParams","hierarchicalMenuList","program","tabs","tab","newTab","tabKey","activeTabKey","newTabs","newActiveTabKey","currentIndex","targetTab","sidebarCollapsed","viewKey","key","value","prev"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";const u=require("zustand"),l=require("./serviceConfig-Cc8jfw_Y.cjs"),v=require("./envUtils-CduTHoHu.cjs"),f=u.create((a,i)=>({favorites:[],isLoading:!1,error:null,fetchFavorites:async({crprCd:e,userId:t})=>{console.log("즐겨찾기 메뉴 요청:",{crprCd:e,userId:t}),a({isLoading:!0,error:null});try{const n=await l.callService(l.getServiceCode("AUTH_BMRK"),{crprCd:e,userId:t});let r=[];if(n?.favorites&&Array.isArray(n.favorites)?r=n.favorites:Array.isArray(n)?r=n:(console.warn("즐겨찾기 데이터가 비어있거나 예상과 다른 구조입니다."),r=[]),console.log("즐겨찾기 메뉴 로드 완료:",r),v.isLocal&&r.length===0){const o=[{crprCd:"100",menuGbCd:"CMPRGRP",menuPrntId:"FAV001",menuId:"FAV_TEST001",menuNm:"API 테스트",scrnId:"TEST001",menuNo:1,scrnPath:"/dev/ApiTest",menuLvl:3,rootMenu:"FAV001",addedAt:new Date().toISOString(),userId:t},{crprCd:"100",menuGbCd:"CMPRGRP",menuPrntId:"FAV001",menuId:"FAV_TEST002",menuNm:"프로젝트 개요",scrnId:"DOCS001",menuNo:2,scrnPath:"/docs/ProjectOverview",menuLvl:3,rootMenu:"FAV001",addedAt:new Date().toISOString(),userId:t}];a({favorites:o,isLoading:!1,error:null}),console.log("개발 모드: 테스트용 즐겨찾기 데이터 추가")}else a({favorites:r,isLoading:!1,error:null})}catch(n){console.error("즐겨찾기 메뉴 로드 실패:",n),a({error:n instanceof Error?n.message:"즐겨찾기 로드 실패",isLoading:!1})}},addFavorite:async(e,t)=>{const{favorites:n}=i();if(n.some(r=>r.menuId===e.menuId)){console.log("이미 즐겨찾기에 추가된 메뉴입니다:",e.menuNm);return}try{await l.callService(l.getServiceCode("AUTH_BMRK"),{action:"add",crprCd:e.crprCd,userId:t,menuId:e.menuId,menuNm:e.menuNm,scrnPath:e.scrnPath});const r={...e,addedAt:new Date().toISOString(),userId:t};a({favorites:[...n,r]}),console.log("즐겨찾기 추가 완료:",e.menuNm)}catch(r){throw console.error("즐겨찾기 추가 실패:",r),r}},removeFavorite:async(e,t)=>{const{favorites:n}=i();try{await l.callService(l.getServiceCode("AUTH_BMRK"),{action:"remove",crprCd:"100",userId:t,menuId:e});const r=n.filter(o=>o.menuId!==e);a({favorites:r}),console.log("즐겨찾기 제거 완료:",e)}catch(r){throw console.error("즐겨찾기 제거 실패:",r),r}},isFavorite:e=>{const{favorites:t}=i();return t.some(n=>n.menuId===e)},clearFavorites:()=>{a({favorites:[],isLoading:!1,error:null})}})),g=a=>{if(!a||!Array.isArray(a)||a.length===0)return[];const i=new Map,e=[];a.forEach(o=>{o&&o.menuId&&i.set(o.menuId,{...o,children:[]})}),a.forEach(o=>{if(!o||!o.menuId)return;const s=i.get(o.menuId);if(s)if(o.menuPrntId&&o.menuPrntId!==""&&o.menuPrntId!=="-"){const c=i.get(o.menuPrntId);c&&c.children.push(s)}else e.push(s)});const t=o=>o.sort((s,c)=>s.menuNo-c.menuNo).map(s=>({...s,children:s.children&&s.children.length>0?t(s.children):void 0})),n=t(e),r=n.filter(o=>o.menuId.startsWith("DEV"));return r.length>0&&console.log("DEV 최종 결과:",r),n},m=u.create((a,i)=>({menuList:[],isLoading:!1,error:null,activeMenu:"1",currentProgram:null,tabs:[],activeTabKey:null,sidebarCollapsed:!1,viewStates:{},_lastFetchParams:null,fetchMenu:async({crprCd:e,userId:t,prntGbcd:n})=>{const r={crprCd:e,userId:t,prntGbcd:n??1},{_lastFetchParams:o}=i();if(o&&o.crprCd===r.crprCd&&o.userId===r.userId&&o.prntGbcd===r.prntGbcd){console.log("동일한 파라미터로 중복 요청 방지:",r);return}console.log("메뉴 데이터 요청 시작:",r),a({isLoading:!0,error:null,_lastFetchParams:r});try{const s=await l.callService(l.getServiceCode("AUTH_MENU"),r);let c=[];s?.menus&&Array.isArray(s.menus)?c=s.menus:Array.isArray(s)?c=s:(console.warn("서버 응답이 비어있거나 예상과 다른 구조입니다. 개발자 메뉴만 표시합니다."),c=[]);const d=g(c);console.log("메뉴 데이터 로드 완료 (계층 구조):",d),a({menuList:d,isLoading:!1,error:null})}catch(s){console.error("메뉴 데이터 로드 실패:",s),a({error:s instanceof Error?s.message:"메뉴 로드 실패",isLoading:!1})}},setActiveMenu:e=>{a({activeMenu:e})},setCurrentProgram:e=>{console.log("setCurrentProgram 호출:",e),a({currentProgram:e})},addTab:e=>{const{tabs:t}=i();if(t.find(r=>r.key===e.menuId))a({activeTabKey:e.menuId});else{const r={key:e.menuId,label:e.menuNm,menuItem:e,closable:!0};a({tabs:[...t,r],activeTabKey:e.menuId})}},removeTab:e=>{const{tabs:t,activeTabKey:n}=i(),r=t.filter(s=>s.key!==e);let o=n;if(n===e){const s=t.findIndex(c=>c.key===e);r.length>0?o=r[Math.min(s,r.length-1)]?.key||null:o=null}a({tabs:r,activeTabKey:o,currentProgram:o&&r.find(s=>s.key===o)?.menuItem||null})},setActiveTab:e=>{const{tabs:t}=i(),n=t.find(r=>r.key===e);n&&a({activeTabKey:e,currentProgram:n.menuItem})},clearTabs:()=>{a({tabs:[],activeTabKey:null,currentProgram:null})},clearMenu:()=>{a({menuList:[],error:null,activeMenu:"1",currentProgram:null,tabs:[],activeTabKey:null,_lastFetchParams:null})},toggleSidebar:()=>{const{sidebarCollapsed:e}=i();a({sidebarCollapsed:!e})},updateViewState:(e,t,n)=>{a(r=>({viewStates:{...r.viewStates,[e]:{...r.viewStates[e],[t]:n}}})),console.log(`뷰 상태 업데이트: ${e}.${t}`,n)}}));exports.useFavoriteStore=f;exports.useMenuStore=m;
2
+ //# sourceMappingURL=menuStore-D7zl2c89.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"menuStore-CBvENehP.cjs","sources":["../../src/stores/favoriteStore.ts","../../src/stores/menuStore.ts"],"sourcesContent":["import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\nimport type { MenuItem } from \"./menuStore\";\r\nimport { isLocal } from \"@/utils\";\r\n\r\n// 즐겨찾기 메뉴 타입 정의\r\nexport interface FavoriteMenuItem extends MenuItem {\r\n addedAt: string; // 즐겨찾기 추가 시간\r\n userId: string; // 사용자 ID\r\n}\r\n\r\n// 즐겨찾기 스토어 타입 정의\r\nexport interface FavoriteStore {\r\n favorites: FavoriteMenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: (params: { crprCd: string; userId: string }) => Promise<void>;\r\n\r\n // 즐겨찾기 추가\r\n addFavorite: (menuItem: MenuItem, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: (menuId: string, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => boolean;\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => void;\r\n}\r\n\r\n// 즐겨찾기 스토어 생성\r\nexport const useFavoriteStore = create<FavoriteStore>((set, get) => ({\r\n favorites: [],\r\n isLoading: false,\r\n error: null,\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: async ({ crprCd, userId }) => {\r\n console.log(\"즐겨찾기 메뉴 요청:\", { crprCd, userId });\r\n set({ isLoading: true, error: null });\r\n\r\n try {\r\n // 서버에서 즐겨찾기 메뉴 가져오기\r\n const data = await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n crprCd,\r\n userId,\r\n });\r\n\r\n let favoritesList: FavoriteMenuItem[] = [];\r\n\r\n if (data?.favorites && Array.isArray(data.favorites)) {\r\n favoritesList = data.favorites;\r\n } else if (Array.isArray(data)) {\r\n favoritesList = data;\r\n } else {\r\n console.warn(\"즐겨찾기 데이터가 비어있거나 예상과 다른 구조입니다.\");\r\n favoritesList = [];\r\n }\r\n\r\n console.log(\"즐겨찾기 메뉴 로드 완료:\", favoritesList);\r\n\r\n // 개발 모드에서 테스트용 즐겨찾기 데이터 추가\r\n if (isLocal && favoritesList.length === 0) {\r\n const testFavorites: FavoriteMenuItem[] = [\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST001\",\r\n menuNm: \"API 테스트\",\r\n scrnId: \"TEST001\",\r\n menuNo: 1,\r\n scrnPath: \"/dev/ApiTest\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST002\",\r\n menuNm: \"프로젝트 개요\",\r\n scrnId: \"DOCS001\",\r\n menuNo: 2,\r\n scrnPath: \"/docs/ProjectOverview\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n ];\r\n set({ favorites: testFavorites, isLoading: false, error: null });\r\n console.log(\"개발 모드: 테스트용 즐겨찾기 데이터 추가\");\r\n } else {\r\n set({ favorites: favoritesList, isLoading: false, error: null });\r\n }\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 addFavorite: async (menuItem: MenuItem, userId: string) => {\r\n const { favorites } = get();\r\n\r\n // 이미 즐겨찾기에 있는지 확인\r\n if (favorites.some((fav) => fav.menuId === menuItem.menuId)) {\r\n console.log(\"이미 즐겨찾기에 추가된 메뉴입니다:\", menuItem.menuNm);\r\n return;\r\n }\r\n\r\n try {\r\n // 서버에 즐겨찾기 추가 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"add\",\r\n crprCd: menuItem.crprCd,\r\n userId,\r\n menuId: menuItem.menuId,\r\n menuNm: menuItem.menuNm,\r\n scrnPath: menuItem.scrnPath,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const newFavorite: FavoriteMenuItem = {\r\n ...menuItem,\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n };\r\n\r\n set({ favorites: [...favorites, newFavorite] });\r\n console.log(\"즐겨찾기 추가 완료:\", menuItem.menuNm);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 추가 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: async (menuId: string, userId: string) => {\r\n const { favorites } = get();\r\n\r\n try {\r\n // 서버에 즐겨찾기 제거 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"remove\",\r\n crprCd: \"100\", // 기본값\r\n userId,\r\n menuId,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const updatedFavorites = favorites.filter((fav) => fav.menuId !== menuId);\r\n set({ favorites: updatedFavorites });\r\n console.log(\"즐겨찾기 제거 완료:\", menuId);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 제거 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => {\r\n const { favorites } = get();\r\n return favorites.some((fav) => fav.menuId === menuId);\r\n },\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => {\r\n set({ favorites: [], isLoading: false, error: null });\r\n },\r\n}));\r\n","import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\n\r\n// 메뉴 아이템 타입 정의 (서버 응답 구조 기반)\r\nexport interface MenuItem {\r\n crprCd: string; // 회사 코드\r\n menuGbCd: string; // 메뉴 구분 코드 (CMPRGRM: 메인, CMPRGRS: 서브, CMPRGRP: 프로그램)\r\n menuPrntId: string; // 부모 메뉴 ID\r\n menuId: string; // 메뉴 ID\r\n menuNm: string; // 메뉴명\r\n scrnId: string; // 화면 ID\r\n menuNo: number; // 메뉴 순서\r\n scrnPath: string; // 화면 경로\r\n menuLvl: number; // 메뉴 레벨 (1: 메인, 2~3: 서브, 2~4: 프로그램)\r\n rootMenu: string; // 루트 메뉴\r\n iconCd?: string; // 아이콘 코드\r\n children?: MenuItem[]; // 하위 메뉴 (클라이언트에서 구성)\r\n}\r\n\r\n// 탭 아이템 타입 정의\r\nexport interface TabItem {\r\n key: string; // 탭 고유 키 (menuId)\r\n label: string; // 탭 표시명 (menuNm)\r\n menuItem: MenuItem; // 메뉴 아이템 정보\r\n closable: boolean; // 닫기 가능 여부\r\n}\r\n\r\n// 개발자 메뉴 데이터 (개발 모드에서만 표시)\r\nconst getDeveloperMenuData = (): MenuItem[] => {\r\n const isDevelopment =\r\n (typeof process !== \"undefined\" &&\r\n process.env.NODE_ENV === \"development\") ||\r\n (typeof window !== \"undefined\" && window.location.hostname === \"localhost\");\r\n //console.log('isDevelopment:', isDevelopment);\r\n\r\n if (!isDevelopment) return [];\r\n\r\n return [\r\n // 1뎁스: 개발자 도구\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRM\",\r\n menuPrntId: \"-\",\r\n menuId: \"DEV001\",\r\n menuNm: \"개발자 도구\",\r\n scrnId: \"\",\r\n menuNo: 0,\r\n scrnPath: \"\",\r\n menuLvl: 1,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 2뎁스: 컴포넌트 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00101\",\r\n menuNm: \"컴포넌트 가이드\",\r\n scrnId: \"\",\r\n menuNo: 1,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgComponentGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010101\",\r\n menuNm: \"기본 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM01\",\r\n menuNo: 9991,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010102\",\r\n menuNm: \"응용 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM02\",\r\n menuNo: 9992,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM02\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n // 2뎁스: 개발자 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00102\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"\",\r\n menuNo: 2,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgDeveloperGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010201\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"BwgDeveloperGuideM01\",\r\n menuNo: 9993,\r\n scrnPath: \"/cm/guide/BwgDeveloperGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010202\",\r\n menuNm: \"React 가이드\",\r\n scrnId: \"BwgReactGuideM01\",\r\n menuNo: 9994,\r\n scrnPath: \"/cm/guide/BwgReactGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010203\",\r\n menuNm: \"연습공간\",\r\n scrnId: \"BwgPracticeM01\",\r\n menuNo: 9995,\r\n scrnPath: \"/cm/guide/BwgPracticeM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n ];\r\n};\r\n\r\ntype fetchMenuParams = {\r\n crprCd: string;\r\n userId: string;\r\n prntGbcd: number;\r\n};\r\n\r\n// 메뉴 스토어 타입 정의\r\n// 뷰 상태 타입 정의\r\nexport interface ViewState {\r\n [key: string]: any;\r\n}\r\n\r\nexport interface MenuStore {\r\n menuList: MenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n activeMenu: string;\r\n currentProgram: MenuItem | null; // 현재 선택된 프로그램\r\n tabs: TabItem[]; // 열린 탭 목록\r\n activeTabKey: string | null; // 현재 활성 탭 키\r\n _lastFetchParams: fetchMenuParams | null; // 마지막 fetch 파라미터 (내부용)\r\n sidebarCollapsed: boolean; // 사이드바 접기/펼치기 상태\r\n viewStates: Record<string, ViewState>; // 뷰별 상태 저장\r\n fetchMenu: (params: fetchMenuParams) => Promise<void>;\r\n setActiveMenu: (menuId: string) => void;\r\n setCurrentProgram: (program: MenuItem | null) => void;\r\n addTab: (menuItem: MenuItem) => void;\r\n removeTab: (tabKey: string) => void;\r\n setActiveTab: (tabKey: string) => void;\r\n clearTabs: () => void;\r\n clearMenu: () => void;\r\n toggleSidebar: () => void; // 사이드바 접기/펼치기 토글\r\n // 뷰 상태 관리 함수들\r\n updateViewState: (viewKey: string, key: string, value: any) => void;\r\n}\r\n\r\n// 계층적 메뉴 구성 함수\r\nconst buildMenuHierarchy = (flatMenuList: MenuItem[]): MenuItem[] => {\r\n if (\r\n !flatMenuList ||\r\n !Array.isArray(flatMenuList) ||\r\n flatMenuList.length === 0\r\n ) {\r\n return [];\r\n }\r\n\r\n const menuMap = new Map<string, MenuItem>();\r\n const rootMenus: MenuItem[] = [];\r\n\r\n // 모든 메뉴를 Map에 저장\r\n flatMenuList.forEach((menu) => {\r\n if (menu && menu.menuId) {\r\n menuMap.set(menu.menuId, { ...menu, children: [] });\r\n }\r\n });\r\n\r\n // 계층 구조 구성\r\n flatMenuList.forEach((menu) => {\r\n if (!menu || !menu.menuId) return;\r\n\r\n const menuWithChildren = menuMap.get(menu.menuId);\r\n if (!menuWithChildren) return;\r\n\r\n // 개발자 메뉴만 로그 출력\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`DEV 메뉴 처리: ${menu.menuId} (${menu.menuNm}), 부모: ${menu.menuPrntId}`)\r\n //}\r\n\r\n if (menu.menuPrntId && menu.menuPrntId !== \"\" && menu.menuPrntId !== \"-\") {\r\n // 부모 메뉴가 있는 경우\r\n const parentMenu = menuMap.get(menu.menuPrntId);\r\n if (parentMenu) {\r\n parentMenu.children!.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 자식 메뉴 추가: ${menu.menuId} → ${menu.menuPrntId}`)\r\n //}\r\n } else {\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.warn(`❌ DEV 부모 메뉴를 찾을 수 없음: ${menu.menuPrntId}`)\r\n //}\r\n }\r\n } else {\r\n // 루트 메뉴인 경우 (부모가 없거나 '-'인 경우)\r\n rootMenus.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 루트 메뉴 추가: ${menu.menuId} (${menu.menuNm})`)\r\n //}\r\n }\r\n });\r\n\r\n // 개발자 메뉴만 확인\r\n //const devRootMenus = rootMenus.filter(m => m.menuId.startsWith('DEV'))\r\n //if (devRootMenus.length > 0) {\r\n //console.log('DEV 루트 메뉴들:', devRootMenus.map(m => `${m.menuId} (${m.menuNm})`))\r\n //} else {\r\n //console.warn('❌ DEV 루트 메뉴가 없습니다!')\r\n //}\r\n\r\n // menuNo로 정렬\r\n const sortMenus = (menus: MenuItem[]): MenuItem[] => {\r\n return menus\r\n .sort((a, b) => a.menuNo - b.menuNo)\r\n .map((menu) => ({\r\n ...menu,\r\n children:\r\n menu.children && menu.children.length > 0\r\n ? sortMenus(menu.children)\r\n : undefined,\r\n }));\r\n };\r\n\r\n const result = sortMenus(rootMenus);\r\n\r\n // 개발자 메뉴만 최종 결과 확인\r\n const devResult = result.filter((m) => m.menuId.startsWith(\"DEV\"));\r\n if (devResult.length > 0) {\r\n console.log(\"DEV 최종 결과:\", devResult);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n// 메뉴 스토어 생성\r\nexport const useMenuStore = create<MenuStore>((set, get) => ({\r\n menuList: [],\r\n isLoading: false,\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n sidebarCollapsed: false, // 사이드바 접기/펼치기 상태\r\n viewStates: {}, // 뷰별 상태 저장\r\n _lastFetchParams: null as fetchMenuParams | null, // 마지막 fetch 파라미터 저장\r\n\r\n // 메뉴 데이터 가져오기\r\n fetchMenu: async ({ crprCd, userId, prntGbcd }: fetchMenuParams) => {\r\n const currentParams = { crprCd, userId, prntGbcd: prntGbcd ?? 1 };\r\n const { _lastFetchParams } = get();\r\n\r\n // 동일한 파라미터로 중복 요청 방지\r\n if (\r\n _lastFetchParams &&\r\n _lastFetchParams.crprCd === currentParams.crprCd &&\r\n _lastFetchParams.userId === currentParams.userId &&\r\n _lastFetchParams.prntGbcd === currentParams.prntGbcd\r\n ) {\r\n console.log(\"동일한 파라미터로 중복 요청 방지:\", currentParams);\r\n return;\r\n }\r\n\r\n console.log(\"메뉴 데이터 요청 시작:\", currentParams);\r\n set({ isLoading: true, error: null, _lastFetchParams: currentParams });\r\n\r\n try {\r\n // 실제 서버에서 메뉴 데이터 가져오기\r\n const data = await callService(\r\n getServiceCode(\"AUTH_MENU\"),\r\n currentParams\r\n );\r\n\r\n // console.log('서버 응답 전체 데이터:', data)\r\n // console.log('서버 응답 타입:', typeof data)\r\n // console.log('data.menuList 존재 여부:', !!data?.menuList)\r\n // console.log('data.menuList 타입:', typeof data?.menuList)\r\n // console.log('data.menuList 길이:', data?.menuList?.length)\r\n\r\n // 서버 응답 구조 확인 및 데이터 추출\r\n let flatMenuList: MenuItem[] = [];\r\n\r\n if (data?.menus && Array.isArray(data.menus)) {\r\n flatMenuList = data.menus;\r\n } else if (Array.isArray(data)) {\r\n // 응답이 바로 배열인 경우\r\n flatMenuList = data;\r\n } else {\r\n console.warn(\r\n \"서버 응답이 비어있거나 예상과 다른 구조입니다. 개발자 메뉴만 표시합니다.\"\r\n );\r\n flatMenuList = [];\r\n }\r\n\r\n // 개발자 메뉴 추가 (개발 모드에서만)\r\n const developerMenus = getDeveloperMenuData();\r\n //console.log('개발자 메뉴 데이터:', developerMenus)\r\n if (developerMenus.length > 0) {\r\n flatMenuList = [...developerMenus, ...flatMenuList];\r\n //console.log('개발자 메뉴 추가 후 flatMenuList 길이:', flatMenuList.length)\r\n }\r\n\r\n // console.log('추출된 flatMenuList:', flatMenuList)\r\n\r\n const hierarchicalMenuList = buildMenuHierarchy(flatMenuList);\r\n\r\n console.log(\"메뉴 데이터 로드 완료 (계층 구조):\", hierarchicalMenuList);\r\n\r\n set({\r\n menuList: hierarchicalMenuList,\r\n isLoading: false,\r\n error: null,\r\n });\r\n } catch (error) {\r\n console.error(\"메뉴 데이터 로드 실패:\", error);\r\n\r\n // 서버 오류 시에도 개발자 메뉴는 표시\r\n const developerMenus = getDeveloperMenuData();\r\n if (developerMenus.length > 0) {\r\n console.log(\"서버 오류로 인해 개발자 메뉴만 표시합니다.\");\r\n const hierarchicalMenuList = buildMenuHierarchy(developerMenus);\r\n set({\r\n menuList: hierarchicalMenuList,\r\n isLoading: false,\r\n error: null,\r\n });\r\n } else {\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 // 활성 메뉴 설정\r\n setActiveMenu: (menuId: string) => {\r\n set({ activeMenu: menuId });\r\n },\r\n\r\n // 현재 프로그램 설정\r\n setCurrentProgram: (program: MenuItem | null) => {\r\n console.log(\"setCurrentProgram 호출:\", program);\r\n set({ currentProgram: program });\r\n },\r\n\r\n // 탭 추가\r\n addTab: (menuItem: MenuItem) => {\r\n const { tabs } = get();\r\n const existingTab = tabs.find((tab) => tab.key === menuItem.menuId);\r\n\r\n if (!existingTab) {\r\n const newTab: TabItem = {\r\n key: menuItem.menuId,\r\n label: menuItem.menuNm,\r\n menuItem,\r\n closable: true,\r\n };\r\n set({\r\n tabs: [...tabs, newTab],\r\n activeTabKey: menuItem.menuId,\r\n });\r\n } else {\r\n // 이미 존재하는 탭이면 활성화만\r\n set({ activeTabKey: menuItem.menuId });\r\n }\r\n },\r\n\r\n // 탭 제거\r\n removeTab: (tabKey: string) => {\r\n const { tabs, activeTabKey } = get();\r\n const newTabs = tabs.filter((tab) => tab.key !== tabKey);\r\n\r\n // 제거된 탭이 현재 활성 탭이었다면 다른 탭을 활성화\r\n let newActiveTabKey = activeTabKey;\r\n if (activeTabKey === tabKey) {\r\n const currentIndex = tabs.findIndex((tab) => tab.key === tabKey);\r\n if (newTabs.length > 0) {\r\n // 제거된 탭 다음 탭을 활성화, 마지막 탭이었다면 이전 탭을 활성화\r\n newActiveTabKey =\r\n newTabs[Math.min(currentIndex, newTabs.length - 1)]?.key || null;\r\n } else {\r\n newActiveTabKey = null;\r\n }\r\n }\r\n\r\n set({\r\n tabs: newTabs,\r\n activeTabKey: newActiveTabKey,\r\n currentProgram: newActiveTabKey\r\n ? newTabs.find((tab) => tab.key === newActiveTabKey)?.menuItem || null\r\n : null,\r\n });\r\n },\r\n\r\n // 활성 탭 설정\r\n setActiveTab: (tabKey: string) => {\r\n const { tabs } = get();\r\n const targetTab = tabs.find((tab) => tab.key === tabKey);\r\n if (targetTab) {\r\n set({\r\n activeTabKey: tabKey,\r\n currentProgram: targetTab.menuItem,\r\n });\r\n }\r\n },\r\n\r\n // 탭 초기화\r\n clearTabs: () => {\r\n set({\r\n tabs: [],\r\n activeTabKey: null,\r\n currentProgram: null,\r\n });\r\n },\r\n\r\n // 메뉴 데이터 초기화\r\n clearMenu: () => {\r\n set({\r\n menuList: [],\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n _lastFetchParams: null, // 마지막 fetch 파라미터도 초기화\r\n });\r\n },\r\n\r\n // 사이드바 접기/펼치기 토글\r\n toggleSidebar: () => {\r\n const { sidebarCollapsed } = get();\r\n set({ sidebarCollapsed: !sidebarCollapsed });\r\n },\r\n\r\n // 뷰 상태 업데이트\r\n updateViewState: (viewKey: string, key: string, value: any) => {\r\n set((prev) => ({\r\n viewStates: {\r\n ...prev.viewStates,\r\n [viewKey]: {\r\n ...prev.viewStates[viewKey],\r\n [key]: value,\r\n },\r\n },\r\n }));\r\n console.log(`뷰 상태 업데이트: ${viewKey}.${key}`, value);\r\n },\r\n}));\r\n"],"names":["useFavoriteStore","create","set","get","crprCd","userId","data","callService","getServiceCode","favoritesList","isLocal","testFavorites","error","menuItem","favorites","fav","newFavorite","menuId","updatedFavorites","getDeveloperMenuData","buildMenuHierarchy","flatMenuList","menuMap","rootMenus","menu","menuWithChildren","parentMenu","sortMenus","menus","a","b","result","devResult","m","useMenuStore","prntGbcd","currentParams","_lastFetchParams","developerMenus","hierarchicalMenuList","program","tabs","tab","newTab","tabKey","activeTabKey","newTabs","newActiveTabKey","currentIndex","targetTab","sidebarCollapsed","viewKey","key","value","prev"],"mappings":"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"}
1
+ {"version":3,"file":"menuStore-D7zl2c89.cjs","sources":["../../src/stores/favoriteStore.ts","../../src/stores/menuStore.ts"],"sourcesContent":["import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\nimport type { MenuItem } from \"./menuStore\";\r\nimport { isLocal } from \"@/utils\";\r\n\r\n// 즐겨찾기 메뉴 타입 정의\r\nexport interface FavoriteMenuItem extends MenuItem {\r\n addedAt: string; // 즐겨찾기 추가 시간\r\n userId: string; // 사용자 ID\r\n}\r\n\r\n// 즐겨찾기 스토어 타입 정의\r\nexport interface FavoriteStore {\r\n favorites: FavoriteMenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: (params: { crprCd: string; userId: string }) => Promise<void>;\r\n\r\n // 즐겨찾기 추가\r\n addFavorite: (menuItem: MenuItem, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: (menuId: string, userId: string) => Promise<void>;\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => boolean;\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => void;\r\n}\r\n\r\n// 즐겨찾기 스토어 생성\r\nexport const useFavoriteStore = create<FavoriteStore>((set, get) => ({\r\n favorites: [],\r\n isLoading: false,\r\n error: null,\r\n\r\n // 즐겨찾기 메뉴 가져오기\r\n fetchFavorites: async ({ crprCd, userId }) => {\r\n console.log(\"즐겨찾기 메뉴 요청:\", { crprCd, userId });\r\n set({ isLoading: true, error: null });\r\n\r\n try {\r\n // 서버에서 즐겨찾기 메뉴 가져오기\r\n const data = await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n crprCd,\r\n userId,\r\n });\r\n\r\n let favoritesList: FavoriteMenuItem[] = [];\r\n\r\n if (data?.favorites && Array.isArray(data.favorites)) {\r\n favoritesList = data.favorites;\r\n } else if (Array.isArray(data)) {\r\n favoritesList = data;\r\n } else {\r\n console.warn(\"즐겨찾기 데이터가 비어있거나 예상과 다른 구조입니다.\");\r\n favoritesList = [];\r\n }\r\n\r\n console.log(\"즐겨찾기 메뉴 로드 완료:\", favoritesList);\r\n\r\n // 개발 모드에서 테스트용 즐겨찾기 데이터 추가\r\n if (isLocal && favoritesList.length === 0) {\r\n const testFavorites: FavoriteMenuItem[] = [\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST001\",\r\n menuNm: \"API 테스트\",\r\n scrnId: \"TEST001\",\r\n menuNo: 1,\r\n scrnPath: \"/dev/ApiTest\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"FAV001\",\r\n menuId: \"FAV_TEST002\",\r\n menuNm: \"프로젝트 개요\",\r\n scrnId: \"DOCS001\",\r\n menuNo: 2,\r\n scrnPath: \"/docs/ProjectOverview\",\r\n menuLvl: 3,\r\n rootMenu: \"FAV001\",\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n },\r\n ];\r\n set({ favorites: testFavorites, isLoading: false, error: null });\r\n console.log(\"개발 모드: 테스트용 즐겨찾기 데이터 추가\");\r\n } else {\r\n set({ favorites: favoritesList, isLoading: false, error: null });\r\n }\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 addFavorite: async (menuItem: MenuItem, userId: string) => {\r\n const { favorites } = get();\r\n\r\n // 이미 즐겨찾기에 있는지 확인\r\n if (favorites.some((fav) => fav.menuId === menuItem.menuId)) {\r\n console.log(\"이미 즐겨찾기에 추가된 메뉴입니다:\", menuItem.menuNm);\r\n return;\r\n }\r\n\r\n try {\r\n // 서버에 즐겨찾기 추가 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"add\",\r\n crprCd: menuItem.crprCd,\r\n userId,\r\n menuId: menuItem.menuId,\r\n menuNm: menuItem.menuNm,\r\n scrnPath: menuItem.scrnPath,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const newFavorite: FavoriteMenuItem = {\r\n ...menuItem,\r\n addedAt: new Date().toISOString(),\r\n userId,\r\n };\r\n\r\n set({ favorites: [...favorites, newFavorite] });\r\n console.log(\"즐겨찾기 추가 완료:\", menuItem.menuNm);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 추가 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 제거\r\n removeFavorite: async (menuId: string, userId: string) => {\r\n const { favorites } = get();\r\n\r\n try {\r\n // 서버에 즐겨찾기 제거 요청\r\n await callService(getServiceCode(\"AUTH_BMRK\"), {\r\n action: \"remove\",\r\n crprCd: \"100\", // 기본값\r\n userId,\r\n menuId,\r\n });\r\n\r\n // 로컬 상태 업데이트\r\n const updatedFavorites = favorites.filter((fav) => fav.menuId !== menuId);\r\n set({ favorites: updatedFavorites });\r\n console.log(\"즐겨찾기 제거 완료:\", menuId);\r\n } catch (error) {\r\n console.error(\"즐겨찾기 제거 실패:\", error);\r\n throw error;\r\n }\r\n },\r\n\r\n // 즐겨찾기 여부 확인\r\n isFavorite: (menuId: string) => {\r\n const { favorites } = get();\r\n return favorites.some((fav) => fav.menuId === menuId);\r\n },\r\n\r\n // 즐겨찾기 초기화\r\n clearFavorites: () => {\r\n set({ favorites: [], isLoading: false, error: null });\r\n },\r\n}));\r\n","import { create } from \"zustand\";\r\nimport { callService } from \"../utils/apiUtils\";\r\nimport { getServiceCode } from \"../utils/serviceConfig\";\r\n\r\n// 메뉴 아이템 타입 정의 (서버 응답 구조 기반)\r\nexport interface MenuItem {\r\n crprCd: string; // 회사 코드\r\n menuGbCd: string; // 메뉴 구분 코드 (CMPRGRM: 메인, CMPRGRS: 서브, CMPRGRP: 프로그램)\r\n menuPrntId: string; // 부모 메뉴 ID\r\n menuId: string; // 메뉴 ID\r\n menuNm: string; // 메뉴명\r\n scrnId: string; // 화면 ID\r\n menuNo: number; // 메뉴 순서\r\n scrnPath: string; // 화면 경로\r\n menuLvl: number; // 메뉴 레벨 (1: 메인, 2~3: 서브, 2~4: 프로그램)\r\n rootMenu: string; // 루트 메뉴\r\n iconCd?: string; // 아이콘 코드\r\n children?: MenuItem[]; // 하위 메뉴 (클라이언트에서 구성)\r\n}\r\n\r\n// 탭 아이템 타입 정의\r\nexport interface TabItem {\r\n key: string; // 탭 고유 키 (menuId)\r\n label: string; // 탭 표시명 (menuNm)\r\n menuItem: MenuItem; // 메뉴 아이템 정보\r\n closable: boolean; // 닫기 가능 여부\r\n}\r\n\r\n// 개발자 메뉴 데이터 (개발 모드에서만 표시)\r\nconst getDeveloperMenuData = (): MenuItem[] => {\r\n const isDevelopment =\r\n (typeof process !== \"undefined\" &&\r\n process.env.NODE_ENV === \"development\") ||\r\n (typeof window !== \"undefined\" && window.location.hostname === \"localhost\");\r\n //console.log('isDevelopment:', isDevelopment);\r\n\r\n if (!isDevelopment) return [];\r\n\r\n return [\r\n // 1뎁스: 개발자 도구\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRM\",\r\n menuPrntId: \"-\",\r\n menuId: \"DEV001\",\r\n menuNm: \"개발자 도구\",\r\n scrnId: \"\",\r\n menuNo: 0,\r\n scrnPath: \"\",\r\n menuLvl: 1,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 2뎁스: 컴포넌트 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00101\",\r\n menuNm: \"컴포넌트 가이드\",\r\n scrnId: \"\",\r\n menuNo: 1,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgComponentGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010101\",\r\n menuNm: \"기본 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM01\",\r\n menuNo: 9991,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00101\",\r\n menuId: \"DEV0010102\",\r\n menuNm: \"응용 컴포넌트\",\r\n scrnId: \"BwgComponentGuideM02\",\r\n menuNo: 9992,\r\n scrnPath: \"/cm/guide/BwgComponentGuideM02\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00101\",\r\n },\r\n // 2뎁스: 개발자 가이드\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRS\",\r\n menuPrntId: \"DEV001\",\r\n menuId: \"DEV00102\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"\",\r\n menuNo: 2,\r\n scrnPath: \"\",\r\n menuLvl: 2,\r\n rootMenu: \"DEV001\",\r\n },\r\n // 3뎁스: BwgDeveloperGuideM01 컴포넌트\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010201\",\r\n menuNm: \"개발자 가이드\",\r\n scrnId: \"BwgDeveloperGuideM01\",\r\n menuNo: 9993,\r\n scrnPath: \"/cm/guide/BwgDeveloperGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010202\",\r\n menuNm: \"React 가이드\",\r\n scrnId: \"BwgReactGuideM01\",\r\n menuNo: 9994,\r\n scrnPath: \"/cm/guide/BwgReactGuideM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n {\r\n crprCd: \"100\",\r\n menuGbCd: \"CMPRGRP\",\r\n menuPrntId: \"DEV00102\",\r\n menuId: \"DEV0010203\",\r\n menuNm: \"연습공간\",\r\n scrnId: \"BwgPracticeM01\",\r\n menuNo: 9995,\r\n scrnPath: \"/cm/guide/BwgPracticeM01\",\r\n menuLvl: 3,\r\n rootMenu: \"DEV00102\",\r\n },\r\n ];\r\n};\r\n\r\ntype fetchMenuParams = {\r\n crprCd: string;\r\n userId: string;\r\n prntGbcd: number;\r\n};\r\n\r\n// 메뉴 스토어 타입 정의\r\n// 뷰 상태 타입 정의\r\nexport interface ViewState {\r\n [key: string]: any;\r\n}\r\n\r\nexport interface MenuStore {\r\n menuList: MenuItem[];\r\n isLoading: boolean;\r\n error: string | null;\r\n activeMenu: string;\r\n currentProgram: MenuItem | null; // 현재 선택된 프로그램\r\n tabs: TabItem[]; // 열린 탭 목록\r\n activeTabKey: string | null; // 현재 활성 탭 키\r\n _lastFetchParams: fetchMenuParams | null; // 마지막 fetch 파라미터 (내부용)\r\n sidebarCollapsed: boolean; // 사이드바 접기/펼치기 상태\r\n viewStates: Record<string, ViewState>; // 뷰별 상태 저장\r\n fetchMenu: (params: fetchMenuParams) => Promise<void>;\r\n setActiveMenu: (menuId: string) => void;\r\n setCurrentProgram: (program: MenuItem | null) => void;\r\n addTab: (menuItem: MenuItem) => void;\r\n removeTab: (tabKey: string) => void;\r\n setActiveTab: (tabKey: string) => void;\r\n clearTabs: () => void;\r\n clearMenu: () => void;\r\n toggleSidebar: () => void; // 사이드바 접기/펼치기 토글\r\n // 뷰 상태 관리 함수들\r\n updateViewState: (viewKey: string, key: string, value: any) => void;\r\n}\r\n\r\n// 계층적 메뉴 구성 함수\r\nconst buildMenuHierarchy = (flatMenuList: MenuItem[]): MenuItem[] => {\r\n if (\r\n !flatMenuList ||\r\n !Array.isArray(flatMenuList) ||\r\n flatMenuList.length === 0\r\n ) {\r\n return [];\r\n }\r\n\r\n const menuMap = new Map<string, MenuItem>();\r\n const rootMenus: MenuItem[] = [];\r\n\r\n // 모든 메뉴를 Map에 저장\r\n flatMenuList.forEach((menu) => {\r\n if (menu && menu.menuId) {\r\n menuMap.set(menu.menuId, { ...menu, children: [] });\r\n }\r\n });\r\n\r\n // 계층 구조 구성\r\n flatMenuList.forEach((menu) => {\r\n if (!menu || !menu.menuId) return;\r\n\r\n const menuWithChildren = menuMap.get(menu.menuId);\r\n if (!menuWithChildren) return;\r\n\r\n // 개발자 메뉴만 로그 출력\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`DEV 메뉴 처리: ${menu.menuId} (${menu.menuNm}), 부모: ${menu.menuPrntId}`)\r\n //}\r\n\r\n if (menu.menuPrntId && menu.menuPrntId !== \"\" && menu.menuPrntId !== \"-\") {\r\n // 부모 메뉴가 있는 경우\r\n const parentMenu = menuMap.get(menu.menuPrntId);\r\n if (parentMenu) {\r\n parentMenu.children!.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 자식 메뉴 추가: ${menu.menuId} → ${menu.menuPrntId}`)\r\n //}\r\n } else {\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.warn(`❌ DEV 부모 메뉴를 찾을 수 없음: ${menu.menuPrntId}`)\r\n //}\r\n }\r\n } else {\r\n // 루트 메뉴인 경우 (부모가 없거나 '-'인 경우)\r\n rootMenus.push(menuWithChildren);\r\n //if (menu.menuId.startsWith('DEV')) {\r\n //console.log(`✅ DEV 루트 메뉴 추가: ${menu.menuId} (${menu.menuNm})`)\r\n //}\r\n }\r\n });\r\n\r\n // 개발자 메뉴만 확인\r\n //const devRootMenus = rootMenus.filter(m => m.menuId.startsWith('DEV'))\r\n //if (devRootMenus.length > 0) {\r\n //console.log('DEV 루트 메뉴들:', devRootMenus.map(m => `${m.menuId} (${m.menuNm})`))\r\n //} else {\r\n //console.warn('❌ DEV 루트 메뉴가 없습니다!')\r\n //}\r\n\r\n // menuNo로 정렬\r\n const sortMenus = (menus: MenuItem[]): MenuItem[] => {\r\n return menus\r\n .sort((a, b) => a.menuNo - b.menuNo)\r\n .map((menu) => ({\r\n ...menu,\r\n children:\r\n menu.children && menu.children.length > 0\r\n ? sortMenus(menu.children)\r\n : undefined,\r\n }));\r\n };\r\n\r\n const result = sortMenus(rootMenus);\r\n\r\n // 개발자 메뉴만 최종 결과 확인\r\n const devResult = result.filter((m) => m.menuId.startsWith(\"DEV\"));\r\n if (devResult.length > 0) {\r\n console.log(\"DEV 최종 결과:\", devResult);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n// 메뉴 스토어 생성\r\nexport const useMenuStore = create<MenuStore>((set, get) => ({\r\n menuList: [],\r\n isLoading: false,\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n sidebarCollapsed: false, // 사이드바 접기/펼치기 상태\r\n viewStates: {}, // 뷰별 상태 저장\r\n _lastFetchParams: null as fetchMenuParams | null, // 마지막 fetch 파라미터 저장\r\n\r\n // 메뉴 데이터 가져오기\r\n fetchMenu: async ({ crprCd, userId, prntGbcd }: fetchMenuParams) => {\r\n const currentParams = { crprCd, userId, prntGbcd: prntGbcd ?? 1 };\r\n const { _lastFetchParams } = get();\r\n\r\n // 동일한 파라미터로 중복 요청 방지\r\n if (\r\n _lastFetchParams &&\r\n _lastFetchParams.crprCd === currentParams.crprCd &&\r\n _lastFetchParams.userId === currentParams.userId &&\r\n _lastFetchParams.prntGbcd === currentParams.prntGbcd\r\n ) {\r\n console.log(\"동일한 파라미터로 중복 요청 방지:\", currentParams);\r\n return;\r\n }\r\n\r\n console.log(\"메뉴 데이터 요청 시작:\", currentParams);\r\n set({ isLoading: true, error: null, _lastFetchParams: currentParams });\r\n\r\n try {\r\n // 실제 서버에서 메뉴 데이터 가져오기\r\n const data = await callService(\r\n getServiceCode(\"AUTH_MENU\"),\r\n currentParams\r\n );\r\n\r\n // console.log('서버 응답 전체 데이터:', data)\r\n // console.log('서버 응답 타입:', typeof data)\r\n // console.log('data.menuList 존재 여부:', !!data?.menuList)\r\n // console.log('data.menuList 타입:', typeof data?.menuList)\r\n // console.log('data.menuList 길이:', data?.menuList?.length)\r\n\r\n // 서버 응답 구조 확인 및 데이터 추출\r\n let flatMenuList: MenuItem[] = [];\r\n\r\n if (data?.menus && Array.isArray(data.menus)) {\r\n flatMenuList = data.menus;\r\n } else if (Array.isArray(data)) {\r\n // 응답이 바로 배열인 경우\r\n flatMenuList = data;\r\n } else {\r\n console.warn(\r\n \"서버 응답이 비어있거나 예상과 다른 구조입니다. 개발자 메뉴만 표시합니다.\"\r\n );\r\n flatMenuList = [];\r\n }\r\n\r\n // 개발자 메뉴 추가 (개발 모드에서만)\r\n // const developerMenus = getDeveloperMenuData();\r\n // if (developerMenus.length > 0) {\r\n // flatMenuList = [...developerMenus, ...flatMenuList];\r\n // }\r\n\r\n // console.log('추출된 flatMenuList:', flatMenuList)\r\n\r\n const hierarchicalMenuList = buildMenuHierarchy(flatMenuList);\r\n\r\n console.log(\"메뉴 데이터 로드 완료 (계층 구조):\", hierarchicalMenuList);\r\n\r\n set({\r\n menuList: hierarchicalMenuList,\r\n isLoading: false,\r\n error: null,\r\n });\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 setActiveMenu: (menuId: string) => {\r\n set({ activeMenu: menuId });\r\n },\r\n\r\n // 현재 프로그램 설정\r\n setCurrentProgram: (program: MenuItem | null) => {\r\n console.log(\"setCurrentProgram 호출:\", program);\r\n set({ currentProgram: program });\r\n },\r\n\r\n // 탭 추가\r\n addTab: (menuItem: MenuItem) => {\r\n const { tabs } = get();\r\n const existingTab = tabs.find((tab) => tab.key === menuItem.menuId);\r\n\r\n if (!existingTab) {\r\n const newTab: TabItem = {\r\n key: menuItem.menuId,\r\n label: menuItem.menuNm,\r\n menuItem,\r\n closable: true,\r\n };\r\n set({\r\n tabs: [...tabs, newTab],\r\n activeTabKey: menuItem.menuId,\r\n });\r\n } else {\r\n // 이미 존재하는 탭이면 활성화만\r\n set({ activeTabKey: menuItem.menuId });\r\n }\r\n },\r\n\r\n // 탭 제거\r\n removeTab: (tabKey: string) => {\r\n const { tabs, activeTabKey } = get();\r\n const newTabs = tabs.filter((tab) => tab.key !== tabKey);\r\n\r\n // 제거된 탭이 현재 활성 탭이었다면 다른 탭을 활성화\r\n let newActiveTabKey = activeTabKey;\r\n if (activeTabKey === tabKey) {\r\n const currentIndex = tabs.findIndex((tab) => tab.key === tabKey);\r\n if (newTabs.length > 0) {\r\n // 제거된 탭 다음 탭을 활성화, 마지막 탭이었다면 이전 탭을 활성화\r\n newActiveTabKey =\r\n newTabs[Math.min(currentIndex, newTabs.length - 1)]?.key || null;\r\n } else {\r\n newActiveTabKey = null;\r\n }\r\n }\r\n\r\n set({\r\n tabs: newTabs,\r\n activeTabKey: newActiveTabKey,\r\n currentProgram: newActiveTabKey\r\n ? newTabs.find((tab) => tab.key === newActiveTabKey)?.menuItem || null\r\n : null,\r\n });\r\n },\r\n\r\n // 활성 탭 설정\r\n setActiveTab: (tabKey: string) => {\r\n const { tabs } = get();\r\n const targetTab = tabs.find((tab) => tab.key === tabKey);\r\n if (targetTab) {\r\n set({\r\n activeTabKey: tabKey,\r\n currentProgram: targetTab.menuItem,\r\n });\r\n }\r\n },\r\n\r\n // 탭 초기화\r\n clearTabs: () => {\r\n set({\r\n tabs: [],\r\n activeTabKey: null,\r\n currentProgram: null,\r\n });\r\n },\r\n\r\n // 메뉴 데이터 초기화\r\n clearMenu: () => {\r\n set({\r\n menuList: [],\r\n error: null,\r\n activeMenu: \"1\",\r\n currentProgram: null,\r\n tabs: [],\r\n activeTabKey: null,\r\n _lastFetchParams: null, // 마지막 fetch 파라미터도 초기화\r\n });\r\n },\r\n\r\n // 사이드바 접기/펼치기 토글\r\n toggleSidebar: () => {\r\n const { sidebarCollapsed } = get();\r\n set({ sidebarCollapsed: !sidebarCollapsed });\r\n },\r\n\r\n // 뷰 상태 업데이트\r\n updateViewState: (viewKey: string, key: string, value: any) => {\r\n set((prev) => ({\r\n viewStates: {\r\n ...prev.viewStates,\r\n [viewKey]: {\r\n ...prev.viewStates[viewKey],\r\n [key]: value,\r\n },\r\n },\r\n }));\r\n console.log(`뷰 상태 업데이트: ${viewKey}.${key}`, value);\r\n },\r\n}));\r\n"],"names":["useFavoriteStore","create","set","get","crprCd","userId","data","callService","getServiceCode","favoritesList","isLocal","testFavorites","error","menuItem","favorites","fav","newFavorite","menuId","updatedFavorites","buildMenuHierarchy","flatMenuList","menuMap","rootMenus","menu","menuWithChildren","parentMenu","sortMenus","menus","a","b","result","devResult","m","useMenuStore","prntGbcd","currentParams","_lastFetchParams","hierarchicalMenuList","program","tabs","tab","newTab","tabKey","activeTabKey","newTabs","newActiveTabKey","currentIndex","targetTab","sidebarCollapsed","viewKey","key","value","prev"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../chunks/SSOHandler-DcN-_XRB.cjs"),r=require("../../chunks/BwgSpace-b0hmM1Ht.cjs"),o=require("../../chunks/realFormat-Cha7OTd9.cjs");exports.BwgButtonGroup=e.BwgButtonGroup;exports.BwgCmptArea=e.BwgCmptArea;exports.BwgCol=e.BwgCol;exports.BwgConfigProvider=e.BwgConfigProvider;exports.BwgDrawer=e.BwgDrawer;exports.BwgGrid=e.BwgGrid;exports.BwgInfoArea=e.BwgInfoArea;exports.BwgPopup=e.BwgPopup;exports.BwgRow=e.BwgRow;exports.BwgTable=e.BwgTable;exports.BwgTabs=e.BwgTabs;exports.BwgTitleBox=e.BwgTitleBox;exports.BwgView=e.BwgView;exports.ContentBox=e.ContentBox;exports.ContentLayOut=e.ContentLayOut;exports.GlobalConfigProvider=e.GlobalConfigProvider;exports.QuickServiceToggle=e.QuickServiceToggle;exports.SSOHandler=e.SSOHandler;exports.SearchBox=e.SearchBox;exports.createBwgGridRenderer=e.createBwgGridRenderer;exports.BwgSpace=r.BwgSpace;exports.realFormat=o.realFormat;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../chunks/SSOHandler-kghWABfM.cjs"),r=require("../../chunks/BwgSpace-b0hmM1Ht.cjs"),o=require("../../chunks/realFormat-Cha7OTd9.cjs");exports.BwgButtonGroup=e.BwgButtonGroup;exports.BwgCmptArea=e.BwgCmptArea;exports.BwgCol=e.BwgCol;exports.BwgConfigProvider=e.BwgConfigProvider;exports.BwgDrawer=e.BwgDrawer;exports.BwgGrid=e.BwgGrid;exports.BwgInfoArea=e.BwgInfoArea;exports.BwgPopup=e.BwgPopup;exports.BwgRow=e.BwgRow;exports.BwgTable=e.BwgTable;exports.BwgTabs=e.BwgTabs;exports.BwgTitleBox=e.BwgTitleBox;exports.BwgView=e.BwgView;exports.ContentBox=e.ContentBox;exports.ContentLayOut=e.ContentLayOut;exports.GlobalConfigProvider=e.GlobalConfigProvider;exports.QuickServiceToggle=e.QuickServiceToggle;exports.SSOHandler=e.SSOHandler;exports.SearchBox=e.SearchBox;exports.createBwgGridRenderer=e.createBwgGridRenderer;exports.BwgSpace=r.BwgSpace;exports.realFormat=o.realFormat;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1,4 +1,4 @@
1
- import { B as r, a as o, b as s, c as B, d as g, e as w, f as t, g as i, h as n, i as l, j as p, k as d, l as f, C, m as c, G as m, Q as x, n as S, S as u, o as G } from "../../chunks/SSOHandler-C-gPpUbk.js";
1
+ import { B as r, a as o, b as s, c as B, d as g, e as w, f as t, g as i, h as n, i as l, j as p, k as d, l as f, C, m as c, G as m, Q as x, n as S, S as u, o as G } from "../../chunks/SSOHandler-Bu3v95k0.js";
2
2
  import { B as T } from "../../chunks/BwgSpace-CnLM4qcg.js";
3
3
  import { r as P } from "../../chunks/realFormat-DRGLFabQ.js";
4
4
  export {