@bwg-ui/core 1.1.23 → 1.1.25

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.
Files changed (161) hide show
  1. package/dist/chunks/AuthContext-CXng9fj0.cjs.map +1 -1
  2. package/dist/chunks/{AuthContext-Ei2P-z4d.js → AuthContext-DrEpBrpB.js} +7 -3
  3. package/dist/chunks/AuthContext-DrEpBrpB.js.map +1 -0
  4. package/dist/chunks/{BwgSwitch-CAI-kEaM.cjs → BwgSwitch-DOlc57wi.cjs} +2 -2
  5. package/dist/chunks/BwgSwitch-DOlc57wi.cjs.map +1 -0
  6. package/dist/chunks/{BwgSwitch-B79pseQM.js → BwgSwitch-D_scwi9_.js} +18 -18
  7. package/dist/chunks/BwgSwitch-D_scwi9_.js.map +1 -0
  8. package/dist/chunks/{BwgUploader-DaNV2URT.cjs → BwgUploader-CkXwkcUL.cjs} +2 -2
  9. package/dist/chunks/BwgUploader-CkXwkcUL.cjs.map +1 -0
  10. package/dist/chunks/{BwgUploader-BcVlE61B.js → BwgUploader-DBFF9BPF.js} +327 -327
  11. package/dist/chunks/BwgUploader-DBFF9BPF.js.map +1 -0
  12. package/dist/chunks/LoadingOverlay-DAZJF5wg.js.map +1 -1
  13. package/dist/chunks/LoadingOverlay-DcmKvoZA.cjs.map +1 -1
  14. package/dist/chunks/{SSOHandler-DiW4Ft9i.cjs → SSOHandler-BY6LXMLc.cjs} +32 -32
  15. package/dist/chunks/SSOHandler-BY6LXMLc.cjs.map +1 -0
  16. package/dist/chunks/{SSOHandler-CkPcSHIm.js → SSOHandler-CxvxEBaH.js} +1977 -1930
  17. package/dist/chunks/SSOHandler-CxvxEBaH.js.map +1 -0
  18. package/dist/chunks/ScreenProtectContext-3my4PHFa.js.map +1 -1
  19. package/dist/chunks/ScreenProtectContext-CVuXrJm6.cjs.map +1 -1
  20. package/dist/chunks/SearchBoxContext-DwFDOyYG.cjs.map +1 -1
  21. package/dist/chunks/{SearchBoxContext-BCvEYyFk.js → SearchBoxContext-gWM7FHIw.js} +3 -5
  22. package/dist/chunks/SearchBoxContext-gWM7FHIw.js.map +1 -0
  23. package/dist/chunks/ViewContainer-Bhq22_B3.cjs.map +1 -1
  24. package/dist/chunks/{ViewContainer-CjpJqoGG.js → ViewContainer-D9SKBnrn.js} +40 -28
  25. package/dist/chunks/ViewContainer-D9SKBnrn.js.map +1 -0
  26. package/dist/chunks/apiUtils-BZ6s0_NI.cjs.map +1 -1
  27. package/dist/chunks/{apiUtils-DxzLqPhU.js → apiUtils-DSwE62oG.js} +14 -5
  28. package/dist/chunks/apiUtils-DSwE62oG.js.map +1 -0
  29. package/dist/chunks/{codeStore-CfI4Wh5M.js → codeStore-vPj4Y0TK.js} +2 -2
  30. package/dist/chunks/{codeStore-CfI4Wh5M.js.map → codeStore-vPj4Y0TK.js.map} +1 -1
  31. package/dist/chunks/{core-bHd8azE6.js → core-Dl0PdDdT.js} +2 -2
  32. package/dist/chunks/{core-bHd8azE6.js.map → core-Dl0PdDdT.js.map} +1 -1
  33. package/dist/chunks/{enc-base64-BQYwLKgk.js → enc-base64-D7t4BoUA.js} +3 -3
  34. package/dist/chunks/{enc-base64-BQYwLKgk.js.map → enc-base64-D7t4BoUA.js.map} +1 -1
  35. package/dist/chunks/{favoriteStore-Cemc-26t.js → favoriteStore-Bh1FuZm9.js} +2 -2
  36. package/dist/chunks/{favoriteStore-Cemc-26t.js.map → favoriteStore-Bh1FuZm9.js.map} +1 -1
  37. package/dist/chunks/{popupStore-Bi6o78lP.js → popupStore-BRRmB4zH.js} +2 -2
  38. package/dist/chunks/{popupStore-Bi6o78lP.js.map → popupStore-BRRmB4zH.js.map} +1 -1
  39. package/dist/chunks/{sha256-BZfJs28k.js → sha256-C2-s1oZe.js} +3 -3
  40. package/dist/chunks/{sha256-BZfJs28k.js.map → sha256-C2-s1oZe.js.map} +1 -1
  41. package/dist/chunks/usePopup-D2JEuDrO.cjs.map +1 -1
  42. package/dist/chunks/{usePopup-BSqsnSz7.js → usePopup-DarKTbRC.js} +3 -3
  43. package/dist/chunks/usePopup-DarKTbRC.js.map +1 -0
  44. package/dist/components/common/BookmarkMngModal.d.ts +1 -1
  45. package/dist/components/common/BookmarkMngModal.d.ts.map +1 -1
  46. package/dist/components/common/BookmarkPopver.d.ts +2 -2
  47. package/dist/components/common/BookmarkPopver.d.ts.map +1 -1
  48. package/dist/components/common/BwgButtonGroup.d.ts +5 -5
  49. package/dist/components/common/BwgButtonGroup.d.ts.map +1 -1
  50. package/dist/components/common/BwgCmptArea.d.ts +7 -7
  51. package/dist/components/common/BwgCmptArea.d.ts.map +1 -1
  52. package/dist/components/common/BwgCol.d.ts +2 -1
  53. package/dist/components/common/BwgCol.d.ts.map +1 -1
  54. package/dist/components/common/BwgConfigProvider.d.ts +2 -2
  55. package/dist/components/common/BwgConfigProvider.d.ts.map +1 -1
  56. package/dist/components/common/BwgDetail.d.ts +2 -1
  57. package/dist/components/common/BwgDetail.d.ts.map +1 -1
  58. package/dist/components/common/BwgDraggable.d.ts +5 -5
  59. package/dist/components/common/BwgDraggable.d.ts.map +1 -1
  60. package/dist/components/common/BwgDrawer.d.ts +2 -1
  61. package/dist/components/common/BwgDrawer.d.ts.map +1 -1
  62. package/dist/components/common/BwgEditor.d.ts +5 -5
  63. package/dist/components/common/BwgEditor.d.ts.map +1 -1
  64. package/dist/components/common/BwgGrid.d.ts +8 -8
  65. package/dist/components/common/BwgGrid.d.ts.map +1 -1
  66. package/dist/components/common/BwgInfoArea.d.ts +4 -4
  67. package/dist/components/common/BwgInfoArea.d.ts.map +1 -1
  68. package/dist/components/common/BwgPopup.d.ts +3 -3
  69. package/dist/components/common/BwgPopup.d.ts.map +1 -1
  70. package/dist/components/common/BwgRow.d.ts +2 -1
  71. package/dist/components/common/BwgRow.d.ts.map +1 -1
  72. package/dist/components/common/BwgTitleBox.d.ts +5 -4
  73. package/dist/components/common/BwgTitleBox.d.ts.map +1 -1
  74. package/dist/components/common/BwgView.d.ts +4 -4
  75. package/dist/components/common/BwgView.d.ts.map +1 -1
  76. package/dist/components/common/ContentBox.d.ts +3 -3
  77. package/dist/components/common/ContentBox.d.ts.map +1 -1
  78. package/dist/components/common/ContentLayOut.d.ts +6 -5
  79. package/dist/components/common/ContentLayOut.d.ts.map +1 -1
  80. package/dist/components/common/GlobalConfigProvider.d.ts +2 -2
  81. package/dist/components/common/GlobalConfigProvider.d.ts.map +1 -1
  82. package/dist/components/common/QuickServiceToggle.d.ts +4 -4
  83. package/dist/components/common/QuickServiceToggle.d.ts.map +1 -1
  84. package/dist/components/common/SSOHandler.d.ts +2 -1
  85. package/dist/components/common/SSOHandler.d.ts.map +1 -1
  86. package/dist/components/common/SearchBox.d.ts +5 -4
  87. package/dist/components/common/SearchBox.d.ts.map +1 -1
  88. package/dist/components/common/index.cjs +1 -1
  89. package/dist/components/common/index.js +1 -1
  90. package/dist/components/core/BwgButton.d.ts +3 -2
  91. package/dist/components/core/BwgButton.d.ts.map +1 -1
  92. package/dist/components/core/BwgDatePicker.d.ts +3 -3
  93. package/dist/components/core/BwgDatePicker.d.ts.map +1 -1
  94. package/dist/components/core/BwgDownload.d.ts +2 -2
  95. package/dist/components/core/BwgDownload.d.ts.map +1 -1
  96. package/dist/components/core/BwgForm.d.ts +2 -1
  97. package/dist/components/core/BwgForm.d.ts.map +1 -1
  98. package/dist/components/core/BwgFormItem.d.ts +3 -3
  99. package/dist/components/core/BwgFormItem.d.ts.map +1 -1
  100. package/dist/components/core/BwgInput.d.ts +2 -2
  101. package/dist/components/core/BwgInput.d.ts.map +1 -1
  102. package/dist/components/core/BwgLargeUploader.d.ts +2 -2
  103. package/dist/components/core/BwgLargeUploader.d.ts.map +1 -1
  104. package/dist/components/core/BwgMaskedInput.d.ts +2 -2
  105. package/dist/components/core/BwgMaskedInput.d.ts.map +1 -1
  106. package/dist/components/core/BwgMaskedPicker.d.ts +2 -2
  107. package/dist/components/core/BwgMaskedPicker.d.ts.map +1 -1
  108. package/dist/components/core/BwgRangePicker.d.ts +3 -3
  109. package/dist/components/core/BwgRangePicker.d.ts.map +1 -1
  110. package/dist/components/core/BwgSearch.d.ts +1 -1
  111. package/dist/components/core/BwgSearch.d.ts.map +1 -1
  112. package/dist/components/core/BwgUploader.d.ts +2 -2
  113. package/dist/components/core/BwgUploader.d.ts.map +1 -1
  114. package/dist/components/core/index.cjs +1 -1
  115. package/dist/components/core/index.js +2 -2
  116. package/dist/components/layout/ErrorBound.d.ts +3 -3
  117. package/dist/components/layout/ErrorBound.d.ts.map +1 -1
  118. package/dist/components/layout/LoadingOverlay.d.ts +3 -2
  119. package/dist/components/layout/LoadingOverlay.d.ts.map +1 -1
  120. package/dist/components/layout/PrivateProtectedOverlay.d.ts +3 -2
  121. package/dist/components/layout/PrivateProtectedOverlay.d.ts.map +1 -1
  122. package/dist/components/layout/ProgressOverlay.d.ts +2 -2
  123. package/dist/components/layout/ProgressOverlay.d.ts.map +1 -1
  124. package/dist/components/layout/ViewContainer.d.ts +3 -3
  125. package/dist/components/layout/ViewContainer.d.ts.map +1 -1
  126. package/dist/components/layout/index.js +1 -1
  127. package/dist/components/popup/MenuReport.d.ts +2 -2
  128. package/dist/components/popup/MenuReport.d.ts.map +1 -1
  129. package/dist/index.cjs +1 -1
  130. package/dist/index.js +11 -11
  131. package/dist/provider/contexts/AuthContext.d.ts +3 -2
  132. package/dist/provider/contexts/AuthContext.d.ts.map +1 -1
  133. package/dist/provider/contexts/CommonCodeContext.d.ts +2 -2
  134. package/dist/provider/contexts/CommonCodeContext.d.ts.map +1 -1
  135. package/dist/provider/contexts/ScreenProtectContext.d.ts +5 -5
  136. package/dist/provider/contexts/ScreenProtectContext.d.ts.map +1 -1
  137. package/dist/provider/contexts/SearchBoxContext.d.ts +3 -3
  138. package/dist/provider/contexts/SearchBoxContext.d.ts.map +1 -1
  139. package/dist/provider/contexts/ServiceCodeContext.d.ts +2 -2
  140. package/dist/provider/contexts/ServiceCodeContext.d.ts.map +1 -1
  141. package/dist/provider/index.js +3 -3
  142. package/dist/stores/index.cjs.map +1 -1
  143. package/dist/stores/index.d.ts +0 -1
  144. package/dist/stores/index.d.ts.map +1 -1
  145. package/dist/stores/index.js +6 -6
  146. package/dist/stores/index.js.map +1 -1
  147. package/dist/stores/menuViewStore.d.ts +6 -5
  148. package/dist/stores/menuViewStore.d.ts.map +1 -1
  149. package/dist/utils/index.js +2 -2
  150. package/package.json +1 -1
  151. package/dist/chunks/AuthContext-Ei2P-z4d.js.map +0 -1
  152. package/dist/chunks/BwgSwitch-B79pseQM.js.map +0 -1
  153. package/dist/chunks/BwgSwitch-CAI-kEaM.cjs.map +0 -1
  154. package/dist/chunks/BwgUploader-BcVlE61B.js.map +0 -1
  155. package/dist/chunks/BwgUploader-DaNV2URT.cjs.map +0 -1
  156. package/dist/chunks/SSOHandler-CkPcSHIm.js.map +0 -1
  157. package/dist/chunks/SSOHandler-DiW4Ft9i.cjs.map +0 -1
  158. package/dist/chunks/SearchBoxContext-BCvEYyFk.js.map +0 -1
  159. package/dist/chunks/ViewContainer-CjpJqoGG.js.map +0 -1
  160. package/dist/chunks/apiUtils-DxzLqPhU.js.map +0 -1
  161. package/dist/chunks/usePopup-BSqsnSz7.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"SearchBoxContext-BCvEYyFk.js","sources":["../../src/provider/contexts/ServiceCodeContext.tsx","../../src/provider/contexts/SearchBoxContext.tsx"],"sourcesContent":["import React, { createContext, useContext, ReactNode, useEffect } from 'react';\r\nimport { ServiceCodeKey, setServiceCodeOverrides } from '../../utils/serviceConfig';\r\n\r\n// 서비스코드 설정을 위한 Context 타입\r\ninterface ServiceCodeContextType {\r\n serviceCodes: Partial<Record<ServiceCodeKey, string>>;\r\n getServiceCode: (key: ServiceCodeKey) => string;\r\n}\r\n\r\n// 기본 서비스코드 정의\r\nconst DEFAULT_SERVICE_CODES = {\r\n // 권한 관련\r\n AUTH_BTNS: 'SCMSIGN00202', // 버튼 권한 조회\r\n AUTH_MENU: 'SCMSIGN00201', // 메뉴 권한 조회\r\n SRCH_CODE: 'SCMSIGN00301', // 코드 조회\r\n \r\n // 팝업 관련\r\n SRCH_POPU: 'SCMPOPU00101', // 팝업 조회\r\n \r\n // 즐겨찾기 관련\r\n AUTH_BMRK: 'SCMBMRK00101', // 즐겨찾기 관리\r\n} as const;\r\n\r\n// Context 생성\r\nconst ServiceCodeContext = createContext<ServiceCodeContextType | null>(null);\r\n\r\n// Provider Props 타입\r\ninterface ServiceCodeProviderProps {\r\n children: ReactNode;\r\n /**\r\n * 서비스코드 오버라이드 설정\r\n * 외부 프로젝트에서 기본 서비스코드를 재정의할 수 있습니다.\r\n * \r\n * @example\r\n * ```tsx\r\n * <ServiceCodeProvider\r\n * serviceCodes={{\r\n * AUTH_BTNS: 'CUSTOM_AUTH_BTNS_CODE',\r\n * AUTH_MENU: 'CUSTOM_AUTH_MENU_CODE',\r\n * SRCH_CODE: 'CUSTOM_SRCH_CODE',\r\n * SRCH_POPU: 'CUSTOM_SRCH_POPU_CODE',\r\n * AUTH_BMRK: 'CUSTOM_AUTH_BMRK_CODE',\r\n * }}\r\n * >\r\n * {children}\r\n * </ServiceCodeProvider>\r\n * ```\r\n * \r\n * @description\r\n * - AUTH_BTNS: 버튼 권한 조회 서비스코드\r\n * - AUTH_MENU: 메뉴 권한 조회 서비스코드 \r\n * - SRCH_CODE: 코드 조회 서비스코드\r\n * - SRCH_POPU: 팝업 조회 서비스코드\r\n * - AUTH_BMRK: 즐겨찾기 관리 서비스코드\r\n * \r\n * 설정하지 않은 서비스코드는 기본값을 사용합니다.\r\n */\r\n serviceCodes?: Partial<Record<ServiceCodeKey, string>>;\r\n}\r\n\r\n/**\r\n * 서비스코드 Provider 컴포넌트\r\n * 외부 프로젝트에서 서비스코드를 설정할 수 있도록 함\r\n * \r\n * @example\r\n * ```tsx\r\n * import { ServiceCodeProvider } from '@bwg/core/provider';\r\n * \r\n * function App() {\r\n * return (\r\n * <ServiceCodeProvider\r\n * serviceCodes={{\r\n * AUTH_BTNS: 'CUSTOM_AUTH_BTNS_CODE',\r\n * AUTH_MENU: 'CUSTOM_AUTH_MENU_CODE',\r\n * }}\r\n * >\r\n * <YourApp />\r\n * </ServiceCodeProvider>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport const ServiceCodeProvider: React.FC<ServiceCodeProviderProps> = ({\r\n children,\r\n serviceCodes = {},\r\n}) => {\r\n // serviceCodes가 변경될 때마다 serviceConfig.ts의 오버라이드를 업데이트\r\n useEffect(() => {\r\n setServiceCodeOverrides(serviceCodes);\r\n }, [serviceCodes]);\r\n\r\n // 서비스코드 가져오기 함수\r\n const getServiceCode = (key: ServiceCodeKey): string => {\r\n // 1. Provider에서 설정된 값 우선 확인\r\n if (serviceCodes[key] && serviceCodes[key]!.trim() !== '') {\r\n console.log(`🔧 Provider 설정 사용: ${key} = ${serviceCodes[key]}`);\r\n return serviceCodes[key]!;\r\n }\r\n\r\n // 2. 기본값 사용\r\n const defaultValue = DEFAULT_SERVICE_CODES[key];\r\n console.log(`🔧 기본값 사용: ${key} = ${defaultValue}`);\r\n return defaultValue;\r\n };\r\n\r\n const contextValue: ServiceCodeContextType = {\r\n serviceCodes,\r\n getServiceCode,\r\n };\r\n\r\n return (\r\n <ServiceCodeContext.Provider value={contextValue}>\r\n {children}\r\n </ServiceCodeContext.Provider>\r\n );\r\n};\r\n\r\n/**\r\n * 서비스코드 Context를 사용하는 Hook\r\n * \r\n * @example\r\n * ```tsx\r\n * const { getServiceCode, serviceCodes } = useServiceCode();\r\n * const authBtnsCode = getServiceCode('AUTH_BTNS');\r\n * ```\r\n */\r\nexport const useServiceCode = (): ServiceCodeContextType => {\r\n const context = useContext(ServiceCodeContext);\r\n if (!context) {\r\n throw new Error('useServiceCode must be used within a ServiceCodeProvider');\r\n }\r\n return context;\r\n};\r\n\r\n/**\r\n * 특정 서비스코드를 가져오는 Hook\r\n * \r\n * @param key - 서비스코드 키\r\n * @returns 실제 서비스코드 값\r\n * \r\n * @example\r\n * ```tsx\r\n * const authBtnsCode = useServiceCodeValue('AUTH_BTNS');\r\n * const authMenuCode = useServiceCodeValue('AUTH_MENU');\r\n * ```\r\n */\r\nexport const useServiceCodeValue = (key: ServiceCodeKey): string => {\r\n const { getServiceCode } = useServiceCode();\r\n return getServiceCode(key);\r\n};\r\n\r\n/**\r\n * 모든 서비스코드를 가져오는 Hook\r\n * \r\n * @returns 모든 서비스코드 객체\r\n * \r\n * @example\r\n * ```tsx\r\n * const allServiceCodes = useAllServiceCodes();\r\n * console.log(allServiceCodes.AUTH_BTNS); // 'SCMSIGN00202' 또는 커스텀 값\r\n * ```\r\n */\r\nexport const useAllServiceCodes = (): Record<ServiceCodeKey, string> => {\r\n const { getServiceCode } = useServiceCode();\r\n const result = {} as Record<ServiceCodeKey, string>;\r\n \r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n result[key] = getServiceCode(key);\r\n }\r\n \r\n return result;\r\n};\r\n\r\n/**\r\n * 서비스코드 설정을 로그로 출력하는 Hook\r\n * 개발 시 현재 설정된 서비스코드를 확인할 수 있습니다.\r\n * \r\n * @example\r\n * ```tsx\r\n * useLogServiceCodeConfig();\r\n * // 콘솔에 현재 설정된 모든 서비스코드가 출력됩니다.\r\n * ```\r\n */\r\nexport const useLogServiceCodeConfig = (): void => {\r\n const { getServiceCode } = useServiceCode();\r\n \r\n console.log('🔧 bwg-core 서비스코드 설정:');\r\n console.log('📋 Provider 설정 > 기본값 순서로 확인');\r\n \r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n const value = getServiceCode(key);\r\n console.log(` ${key}: ${value}`);\r\n }\r\n};\r\n\r\n// 타입 내보내기\r\nexport type { ServiceCodeKey };\r\n","import React, { createContext, useContext, useRef, ReactNode } from 'react';\r\nimport { SearchBoxRef } from '../../components/common/SearchBox';\r\n\r\n// SearchBox Context 타입\r\ninterface SearchBoxContextType {\r\n searchBoxRef: React.RefObject<SearchBoxRef> | null;\r\n getFormData: () => any;\r\n setFormData: (data: any) => void;\r\n resetForm: () => void;\r\n validateForm: () => Promise<any>;\r\n}\r\n\r\n// Context 생성\r\nconst SearchBoxContext = createContext<SearchBoxContextType | null>(null);\r\n\r\n// Provider Props\r\ninterface SearchBoxProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\n// Provider 컴포넌트\r\nexport const SearchBoxProvider: React.FC<SearchBoxProviderProps> = ({\r\n children,\r\n}) => {\r\n const searchBoxRef = useRef<SearchBoxRef>(null);\r\n\r\n const getFormData = () => {\r\n return searchBoxRef.current?.getFormData() || {};\r\n };\r\n\r\n const setFormData = (data: any) => {\r\n searchBoxRef.current?.setFormData(data);\r\n };\r\n\r\n const resetForm = () => {\r\n searchBoxRef.current?.resetForm();\r\n };\r\n\r\n const validateForm = async () => {\r\n return (\r\n (await searchBoxRef.current?.validateForm()) || {\r\n success: false,\r\n error: null,\r\n }\r\n );\r\n };\r\n\r\n const value: SearchBoxContextType = {\r\n searchBoxRef,\r\n getFormData,\r\n setFormData,\r\n resetForm,\r\n validateForm,\r\n };\r\n\r\n return (\r\n <SearchBoxContext.Provider value={value}>\r\n {children}\r\n </SearchBoxContext.Provider>\r\n );\r\n};\r\n\r\n// Hook\r\nexport const useSearchBox = () => {\r\n const context = useContext(SearchBoxContext);\r\n if (!context) {\r\n throw new Error('useSearchBox must be used within a SearchBoxProvider');\r\n }\r\n return context;\r\n};\r\n"],"names":["DEFAULT_SERVICE_CODES","ServiceCodeContext","createContext","ServiceCodeProvider","children","serviceCodes","useEffect","setServiceCodeOverrides","contextValue","key","defaultValue","useServiceCode","context","useContext","useServiceCodeValue","getServiceCode","useAllServiceCodes","result","useLogServiceCodeConfig","value","SearchBoxContext","SearchBoxProvider","searchBoxRef","useRef","data","jsx","useSearchBox"],"mappings":";;;AAUA,MAAMA,IAAwB;AAAA;AAAA,EAE5B,WAAW;AAAA;AAAA,EACX,WAAW;AAAA;AAAA,EACX,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AACb,GAGMC,IAAqBC,EAA6C,IAAI,GA0D/DC,IAA0D,CAAC;AAAA,EACtE,UAAAC;AAAA,EACA,cAAAC,IAAe,CAAA;AACjB,MAAM;AAEJ,EAAAC,EAAU,MAAM;AACd,IAAAC,EAAwBF,CAAY;AAAA,EACtC,GAAG,CAACA,CAAY,CAAC;AAgBjB,QAAMG,IAAuC;AAAA,IAC3C,cAAAH;AAAA,IACA,gBAfqB,CAACI,MAAgC;AAEtD,UAAIJ,EAAaI,CAAG,KAAKJ,EAAaI,CAAG,EAAG,KAAA,MAAW;AACrD,uBAAQ,IAAI,sBAAsBA,CAAG,MAAMJ,EAAaI,CAAG,CAAC,EAAE,GACvDJ,EAAaI,CAAG;AAIzB,YAAMC,IAAeV,EAAsBS,CAAG;AAC9C,qBAAQ,IAAI,cAAcA,CAAG,MAAMC,CAAY,EAAE,GAC1CA;AAAA,IACT;AAAA,EAIE;AAGF,+BACGT,EAAmB,UAAnB,EAA4B,OAAOO,GACjC,UAAAJ,GACH;AAEJ,GAWaO,IAAiB,MAA8B;AAC1D,QAAMC,IAAUC,EAAWZ,CAAkB;AAC7C,MAAI,CAACW;AACH,UAAM,IAAI,MAAM,0DAA0D;AAE5E,SAAOA;AACT,GAcaE,IAAsB,CAACL,MAAgC;AAClE,QAAM,EAAE,gBAAAM,EAAA,IAAmBJ,EAAA;AAC3B,SAAOI,EAAeN,CAAG;AAC3B,GAaaO,IAAqB,MAAsC;AACtE,QAAM,EAAE,gBAAAD,EAAA,IAAmBJ,EAAA,GACrBM,IAAS,CAAA;AAEf,aAAWR,KAAO,OAAO,KAAKT,CAAqB;AACjD,IAAAiB,EAAOR,CAAG,IAAIM,EAAeN,CAAG;AAGlC,SAAOQ;AACT,GAYaC,IAA0B,MAAY;AACjD,QAAM,EAAE,gBAAAH,EAAA,IAAmBJ,EAAA;AAE3B,UAAQ,IAAI,uBAAuB,GACnC,QAAQ,IAAI,6BAA6B;AAEzC,aAAWF,KAAO,OAAO,KAAKT,CAAqB,GAAuB;AACxE,UAAMmB,IAAQJ,EAAeN,CAAG;AAChC,YAAQ,IAAI,KAAKA,CAAG,KAAKU,CAAK,EAAE;AAAA,EAClC;AACF,GCpLMC,IAAmBlB,EAA2C,IAAI,GAQ3DmB,IAAsD,CAAC;AAAA,EAClE,UAAAjB;AACF,MAAM;AACJ,QAAMkB,IAAeC,EAAqB,IAAI,GAuBxCJ,IAA8B;AAAA,IAClC,cAAAG;AAAA,IACA,aAvBkB,MACXA,EAAa,SAAS,YAAA,KAAiB,CAAA;AAAA,IAuB9C,aApBkB,CAACE,MAAc;AACjC,MAAAF,EAAa,SAAS,YAAYE,CAAI;AAAA,IACxC;AAAA,IAmBE,WAjBgB,MAAM;AACtB,MAAAF,EAAa,SAAS,UAAA;AAAA,IACxB;AAAA,IAgBE,cAdmB,YAEhB,MAAMA,EAAa,SAAS,kBAAmB;AAAA,MAC9C,SAAS;AAAA,MACT,OAAO;AAAA,IAAA;AAAA,EAUX;AAGF,SACEG,gBAAAA,EAAAA,IAACL,EAAiB,UAAjB,EAA0B,OAAAD,GACxB,UAAAf,EAAA,CACH;AAEJ,GAGasB,IAAe,MAAM;AAChC,QAAMd,IAAUC,EAAWO,CAAgB;AAC3C,MAAI,CAACR;AACH,UAAM,IAAI,MAAM,sDAAsD;AAExE,SAAOA;AACT;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ViewContainer-CjpJqoGG.js","sources":["../../src/components/layout/ErrorBound.tsx","../../src/components/layout/PrivateProtectedOverlay.tsx","../../src/components/layout/ProgressOverlay.tsx","../../src/components/layout/ProtectLayout.tsx","../../src/components/layout/PublicLayout.tsx","../../src/components/layout/ViewContainer.tsx"],"sourcesContent":["import React, { Component, ErrorInfo, ReactNode } from 'react';\r\nimport { Result, Button } from 'antd';\r\nimport { ReloadOutlined, HomeOutlined } from '@ant-design/icons';\r\nimport { useNavigate } from 'react-router-dom';\r\n\r\ninterface Props {\r\n children: ReactNode;\r\n fallback?: ReactNode;\r\n}\r\n\r\ninterface State {\r\n hasError: boolean;\r\n error?: Error;\r\n errorInfo?: ErrorInfo;\r\n}\r\n\r\n// 에러 페이지 컴포넌트\r\nexport const ErrorPage: React.FC<{\r\n error?: Error;\r\n resetError?: () => void;\r\n onGoHome?: () => void;\r\n}> = ({ error, resetError, onGoHome }) => {\r\n const navigate = useNavigate();\r\n\r\n const handleGoHome = () => {\r\n if (onGoHome) {\r\n onGoHome();\r\n } else {\r\n // 기본 홈 이동 로직\r\n navigate('/');\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '40px 20px',\r\n textAlign: 'center',\r\n backgroundColor: '#fafafa',\r\n minHeight: '400px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <Result\r\n status=\"error\"\r\n title=\"컴포넌트 로딩 중 오류가 발생했습니다\"\r\n subTitle={\r\n error\r\n ? `오류 내용: ${error.message}`\r\n : '알 수 없는 오류가 발생했습니다'\r\n }\r\n extra={[\r\n <Button\r\n key=\"retry\"\r\n type=\"primary\"\r\n icon={<ReloadOutlined />}\r\n onClick={resetError}\r\n style={{ marginRight: 8 }}\r\n >\r\n 다시 시도\r\n </Button>,\r\n <Button key=\"home\" icon={<HomeOutlined />} onClick={handleGoHome}>\r\n 홈으로\r\n </Button>,\r\n ]}\r\n />\r\n {error && (\r\n <details\r\n style={{\r\n marginTop: '20px',\r\n textAlign: 'left',\r\n maxWidth: '600px',\r\n backgroundColor: '#fff',\r\n padding: '16px',\r\n borderRadius: '6px',\r\n border: '1px solid #d9d9d9',\r\n }}\r\n >\r\n <summary style={{ cursor: 'pointer', fontWeight: 'bold' }}>\r\n 오류 상세 정보\r\n </summary>\r\n <pre\r\n style={{\r\n marginTop: '8px',\r\n fontSize: '12px',\r\n color: '#666',\r\n whiteSpace: 'pre-wrap',\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {error.stack}\r\n </pre>\r\n </details>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// 에러 경계 클래스 컴포넌트\r\nexport class ErrorBound extends Component<Props, State> {\r\n constructor(props: Props) {\r\n super(props);\r\n this.state = { hasError: false };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): State {\r\n return { hasError: true, error };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n console.error('ErrorBound caught an error:', error, errorInfo);\r\n this.setState({\r\n error,\r\n errorInfo,\r\n });\r\n }\r\n\r\n resetError = () => {\r\n this.setState({ hasError: false, error: undefined, errorInfo: undefined });\r\n };\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n if (this.props.fallback) {\r\n return this.props.fallback;\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '40px 20px',\r\n textAlign: 'center',\r\n backgroundColor: '#fafafa',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <Result\r\n status=\"error\"\r\n title=\"컴포넌트 로딩 중 오류가 발생했습니다\"\r\n subTitle={\r\n this.state.error\r\n ? `오류 내용: ${this.state.error.message}`\r\n : '알 수 없는 오류가 발생했습니다'\r\n }\r\n extra={[\r\n <Button\r\n key=\"retry\"\r\n type=\"primary\"\r\n icon={<ReloadOutlined />}\r\n onClick={this.resetError}\r\n style={{ marginRight: 8 }}\r\n >\r\n 다시 시도\r\n </Button>,\r\n ]}\r\n />\r\n {this.state.error && (\r\n <details\r\n style={{\r\n marginTop: '20px',\r\n textAlign: 'left',\r\n maxWidth: '600px',\r\n backgroundColor: '#fff',\r\n padding: '16px',\r\n borderRadius: '6px',\r\n border: '1px solid #d9d9d9',\r\n }}\r\n >\r\n <summary style={{ cursor: 'pointer', fontWeight: 'bold' }}>\r\n 오류 상세 정보\r\n </summary>\r\n <pre\r\n style={{\r\n marginTop: '8px',\r\n fontSize: '12px',\r\n color: '#666',\r\n whiteSpace: 'pre-wrap',\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {this.state.error.stack}\r\n </pre>\r\n </details>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\n// 함수형 컴포넌트용 에러 경계 훅\r\nexport const useErrorHandler = () => {\r\n const [error, setError] = React.useState<Error | null>(null);\r\n\r\n const handleError = React.useCallback((error: Error) => {\r\n console.error('useErrorHandler caught an error:', error);\r\n setError(error);\r\n }, []);\r\n\r\n const resetError = React.useCallback(() => {\r\n setError(null);\r\n }, []);\r\n\r\n return { error, handleError, resetError };\r\n};\r\n","import { ScreenProtectProvider, useLock } from \"@/provider/contexts/ScreenProtectContext\";\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\n// ──────────────────────────────────────────────\r\n// 공통 스타일 유틸\r\n// ──────────────────────────────────────────────\r\nconst createTabStyle = (isActive: boolean) => ({\r\n position: 'absolute' as const,\r\n inset: 0,\r\n visibility: isActive ? ('visible' as const) : ('hidden' as const),\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? ('auto' as const) : ('none' as const),\r\n });\r\n\r\n// ──────────────────────────────────────────────\r\n// AutoLock (활성 탭일 때 잠금 트리거)\r\n// ──────────────────────────────────────────────\r\nconst AutoLock: React.FC<{ once?: boolean }> = ({ once = true }) => {\r\n const { lock } = useLock();\r\n const called = useRef(false);\r\n useEffect(() => {\r\n if (once && called.current) return;\r\n called.current = true;\r\n lock();\r\n }, [once, lock]);\r\n return null;\r\n };\r\n\r\n// ──────────────────────────────────────────────\r\n// PrivateProtectedOverlay (개인정보 포함 화면 보호레이어)\r\n// ──────────────────────────────────────────────\r\nconst PrivateProtectedOverlay: React.FC<{\r\n isActive: boolean;\r\n flagged: boolean;\r\n tabKey: string;\r\n onUnlock: () => void;\r\n children: React.ReactNode;\r\n }> = ({ isActive, flagged, tabKey, onUnlock, children }) => {\r\n const shellRef = useRef<HTMLDivElement>(null);\r\n const [ready, setReady] = useState(false);\r\n \r\n const setShellRef = useCallback((el: HTMLDivElement | null) => {\r\n (shellRef as React.MutableRefObject<HTMLDivElement | null>).current = el;\r\n setReady(!!el);\r\n }, []);\r\n \r\n const shellStyle = createTabStyle(isActive);\r\n \r\n return (\r\n <div ref={setShellRef} style={shellStyle}>\r\n {ready ? (\r\n <ScreenProtectProvider\r\n idleMs={Number.POSITIVE_INFINITY}\r\n persistLocked={false}\r\n overlayScope=\"scoped\"\r\n overlayPosition=\"absolute\"\r\n eventTarget={shellRef.current!}\r\n overlayId={`tab-overlay-${tabKey}`}\r\n onUnlock={async () => {\r\n onUnlock();\r\n return true;\r\n }}\r\n >\r\n {isActive && flagged ? <AutoLock once /> : null}\r\n {children}\r\n </ScreenProtectProvider>\r\n ) : (\r\n children\r\n )}\r\n </div>\r\n );\r\n };\r\n\r\n export default PrivateProtectedOverlay;","import { useAuth } from \"@/provider/contexts/AuthContext\";\r\nimport { Spin } from \"antd\";\r\nimport React, { useEffect } from 'react';\r\n\r\nconst DOTLINE_STYLE_ID = 'bwg-dot-line-wave-v4';\r\nfunction ensureDotLineWaveStylesV4() {\r\n if (typeof document === 'undefined') return;\r\n if (document.getElementById(DOTLINE_STYLE_ID)) return;\r\n\r\n const style = document.createElement('style');\r\n style.id = DOTLINE_STYLE_ID;\r\n style.textContent = `\r\n .bwg-dotline {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: var(--bwg-gap, 12px);\r\n height: calc(var(--bwg-size, 12px) + 2 * var(--bwg-amp, 12px));\r\n line-height: 0;\r\n }\r\n .bwg-dotline .dot {\r\n width: var(--bwg-size, 12px);\r\n height: var(--bwg-size, 12px);\r\n border-radius: 50%;\r\n background: currentColor;\r\n will-change: transform, opacity;\r\n filter: drop-shadow(0 1px 2px rgba(0,0,0,.12));\r\n animation: bwg-dotline-sine var(--bwg-speed, 780ms) linear infinite;\r\n }\r\n\r\n /* sin(θ) 근사: 0, 45, 90, 135, 180, 225, 270, 315, 360deg */\r\n @keyframes bwg-dotline-sine {\r\n 0% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n 12.5%{ transform: translate3d(0, calc(-0.7071 * var(--bwg-amp, 12px)), 0) scale(1.03); opacity: .92; }\r\n 25% { transform: translate3d(0, calc(-1 * var(--bwg-amp, 12px)), 0) scale(1.06); opacity: 1; }\r\n 37.5%{ transform: translate3d(0, calc(-0.7071 * var(--bwg-amp, 12px)), 0) scale(1.03); opacity: .92; }\r\n 50% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n 62.5%{ transform: translate3d(0, calc( 0.7071 * var(--bwg-amp, 12px)), 0) scale(.97); opacity: .78; }\r\n 75% { transform: translate3d(0, calc( 1 * var(--bwg-amp, 12px)), 0) scale(.96); opacity: .76; }\r\n 87.5%{ transform: translate3d(0, calc( 0.7071 * var(--bwg-amp, 12px)), 0) scale(.97); opacity: .78; }\r\n 100% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .bwg-dotline .dot { animation: none; }\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n}\r\n\r\n/* 직선 도트 파동 인디케이터 */\r\nconst DotLineSmoothIndicator: React.FC<{\r\n colors?: string[]; // 각 점 색\r\n count?: number; // 점 개수 (기본: colors 길이)\r\n size?: number; // 점 지름\r\n gap?: number; // 점 간격\r\n amp?: number; // 진폭(px)\r\n speedMs?: number; // 한 주기(ms)\r\n direction?: 'ltr' | 'rtl'; // 파동 진행 방향\r\n phase?: number; // 점 간 지연 비율(0~1) — 낮출수록 부드러움\r\n}> = ({\r\n colors = ['#DAD3FF', '#B3A6FF', '#9380FF', '#816BFA'],\r\n count,\r\n size = 12,\r\n gap = 10,\r\n amp = 16,\r\n speedMs = 900,\r\n direction = 'ltr',\r\n phase = 0.7,\r\n}) => {\r\n useEffect(() => { ensureDotLineWaveStylesV4(); }, []);\r\n\r\n const n = count ?? colors.length;\r\n const dots = Array.from({ length: n });\r\n const baseStyle = {\r\n ['--bwg-size' as any]: `${size}px`,\r\n ['--bwg-gap' as any]: `${gap}px`,\r\n ['--bwg-amp' as any]: `${amp}px`,\r\n ['--bwg-speed' as any]: `${speedMs}ms`,\r\n } as React.CSSProperties;\r\n\r\n const perDotDelay = (speedMs / n) * phase;\r\n\r\n return (\r\n <span className=\"bwg-dotline\" role=\"img\" aria-label=\"loading\" style={baseStyle}>\r\n {dots.map((_, i) => (\r\n <span\r\n key={i}\r\n className=\"dot\"\r\n style={{\r\n backgroundColor: colors[i % colors.length],\r\n animationDelay:\r\n direction === 'ltr'\r\n ? `${(i * perDotDelay)}ms`\r\n : `${((n - 1 - i) * perDotDelay)}ms`,\r\n }}\r\n />\r\n ))}\r\n </span>\r\n );\r\n};\r\n\r\n\r\n/**\r\n * 진행 중 표시\r\n * @returns ProgressOverlay\r\n */\r\nconst ProgressOverlay: React.FC<{spin?: boolean | null; text?: string }> = ({spin = null, text = '인증중...',}) => {\r\n const { busy } = useAuth();\r\n const show = (spin ?? busy);\r\n if (!show) return null;\r\n return (\r\n <div\r\n style={{\r\n position: \"fixed\",\r\n height: \"100vh\",\r\n left: 0,\r\n right: 0,\r\n top: 0,\r\n display: \"flex\",\r\n flexDirection:'column',\r\n justifyContent: \"center\",\r\n alignItems: \"center\",\r\n gap: 8,\r\n padding: \"8px 12px\",\r\n background: \"rgba(0,0,0,0.6)\",\r\n color: \"#fff\",\r\n zIndex: 10000,\r\n }}\r\n aria-live=\"polite\"\r\n aria-busy=\"true\"\r\n role=\"status\"\r\n >\r\n <Spin\r\n indicator={\r\n <DotLineSmoothIndicator\r\n colors={['#DAD3FF', '#B3A6FF', '#9380FF', '#816BFA']}\r\n size={12}\r\n gap={10}\r\n amp={16}\r\n speedMs={900}\r\n phase={0.75} \r\n direction=\"ltr\"\r\n />\r\n }\r\n />\r\n <span className=\"bwg-spin-txt\" style={{marginTop:\"15px\"}}>{text}</span>\r\n </div>\r\n );\r\n };\r\n\r\nexport default ProgressOverlay;","import { useAuth } from \"@/provider/contexts/AuthContext\";\r\nimport { ScreenProtectProvider } from \"@/provider/contexts/ScreenProtectContext\";\r\nimport { isLocal } from \"@/utils/envUtils\";\r\nimport { ConfigProvider } from \"antd\";\r\nimport { Outlet } from \"react-router-dom\";\r\nimport ProgressOverlay from \"./ProgressOverlay\";\r\n\r\n/**\r\n * 보호 레이아웃\r\n * @returns ProtectedLayout\r\n */\r\nconst ProtectedLayout = () => {\r\n const { reauthWithPin } = useAuth();\r\n // NOTE: 인증 여부 체크는 각 페이지(/main)의 스토어 가드에 위임합니다.\r\n // 필요하다면 여기서도 RequireAuth로 감싸세요.\r\n return (\r\n <ScreenProtectProvider idleMs={30 * 60_000} onUnlock={async (pin) => {\r\n if(isLocal) {\r\n // 로컬에서는 항상 true\r\n return true;\r\n }\r\n return !!pin && (await reauthWithPin(pin));\r\n }}>\r\n {/* Ensure AntD portals mount inside protected shell if you need it */}\r\n <ConfigProvider getPopupContainer={() => document.getElementById(\"app-shell\") || document.body}>\r\n <div id=\"app-shell\">\r\n <ProgressOverlay />\r\n <Outlet />\r\n </div>\r\n </ConfigProvider>\r\n </ScreenProtectProvider>\r\n );\r\n }\r\n\r\n export default ProtectedLayout;","import { Outlet } from \"react-router-dom\";\r\nimport ProgressOverlay from \"./ProgressOverlay\";\r\n\r\n/**\r\n * 공개 레이아웃\r\n * @returns PublicLayout\r\n */\r\nconst PublicLayout = () => {\r\n return (\r\n <div>\r\n <ProgressOverlay />\r\n <Outlet />\r\n </div>\r\n );\r\n}\r\n\r\nexport default PublicLayout;","import { CloseOutlined, ExclamationCircleTwoTone } from \"@ant-design/icons\";\r\nimport { Button, Result, Space, Typography } from \"antd\";\r\nimport React, { memo, Suspense } from \"react\";\r\nimport { useMenuViewStore } from \"../../stores/menuViewStore\";\r\nimport { ErrorBound } from \"./ErrorBound\";\r\n\r\nconst ViewContainer = ({\r\n isActive,\r\n instance,\r\n params,\r\n }: {\r\n isActive: boolean;\r\n instance?: React.ComponentType;\r\n params?: Record<string, any>;\r\n }) => {\r\n const { activeMenuId, closeTab } = useMenuViewStore();\r\n\r\n // 현재 활성 탭 닫기 핸들러\r\n const onClose = () => {\r\n if (activeMenuId) {\r\n closeTab(activeMenuId);\r\n }\r\n };\r\n\r\n if(instance) {\r\n return (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n visibility: isActive ? 'visible' : 'hidden',\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? 'auto' : 'none',\r\n }}\r\n >\r\n <ErrorBound>\r\n <Suspense fallback={null}>\r\n {instance && React.createElement(instance, { params } as any)}\r\n </Suspense>\r\n </ErrorBound>\r\n </div>\r\n );\r\n } else {\r\n return (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n visibility: isActive ? 'visible' : 'hidden',\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? 'auto' : 'none',\r\n }}\r\n >\r\n <div\r\n style={{\r\n width: 500,\r\n maxWidth: '90%',\r\n background: '#fff',\r\n borderRadius: 16,\r\n boxShadow: '0 8px 30px rgba(0,0,0,0.05)',\r\n padding: 24,\r\n }}\r\n >\r\n <Result\r\n icon={<ExclamationCircleTwoTone twoToneColor=\"#69b1ff\" />}\r\n status=\"warning\"\r\n title=\"등록된 메뉴 정보가 없거나 유효한 메뉴가 아닙니다.\"\r\n subTitle={\r\n <Typography.Text type=\"secondary\">\r\n 자세한 내용은 관리자에게 문의바랍니다.\r\n </Typography.Text>\r\n }\r\n extra={\r\n <Space>\r\n <Button icon={<CloseOutlined />} onClick={onClose}>\r\n 탭 닫기\r\n </Button>\r\n </Space>\r\n }\r\n />\r\n </div>\r\n </div>\r\n );\r\n }\r\n};\r\n\r\nexport default memo(ViewContainer);"],"names":["ErrorBound","Component","props","error","errorInfo","jsxs","jsx","Result","Button","ReloadOutlined","createTabStyle","isActive","AutoLock","once","lock","useLock","called","useRef","useEffect","PrivateProtectedOverlay","flagged","tabKey","onUnlock","children","shellRef","ready","setReady","useState","setShellRef","useCallback","el","shellStyle","ScreenProtectProvider","DOTLINE_STYLE_ID","ensureDotLineWaveStylesV4","style","DotLineSmoothIndicator","colors","count","size","gap","amp","speedMs","direction","phase","n","dots","baseStyle","perDotDelay","_","i","ProgressOverlay","spin","text","busy","useAuth","Spin","ProtectedLayout","reauthWithPin","pin","isLocal","ConfigProvider","Outlet","PublicLayout","ViewContainer","instance","params","activeMenuId","closeTab","useMenuViewStore","onClose","Suspense","React","ExclamationCircleTwoTone","Typography","Space","CloseOutlined","ViewContainer$1","memo"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"apiUtils-DxzLqPhU.js","sources":["../../src/utils/serviceConfig.ts","../../node_modules/zustand/esm/middleware.mjs","../../src/stores/userStore.ts","../../src/utils/userUtils.ts","../../src/stores/menuModelStore.ts","../../src/stores/menuViewStore.ts","../../src/stores/loadingStore.ts","../../node_modules/dayjs/locale/ko.js","../../node_modules/dayjs/plugin/relativeTime.js","../../node_modules/dayjs/plugin/timezone.js","../../node_modules/dayjs/plugin/utc.js","../../src/utils/commonUtils.ts","../../src/utils/envUtils.ts","../../src/utils/notificationUtils.ts","../../src/utils/apiUtils.ts"],"sourcesContent":["/**\r\n * 서비스코드 관리 유틸리티\r\n * Provider 패턴을 우선적으로 사용하고, 기본값을 fallback으로 사용\r\n */\r\n\r\n// 서비스코드 기본값 정의\r\nconst DEFAULT_SERVICE_CODES = {\r\n // 권한 관련\r\n AUTH_BTNS: 'SCMSIGN00202', // 버튼 권한 조회\r\n AUTH_MENU: 'SCMSIGN00201', // 메뉴 권한 조회\r\n SRCH_CODE: 'SCMSIGN00301', // 코드 조회\r\n \r\n // 팝업 관련\r\n SRCH_POPU: 'SCMPOPU00101', // 팝업 조회\r\n \r\n // 즐겨찾기 관련\r\n AUTH_BMRK: 'SCMBMRK00101', // 즐겨찾기 관리\r\n} as const;\r\n\r\ntype ServiceCodeKey = keyof typeof DEFAULT_SERVICE_CODES;\r\n\r\n// Provider에서 설정된 서비스코드 오버라이드를 저장할 모듈 스코프 변수\r\nlet serviceCodeOverrides: Partial<Record<ServiceCodeKey, string>> = {};\r\n\r\n/**\r\n * Provider에서 설정된 서비스코드 오버라이드를 설정하는 함수\r\n * ServiceCodeProvider에서 내부적으로 사용\r\n */\r\nexport function setServiceCodeOverrides(overrides: Partial<Record<ServiceCodeKey, string>>): void {\r\n serviceCodeOverrides = overrides;\r\n console.log('🔧 Provider 서비스코드 오버라이드 설정:', overrides);\r\n}\r\n\r\n/**\r\n * 서비스코드 값을 가져오는 함수\r\n * Provider 설정 > 기본값 순서로 우선순위 적용\r\n * @param serviceCodeKey 서비스코드 키\r\n * @returns 실제 서비스코드 값\r\n */\r\nexport function getServiceCode(serviceCodeKey: ServiceCodeKey): string {\r\n // 1. Provider에서 설정된 값 우선 확인\r\n if (serviceCodeOverrides[serviceCodeKey] && serviceCodeOverrides[serviceCodeKey]!.trim() !== '') {\r\n //console.log(`🔧 Provider 설정 사용: ${serviceCodeKey} = ${serviceCodeOverrides[serviceCodeKey]}`);\r\n return serviceCodeOverrides[serviceCodeKey]!;\r\n }\r\n \r\n // 2. 기본값 사용\r\n const defaultValue = DEFAULT_SERVICE_CODES[serviceCodeKey];\r\n //console.log(`🔧 기본값 사용: ${serviceCodeKey} = ${defaultValue}`);\r\n return defaultValue;\r\n}\r\n\r\n/**\r\n * 모든 서비스코드를 한 번에 가져오는 함수\r\n * @returns 모든 서비스코드 객체\r\n */\r\nexport function getAllServiceCodes(): Record<ServiceCodeKey, string> {\r\n const result = {} as Record<ServiceCodeKey, string>;\r\n \r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n result[key] = getServiceCode(key);\r\n }\r\n \r\n return result;\r\n}\r\n\r\n/**\r\n * 서비스코드 설정을 초기화하는 함수\r\n * 개발 시 설정 확인용\r\n */\r\nexport function logServiceCodeConfig(): void {\r\n console.log('🔧 bwg-core 서비스코드 설정:');\r\n console.log('📋 Provider 설정 > 기본값 순서로 확인');\r\n \r\n const allCodes = getAllServiceCodes();\r\n for (const [key, value] of Object.entries(allCodes)) {\r\n const source = serviceCodeOverrides[key as ServiceCodeKey] ? 'Provider 설정' : '기본값';\r\n console.log(` ${key}: ${value} (${source})`);\r\n }\r\n}\r\n\r\n// 타입 내보내기\r\nexport type { ServiceCodeKey };\r\n\r\n","const reduxImpl = (reducer, initial) => (set, _get, api) => {\n api.dispatch = (action) => {\n set((state) => reducer(state, action), false, action);\n return action;\n };\n api.dispatchFromDevtools = true;\n return { dispatch: (...args) => api.dispatch(...args), ...initial };\n};\nconst redux = reduxImpl;\n\nconst trackedConnections = /* @__PURE__ */ new Map();\nconst getTrackedConnectionState = (name) => {\n const api = trackedConnections.get(name);\n if (!api) return {};\n return Object.fromEntries(\n Object.entries(api.stores).map(([key, api2]) => [key, api2.getState()])\n );\n};\nconst extractConnectionInformation = (store, extensionConnector, options) => {\n if (store === void 0) {\n return {\n type: \"untracked\",\n connection: extensionConnector.connect(options)\n };\n }\n const existingConnection = trackedConnections.get(options.name);\n if (existingConnection) {\n return { type: \"tracked\", store, ...existingConnection };\n }\n const newConnection = {\n connection: extensionConnector.connect(options),\n stores: {}\n };\n trackedConnections.set(options.name, newConnection);\n return { type: \"tracked\", store, ...newConnection };\n};\nconst removeStoreFromTrackedConnections = (name, store) => {\n if (store === void 0) return;\n const connectionInfo = trackedConnections.get(name);\n if (!connectionInfo) return;\n delete connectionInfo.stores[store];\n if (Object.keys(connectionInfo.stores).length === 0) {\n trackedConnections.delete(name);\n }\n};\nconst findCallerName = (stack) => {\n var _a, _b;\n if (!stack) return void 0;\n const traceLines = stack.split(\"\\n\");\n const apiSetStateLineIndex = traceLines.findIndex(\n (traceLine) => traceLine.includes(\"api.setState\")\n );\n if (apiSetStateLineIndex < 0) return void 0;\n const callerLine = ((_a = traceLines[apiSetStateLineIndex + 1]) == null ? void 0 : _a.trim()) || \"\";\n return (_b = /.+ (.+) .+/.exec(callerLine)) == null ? void 0 : _b[1];\n};\nconst devtoolsImpl = (fn, devtoolsOptions = {}) => (set, get, api) => {\n const { enabled, anonymousActionType, store, ...options } = devtoolsOptions;\n let extensionConnector;\n try {\n extensionConnector = (enabled != null ? enabled : (import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") && window.__REDUX_DEVTOOLS_EXTENSION__;\n } catch (e) {\n }\n if (!extensionConnector) {\n return fn(set, get, api);\n }\n const { connection, ...connectionInformation } = extractConnectionInformation(store, extensionConnector, options);\n let isRecording = true;\n api.setState = ((state, replace, nameOrAction) => {\n const r = set(state, replace);\n if (!isRecording) return r;\n const action = nameOrAction === void 0 ? {\n type: anonymousActionType || findCallerName(new Error().stack) || \"anonymous\"\n } : typeof nameOrAction === \"string\" ? { type: nameOrAction } : nameOrAction;\n if (store === void 0) {\n connection == null ? void 0 : connection.send(action, get());\n return r;\n }\n connection == null ? void 0 : connection.send(\n {\n ...action,\n type: `${store}/${action.type}`\n },\n {\n ...getTrackedConnectionState(options.name),\n [store]: api.getState()\n }\n );\n return r;\n });\n api.devtools = {\n cleanup: () => {\n if (connection && typeof connection.unsubscribe === \"function\") {\n connection.unsubscribe();\n }\n removeStoreFromTrackedConnections(options.name, store);\n }\n };\n const setStateFromDevtools = (...a) => {\n const originalIsRecording = isRecording;\n isRecording = false;\n set(...a);\n isRecording = originalIsRecording;\n };\n const initialState = fn(api.setState, get, api);\n if (connectionInformation.type === \"untracked\") {\n connection == null ? void 0 : connection.init(initialState);\n } else {\n connectionInformation.stores[connectionInformation.store] = api;\n connection == null ? void 0 : connection.init(\n Object.fromEntries(\n Object.entries(connectionInformation.stores).map(([key, store2]) => [\n key,\n key === connectionInformation.store ? initialState : store2.getState()\n ])\n )\n );\n }\n if (api.dispatchFromDevtools && typeof api.dispatch === \"function\") {\n let didWarnAboutReservedActionType = false;\n const originalDispatch = api.dispatch;\n api.dispatch = (...args) => {\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\" && args[0].type === \"__setState\" && !didWarnAboutReservedActionType) {\n console.warn(\n '[zustand devtools middleware] \"__setState\" action type is reserved to set state from the devtools. Avoid using it.'\n );\n didWarnAboutReservedActionType = true;\n }\n originalDispatch(...args);\n };\n }\n connection.subscribe((message) => {\n var _a;\n switch (message.type) {\n case \"ACTION\":\n if (typeof message.payload !== \"string\") {\n console.error(\n \"[zustand devtools middleware] Unsupported action format\"\n );\n return;\n }\n return parseJsonThen(\n message.payload,\n (action) => {\n if (action.type === \"__setState\") {\n if (store === void 0) {\n setStateFromDevtools(action.state);\n return;\n }\n if (Object.keys(action.state).length !== 1) {\n console.error(\n `\n [zustand devtools middleware] Unsupported __setState action format.\n When using 'store' option in devtools(), the 'state' should have only one key, which is a value of 'store' that was passed in devtools(),\n and value of this only key should be a state object. Example: { \"type\": \"__setState\", \"state\": { \"abc123Store\": { \"foo\": \"bar\" } } }\n `\n );\n }\n const stateFromDevtools = action.state[store];\n if (stateFromDevtools === void 0 || stateFromDevtools === null) {\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(stateFromDevtools)) {\n setStateFromDevtools(stateFromDevtools);\n }\n return;\n }\n if (!api.dispatchFromDevtools) return;\n if (typeof api.dispatch !== \"function\") return;\n api.dispatch(action);\n }\n );\n case \"DISPATCH\":\n switch (message.payload.type) {\n case \"RESET\":\n setStateFromDevtools(initialState);\n if (store === void 0) {\n return connection == null ? void 0 : connection.init(api.getState());\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"COMMIT\":\n if (store === void 0) {\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n return connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n case \"ROLLBACK\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n connection == null ? void 0 : connection.init(api.getState());\n return;\n }\n setStateFromDevtools(state[store]);\n connection == null ? void 0 : connection.init(getTrackedConnectionState(options.name));\n });\n case \"JUMP_TO_STATE\":\n case \"JUMP_TO_ACTION\":\n return parseJsonThen(message.state, (state) => {\n if (store === void 0) {\n setStateFromDevtools(state);\n return;\n }\n if (JSON.stringify(api.getState()) !== JSON.stringify(state[store])) {\n setStateFromDevtools(state[store]);\n }\n });\n case \"IMPORT_STATE\": {\n const { nextLiftedState } = message.payload;\n const lastComputedState = (_a = nextLiftedState.computedStates.slice(-1)[0]) == null ? void 0 : _a.state;\n if (!lastComputedState) return;\n if (store === void 0) {\n setStateFromDevtools(lastComputedState);\n } else {\n setStateFromDevtools(lastComputedState[store]);\n }\n connection == null ? void 0 : connection.send(\n null,\n // FIXME no-any\n nextLiftedState\n );\n return;\n }\n case \"PAUSE_RECORDING\":\n return isRecording = !isRecording;\n }\n return;\n }\n });\n return initialState;\n};\nconst devtools = devtoolsImpl;\nconst parseJsonThen = (stringified, fn) => {\n let parsed;\n try {\n parsed = JSON.parse(stringified);\n } catch (e) {\n console.error(\n \"[zustand devtools middleware] Could not parse the received json\",\n e\n );\n }\n if (parsed !== void 0) fn(parsed);\n};\n\nconst subscribeWithSelectorImpl = (fn) => (set, get, api) => {\n const origSubscribe = api.subscribe;\n api.subscribe = ((selector, optListener, options) => {\n let listener = selector;\n if (optListener) {\n const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;\n let currentSlice = selector(api.getState());\n listener = (state) => {\n const nextSlice = selector(state);\n if (!equalityFn(currentSlice, nextSlice)) {\n const previousSlice = currentSlice;\n optListener(currentSlice = nextSlice, previousSlice);\n }\n };\n if (options == null ? void 0 : options.fireImmediately) {\n optListener(currentSlice, currentSlice);\n }\n }\n return origSubscribe(listener);\n });\n const initialState = fn(set, get, api);\n return initialState;\n};\nconst subscribeWithSelector = subscribeWithSelectorImpl;\n\nfunction combine(initialState, create) {\n return (...args) => Object.assign({}, initialState, create(...args));\n}\n\nfunction createJSONStorage(getStorage, options) {\n let storage;\n try {\n storage = getStorage();\n } catch (e) {\n return;\n }\n const persistStorage = {\n getItem: (name) => {\n var _a;\n const parse = (str2) => {\n if (str2 === null) {\n return null;\n }\n return JSON.parse(str2, options == null ? void 0 : options.reviver);\n };\n const str = (_a = storage.getItem(name)) != null ? _a : null;\n if (str instanceof Promise) {\n return str.then(parse);\n }\n return parse(str);\n },\n setItem: (name, newValue) => storage.setItem(name, JSON.stringify(newValue, options == null ? void 0 : options.replacer)),\n removeItem: (name) => storage.removeItem(name)\n };\n return persistStorage;\n}\nconst toThenable = (fn) => (input) => {\n try {\n const result = fn(input);\n if (result instanceof Promise) {\n return result;\n }\n return {\n then(onFulfilled) {\n return toThenable(onFulfilled)(result);\n },\n catch(_onRejected) {\n return this;\n }\n };\n } catch (e) {\n return {\n then(_onFulfilled) {\n return this;\n },\n catch(onRejected) {\n return toThenable(onRejected)(e);\n }\n };\n }\n};\nconst persistImpl = (config, baseOptions) => (set, get, api) => {\n let options = {\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => state,\n version: 0,\n merge: (persistedState, currentState) => ({\n ...currentState,\n ...persistedState\n }),\n ...baseOptions\n };\n let hasHydrated = false;\n const hydrationListeners = /* @__PURE__ */ new Set();\n const finishHydrationListeners = /* @__PURE__ */ new Set();\n let storage = options.storage;\n if (!storage) {\n return config(\n (...args) => {\n console.warn(\n `[zustand persist middleware] Unable to update item '${options.name}', the given storage is currently unavailable.`\n );\n set(...args);\n },\n get,\n api\n );\n }\n const setItem = () => {\n const state = options.partialize({ ...get() });\n return storage.setItem(options.name, {\n state,\n version: options.version\n });\n };\n const savedSetState = api.setState;\n api.setState = (state, replace) => {\n savedSetState(state, replace);\n return setItem();\n };\n const configResult = config(\n (...args) => {\n set(...args);\n return setItem();\n },\n get,\n api\n );\n api.getInitialState = () => configResult;\n let stateFromStorage;\n const hydrate = () => {\n var _a, _b;\n if (!storage) return;\n hasHydrated = false;\n hydrationListeners.forEach((cb) => {\n var _a2;\n return cb((_a2 = get()) != null ? _a2 : configResult);\n });\n const postRehydrationCallback = ((_b = options.onRehydrateStorage) == null ? void 0 : _b.call(options, (_a = get()) != null ? _a : configResult)) || void 0;\n return toThenable(storage.getItem.bind(storage))(options.name).then((deserializedStorageValue) => {\n if (deserializedStorageValue) {\n if (typeof deserializedStorageValue.version === \"number\" && deserializedStorageValue.version !== options.version) {\n if (options.migrate) {\n const migration = options.migrate(\n deserializedStorageValue.state,\n deserializedStorageValue.version\n );\n if (migration instanceof Promise) {\n return migration.then((result) => [true, result]);\n }\n return [true, migration];\n }\n console.error(\n `State loaded from storage couldn't be migrated since no migrate function was provided`\n );\n } else {\n return [false, deserializedStorageValue.state];\n }\n }\n return [false, void 0];\n }).then((migrationResult) => {\n var _a2;\n const [migrated, migratedState] = migrationResult;\n stateFromStorage = options.merge(\n migratedState,\n (_a2 = get()) != null ? _a2 : configResult\n );\n set(stateFromStorage, true);\n if (migrated) {\n return setItem();\n }\n }).then(() => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(stateFromStorage, void 0);\n stateFromStorage = get();\n hasHydrated = true;\n finishHydrationListeners.forEach((cb) => cb(stateFromStorage));\n }).catch((e) => {\n postRehydrationCallback == null ? void 0 : postRehydrationCallback(void 0, e);\n });\n };\n api.persist = {\n setOptions: (newOptions) => {\n options = {\n ...options,\n ...newOptions\n };\n if (newOptions.storage) {\n storage = newOptions.storage;\n }\n },\n clearStorage: () => {\n storage == null ? void 0 : storage.removeItem(options.name);\n },\n getOptions: () => options,\n rehydrate: () => hydrate(),\n hasHydrated: () => hasHydrated,\n onHydrate: (cb) => {\n hydrationListeners.add(cb);\n return () => {\n hydrationListeners.delete(cb);\n };\n },\n onFinishHydration: (cb) => {\n finishHydrationListeners.add(cb);\n return () => {\n finishHydrationListeners.delete(cb);\n };\n }\n };\n if (!options.skipHydration) {\n hydrate();\n }\n return stateFromStorage || configResult;\n};\nconst persist = persistImpl;\n\nexport { combine, createJSONStorage, devtools, persist, redux, subscribeWithSelector };\n","import { create } from 'zustand'\r\nimport { persist } from 'zustand/middleware'\r\n\r\n// 사용자 타입 정의\r\nexport interface UserInfo {\r\n crprCd: string | number // 회사정보\r\n userId: string // 사용자ID\r\n userNm: string // 사용자명\r\n userDvsn: string // 사용자구분\r\n emplNo: string // 사번\r\n dprtCd: string | number // 부서코드\r\n dprtNm: string // 부서명\r\n roleList: string[] // 사용자 역할목록\r\n}\r\n\r\n// 사용자 스토어 타입 정의\r\nexport interface UserStore {\r\n user: UserInfo | null\r\n isLoggedIn: boolean\r\n login: (user: UserInfo) => void\r\n logout: () => void\r\n updateUser: (userData: Partial<UserInfo>) => void\r\n}\r\n\r\n// 사용자 스토어 생성 (지속성 포함)\r\nexport const useUserStore = create<UserStore>()(\r\n persist(\r\n (set, get) => ({\r\n user: null,\r\n isLoggedIn: false,\r\n\r\n // 로그인\r\n login: (user: UserInfo) => {\r\n set({ user, isLoggedIn: true })\r\n console.log('사용자 로그인:', user)\r\n },\r\n\r\n // 로그아웃\r\n logout: () => {\r\n set({ user: null, isLoggedIn: false })\r\n console.log('사용자 로그아웃')\r\n },\r\n\r\n // 사용자 정보 업데이트\r\n updateUser: (userData: Partial<UserInfo>) => {\r\n const currentUser = get().user\r\n if (currentUser) {\r\n set({ user: { ...currentUser, ...userData } })\r\n }\r\n }\r\n }),\r\n {\r\n name: 'user-storage', // 로컬 스토리지 키\r\n partialize: (state) => ({ \r\n user: state.user, \r\n isLoggedIn: state.isLoggedIn \r\n }) // 저장할 상태만 선택\r\n }\r\n )\r\n) ","import { useUserStore } from '../stores/userStore'\r\n\r\n/**\r\n * 사용자 정보 관련 유틸리티 함수들\r\n */\r\n\r\n// 회사정보 가져오기\r\nexport const getCrprCd = (): string | number | null => {\r\n const user = useUserStore.getState().user\r\n return user?.crprCd || null\r\n}\r\n\r\n// 사용자ID 가져오기\r\nexport const getUserId = (): string | null => {\r\n const user = useUserStore.getState().user\r\n return user?.userId || null\r\n}\r\n\r\n// 사용자명 가져오기\r\nexport const getUserNm = (): string | null => {\r\n const user = useUserStore.getState().user\r\n return user?.userNm || null\r\n}\r\n\r\n// 사용자구분 가져오기\r\nexport const getUserDvsn = (): string | null => {\r\n const user = useUserStore.getState().user\r\n return user?.userDvsn || null\r\n}\r\n\r\n// 사번 가져오기\r\nexport const getEmplNo = (): string | null => {\r\n const user = useUserStore.getState().user\r\n return user?.emplNo || null\r\n}\r\n\r\n// 부서코드 가져오기\r\nexport const getDprtCd = (): string | number | null => {\r\n const user = useUserStore.getState().user\r\n return user?.dprtCd || null\r\n}\r\n\r\n// 부서명 가져오기\r\nexport const getDprtNm = (): string | null => {\r\n const user = useUserStore.getState().user\r\n return user?.dprtNm || null\r\n}\r\n\r\n// 사용자 역할목록 가져오기\r\nexport const getRoleList = (): string[] | null => {\r\n const user = useUserStore.getState().user\r\n return user?.roleList || null\r\n}\r\n\r\n// 특정 역할이 있는지 확인\r\nexport const hasRole = (role: string): boolean => {\r\n const roleList = getRoleList()\r\n return roleList ? roleList.includes(role) : false\r\n}\r\n\r\n// 여러 역할 중 하나라도 있는지 확인\r\nexport const hasAnyRole = (roles: string[]): boolean => {\r\n const roleList = getRoleList()\r\n if (!roleList) return false\r\n return roles.some(role => roleList.includes(role))\r\n}\r\n\r\n// 모든 역할이 있는지 확인\r\nexport const hasAllRoles = (roles: string[]): boolean => {\r\n const roleList = getRoleList()\r\n if (!roleList) return false\r\n return roles.every(role => roleList.includes(role))\r\n}\r\n\r\n// 로그인 상태 확인\r\nexport const isLoggedIn = (): boolean => {\r\n return useUserStore.getState().isLoggedIn\r\n}\r\n\r\n// 전체 사용자 정보 가져오기\r\nexport const getUserInfo = () => {\r\n return useUserStore.getState().user\r\n}\r\n\r\n// 사용자 정보가 있는지 확인\r\nexport const hasUserInfo = (): boolean => {\r\n const user = getUserInfo()\r\n return user !== null\r\n}\r\n\r\n// 사용자 표시명 가져오기 (사용자명이 없으면 사용자ID 반환)\r\nexport const getDisplayName = (): string | null => {\r\n const userNm = getUserNm()\r\n const userId = getUserId()\r\n return userNm || userId || null\r\n}\r\n\r\n// 부서 정보 가져오기 (부서명이 있으면 부서명, 없으면 부서코드)\r\nexport const getDepartmentInfo = (): string | null => {\r\n const dprtNm = getDprtNm()\r\n const dprtCd = getDprtCd()\r\n return dprtNm || (dprtCd ? String(dprtCd) : null)\r\n} ","import { create } from \"zustand\";\r\n// 필요에 맞게 경로 조정\r\nimport { callService } from \"@/utils/apiUtils\";\r\nimport { getServiceCode } from \"@/utils/serviceConfig\";\r\n\r\n/* ──── Constants ──── */\r\nconst MENU_CONSTANTS = {\r\n DEFAULT_ACTIVE_MENU: \"1\",\r\n DEFAULT_PRNT_GBCD: 1,\r\n COMPANY_CODE: \"100\",\r\n MENU_PARENT_ROOT: \"-\",\r\n MENU_TYPE: { MAIN: \"CMPRGRM\", SUB: \"CMPRGRS\", PROGRAM: \"CMPRGRP\" } as const,\r\n} as const;\r\n\r\n/* ──── Types (이 파일 전용) ──── */\r\nexport interface MenuItem {\r\n crprCd: string;\r\n menuGbCd: string;\r\n menuPrntId: string;\r\n menuId: string;\r\n menuNm: string;\r\n menuNo?: number;\r\n scrnId?: string;\r\n scrnPath?: string;\r\n prsnInfoYn?: \"Y\" | \"N\";\r\n rootMenu: string;\r\n iconCd?: string;\r\n children?: MenuItem[];\r\n}\r\n\r\nexport type FetchMenuParams = {\r\n crprCd: string;\r\n userId: string;\r\n prntGbcd: number;\r\n};\r\n\r\nexport interface MenuApiResponse {\r\n menus?: MenuItem[];\r\n [k: string]: any;\r\n}\r\n\r\n/* 런타임 타입가드 */\r\nconst isMenuItem = (v: any): v is MenuItem =>\r\n v &&\r\n typeof v === 'object' &&\r\n typeof v.menuId === 'string' &&\r\n typeof v.menuNm === 'string';\r\n\r\nconst isMenuItemArray = (v: any): v is MenuItem[] =>\r\n Array.isArray(v) && v.every(isMenuItem);\r\n\r\n/* ──── State Shape ──── */\r\ntype MenuModelState = {\r\n // 📊 State (상태)\r\n // 계층형 메뉴 트리 구조 (부모-자식 관계)\r\n menuList: MenuItem[];\r\n // 평면화된 메뉴 리스트 (검색/조회용)\r\n flatMenuList: MenuItem[];\r\n // 메뉴 데이터 로딩 상태\r\n isLoading: boolean;\r\n // 에러 메시지\r\n error: string | null;\r\n // 마지막 조회 파라미터 (중복 요청 방지)\r\n _lastFetchParams: FetchMenuParams | null;\r\n\r\n // 🔧 Actions (액션 함수들)\r\n // 서버에서 메뉴 데이터 조회\r\n fetchMenu: (p: FetchMenuParams) => Promise<void>;\r\n // 메뉴 데이터 초기화\r\n clearMenu: () => void;\r\n // 메뉴 ID로 특정 메뉴 찾기\r\n findMenuById: (menuId: string) => MenuItem | null;\r\n};\r\n\r\n/* ──── Local Memoization Cache ──── */\r\nlet _lastFlat: MenuItem[] = [];\r\nlet _cachedTree: MenuItem[] = [];\r\n\r\n/* ──── Helpers ──── */\r\nconst parseMenuResponse = (data: unknown): MenuItem[] => {\r\n if (data && typeof data === \"object\") {\r\n const r = data as MenuApiResponse;\r\n if (r.menus && isMenuItemArray(r.menus)) return r.menus;\r\n if (isMenuItemArray(data)) return data;\r\n }\r\n console.warn(\"⚠️ 메뉴 응답이 비어있거나 예상과 다릅니다.\");\r\n return [];\r\n};\r\n\r\nconst sameParams = (a: FetchMenuParams, b: FetchMenuParams | null) =>\r\n !!b &&\r\n a.crprCd === b.crprCd &&\r\n a.userId === b.userId &&\r\n (a.prntGbcd ?? MENU_CONSTANTS.DEFAULT_PRNT_GBCD) ===\r\n (b.prntGbcd ?? MENU_CONSTANTS.DEFAULT_PRNT_GBCD);\r\n\r\nconst buildHierarchy = (flat: MenuItem[]): MenuItem[] => {\r\n if (\r\n _lastFlat.length === flat.length &&\r\n _lastFlat.every(\r\n (x, i) =>\r\n x.menuId === flat[i]?.menuId && x.menuPrntId === flat[i]?.menuPrntId\r\n )\r\n )\r\n return _cachedTree;\r\n\r\n if (!flat.length) return [];\r\n\r\n const map = new Map<string, MenuItem>();\r\n const roots: MenuItem[] = [];\r\n\r\n flat.forEach((m) => m?.menuId && map.set(m.menuId, { ...m, children: [] }));\r\n flat.forEach((m) => {\r\n const cur = map.get(m.menuId);\r\n if (!cur) return;\r\n if (m.menuPrntId && m.menuPrntId !== \"\" && m.menuPrntId !== \"-\") {\r\n const p = map.get(m.menuPrntId);\r\n p?.children?.push(cur);\r\n } else {\r\n roots.push(cur);\r\n }\r\n });\r\n\r\n const sortRec = (arr: MenuItem[]): MenuItem[] =>\r\n arr\r\n .sort((a, b) => (a?.menuNo ?? 0) - (b?.menuNo ?? 0))\r\n .map((x) => ({\r\n ...x,\r\n children:\r\n x.children && x.children.length ? sortRec(x.children) : undefined,\r\n }));\r\n\r\n const out = sortRec(roots);\r\n _lastFlat = [...flat];\r\n _cachedTree = out;\r\n return out;\r\n};\r\n\r\n/* ──── Store ──── */\r\nexport const useMenuModelStore = create<MenuModelState>((set, get) => ({\r\n // 📊 초기 상태값\r\n menuList: [],\r\n flatMenuList: [],\r\n isLoading: false,\r\n error: null,\r\n _lastFetchParams: null,\r\n\r\n // 🔧 메뉴 모델 조회\r\n // 서버에서 사용자별 메뉴 권한 데이터를 가져와서 트리/플랫 구조로 저장\r\n fetchMenu: async ({ crprCd, userId, prntGbcd }: FetchMenuParams) => {\r\n const p = {\r\n crprCd,\r\n userId,\r\n prntGbcd: prntGbcd ?? MENU_CONSTANTS.DEFAULT_PRNT_GBCD,\r\n };\r\n // 중복 요청 방지\r\n if (sameParams(p, get()._lastFetchParams)) {\r\n console.log(\"✅ 중복 fetch 차단\", p);\r\n return;\r\n }\r\n set({ isLoading: true, error: null, _lastFetchParams: p });\r\n try {\r\n // API 호출하여 메뉴 데이터 가져오기\r\n const data = await callService(getServiceCode(\"AUTH_MENU\"), p);\r\n const flat = parseMenuResponse(data); // 응답 데이터 파싱\r\n const tree = buildHierarchy(flat); // 계층 구조 생성\r\n set({\r\n flatMenuList: flat, // 평면 리스트 저장\r\n menuList: tree, // 트리 구조 저장\r\n isLoading: false,\r\n error: null,\r\n });\r\n } catch (e: any) {\r\n set({ isLoading: false, error: e?.message ?? \"메뉴 로드 실패\" });\r\n }\r\n },\r\n\r\n // 🔧 메뉴 모델 초기화\r\n // 로그아웃 시나 사용자 변경 시 메뉴 모델 클리어\r\n clearMenu: () => {\r\n set({\r\n menuList: [],\r\n flatMenuList: [],\r\n error: null,\r\n _lastFetchParams: null,\r\n });\r\n },\r\n\r\n // 🔧 메뉴 ID로 메뉴 아이템 찾기\r\n // URL 파라미터나 프로그래밍 방식으로 특정 메뉴를 찾을 때 사용\r\n findMenuById: (menuId: string) => {\r\n const { flatMenuList } = get();\r\n return flatMenuList.find((m) => m.menuId === menuId) ?? null;\r\n },\r\n}));\r\n","import { message } from \"antd\";\r\nimport { create } from \"zustand\";\r\nimport { MenuItem, useMenuModelStore } from \"./menuModelStore\";\r\n\r\n/* ──── Constants (UI 측에도 독립적으로 존재) ──── */\r\nconst MENU_CONSTANTS = {\r\n DEFAULT_ACTIVE_MENU: \"1\",\r\n MAX_TABS: 15,\r\n} as const;\r\n\r\nexport interface ViewItem {\r\n viewId: string;\r\n viewLabel: string | React.ReactNode;\r\n viewParams?: Record<string, any>;\r\n prntInfo?:{\r\n menuId: string;\r\n menuNm: string;\r\n }\r\n}\r\n\r\n/* ──── Types (이 파일 전용) ──── */\r\nexport interface TabItem {\r\n key: string; // menuId\r\n label: string | React.ReactNode; // menuNm\r\n gubun: \"M\" | \"C\"; // menuId or componentPath\r\n menuItem?: MenuItem;\r\n componentItem?: {\r\n scrnPath: string;\r\n prsnInfoYn?: \"Y\" | \"N\";\r\n prntInfo?: {\r\n menuId: string;\r\n menuNm: string;\r\n };\r\n };\r\n closable: boolean;\r\n}\r\n\r\n\r\n/* ──── State Shape ──── */\r\ntype MenuViewState = {\r\n // 📊 UI State (화면 상태)\r\n // 현재 활성화된 메뉴 ID\r\n activeMenuId: string | undefined | null;\r\n // 현재 활성화된 메뉴 정보\r\n activeMenuItem: MenuItem | null;\r\n // 현재 활성화된 상세 정보\r\n activeDetailItem: ViewItem | null;\r\n // 열린 탭 목록\r\n tabs: TabItem[];\r\n // 사이드바 접힘/펼침 상태\r\n sidebarCollapsed: boolean;\r\n // 최대 탭 개수\r\n maxTabs: number;\r\n tabProtectFlag: Record<string, boolean>;\r\n // 탭 파라미터\r\n tabParams: Record<string, Record<string, any>>;\r\n // 컴포넌트 라벨 맵\r\n componentLabelMap: Record<string, string>;\r\n\r\n /* 🛠 UI Actions (UI 액션 함수들) */\r\n // 메뉴 아이템으로 탭 추가\r\n openTabFromMenu: (menuItem: MenuItem, params?: Record<string, any>) => void;\r\n // 메뉴 ID로 탭 추가 (URL 파라미터 처리용)\r\n openTabByMenuId: (menuId: string, params?: Record<string, any>) => void;\r\n /**\r\n * 상세 탭 추가\r\n * @param viewInfo 상세 컴포넌트 정보\r\n * @param scrnPath 상세 컴포넌트 경로\r\n * @returns \r\n * @description 상세 탭 추가\r\n */\r\n openDetailView: (viewInfo: ViewItem, scrnPath: string, prsnInfoYn?: \"Y\" | \"N\") => void;\r\n // 활성 탭 변경\r\n focusTab: (tabKey: string) => void;\r\n // 탭 제거\r\n closeTab: (tabKey: string) => void;\r\n // 모든 탭 제거\r\n closeAllTabs: () => void;\r\n // 사이드바 토글\r\n toggleSidebar: () => void;\r\n // 탭 순서 변경\r\n reorderTabs: (keys: string[]) => void;\r\n // 개인정보 포함여부에 따른 탭 잠금 Flag 설정\r\n setProtectFlagForKey: (key: string) => void;\r\n // 개인정보 포함여부에 따른 탭 잠금 해제\r\n clearProtectFlagForKey: (key: string) => void;\r\n // 탭 파라미터 설정\r\n setTabParams: (key: string, params: Record<string, any>) => void;\r\n //컴포넌트 라벨 맵 설정\r\n setComponentLabelMap: (map: Record<string, string>, merge?: boolean) => void;\r\n};\r\n\r\n/* ──── Store ──── */\r\nexport const useMenuViewStore = create<MenuViewState>((set, get) => ({\r\n // 📊 초기 상태값\r\n activeMenuId: null,\r\n activeMenuItem: null,\r\n activeDetailItem: null,\r\n tabs: [],\r\n sidebarCollapsed: false,\r\n maxTabs: MENU_CONSTANTS.MAX_TABS,\r\n tabProtectFlag: {},\r\n tabParams: {},\r\n componentLabelMap: {},\r\n // 🔧 탭 추가 (메뉴 아이템 객체로)\r\n // 사이드바에서 메뉴 클릭 시 호출되는 메인 함수\r\n openTabFromMenu: (menuItem, params) => {\r\n const { tabs, activeMenuId } = get();\r\n const exists = tabs.find((t) => t.key === menuItem.menuId);\r\n const findTab = tabs.find((t) => t.key === menuItem.menuId);\r\n\r\n // 새 탭 생성\r\n if (!exists) {\r\n // 2. 최대 탭 개수 확인\r\n if (tabs.length > MENU_CONSTANTS.MAX_TABS) {\r\n console.warn(\"❌ 최대 탭 개수를 초과했습니다.\");\r\n message.warning(\r\n `최대 ${MENU_CONSTANTS.MAX_TABS}개의 탭만 열 수 있습니다.\\n기존 탭을 닫고 다시 시도해주세요.`\r\n );\r\n return;\r\n }\r\n const newTab: TabItem = {\r\n key: menuItem.menuId,\r\n label: menuItem.menuNm,\r\n gubun: \"M\",\r\n menuItem: menuItem as MenuItem,\r\n closable: true,\r\n };\r\n set({\r\n tabs: [...tabs, newTab], // 탭 목록에 추가\r\n activeMenuId: menuItem.menuId, // 새 탭을 활성화\r\n activeMenuItem: menuItem, // 현재 프로그램으로 설정\r\n });\r\n get().setTabParams(menuItem.menuId, params || {});\r\n //console.log(\"✅ 새 탭 추가 - activeMenuItem:\", menuItem);\r\n\r\n // 개인정보 메뉴만 Protect\r\n if (menuItem?.prsnInfoYn === \"Y\") {\r\n get().setProtectFlagForKey(menuItem.menuId);\r\n }\r\n } else if (findTab !== null && findTab !== undefined) {\r\n // 이미 존재하는 탭이면 활성화만\r\n set({ activeMenuId: menuItem.menuId, activeMenuItem: menuItem });\r\n //console.log(\"✅ 기존 탭 활성화 - activeMenuItem:\", menuItem);\r\n get().setTabParams(menuItem.menuId, params || {});\r\n // 개인정보 메뉴만 Protect\r\n if (menuItem?.prsnInfoYn === \"Y\") {\r\n get().setProtectFlagForKey(menuItem.menuId);\r\n }\r\n } else {\r\n //console.warn(\"❌ 유효하지 않은 메뉴정보\", menuItem.menuId);\r\n message.warning(\"유효하지 않은 메뉴정보입니다.\");\r\n }\r\n },\r\n // 🔧 탭 추가 (메뉴 ID로)\r\n // URL 파라미터로 메뉴 열기 시 사용 (예: ?menuId=CM000301)\r\n openTabByMenuId: (menuId, params) => {\r\n const target = useMenuModelStore.getState().findMenuById(menuId);\r\n if (!target) {\r\n //console.warn(\"❌ 메뉴 ID를 찾을 수 없음:\", menuId);\r\n message.warning(\"메뉴 ID를 찾을 수 없습니다.\");\r\n } else {\r\n get().openTabFromMenu(target, params); // 찾은 메뉴로 탭 추가\r\n }\r\n },\r\n openDetailView: (viewInfo, scrnPath, prsnInfoYn) => {\r\n const { tabs, activeMenuId } = get();\r\n const exists = tabs.find((t) => t.key === viewInfo.viewId);\r\n \r\n if (!exists) {\r\n const newTab: TabItem = {\r\n key: viewInfo.viewId,\r\n label: viewInfo.viewLabel,\r\n gubun: \"C\",\r\n componentItem: {\r\n scrnPath: scrnPath,\r\n prsnInfoYn: prsnInfoYn,\r\n prntInfo: viewInfo.prntInfo,\r\n },\r\n closable: true,\r\n };\r\n set({\r\n tabs: [...tabs, newTab], // 탭 목록에 추가\r\n activeMenuId: viewInfo.viewId, // 새 탭을 활성화\r\n activeDetailItem: viewInfo,\r\n });\r\n get().setTabParams(viewInfo.viewId, viewInfo.viewParams || {});\r\n } else {\r\n get().focusTab(viewInfo.viewId);\r\n }\r\n },\r\n // 🔧 탭 제거\r\n // X 버튼 클릭 시 탭을 닫고 관련 상태도 정리\r\n closeTab: (tabKey) => {\r\n const { tabs, activeMenuId } = get();\r\n const removed = tabs.find((t) => t.key === tabKey);\r\n const nextTabs = tabs.filter((t) => t.key !== tabKey);\r\n\r\n // 닫힌 탭이 현재 활성 탭이면 다음 탭으로 이동\r\n let nextActive = activeMenuId;\r\n if (activeMenuId === tabKey) {\r\n const idx = tabs.findIndex((t) => t.key === tabKey);\r\n nextActive = nextTabs.length\r\n ? nextTabs[Math.min(idx, nextTabs.length - 1)]?.key ?? null\r\n : null;\r\n }\r\n\r\n set({\r\n tabs: nextTabs,\r\n });\r\n\r\n if (nextActive) get().focusTab(nextActive);\r\n },\r\n // 🔧 활성 탭 변경\r\n // 탭 헤더 클릭 시 해당 탭으로 전환\r\n focusTab: (tabKey) => {\r\n const { tabs } = get();\r\n const target = tabs.find((t) => t.key === tabKey);\r\n\r\n if (target) {\r\n // activeDetailItem 업데이트 (컴포넌트 탭인 경우)\r\n const activeDetailItem = target.gubun === \"C\" ? {\r\n viewId: target.key,\r\n viewLabel: target.label,\r\n prntInfo: target.componentItem?.prntInfo\r\n } : null;\r\n\r\n if (target.menuItem?.prsnInfoYn === \"Y\") {\r\n set({\r\n activeMenuId: tabKey,\r\n activeMenuItem: target.menuItem,\r\n activeDetailItem,\r\n });\r\n console.log(\r\n \"✅ 탭 포커스 (개인정보) - activeMenuItem:\",\r\n target.menuItem\r\n );\r\n get().setProtectFlagForKey(tabKey);\r\n } else {\r\n set({\r\n activeMenuId: tabKey,\r\n activeMenuItem: target.menuItem,\r\n activeDetailItem,\r\n });\r\n //console.log(\"✅ 탭 포커스 (일반) - activeMenuItem:\", target.menuItem);\r\n get().clearProtectFlagForKey(tabKey);\r\n }\r\n } else {\r\n set({ activeMenuId: tabKey, activeMenuItem: null, activeDetailItem: null });\r\n console.warn(\"❌ 탭을 찾을 수 없음:\", tabKey);\r\n }\r\n },\r\n\r\n // 🔧 모든 탭 제거\r\n // 로그아웃이나 전체 초기화 시 사용\r\n closeAllTabs: () =>\r\n set({ tabs: [], activeMenuId: null, activeMenuItem: null, activeDetailItem: null }),\r\n\r\n // 🔧 사이드바 토글\r\n // 햄버거 메뉴 클릭 시 사이드바 접기/펼치기\r\n toggleSidebar: () => set((s) => ({ sidebarCollapsed: !s.sidebarCollapsed })),\r\n\r\n // useMenuViewStore.ts\r\n reorderTabs: (keys: string[]) =>\r\n set((state) => {\r\n const map = new Map(state.tabs.map((t) => [t.key, t]));\r\n return { tabs: keys.map((k) => map.get(k)!).filter(Boolean) };\r\n }),\r\n // 개인정보 포함여부에 따른 탭 잠금 Flag 설정\r\n setProtectFlagForKey: (key: string) =>\r\n set((s) => ({\r\n tabProtectFlag: { ...s.tabProtectFlag, [key]: true },\r\n })),\r\n // 개인정보 포함여부에 따른 탭 잠금 해제\r\n clearProtectFlagForKey: (key: string) =>\r\n set((s) => {\r\n const newFlags = { ...s.tabProtectFlag };\r\n delete newFlags[key];\r\n return { tabProtectFlag: newFlags };\r\n }),\r\n // 탭 파라미터 설정\r\n setTabParams: (key, params) =>\r\n set((state) => {\r\n const prev = state.tabParams[key] || {};\r\n const next = { ...(params || {}) }; // 새 객체 (불변 보장)\r\n\r\n // shallow equal이면 스킵(불필요 렌더 방지)\r\n const isShallowEqual =\r\n Object.keys(prev).length === Object.keys(next).length &&\r\n Object.keys(next).every((k) => prev[k] === next[k]);\r\n if (isShallowEqual) return state;\r\n\r\n return {\r\n tabParams: { ...state.tabParams, [key]: next },\r\n };\r\n }),\r\n // 컴포넌트 라벨 맵 설정\r\n setComponentLabelMap: (map: Record<string, string>, merge?: boolean) =>\r\n set({ componentLabelMap: map }),\r\n}));\r\n","import { create } from 'zustand';\r\n\r\ninterface LoadingState {\r\n requestCount: number;\r\n loading: boolean;\r\n showLoading: () => void;\r\n hideLoading: () => void;\r\n}\r\n\r\nexport const useLoadingStore = create<LoadingState>((set) => ({\r\n requestCount: 0,\r\n loading: false,\r\n showLoading: () =>\r\n set((state) => {\r\n const newCount = state.requestCount + 1;\r\n return { requestCount: newCount, loading: newCount > 0 };\r\n }),\r\n hideLoading: () =>\r\n set((state) => {\r\n const newCount = Math.max(0, state.requestCount - 1);\r\n return { requestCount: newCount, loading: newCount > 0 };\r\n }),\r\n}));\r\n\r\nexport const usePopupLoadingStore = create<LoadingState>(set => ({\r\n requestCount: 0,\r\n loading: false,\r\n showLoading: () =>\r\n set(state => {\r\n const newCount = state.requestCount + 1;\r\n return { requestCount: newCount, loading: newCount > 0 };\r\n }),\r\n hideLoading: () =>\r\n set(state => {\r\n const newCount = Math.max(0, state.requestCount - 1);\r\n return { requestCount: newCount, loading: newCount > 0 };\r\n }),\r\n}));","!function(e,_){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=_(require(\"dayjs\")):\"function\"==typeof define&&define.amd?define([\"dayjs\"],_):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).dayjs_locale_ko=_(e.dayjs)}(this,(function(e){\"use strict\";function _(e){return e&&\"object\"==typeof e&&\"default\"in e?e:{default:e}}var d=_(e),t={name:\"ko\",weekdays:\"일요일_월요일_화요일_수요일_목요일_금요일_토요일\".split(\"_\"),weekdaysShort:\"일_월_화_수_목_금_토\".split(\"_\"),weekdaysMin:\"일_월_화_수_목_금_토\".split(\"_\"),months:\"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월\".split(\"_\"),monthsShort:\"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월\".split(\"_\"),ordinal:function(e){return e+\"일\"},formats:{LT:\"A h:mm\",LTS:\"A h:mm:ss\",L:\"YYYY.MM.DD.\",LL:\"YYYY년 MMMM D일\",LLL:\"YYYY년 MMMM D일 A h:mm\",LLLL:\"YYYY년 MMMM D일 dddd A h:mm\",l:\"YYYY.MM.DD.\",ll:\"YYYY년 MMMM D일\",lll:\"YYYY년 MMMM D일 A h:mm\",llll:\"YYYY년 MMMM D일 dddd A h:mm\"},meridiem:function(e){return e<12?\"오전\":\"오후\"},relativeTime:{future:\"%s 후\",past:\"%s 전\",s:\"몇 초\",m:\"1분\",mm:\"%d분\",h:\"한 시간\",hh:\"%d시간\",d:\"하루\",dd:\"%d일\",M:\"한 달\",MM:\"%d달\",y:\"일 년\",yy:\"%d년\"}};return d.default.locale(t,null,!0),t}));","!function(r,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define(e):(r=\"undefined\"!=typeof globalThis?globalThis:r||self).dayjs_plugin_relativeTime=e()}(this,(function(){\"use strict\";return function(r,e,t){r=r||{};var n=e.prototype,o={future:\"in %s\",past:\"%s ago\",s:\"a few seconds\",m:\"a minute\",mm:\"%d minutes\",h:\"an hour\",hh:\"%d hours\",d:\"a day\",dd:\"%d days\",M:\"a month\",MM:\"%d months\",y:\"a year\",yy:\"%d years\"};function i(r,e,t,o){return n.fromToBase(r,e,t,o)}t.en.relativeTime=o,n.fromToBase=function(e,n,i,d,u){for(var f,a,s,l=i.$locale().relativeTime||o,h=r.thresholds||[{l:\"s\",r:44,d:\"second\"},{l:\"m\",r:89},{l:\"mm\",r:44,d:\"minute\"},{l:\"h\",r:89},{l:\"hh\",r:21,d:\"hour\"},{l:\"d\",r:35},{l:\"dd\",r:25,d:\"day\"},{l:\"M\",r:45},{l:\"MM\",r:10,d:\"month\"},{l:\"y\",r:17},{l:\"yy\",d:\"year\"}],m=h.length,c=0;c<m;c+=1){var y=h[c];y.d&&(f=d?t(e).diff(i,y.d,!0):i.diff(e,y.d,!0));var p=(r.rounding||Math.round)(Math.abs(f));if(s=f>0,p<=y.r||!y.r){p<=1&&c>0&&(y=h[c-1]);var v=l[y.l];u&&(p=u(\"\"+p)),a=\"string\"==typeof v?v.replace(\"%d\",p):v(p,n,y.l,s);break}}if(n)return a;var M=s?l.future:l.past;return\"function\"==typeof M?M(a):M.replace(\"%s\",a)},n.to=function(r,e){return i(r,e,this,!0)},n.from=function(r,e){return i(r,e,this)};var d=function(r){return r.$u?t.utc():t()};n.toNow=function(r){return this.to(d(this),r)},n.fromNow=function(r){return this.from(d(this),r)}}}));","!function(t,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define(e):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).dayjs_plugin_timezone=e()}(this,(function(){\"use strict\";var t={year:0,month:1,day:2,hour:3,minute:4,second:5},e={};return function(n,i,o){var r,a=function(t,n,i){void 0===i&&(i={});var o=new Date(t),r=function(t,n){void 0===n&&(n={});var i=n.timeZoneName||\"short\",o=t+\"|\"+i,r=e[o];return r||(r=new Intl.DateTimeFormat(\"en-US\",{hour12:!1,timeZone:t,year:\"numeric\",month:\"2-digit\",day:\"2-digit\",hour:\"2-digit\",minute:\"2-digit\",second:\"2-digit\",timeZoneName:i}),e[o]=r),r}(n,i);return r.formatToParts(o)},u=function(e,n){for(var i=a(e,n),r=[],u=0;u<i.length;u+=1){var f=i[u],s=f.type,m=f.value,c=t[s];c>=0&&(r[c]=parseInt(m,10))}var d=r[3],l=24===d?0:d,h=r[0]+\"-\"+r[1]+\"-\"+r[2]+\" \"+l+\":\"+r[4]+\":\"+r[5]+\":000\",v=+e;return(o.utc(h).valueOf()-(v-=v%1e3))/6e4},f=i.prototype;f.tz=function(t,e){void 0===t&&(t=r);var n,i=this.utcOffset(),a=this.toDate(),u=a.toLocaleString(\"en-US\",{timeZone:t}),f=Math.round((a-new Date(u))/1e3/60),s=15*-Math.round(a.getTimezoneOffset()/15)-f;if(!Number(s))n=this.utcOffset(0,e);else if(n=o(u,{locale:this.$L}).$set(\"millisecond\",this.$ms).utcOffset(s,!0),e){var m=n.utcOffset();n=n.add(i-m,\"minute\")}return n.$x.$timezone=t,n},f.offsetName=function(t){var e=this.$x.$timezone||o.tz.guess(),n=a(this.valueOf(),e,{timeZoneName:t}).find((function(t){return\"timezonename\"===t.type.toLowerCase()}));return n&&n.value};var s=f.startOf;f.startOf=function(t,e){if(!this.$x||!this.$x.$timezone)return s.call(this,t,e);var n=o(this.format(\"YYYY-MM-DD HH:mm:ss:SSS\"),{locale:this.$L});return s.call(n,t,e).tz(this.$x.$timezone,!0)},o.tz=function(t,e,n){var i=n&&e,a=n||e||r,f=u(+o(),a);if(\"string\"!=typeof t)return o(t).tz(a);var s=function(t,e,n){var i=t-60*e*1e3,o=u(i,n);if(e===o)return[i,e];var r=u(i-=60*(o-e)*1e3,n);return o===r?[i,o]:[t-60*Math.min(o,r)*1e3,Math.max(o,r)]}(o.utc(t,i).valueOf(),f,a),m=s[0],c=s[1],d=o(m).utcOffset(c);return d.$x.$timezone=a,d},o.tz.guess=function(){return Intl.DateTimeFormat().resolvedOptions().timeZone},o.tz.setDefault=function(t){r=t}}}));","!function(t,i){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=i():\"function\"==typeof define&&define.amd?define(i):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).dayjs_plugin_utc=i()}(this,(function(){\"use strict\";var t=\"minute\",i=/[+-]\\d\\d(?::?\\d\\d)?/g,e=/([+-]|\\d\\d)/g;return function(s,f,n){var u=f.prototype;n.utc=function(t){var i={date:t,utc:!0,args:arguments};return new f(i)},u.utc=function(i){var e=n(this.toDate(),{locale:this.$L,utc:!0});return i?e.add(this.utcOffset(),t):e},u.local=function(){return n(this.toDate(),{locale:this.$L,utc:!1})};var r=u.parse;u.parse=function(t){t.utc&&(this.$u=!0),this.$utils().u(t.$offset)||(this.$offset=t.$offset),r.call(this,t)};var o=u.init;u.init=function(){if(this.$u){var t=this.$d;this.$y=t.getUTCFullYear(),this.$M=t.getUTCMonth(),this.$D=t.getUTCDate(),this.$W=t.getUTCDay(),this.$H=t.getUTCHours(),this.$m=t.getUTCMinutes(),this.$s=t.getUTCSeconds(),this.$ms=t.getUTCMilliseconds()}else o.call(this)};var a=u.utcOffset;u.utcOffset=function(s,f){var n=this.$utils().u;if(n(s))return this.$u?0:n(this.$offset)?a.call(this):this.$offset;if(\"string\"==typeof s&&(s=function(t){void 0===t&&(t=\"\");var s=t.match(i);if(!s)return null;var f=(\"\"+s[0]).match(e)||[\"-\",0,0],n=f[0],u=60*+f[1]+ +f[2];return 0===u?0:\"+\"===n?u:-u}(s),null===s))return this;var u=Math.abs(s)<=16?60*s:s;if(0===u)return this.utc(f);var r=this.clone();if(f)return r.$offset=u,r.$u=!1,r;var o=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();return(r=this.local().add(u+o,t)).$offset=u,r.$x.$localOffset=o,r};var h=u.format;u.format=function(t){var i=t||(this.$u?\"YYYY-MM-DDTHH:mm:ss[Z]\":\"\");return h.call(this,i)},u.valueOf=function(){var t=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*t},u.isUTC=function(){return!!this.$u},u.toISOString=function(){return this.toDate().toISOString()},u.toString=function(){return this.toDate().toUTCString()};var l=u.toDate;u.toDate=function(t){return\"s\"===t&&this.$offset?n(this.format(\"YYYY-MM-DD HH:mm:ss:SSS\")).toDate():l.call(this)};var c=u.diff;u.diff=function(t,i,e){if(t&&this.$u===t.$u)return c.call(this,t,i,e);var s=this.local(),f=n(t).local();return c.call(s,f,i,e)}}}));","///////////////////////////////////////// 상수 관련 //////////////////////////////////////////\r\n/**\r\n * 테마 관련 쿠키 상수\r\n */\r\nexport const THEME_COOKIE_NAME = \"ui_theme\";\r\n\r\n/**\r\n * String 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isString = (value: any): value is string =>\r\n typeof value === \"string\";\r\n/**\r\n * Number 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isNumber = (value: any): value is number =>\r\n typeof value === \"number\" && !isNaN(value);\r\n/**\r\n * Boolean 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isBoolean = (value: any): value is boolean =>\r\n typeof value === \"boolean\";\r\n/**\r\n * Function 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isFunction = (value: any): value is Function =>\r\n typeof value === \"function\";\r\n/**\r\n * Object 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isObject = (value: any): value is object =>\r\n value !== null && typeof value === \"object\";\r\n/**\r\n * Array 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isArray = (value: any): value is any[] => Array.isArray(value);\r\n/**\r\n * Null 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isNull = (value: any): value is null => value === null;\r\n/**\r\n * Undefined 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isUndefined = (value: any): value is undefined =>\r\n value === undefined;\r\n/**\r\n * Null 또는 Undefined 타입 가드 함수\r\n * @param value\r\n * @returns\r\n */\r\nexport const isNullOrUndefined = (value: any): value is null | undefined =>\r\n value === null || value === undefined;\r\n\r\n/**\r\n * 쓰로틀 함수\r\n * : 일정 시간 간격으로 함수를 호출한다.\r\n * @param func\r\n * @param delay\r\n * @returns\r\n */\r\nexport const throttle = <T extends (...args: any[]) => any>(\r\n func: T,\r\n delay: number\r\n): ((...args: Parameters<T>) => void) => {\r\n let lastCall = 0;\r\n\r\n return (...args: Parameters<T>) => {\r\n const now = Date.now();\r\n if (now - lastCall >= delay) {\r\n lastCall = now;\r\n func(...args);\r\n }\r\n };\r\n};\r\n\r\n/**\r\n * 디바운스 함수\r\n * : 마지막 호출 후 일정 시간 간격으로 함수를 호출한다.\r\n * @param func\r\n * @param delay\r\n * @returns\r\n */\r\nexport const debounce = <T extends (...args: any[]) => any>(\r\n func: T,\r\n delay: number\r\n): ((...args: Parameters<T>) => void) => {\r\n let timeoutId: ReturnType<typeof setTimeout>;\r\n\r\n return (...args: Parameters<T>) => {\r\n clearTimeout(timeoutId);\r\n timeoutId = setTimeout(() => func(...args), delay);\r\n };\r\n};\r\n\r\n/**\r\n * 클립보드 복사 함수\r\n * @param text\r\n * @returns\r\n */\r\nexport const copyToClipboard = async (text: string): Promise<boolean> => {\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n return true;\r\n } catch (error) {\r\n console.error(\"Error copying to clipboard:\", error);\r\n return false;\r\n }\r\n};\r\n\r\n/**\r\n * 디바이스 타입 가져오기\r\n * @returns\r\n */\r\nexport const getDeviceType = (): \"mobile\" | \"tablet\" | \"desktop\" => {\r\n const width = window.innerWidth;\r\n if (width < 768) return \"mobile\";\r\n if (width < 1024) return \"tablet\";\r\n return \"desktop\";\r\n};\r\n\r\n/**\r\n * 모바일 타입 가드 함수\r\n * @returns\r\n */\r\nexport const isMobile = (): boolean => getDeviceType() === \"mobile\";\r\n/**\r\n * 태블릿 타입 가드 함수\r\n * @returns\r\n */\r\nexport const isTablet = (): boolean => getDeviceType() === \"tablet\";\r\n/**\r\n * 데스크탑 타입 가드 함수\r\n * @returns\r\n */\r\nexport const isDesktop = (): boolean => getDeviceType() === \"desktop\";\r\n\r\n/**\r\n * 랜덤 색상 생성 함수\r\n * @returns\r\n */\r\nexport const generateRandomColor = (): string => {\r\n return \"#\" + Math.floor(Math.random() * 16777215).toString(16);\r\n};\r\n\r\n///////////////////////////////////////// 배열 관련 //////////////////////////////////////////\r\n/**\r\n * 배열이 비어있는지 확인\r\n * @param arr\r\n * @returns\r\n */\r\nexport const isEmptyArray = <T>(arr: T[]): boolean => {\r\n return !arr || arr.length === 0;\r\n};\r\n\r\n/**\r\n * 배열 중복 제거\r\n * @param arr\r\n * @returns\r\n */\r\nexport const arrUnique = <T>(arr: T[]): T[] => {\r\n return [...new Set(arr)];\r\n};\r\n\r\n/**\r\n * 배열에서 최대값 찾기\r\n * @param arr\r\n * @returns\r\n */\r\nexport const arrMax = (arr: number[]): number | undefined => {\r\n if (isEmptyArray(arr)) return undefined;\r\n return Math.max(...arr);\r\n};\r\n\r\n/**\r\n * 배열에서 최소값 찾기\r\n * @param arr\r\n * @returns\r\n */\r\nexport const arrMin = (arr: number[]): number | undefined => {\r\n if (isEmptyArray(arr)) return undefined;\r\n return Math.min(...arr);\r\n};\r\n\r\n/**\r\n * 배열 평균 계산\r\n * @param arr\r\n * @returns\r\n */\r\nexport const arrAverage = (arr: number[]): number | undefined => {\r\n if (isEmptyArray(arr)) return undefined;\r\n return arr.reduce((sum, num) => sum + num, 0) / arr.length;\r\n};\r\n\r\n/**\r\n * 배열 합계 계산\r\n * @param arr\r\n * @returns\r\n */\r\nexport const arrSum = (arr: number[]): number => {\r\n return arr.reduce((sum, num) => sum + num, 0);\r\n};\r\n\r\n/**\r\n * 배열에서 특정 조건을 만족하는 요소 개수 세기\r\n * @param arr\r\n * @param predicate\r\n * @returns\r\n */\r\nexport const arrCount = <T>(\r\n arr: T[],\r\n predicate: (item: T) => boolean\r\n): number => {\r\n return arr.filter(predicate).length;\r\n};\r\n\r\n/**\r\n * 배열을 뒤집기\r\n * @param arr\r\n * @returns\r\n */\r\nexport const arrReverse = <T>(arr: T[]): T[] => {\r\n return [...arr].reverse();\r\n};\r\n\r\n/**\r\n * 배열에서 중복 요소들 찾기\r\n * @param arr\r\n * @returns\r\n */\r\nexport const duplicates = <T>(arr: T[]): T[] => {\r\n const seen = new Set<T>();\r\n const duplicates = new Set<T>();\r\n\r\n arr.forEach((item) => {\r\n if (seen.has(item)) {\r\n duplicates.add(item);\r\n } else {\r\n seen.add(item);\r\n }\r\n });\r\n\r\n return Array.from(duplicates);\r\n};\r\n\r\n///////////////////////////////////////// 숫자 관련 //////////////////////////////////////////\r\n/**\r\n * 랜덤 관련\r\n * @param min\r\n * @param max\r\n * @returns\r\n */\r\nexport const random = (min: number, max: number): number => {\r\n return Math.random() * (max - min) + min;\r\n};\r\n\r\nexport const clamp = (value: number, min: number, max: number): number => {\r\n return Math.min(Math.max(value, min), max);\r\n};\r\n\r\nexport const round = (value: number, decimals: number = 0): number => {\r\n return Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);\r\n};\r\n\r\n///////////////////////////////////////// 세션 스토리지 관련 //////////////////////////////////////////\r\n/**\r\n * 세션 스토리지 설정\r\n * @param key\r\n * @param value\r\n * @returns\r\n */\r\nexport const setSessionStorage = (key: string, value: any): void => {\r\n try {\r\n sessionStorage.setItem(key, JSON.stringify(value));\r\n } catch (error) {\r\n console.error(\"Error saving to sessionStorage:\", error);\r\n }\r\n};\r\n\r\n/**\r\n * 세션 스토리지 가져오기\r\n * @param key\r\n * @param defaultValue\r\n * @returns\r\n */\r\nexport const getSessionStorage = <T>(\r\n key: string,\r\n defaultValue?: T\r\n): T | null => {\r\n try {\r\n const item = sessionStorage.getItem(key);\r\n return item ? JSON.parse(item) : defaultValue || null;\r\n } catch (error) {\r\n console.error(\"Error reading from sessionStorage:\", error);\r\n return defaultValue || null;\r\n }\r\n};\r\n\r\n/**\r\n * 세션 스토리지 삭제\r\n * @param key\r\n * @returns\r\n */\r\nexport const removeSessionStorage = (key: string): void => {\r\n try {\r\n sessionStorage.removeItem(key);\r\n } catch (error) {\r\n console.error(\"Error removing from sessionStorage:\", error);\r\n }\r\n};\r\n\r\n/**\r\n * 세션 스토리지 초기화\r\n * @returns\r\n */\r\nexport const clearSessionStorage = (): void => {\r\n try {\r\n sessionStorage.clear();\r\n } catch (error) {\r\n console.error(\"Error clearing sessionStorage:\", error);\r\n }\r\n};\r\n\r\n///////////////////////////////////////// 쿠키 관련 //////////////////////////////////////////\r\n/**\r\n * 쿠키 설정\r\n * @param name\r\n * @param value\r\n * @param days\r\n * @returns\r\n */\r\nexport const setCookie = (name: string, value: string, days: number = 30) => {\r\n const expires = new Date();\r\n expires.setTime(expires.getTime() + days * 24 * 60 * 60 * 1000);\r\n document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=/`;\r\n};\r\n\r\n/**\r\n * 쿠키 가져오기\r\n * @param name\r\n * @returns\r\n */\r\nexport const getCookie = (name: string): string | null => {\r\n const nameEQ = name + \"=\";\r\n const ca = document.cookie.split(\";\");\r\n for (let i = 0; i < ca.length; i++) {\r\n let c = ca[i];\r\n while (c.charAt(0) === \" \") c = c.substring(1, c.length);\r\n if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length);\r\n }\r\n return null;\r\n};\r\n\r\n/**\r\n * 쿠키 삭제\r\n * @param name\r\n * @returns\r\n */\r\nexport const deleteCookie = (name: string) => {\r\n document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;\r\n};\r\n\r\n///////////////////////////////////////// 문자열 관련 //////////////////////////////////////////\r\n\r\n// 문자열이 비어있는지 확인\r\nexport const isEmpty = (str: any): boolean => {\r\n if (typeof str !== \"string\") return !str;\r\n return str.trim().length === 0;\r\n};\r\n\r\n/**\r\n * 문자열이 비어있는지 확인하고, 비어있으면 defaultValue를 반환\r\n * @param str - 문자열\r\n * @param defaultValue - 비어있을 때 반환할 기본값\r\n * @returns 문자열이 비어있으면 defaultValue, 아니면 str\r\n */\r\nexport const isSafeEmpty = (\r\n str: string | null | undefined,\r\n defaultValue: string\r\n): string => {\r\n return isEmpty(str) ? defaultValue : str || \"\";\r\n};\r\n\r\n// 카멜케이스로 변환\r\nexport const toCamelCase = (str: string): string => {\r\n return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());\r\n};\r\n\r\n// 이메일 유효성 검사\r\nexport const isValidEmail = (email: string): boolean => {\r\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\r\n return emailRegex.test(email);\r\n};\r\n\r\n// URL 유효성 검사\r\nexport const isValidUrl = (url: string): boolean => {\r\n try {\r\n new URL(url);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\n// 문자열 패딩 (왼쪽)\r\nexport const padLeft = (\r\n str: string,\r\n length: number,\r\n char: string = \" \"\r\n): string => {\r\n return str.padStart(length, char);\r\n};\r\n\r\n// 문자열 패딩 (오른쪽)\r\nexport const padRight = (\r\n str: string,\r\n length: number,\r\n char: string = \" \"\r\n): string => {\r\n return str.padEnd(length, char);\r\n};\r\n\r\n// 랜덤 문자열 생성\r\nexport const generateRandomString = (\r\n length: number,\r\n chars: string = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\"\r\n): string => {\r\n let result = \"\";\r\n for (let i = 0; i < length; i++) {\r\n result += chars.charAt(Math.floor(Math.random() * chars.length));\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * UUID v4 생성 (하이픈 포함)\r\n */\r\nconst generateUUIDv4 = (): string => {\r\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\r\n const r = (Math.random() * 16) | 0;\r\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\r\n return v.toString(16);\r\n });\r\n};\r\n\r\n/**\r\n * Random UID 생성 (하이픈 제거)\r\n * @param length - UID 길이 (기본값: 32)\r\n * @returns 하이픈이 제거된 UID 문자열\r\n */\r\nexport const generateUID = (length: number = 32): string => {\r\n const uuid = generateUUIDv4();\r\n const uidWithoutHyphens = uuid.replace(/-/g, \"\");\r\n if (length >= 32) {\r\n return (\r\n uidWithoutHyphens + generateRandomString(length - 32, \"0123456789abcdef\")\r\n );\r\n } else {\r\n return uidWithoutHyphens.substring(0, length);\r\n }\r\n};\r\n\r\n/**\r\n * SHA256 단방향 암호화\r\n * @param data\r\n * @returns\r\n\r\n */\r\n\r\nexport async function encryptSha256(input: string): Promise<string> {\r\n const [{ default: SHA256 }, { default: encBase64 }] = await Promise.all([\r\n import(\"crypto-js/sha256\"),\r\n import(\"crypto-js/enc-base64\"),\r\n ]);\r\n return SHA256(input).toString(encBase64); // ← Base64 해시\r\n}\r\n\r\n///////////////////////////////////////// 날짜 관련 //////////////////////////////////////////\r\nimport dayjs, { Dayjs } from \"dayjs\";\r\nimport \"dayjs/locale/ko\";\r\nimport relativeTime from \"dayjs/plugin/relativeTime\";\r\nimport timezone from \"dayjs/plugin/timezone\";\r\nimport utc from \"dayjs/plugin/utc\";\r\n\r\n// dayjs 플러그인 설정\r\ndayjs.extend(relativeTime);\r\ndayjs.extend(utc);\r\ndayjs.extend(timezone);\r\ndayjs.locale(\"ko\");\r\n\r\n/**\r\n * 현재 날짜/시간 가져오기\r\n * @returns\r\n */\r\nexport const getCurrentDate = (): Dayjs => dayjs();\r\n/**\r\n * 현재 날짜/시간 가져오기\r\n * @param format\r\n * @returns\r\n */\r\nexport const getCurrentDateString = (format: string = \"YYYY-MM-DD\"): string =>\r\n dayjs().format(format);\r\n","/**\r\n * 현재 코드가 실행되는 최종 애플리케이션의 환경이 개발 환경인지 여부를 반환합니다.\r\n * 이 라이브러리를 사용하는 프로젝트의 빌드 도구(Vite 등)가 이 값을 결정합니다.\r\n *\r\n * @example\r\n * // 최종 앱이 `npm run dev`로 실행될 때: isLocal === true\r\n * // 최종 앱이 `npm run build`로 빌드될 때: isLocal === false\r\n */\r\nexport const isLocal: boolean = (() => {\r\n try {\r\n // `import.meta.env.DEV`는 Vite와 같은 모던 빌드 도구에서 제공하는 표준적인 방식입니다.\r\n // 라이브러리 빌드 시점에는 이 코드가 그대로 유지되며,\r\n // 최종 사용되는 프로젝트에서 빌드될 때 해당 프로젝트의 환경에 맞게 `true` 또는 `false`로 대체됩니다.\r\n if ((import.meta as any).env.DEV) {\r\n return true;\r\n }\r\n } catch (e) {\r\n // `import.meta`를 지원하지 않는 환경(예: CommonJS, 일부 테스트 환경)을 위한 폴백입니다.\r\n }\r\n return false;\r\n})();\r\n\r\nlet devHosts: string[] = [];\r\nlet prodHosts: string[] = [];\r\n\r\nexport function configureEnvUtils(opts: {\r\n devHosts?: string[];\r\n prodHosts?: string[];\r\n}) {\r\n if (opts.devHosts) devHosts = opts.devHosts;\r\n if (opts.prodHosts) prodHosts = opts.prodHosts;\r\n}\r\n\r\nfunction getHostName(): string | undefined {\r\n if (typeof window !== \"undefined\" && window.location) {\r\n return window.location.hostname;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport const isDev: boolean = (() => {\r\n const host = getHostName();\r\n return !!(host && devHosts.includes(host));\r\n})();\r\n\r\nexport const isProd: boolean = (() => {\r\n const host = getHostName();\r\n return !!(host && prodHosts.includes(host));\r\n})();\r\n\r\n// ✅ 환경코드 반환 유틸\r\nexport function getEnvCode(): \"X\" | \"D\" | \"P\" {\r\n if (isLocal) return \"X\"; // Local\r\n if (isDev) return \"D\"; // Dev\r\n if (isProd) return \"P\"; // Prod\r\n return \"X\"; // 기본값은 Local로\r\n}\r\n","import type { NotificationArgsProps } from \"antd\";\r\nimport { notification } from \"antd\";\r\n\r\n// Notification 타입 정의\r\nexport type NotificationType = \"success\" | \"error\" | \"info\" | \"warning\";\r\n\r\n// BwgError 전용 인터페이스\r\nexport interface BwgErrorProps {\r\n message: string;\r\n description?: string;\r\n duration?: number;\r\n placement?: NotificationArgsProps[\"placement\"];\r\n}\r\n\r\n// 기본 설정\r\nconst DEFAULT_CONFIG = {\r\n duration: 4.5, // 4.5초\r\n placement: \"topRight\" as const,\r\n maxCount: 3, // 최대 3개까지 표시\r\n};\r\n\r\n// 전역 Notification 유틸리티 클래스\r\nclass NotificationService {\r\n private static instance: NotificationService;\r\n\r\n private constructor() {\r\n // 싱글톤 패턴\r\n }\r\n\r\n public static getInstance(): NotificationService {\r\n if (!NotificationService.instance) {\r\n NotificationService.instance = new NotificationService();\r\n }\r\n return NotificationService.instance;\r\n }\r\n\r\n /**\r\n * BwgError 전용 에러 알림\r\n * @param props - 에러 메시지 설정\r\n */\r\n public showBwgError(props: BwgErrorProps): void {\r\n const {\r\n message,\r\n description,\r\n duration = DEFAULT_CONFIG.duration,\r\n placement = DEFAULT_CONFIG.placement,\r\n } = props;\r\n\r\n notification.error({\r\n message: `${message}`,\r\n description: description || \"오류가 발생했습니다. 다시 시도해주세요.\",\r\n duration,\r\n placement,\r\n style: {\r\n borderLeft: \"4px solid #ff4d4f\",\r\n backgroundColor: \"#fff2f0\",\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * 성공 알림\r\n */\r\n public showSuccess(\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n ): void {\r\n notification.success({\r\n message: `${message}`,\r\n description,\r\n duration: duration || DEFAULT_CONFIG.duration,\r\n placement: DEFAULT_CONFIG.placement,\r\n });\r\n }\r\n\r\n /**\r\n * 정보 알림\r\n */\r\n public showInfo(\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n ): void {\r\n notification.info({\r\n message: `${message}`,\r\n description,\r\n duration: duration || DEFAULT_CONFIG.duration,\r\n placement: DEFAULT_CONFIG.placement,\r\n });\r\n }\r\n\r\n /**\r\n * 경고 알림\r\n */\r\n public showWarning(\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n ): void {\r\n notification.warning({\r\n message: `${message}`,\r\n description,\r\n duration: duration || DEFAULT_CONFIG.duration,\r\n placement: DEFAULT_CONFIG.placement,\r\n });\r\n }\r\n\r\n /**\r\n * 일반 에러 알림\r\n */\r\n public showError(\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n ): void {\r\n notification.error({\r\n message: `${message}`,\r\n description,\r\n duration: duration || DEFAULT_CONFIG.duration,\r\n placement: DEFAULT_CONFIG.placement,\r\n });\r\n }\r\n\r\n /**\r\n * 모든 알림 닫기\r\n */\r\n public destroy(): void {\r\n notification.destroy();\r\n }\r\n\r\n /**\r\n * 특정 키의 알림 닫기\r\n */\r\n public close(key: string): void {\r\n // antd notification API에서는 개별 close 메서드가 없으므로 destroy 사용\r\n notification.destroy();\r\n }\r\n}\r\n\r\n// 싱글톤 인스턴스 생성\r\nexport const notificationService = NotificationService.getInstance();\r\n\r\n// 편의 함수들\r\nexport const notiBwgError = (props: BwgErrorProps): void => {\r\n notificationService.showBwgError(props);\r\n};\r\n\r\nexport const notiSuccess = (\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n): void => {\r\n notificationService.showSuccess(message, description, duration);\r\n};\r\n\r\nexport const notiInfo = (\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n): void => {\r\n notificationService.showInfo(message, description, duration);\r\n};\r\n\r\nexport const notiWarning = (\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n): void => {\r\n notificationService.showWarning(message, description, duration);\r\n};\r\n\r\nexport const notiError = (\r\n message: string,\r\n description?: string,\r\n duration?: number\r\n): void => {\r\n notificationService.showError(message, description, duration);\r\n};\r\n\r\nexport const destroyNotifications = (): void => {\r\n notificationService.destroy();\r\n};\r\n\r\nexport const closeNotification = (key: string): void => {\r\n notificationService.close(key);\r\n};\r\n","import {\r\n useLoadingStore,\r\n useMenuViewStore,\r\n usePopupLoadingStore,\r\n} from '@/stores';\r\nimport type { AxiosRequestConfig, AxiosResponse } from 'axios';\r\nimport axios, { AxiosError } from 'axios';\r\nimport { generateUID } from './commonUtils';\r\nimport { isLocal } from './envUtils';\r\nimport { notiBwgError, notiInfo, notiWarning } from './notificationUtils';\r\nimport { getUserInfo } from './userUtils';\r\n\r\n// 클라이언트 IP 저장 변수 (읽기 전용)\r\nlet clientIp: string | null = null;\r\n\r\n/**\r\n * 클라이언트 IP 설정 (초기화 시에만 사용)\r\n * @param ip - 클라이언트 IP 주소\r\n */\r\nexport const setClientIp = async (ip?: string): Promise<void> => {\r\n // 이미 설정된 경우 재설정 방지\r\n if (clientIp !== null) {\r\n return;\r\n }\r\n\r\n if (ip === undefined) {\r\n try {\r\n //ip가 널로 드러왔을경우 기존 /api/ip를 통해 ip입력\r\n const res = await axios.get('/api/ip');\r\n let ipAddr: string = res.data.trim();\r\n // 모든 공백 문자 제거 (공백, 탭, 줄바꿈 등)\r\n ipAddr = ipAddr.replace(/\\s+/g, '');\r\n clientIp = ipAddr;\r\n } catch (error) {\r\n console.warn('IP 가져오기 실패:', error);\r\n // IP 가져오기 실패해도 기본값 설정\r\n clientIp = 'unknown';\r\n }\r\n } else {\r\n clientIp = ip;\r\n }\r\n};\r\n\r\n/**\r\n * 클라이언트 IP 가져오기 (읽기 전용)\r\n * @returns 클라이언트 IP 주소 또는 null\r\n */\r\nexport const getClientIp = (): string | null => {\r\n return clientIp;\r\n};\r\n\r\n/**\r\n * 서버에서 실제 클라이언트 IP 확인 (보안 강화)\r\n * @returns Promise<string> - 서버가 확인한 실제 IP\r\n */\r\nexport const verifyClientIp = async (): Promise<string> => {\r\n // IP 검증 비활성화 (성능 최적화)\r\n console.log('IP 검증 비활성화됨 (성능 최적화)');\r\n return clientIp || 'unknown';\r\n\r\n // 아래 코드는 주석 처리 (필요시 활성화)\r\n /*\r\n try {\r\n const response = await axios.get('/api/ip', {\r\n headers: {\r\n 'Cache-Control': 'no-cache',\r\n Pragma: 'no-cache',\r\n },\r\n });\r\n\r\n let serverIp = response.data.trim().replace(/\\s+/g, '');\r\n\r\n // 클라이언트 IP와 서버 IP 비교\r\n if (clientIp && clientIp !== serverIp) {\r\n console.warn('⚠️ IP 불일치 감지:', {\r\n client: clientIp,\r\n server: serverIp,\r\n });\r\n }\r\n\r\n return serverIp;\r\n } catch (error) {\r\n console.error('IP 확인 실패:', error);\r\n return clientIp || 'unknown';\r\n }\r\n */\r\n};\r\n\r\n// API 응답 타입 정의\r\nexport interface ApiResponse<T = any> {\r\n success: boolean;\r\n data?: T;\r\n message?: string;\r\n error?: string;\r\n code?: number;\r\n}\r\n\r\n// API 요청 옵션 타입 정의\r\nexport interface ApiOptions {\r\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\r\n headers?: Record<string, string>;\r\n timeout?: number;\r\n withCredentials?: boolean;\r\n params?: Record<string, any>;\r\n data?: any;\r\n showLoading?: boolean;\r\n isPopup?: boolean;\r\n showError?: boolean;\r\n retryCount?: number;\r\n retryDelay?: number;\r\n}\r\n\r\n/**\r\n * 사용자 정의 API 에러 클래스\r\n * @param {string} message - 기본 에러 메시지 (basicMsg)\r\n * @param {string} detailMsg - 상세 에러 메시지 (detailMsgs)\r\n * @param {AxiosResponse} [response] - Axios 응답 객체 (선택 사항)\r\n * @param {string} [msgCd] - 서버 메시지 코드 (선택 사항)\r\n */\r\nexport class ApiError extends Error {\r\n detailMsg: string;\r\n response?: AxiosResponse;\r\n msgCd?: string;\r\n errorType?: string;\r\n\r\n constructor(\r\n message: string,\r\n detailMsg: string,\r\n response?: AxiosResponse,\r\n msgCd?: string,\r\n errorType?: string\r\n ) {\r\n super(message);\r\n this.name = 'ApiError';\r\n this.detailMsg = detailMsg;\r\n this.response = response;\r\n this.msgCd = msgCd;\r\n this.errorType = errorType;\r\n\r\n // 스택 트레이스 복원 (V8 엔진 환경 등)\r\n if (Error.captureStackTrace) {\r\n Error.captureStackTrace(this, ApiError);\r\n }\r\n }\r\n}\r\n\r\n// 기본 설정\r\nconst DEFAULT_OPTIONS: ApiOptions = {\r\n method: 'POST',\r\n timeout: 30000, // 30초\r\n withCredentials: true, // 쿠키 포함\r\n showLoading: true,\r\n isPopup: false,\r\n showError: true,\r\n retryCount: 0,\r\n retryDelay: 1000,\r\n};\r\n\r\n// axios 인스턴스 생성\r\nconst apiClient = axios.create({\r\n timeout: DEFAULT_OPTIONS.timeout,\r\n withCredentials: DEFAULT_OPTIONS.withCredentials,\r\n headers: {\r\n 'Content-Type': 'application/json; charset=utf-8',\r\n Accept: 'application/json; charset=utf-8',\r\n 'Apm-Guid': generateUID(),\r\n },\r\n});\r\n\r\n// 요청 인터셉터\r\napiClient.interceptors.request.use(\r\n config => {\r\n // showLoading 옵션이 true일 경우 로딩 표시\r\n if ((config as any).showLoading && !(config as any).isPopup) {\r\n useLoadingStore.getState().showLoading();\r\n }\r\n if ((config as any).showLoading && (config as any).isPopup) {\r\n usePopupLoadingStore.getState().showLoading();\r\n }\r\n\r\n // trxCd와 guid 추출 (requestData에서)\r\n let trxCd = 'UNKNOWN';\r\n const requestTime = new Date().getTime();\r\n\r\n try {\r\n if (config.data && config.data.header) {\r\n trxCd = config.data.header.trxCd || 'UNKNOWN';\r\n } else if (config.params && config.params.header) {\r\n trxCd = config.params.header.trxCd || 'UNKNOWN';\r\n }\r\n } catch (error) {\r\n console.warn('trxCd/guid 추출 실패:', error);\r\n }\r\n\r\n // trxCd, guid와 요청 시작 시간을 config에 저장 (응답 인터셉터에서 사용)\r\n (config as any).trxCd = trxCd;\r\n (config as any).requestStartTime = Date.now();\r\n\r\n // 로딩 표시\r\n console.log(\r\n `🚀 API 요청 시작 [거래코드: ${trxCd} / 서비스요청자: ${\r\n getUserInfo()?.userId\r\n }]`\r\n );\r\n\r\n // 토큰이 있다면 헤더에 추가\r\n const token = localStorage.getItem('accessToken');\r\n if (token) {\r\n config.headers.Authorization = `Bearer ${token}`;\r\n }\r\n\r\n // UTF-8 인코딩 명시적 설정\r\n config.headers['Content-Type'] = 'application/json; charset=UTF-8';\r\n config.headers['Accept'] = 'application/json; charset=UTF-8';\r\n\r\n return config;\r\n },\r\n error => {\r\n console.error('❌ 요청 인터셉터 에러:', error);\r\n return Promise.reject(error);\r\n }\r\n);\r\n\r\n// 응답 인터셉터\r\napiClient.interceptors.response.use(\r\n (response: AxiosResponse) => {\r\n // showLoading 옵션이 true였던 요청에 대해 로딩 숨김\r\n if (\r\n (response.config as any).showLoading &&\r\n !(response.config as any).isPopup\r\n ) {\r\n useLoadingStore.getState().hideLoading();\r\n }\r\n if ((response.config as any).isPopup) {\r\n usePopupLoadingStore.getState().hideLoading();\r\n }\r\n\r\n // trxCd와 guid 추출 (요청 시 저장된 값 사용)\r\n let trxCd = 'UNKNOWN';\r\n let guid = 'UNKNOWN';\r\n const responseTime = new Date().getTime();\r\n\r\n try {\r\n // 요청 시 저장된 trxCd와 guid 사용\r\n if ((response.config as any).trxCd) {\r\n trxCd = (response.config as any).trxCd;\r\n }\r\n if ((response.config as any).guid) {\r\n guid = (response.config as any).guid;\r\n }\r\n // 응답 데이터에서도 확인\r\n else if (\r\n response.data &&\r\n response.data.header &&\r\n response.data.header.trxCd\r\n ) {\r\n trxCd = response.data.header.trxCd;\r\n guid = response.data.header.guid || 'UNKNOWN';\r\n }\r\n // 요청 설정에서도 확인\r\n else if (response.config.data && response.config.data.header) {\r\n trxCd = response.config.data.header.trxCd || 'UNKNOWN';\r\n guid = response.config.data.header.guid || 'UNKNOWN';\r\n } else if (response.config.params && response.config.params.header) {\r\n trxCd = response.config.params.header.trxCd || 'UNKNOWN';\r\n guid = response.config.params.header.guid || 'UNKNOWN';\r\n }\r\n } catch (error) {\r\n console.warn('trxCd/guid 추출 실패:', error);\r\n }\r\n\r\n // 소요 시간 계산\r\n let duration = 0;\r\n if ((response.config as any).requestStartTime) {\r\n duration = responseTime - (response.config as any).requestStartTime;\r\n }\r\n\r\n // 로딩 숨김\r\n console.log(\r\n `✅ API 응답 성공 [거래코드: ${trxCd} / GUID : ${guid}] - (소요시간: ${duration}ms)`\r\n );\r\n\r\n return response;\r\n },\r\n async (error: AxiosError) => {\r\n // showLoading 옵션이 true였던 요청에 대해 로딩 숨김 (에러 발생 시)\r\n if (\r\n error.config &&\r\n (error.config as any).showLoading &&\r\n !(error.config as any).isPopup\r\n ) {\r\n useLoadingStore.getState().hideLoading();\r\n }\r\n if (error.config && (error.config as any).isPopup) {\r\n usePopupLoadingStore.getState().hideLoading();\r\n }\r\n\r\n console.error('❌ API 응답 에러:', error);\r\n\r\n // 개발 환경에서 에러 정보 출력\r\n if (isLocal) {\r\n console.error('🚨 Error Details:', {\r\n message: error.message,\r\n status: error.response?.status,\r\n statusText: error.response?.statusText,\r\n data: error.response?.data,\r\n config: {\r\n url: error.config?.url,\r\n method: error.config?.method,\r\n baseURL: error.config?.baseURL,\r\n },\r\n });\r\n }\r\n\r\n // 401 에러 시 토큰 갱신 시도\r\n if (error.response?.status === 401) {\r\n const refreshToken = localStorage.getItem('refreshToken');\r\n if (refreshToken) {\r\n try {\r\n const refreshResponse = await axios.post('/auth/refresh', {\r\n refreshToken,\r\n });\r\n\r\n if (refreshResponse.data.accessToken) {\r\n localStorage.setItem(\r\n 'accessToken',\r\n refreshResponse.data.accessToken\r\n );\r\n\r\n // 원래 요청 재시도\r\n const originalRequest = error.config;\r\n if (originalRequest) {\r\n originalRequest.headers.Authorization = `Bearer ${refreshResponse.data.accessToken}`;\r\n return apiClient(originalRequest);\r\n }\r\n }\r\n } catch (refreshError) {\r\n // 토큰 갱신 실패 시 로그아웃\r\n localStorage.removeItem('accessToken');\r\n localStorage.removeItem('refreshToken');\r\n window.location.href = '/login';\r\n }\r\n }\r\n }\r\n\r\n return Promise.reject(error);\r\n }\r\n);\r\n\r\n/**\r\n * Tomcat WAS와 통신하는 범용 API 호출 함수\r\n * @param trxCd - 거래코드드\r\n * @param data - 요청 데이터 (GET 요청 시 params로 사용)\r\n * @param options - 옵션 파라미터 (선택사항)\r\n * @returns Promise<ApiResponse<T>>\r\n */\r\nexport const callService = async <T = any>(\r\n trxCd: string,\r\n data?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n try {\r\n // 옵션 병합\r\n const mergedOptions: ApiOptions = {\r\n ...DEFAULT_OPTIONS,\r\n ...options,\r\n };\r\n\r\n //로드된 메뉴ID조회\r\n const { activeMenuId } = useMenuViewStore.getState();\r\n\r\n //ip가 없을경우 ip값 할당\r\n if (clientIp === null) {\r\n const ipStartTime = Date.now();\r\n await setClientIp();\r\n const ipEndTime = Date.now();\r\n console.log(`[INFO] IP 조회 소요시간: ${ipEndTime - ipStartTime}ms`);\r\n }\r\n\r\n // 요청 설정\r\n const config: AxiosRequestConfig & {\r\n showLoading?: boolean;\r\n isPopup?: boolean;\r\n } = {\r\n method: mergedOptions.method,\r\n url: '/api/service',\r\n timeout: mergedOptions.timeout,\r\n withCredentials: mergedOptions.withCredentials,\r\n showLoading: mergedOptions.showLoading,\r\n isPopup: mergedOptions.isPopup,\r\n };\r\n\r\n // 헤더 설정\r\n if (mergedOptions.headers) {\r\n config.headers = mergedOptions.headers;\r\n }\r\n\r\n // IP가 설정되지 않은 경우 기본값 사용 (추가 IP 호출 방지)\r\n const currentClientIp = clientIp || 'unknown';\r\n\r\n // vite.config.ts에서 define으로 주입된 전역 변수를 사용합니다.\r\n // @ts-ignore - __APP_CD__는 Vite에 의해 빌드 시점에 주입되는 전역 변수입니다.\r\n const appCd = __APP_CD__;\r\n const sysCd = __SYS_CD__;\r\n\r\n const requestData = {\r\n header: {\r\n trxCd: trxCd,\r\n userInfo: getUserInfo(),\r\n clientIp: currentClientIp, // 클라이언트 IP 추가 (서버에서 재확인 권장)\r\n domainId: 'DEFAULT',\r\n appCd,\r\n sysCd,\r\n screenId: activeMenuId,\r\n },\r\n // data: bxmEncrypt(JSON.stringify(data)),\r\n data: data,\r\n };\r\n\r\n // 개발 환경에서 요청 정보 출력\r\n // if (isLocal) {\r\n // console.log(\"__BWG_LOCAL__ 테스트 입니다. \", isLocal);\r\n // }\r\n\r\n // HTTP 메서드에 따른 데이터 설정\r\n if (mergedOptions.method === 'GET') {\r\n config.params = requestData || mergedOptions.params;\r\n } else {\r\n config.data = requestData || mergedOptions.data;\r\n if (mergedOptions.params) {\r\n config.params = mergedOptions.params;\r\n }\r\n }\r\n\r\n // 재시도 로직\r\n let lastError: Error | undefined;\r\n for (\r\n let attempt = 0;\r\n attempt <= (mergedOptions.retryCount || 0);\r\n attempt++\r\n ) {\r\n try {\r\n const response = await apiClient(config);\r\n\r\n // 성공 응답 처리\r\n if (response.data.header?.resCd == 0) {\r\n // resCd가 0인 경우, header를 제외한 데이터 반환\r\n for (const key in response.data) {\r\n if (key !== 'header') {\r\n return response.data[key];\r\n }\r\n }\r\n // 데이터 필드가 없는 성공 응답의 경우, 빈 객체를 반환\r\n return {} as T;\r\n } else {\r\n // 실패 시 에러 생성 및 throw (비즈니스 에러)\r\n const header = response.data.header;\r\n const basicMsg =\r\n header?.msgs?.basicMsg || '요청 처리 중 오류가 발생했습니다.';\r\n const detailMsg = header?.msgs?.detailMsgs || basicMsg;\r\n const msgCd = header?.msgCd;\r\n const errorType = header?.msgs?.type;\r\n\r\n // ApiError를 생성하여 throw\r\n throw new ApiError(basicMsg, detailMsg, response, msgCd, errorType);\r\n }\r\n } catch (error) {\r\n // Axios 에러이고, 서버 응답이 있는 경우 (e.g., 500 에러)\r\n if (\r\n (error as AxiosError).isAxiosError &&\r\n (error as AxiosError).response\r\n ) {\r\n const axiosError = error as AxiosError;\r\n const response = axiosError.response!;\r\n const responseData = response.data as any;\r\n\r\n // 서버 응답 본문에서 메시지 추출 시도\r\n const basicMsg =\r\n responseData?.header?.msgs?.basicMsg ||\r\n axiosError.message || // 실패 시 Axios 에러 메시지 사용\r\n '서버에서 오류가 발생했습니다.';\r\n const detailMsg =\r\n responseData?.header?.msgs?.detailMsgs ||\r\n // 상세 메시지로 응답 본문 제공 (문자열이 아니면 JSON으로 변환)\r\n (typeof response.data === 'string'\r\n ? response.data\r\n : JSON.stringify(response.data)) ||\r\n basicMsg;\r\n const msgCd = responseData?.header?.msgCd;\r\n const errorType = responseData?.header?.msgs?.type;\r\n\r\n // AxiosError를 ApiError로 변환하여 lastError에 저장\r\n lastError = new ApiError(\r\n basicMsg,\r\n detailMsg,\r\n response,\r\n msgCd,\r\n errorType\r\n );\r\n } else {\r\n // 네트워크 에러 또는 try 블록에서 throw된 커스텀 에러(ApiError)\r\n lastError = error as Error;\r\n }\r\n\r\n // 재시도 로직\r\n if (\r\n (error as AxiosError).isAxiosError &&\r\n shouldRetry(error as AxiosError) &&\r\n attempt < (mergedOptions.retryCount || 0)\r\n ) {\r\n await delay(mergedOptions.retryDelay || 1000);\r\n continue;\r\n }\r\n\r\n // 재시도 불가능하거나 재시도 횟수 초과 시 루프 중단\r\n break;\r\n }\r\n }\r\n\r\n // 루프 종료 후 에러 처리 (lastError가 설정된 경우)\r\n if (lastError) {\r\n // 에러 표시 옵션이 활성화된 경우, 통합된 에러 메시지를 표시합니다.\r\n if (mergedOptions.showError) {\r\n const errorMessage =\r\n lastError instanceof ApiError\r\n ? lastError.message\r\n : '요청 처리 중 오류가 발생했습니다.';\r\n const errorCode =\r\n lastError instanceof ApiError\r\n ? lastError.msgCd\r\n : '요청 처리 중 오류가 발생했습니다.';\r\n const errorDescription =\r\n lastError instanceof ApiError\r\n ? lastError.detailMsg\r\n : lastError.message;\r\n const errorType =\r\n lastError instanceof ApiError ? lastError.errorType : '';\r\n\r\n if (errorCode?.startsWith('BXM'))\r\n notiBwgError({\r\n message: errorMessage,\r\n description: errorDescription,\r\n duration: 5,\r\n });\r\n else if ('I' == errorType) {\r\n notiInfo(errorMessage, errorDescription, 5);\r\n } else {\r\n notiWarning(errorMessage, errorDescription, 5);\r\n }\r\n }\r\n // 최종 에러를 호출자에게 throw합니다.\r\n throw lastError;\r\n }\r\n\r\n // 이 코드는 이론적으로 도달할 수 없지만, lastError가 없는 경우를 대비한 방어 코드입니다.\r\n throw new Error('알 수 없는 API 오류가 발생했습니다.');\r\n } catch (error: any) {\r\n // 최종 에러 처리 및 전파\r\n // callService에서 발생하는 모든 에러는 ApiError 형태로 변환하여 throw합니다.\r\n console.error('callService 최종 에러:', error);\r\n\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * Tomcat WAS와 통신하는 범용 API 호출 함수\r\n * @param trxCd - 거래코드드\r\n * @param data - 요청 데이터 (GET 요청 시 params로 사용)\r\n * @param options - 옵션 파라미터 (선택사항)\r\n * @returns Promise<ApiResponse<T>>\r\n */\r\nexport const callService_SYSCD = async <T = any>(\r\n _sysCd: string,\r\n trxCd: string,\r\n data?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n try {\r\n // 옵션 병합\r\n const mergedOptions: ApiOptions = {\r\n ...DEFAULT_OPTIONS,\r\n ...options,\r\n };\r\n\r\n //로드된 메뉴ID조회\r\n const { activeMenuId } = useMenuViewStore.getState();\r\n\r\n //ip가 없을경우 ip값 할당\r\n if (clientIp === null) {\r\n const ipStartTime = Date.now();\r\n await setClientIp();\r\n const ipEndTime = Date.now();\r\n console.log(`[INFO] IP 조회 소요시간: ${ipEndTime - ipStartTime}ms`);\r\n }\r\n\r\n // 요청 설정\r\n const config: AxiosRequestConfig & {\r\n showLoading?: boolean;\r\n isPopup?: boolean;\r\n } = {\r\n method: mergedOptions.method,\r\n url: '/api/' + _sysCd + '/service',\r\n timeout: mergedOptions.timeout,\r\n withCredentials: mergedOptions.withCredentials,\r\n showLoading: mergedOptions.showLoading,\r\n isPopup: mergedOptions.isPopup,\r\n };\r\n\r\n // 헤더 설정\r\n if (mergedOptions.headers) {\r\n config.headers = mergedOptions.headers;\r\n }\r\n\r\n // IP가 설정되지 않은 경우 기본값 사용 (추가 IP 호출 방지)\r\n const currentClientIp = clientIp || 'unknown';\r\n\r\n // vite.config.ts에서 define으로 주입된 전역 변수를 사용합니다.\r\n // @ts-ignore - __APP_CD__는 Vite에 의해 빌드 시점에 주입되는 전역 변수입니다.\r\n const appCd = __APP_CD__;\r\n const sysCd = __SYS_CD__;\r\n\r\n const requestData = {\r\n header: {\r\n trxCd: trxCd,\r\n userInfo: getUserInfo(),\r\n clientIp: currentClientIp, // 클라이언트 IP 추가 (서버에서 재확인 권장)\r\n domainId: 'DEFAULT',\r\n appCd,\r\n sysCd,\r\n screenId: activeMenuId,\r\n },\r\n // data: bxmEncrypt(JSON.stringify(data)),\r\n data: data,\r\n };\r\n\r\n // 개발 환경에서 요청 정보 출력\r\n if (isLocal) {\r\n console.log('__BWG_LOCAL__ 테스트 입니다. ', isLocal);\r\n }\r\n\r\n // HTTP 메서드에 따른 데이터 설정\r\n if (mergedOptions.method === 'GET') {\r\n config.params = requestData || mergedOptions.params;\r\n } else {\r\n config.data = requestData || mergedOptions.data;\r\n if (mergedOptions.params) {\r\n config.params = mergedOptions.params;\r\n }\r\n }\r\n\r\n // 재시도 로직\r\n let lastError: Error | undefined;\r\n for (\r\n let attempt = 0;\r\n attempt <= (mergedOptions.retryCount || 0);\r\n attempt++\r\n ) {\r\n try {\r\n const response = await apiClient(config);\r\n\r\n // 성공 응답 처리\r\n if (response.data.header?.resCd == 0) {\r\n // resCd가 0인 경우, header를 제외한 데이터 반환\r\n for (const key in response.data) {\r\n if (key !== 'header') {\r\n return response.data[key];\r\n }\r\n }\r\n // 데이터 필드가 없는 성공 응답의 경우, 빈 객체를 반환\r\n return {} as T;\r\n } else {\r\n // 실패 시 에러 생성 및 throw (비즈니스 에러)\r\n const header = response.data.header;\r\n const basicMsg =\r\n header?.msgs?.basicMsg || '요청 처리 중 오류가 발생했습니다.';\r\n const detailMsg = header?.msgs?.detailMsgs || basicMsg;\r\n const msgCd = header?.msgCd;\r\n const errorType = header?.msgs?.type;\r\n\r\n // ApiError를 생성하여 throw\r\n throw new ApiError(basicMsg, detailMsg, response, msgCd, errorType);\r\n }\r\n } catch (error) {\r\n // Axios 에러이고, 서버 응답이 있는 경우 (e.g., 500 에러)\r\n if (\r\n (error as AxiosError).isAxiosError &&\r\n (error as AxiosError).response\r\n ) {\r\n const axiosError = error as AxiosError;\r\n const response = axiosError.response!;\r\n const responseData = response.data as any;\r\n\r\n // 서버 응답 본문에서 메시지 추출 시도\r\n const basicMsg =\r\n responseData?.header?.msgs?.basicMsg ||\r\n axiosError.message || // 실패 시 Axios 에러 메시지 사용\r\n '서버에서 오류가 발생했습니다.';\r\n const detailMsg =\r\n responseData?.header?.msgs?.detailMsgs ||\r\n // 상세 메시지로 응답 본문 제공 (문자열이 아니면 JSON으로 변환)\r\n (typeof response.data === 'string'\r\n ? response.data\r\n : JSON.stringify(response.data)) ||\r\n basicMsg;\r\n const msgCd = responseData?.header?.msgCd;\r\n const errorType = responseData?.header?.msgs?.type;\r\n\r\n // AxiosError를 ApiError로 변환하여 lastError에 저장\r\n lastError = new ApiError(\r\n basicMsg,\r\n detailMsg,\r\n response,\r\n msgCd,\r\n errorType\r\n );\r\n } else {\r\n // 네트워크 에러 또는 try 블록에서 throw된 커스텀 에러(ApiError)\r\n lastError = error as Error;\r\n }\r\n\r\n // 재시도 로직\r\n if (\r\n (error as AxiosError).isAxiosError &&\r\n shouldRetry(error as AxiosError) &&\r\n attempt < (mergedOptions.retryCount || 0)\r\n ) {\r\n await delay(mergedOptions.retryDelay || 1000);\r\n continue;\r\n }\r\n\r\n // 재시도 불가능하거나 재시도 횟수 초과 시 루프 중단\r\n break;\r\n }\r\n }\r\n\r\n // 루프 종료 후 에러 처리 (lastError가 설정된 경우)\r\n if (lastError) {\r\n // 에러 표시 옵션이 활성화된 경우, 통합된 에러 메시지를 표시합니다.\r\n if (mergedOptions.showError) {\r\n const errorMessage =\r\n lastError instanceof ApiError\r\n ? lastError.message\r\n : '요청 처리 중 오류가 발생했습니다.';\r\n const errorCode =\r\n lastError instanceof ApiError\r\n ? lastError.msgCd\r\n : '요청 처리 중 오류가 발생했습니다.';\r\n const errorDescription =\r\n lastError instanceof ApiError\r\n ? lastError.detailMsg\r\n : lastError.message;\r\n const errorType =\r\n lastError instanceof ApiError ? lastError.errorType : '';\r\n\r\n if (errorCode?.startsWith('BXM'))\r\n notiBwgError({\r\n message: errorMessage,\r\n description: errorDescription,\r\n duration: 5,\r\n });\r\n else if ('I' == errorType) {\r\n notiInfo(errorMessage, errorDescription, 5);\r\n } else {\r\n notiWarning(errorMessage, errorDescription, 5);\r\n }\r\n }\r\n // 최종 에러를 호출자에게 throw합니다.\r\n throw lastError;\r\n }\r\n\r\n // 이 코드는 이론적으로 도달할 수 없지만, lastError가 없는 경우를 대비한 방어 코드입니다.\r\n throw new Error('알 수 없는 API 오류가 발생했습니다.');\r\n } catch (error: any) {\r\n // 최종 에러 처리 및 전파\r\n // callService에서 발생하는 모든 에러는 ApiError 형태로 변환하여 throw합니다.\r\n console.error('callService 최종 에러:', error);\r\n\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * 재시도 가능한 에러인지 확인\r\n */\r\nconst shouldRetry = (error: AxiosError): boolean => {\r\n // 네트워크 에러 또는 5xx 서버 에러만 재시도\r\n return (\r\n !error.response ||\r\n (error.response.status >= 500 && error.response.status < 600)\r\n );\r\n};\r\n\r\n/**\r\n * 지연 함수\r\n */\r\nconst delay = (ms: number): Promise<void> => {\r\n return new Promise(resolve => setTimeout(resolve, ms));\r\n};\r\n\r\n/**\r\n * 에러 처리 함수\r\n */\r\nconst handleError = (\r\n error: AxiosError,\r\n showError: boolean = true\r\n): ApiResponse => {\r\n let errorMessage = '알 수 없는 오류가 발생했습니다.';\r\n let errorCode = 500;\r\n\r\n if (error.response) {\r\n // 서버 응답이 있는 경우\r\n errorCode = error.response.status;\r\n const responseData = error.response.data as any;\r\n\r\n errorMessage =\r\n responseData?.message ||\r\n responseData?.error ||\r\n getErrorMessage(errorCode);\r\n } else if (error.request) {\r\n // 요청은 보냈지만 응답이 없는 경우\r\n errorMessage = '서버에 연결할 수 없습니다.';\r\n errorCode = 0;\r\n } else {\r\n // 요청 설정 중 에러\r\n errorMessage = error.message || '요청 설정 중 오류가 발생했습니다.';\r\n }\r\n\r\n // 에러 메시지 표시 (옵션)\r\n if (showError) {\r\n console.error(`API 에러 [${errorCode}]: ${errorMessage}`);\r\n // 여기서 전역 에러 처리 (예: toast, alert 등)를 할 수 있습니다\r\n }\r\n\r\n return {\r\n success: false,\r\n error: errorMessage,\r\n code: errorCode,\r\n };\r\n};\r\n\r\n/**\r\n * HTTP 상태 코드별 에러 메시지\r\n */\r\nconst getErrorMessage = (statusCode: number): string => {\r\n const errorMessages: Record<number, string> = {\r\n 400: '잘못된 요청입니다.',\r\n 401: '인증이 필요합니다.',\r\n 403: '접근이 거부되었습니다.',\r\n 404: '요청한 리소스를 찾을 수 없습니다.',\r\n 405: '허용되지 않는 메서드입니다.',\r\n 408: '요청 시간이 초과되었습니다.',\r\n 409: '요청이 충돌했습니다.',\r\n 422: '처리할 수 없는 엔티티입니다.',\r\n 429: '너무 많은 요청이 발생했습니다.',\r\n 500: '서버 내부 오류가 발생했습니다.',\r\n 502: '잘못된 게이트웨이입니다.',\r\n 503: '서비스를 사용할 수 없습니다.',\r\n 504: '게이트웨이 시간 초과입니다.',\r\n };\r\n\r\n return errorMessages[statusCode] || '알 수 없는 오류가 발생했습니다.';\r\n};\r\n\r\n// 편의 함수들\r\nexport const apiGet = <T = any>(\r\n trxCd: string,\r\n params?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n return callService<T>(trxCd, params, { ...options, method: 'GET' });\r\n};\r\n\r\nexport const apiPost = <T = any>(\r\n trxCd: string,\r\n data?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n return callService<T>(trxCd, data, { ...options, method: 'POST' });\r\n};\r\n\r\nexport const apiPut = <T = any>(\r\n trxCd: string,\r\n data?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n return callService<T>(trxCd, data, { ...options, method: 'PUT' });\r\n};\r\n\r\nexport const apiDelete = <T = any>(\r\n trxCd: string,\r\n data?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n return callService<T>(trxCd, data, { ...options, method: 'DELETE' });\r\n};\r\n\r\nexport const apiPatch = <T = any>(\r\n trxCd: string,\r\n data?: any,\r\n options?: ApiOptions\r\n): Promise<T> => {\r\n return callService<T>(trxCd, data, { ...options, method: 'PATCH' });\r\n};\r\n\r\n/**\r\n * 권한 확인 서비스\r\n * @param userId 사용자 ID\r\n * @param menuId 메뉴 ID\r\n * @param popupId 팝업 ID (선택사항)\r\n * @returns 권한 정보\r\n */\r\nexport const getPermissionService = async (\r\n userId: string,\r\n menuId: string,\r\n popupId?: string\r\n) => {\r\n try {\r\n const response = await fetch('/api/permissions', {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n },\r\n body: JSON.stringify({\r\n userId,\r\n menuId,\r\n popupId,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`권한 확인 실패: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n return data;\r\n } catch (error) {\r\n console.error('권한 확인 서비스 오류:', error);\r\n throw error;\r\n }\r\n};\r\n\r\n/**\r\n * 권한 정보 타입\r\n */\r\nexport interface PermissionInfo {\r\n // 공통 권한 버튼들\r\n commonButtons: Array<{\r\n id: string;\r\n label: string;\r\n type: 'primary' | 'default' | 'dashed' | 'link' | 'text';\r\n disabled?: boolean;\r\n visible?: boolean;\r\n }>;\r\n // 커스텀 버튼 그룹들\r\n customButtonGroups: {\r\n [groupId: string]: {\r\n [buttonId: string]: {\r\n label: string;\r\n type: 'primary' | 'default' | 'dashed' | 'link' | 'text';\r\n disabled?: boolean;\r\n visible?: boolean;\r\n isHeader?: boolean;\r\n };\r\n };\r\n };\r\n // 전체 권한 여부\r\n hasAccess: boolean;\r\n // 에러 메시지\r\n errorMessage?: string;\r\n}\r\n"],"names":["DEFAULT_SERVICE_CODES","serviceCodeOverrides","setServiceCodeOverrides","overrides","getServiceCode","serviceCodeKey","getAllServiceCodes","result","key","logServiceCodeConfig","allCodes","value","source","createJSONStorage","getStorage","options","storage","name","_a","parse","str2","str","newValue","toThenable","fn","input","onFulfilled","_onRejected","e","_onFulfilled","onRejected","persistImpl","config","baseOptions","set","get","api","state","persistedState","currentState","hasHydrated","hydrationListeners","finishHydrationListeners","args","setItem","savedSetState","replace","configResult","stateFromStorage","hydrate","_b","cb","_a2","postRehydrationCallback","deserializedStorageValue","migration","migrationResult","migrated","migratedState","newOptions","persist","useUserStore","create","user","userData","currentUser","getCrprCd","getUserId","getUserNm","getUserDvsn","getEmplNo","getDprtCd","getDprtNm","getRoleList","hasRole","role","roleList","hasAnyRole","roles","hasAllRoles","isLoggedIn","getUserInfo","hasUserInfo","getDisplayName","userNm","userId","getDepartmentInfo","dprtNm","dprtCd","MENU_CONSTANTS","isMenuItem","v","isMenuItemArray","_lastFlat","_cachedTree","parseMenuResponse","data","sameParams","a","b","buildHierarchy","flat","x","map","roots","m","cur","sortRec","arr","out","useMenuModelStore","crprCd","prntGbcd","p","callService","tree","menuId","flatMenuList","useMenuViewStore","menuItem","params","tabs","activeMenuId","exists","t","findTab","message","newTab","target","viewInfo","scrnPath","prsnInfoYn","tabKey","nextTabs","nextActive","idx","activeDetailItem","s","keys","k","newFlags","prev","next","merge","useLoadingStore","newCount","usePopupLoadingStore","_","module","require$$0","this","d","r","n","o","i","f","l","h","c","y","M","u","THEME_COOKIE_NAME","isString","isNumber","isBoolean","isFunction","isObject","isArray","isNull","isUndefined","isNullOrUndefined","throttle","func","delay","lastCall","now","debounce","timeoutId","copyToClipboard","text","error","getDeviceType","width","isMobile","isTablet","isDesktop","generateRandomColor","isEmptyArray","arrUnique","arrMax","arrMin","arrAverage","sum","num","arrSum","arrCount","predicate","arrReverse","duplicates","seen","item","random","min","max","clamp","round","decimals","setSessionStorage","getSessionStorage","defaultValue","removeSessionStorage","clearSessionStorage","setCookie","days","expires","getCookie","nameEQ","ca","deleteCookie","isEmpty","isSafeEmpty","toCamelCase","g","isValidEmail","email","isValidUrl","url","padLeft","length","char","padRight","generateRandomString","chars","generateUUIDv4","generateUID","uidWithoutHyphens","encryptSha256","SHA256","encBase64","dayjs","relativeTime","utc","timezone","getCurrentDate","getCurrentDateString","format","isLocal","devHosts","prodHosts","configureEnvUtils","opts","getHostName","isDev","host","isProd","getEnvCode","DEFAULT_CONFIG","NotificationService","props","description","duration","placement","notification","notificationService","notiBwgError","notiSuccess","notiInfo","notiWarning","notiError","destroyNotifications","closeNotification","clientIp","setClientIp","ip","ipAddr","axios","getClientIp","verifyClientIp","ApiError","detailMsg","response","msgCd","errorType","DEFAULT_OPTIONS","apiClient","trxCd","token","guid","responseTime","refreshToken","refreshResponse","originalRequest","mergedOptions","ipStartTime","ipEndTime","currentClientIp","appCd","sysCd","requestData","lastError","attempt","header","basicMsg","axiosError","responseData","shouldRetry","errorMessage","errorCode","errorDescription","callService_SYSCD","_sysCd","ms","resolve","apiGet","apiPost","apiPut","apiDelete","apiPatch","getPermissionService","popupId"],"mappings":"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","x_google_ignoreList":[1,7,8,9,10]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"usePopup-BSqsnSz7.js","sources":["../../src/provider/contexts/CommonCodeContext.tsx","../../src/provider/hooks/usePopup.ts"],"sourcesContent":["import { useCodeStore, type CommonCodeContextType } from '../../stores/codeStore';\r\nimport { createContext, useContext, ReactNode } from 'react';\r\n\r\n// 공통코드 컨텍스트 생성\r\nconst CommonCodeContext = createContext<CommonCodeContextType | undefined>(\r\n undefined\r\n);\r\n\r\n// 공통코드 컨텍스트 프로바이더 컴포넌트\r\ninterface CommonCodeProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport const CommonCodeProvider: React.FC<CommonCodeProviderProps> = ({\r\n children,\r\n}) => {\r\n const {\r\n codeData,\r\n isLoading,\r\n error,\r\n lastUpdated,\r\n getCodeList,\r\n getCodeListByOption,\r\n getCodeName,\r\n getCodeColor,\r\n getCodeByOption,\r\n getAvailableGroupCodes,\r\n getGridLookup,\r\n fetchCommonCodes,\r\n } = useCodeStore();\r\n\r\n const contextValue: CommonCodeContextType = {\r\n codeData,\r\n isLoading,\r\n error,\r\n lastUpdated,\r\n getCodeList,\r\n getCodeListByOption,\r\n getCodeName,\r\n getCodeColor,\r\n getCodeByOption,\r\n getAvailableGroupCodes,\r\n getGridLookup,\r\n refreshCodes: fetchCommonCodes,\r\n };\r\n\r\n return (\r\n <CommonCodeContext.Provider value={contextValue}>\r\n {children}\r\n </CommonCodeContext.Provider>\r\n );\r\n};\r\n\r\n// 공통코드 컨텍스트 사용 훅\r\nexport const useCommonCode = (): CommonCodeContextType => {\r\n const context = useContext(CommonCodeContext);\r\n if (context === undefined) {\r\n throw new Error('useCommonCode must be used within a CommonCodeProvider');\r\n }\r\n return context;\r\n};\r\n\r\n// 편의 훅들 (Fast Refresh 호환성을 위해 매개변수 없는 함수로 변경)\r\nexport const useCodeList = () => {\r\n const { getCodeList, isLoading, error } = useCommonCode();\r\n return {\r\n getCodeList,\r\n isLoading,\r\n error,\r\n };\r\n};\r\n\r\nexport const useCodeName = () => {\r\n const { getCodeName, isLoading, error } = useCommonCode();\r\n return {\r\n getCodeName,\r\n isLoading,\r\n error,\r\n };\r\n};\r\n\r\nexport const useCodeColor = () => {\r\n const { getCodeColor, isLoading, error } = useCommonCode();\r\n return {\r\n getCodeColor,\r\n isLoading,\r\n error,\r\n };\r\n};\r\n\r\nexport const useCodeListByOption = () => {\r\n const { getCodeListByOption, isLoading, error } = useCommonCode();\r\n return {\r\n getCodeListByOption,\r\n isLoading,\r\n error,\r\n };\r\n};\r\n\r\nexport const useGridLookup = () => {\r\n const { getGridLookup, isLoading, error } = useCommonCode();\r\n return {\r\n getGridLookup,\r\n isLoading,\r\n error,\r\n };\r\n};\r\n","import { useCallback } from 'react';\r\nimport { usePopupStore, type PopupConfig } from '../../stores/popupStore';\r\n\r\n/**\r\n * 팝업 컨텍스트를 감지하는 훅\r\n * 팝업 내부에서 사용하면 true, 일반 페이지에서는 false 반환\r\n */\r\nexport const usePopupContext = (): boolean => {\r\n // 팝업 내부에서만 true를 반환하도록 수정\r\n // 현재는 팝업이 열려있으면 모든 컴포넌트가 팝업으로 인식되는 문제가 있음\r\n // 임시로 false 반환 (수동으로 isPopup prop 사용 권장)\r\n return false;\r\n};\r\n\r\n/**\r\n * 팝업 데이터와 이벤트를 관리하는 훅\r\n */\r\nexport const usePopup = () => {\r\n const { popups, activePopupId, setActivePopup, closePopup, openPopup } =\r\n usePopupStore();\r\n\r\n // 팝업 열기 함수\r\n const showPopup = useCallback(\r\n async (popupCode: string, popParams?: any, config?: PopupConfig) => {\r\n try {\r\n await openPopup(popupCode, popParams, config);\r\n } catch (error) {\r\n console.error('팝업 열기 실패:', error);\r\n throw error;\r\n }\r\n },\r\n [openPopup]\r\n );\r\n\r\n return {\r\n popups,\r\n activePopupId,\r\n setActivePopup,\r\n closePopup,\r\n showPopup,\r\n isPopup: popups.length > 0,\r\n };\r\n};\r\n"],"names":["CommonCodeContext","createContext","CommonCodeProvider","children","codeData","isLoading","error","lastUpdated","getCodeList","getCodeListByOption","getCodeName","getCodeColor","getCodeByOption","getAvailableGroupCodes","getGridLookup","fetchCommonCodes","useCodeStore","contextValue","useCommonCode","context","useContext","useCodeList","useCodeName","useCodeColor","useCodeListByOption","useGridLookup","usePopupContext","usePopup","popups","activePopupId","setActivePopup","closePopup","openPopup","usePopupStore","showPopup","useCallback","popupCode","popParams","config"],"mappings":";;;;AAIA,MAAMA,IAAoBC;AAAA,EACxB;AACF,GAOaC,IAAwD,CAAC;AAAA,EACpE,UAAAC;AACF,MAAM;AACJ,QAAM;AAAA,IACJ,UAAAC;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,wBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,kBAAAC;AAAA,EAAA,IACEC,EAAA,GAEEC,IAAsC;AAAA,IAC1C,UAAAb;AAAA,IACA,WAAAC;AAAA,IACA,OAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,wBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,cAAcC;AAAA,EAAA;AAGhB,+BACGf,EAAkB,UAAlB,EAA2B,OAAOiB,GAChC,UAAAd,GACH;AAEJ,GAGae,IAAgB,MAA6B;AACxD,QAAMC,IAAUC,EAAWpB,CAAiB;AAC5C,MAAImB,MAAY;AACd,UAAM,IAAI,MAAM,wDAAwD;AAE1E,SAAOA;AACT,GAGaE,IAAc,MAAM;AAC/B,QAAM,EAAE,aAAAb,GAAa,WAAAH,GAAW,OAAAC,EAAA,IAAUY,EAAA;AAC1C,SAAO;AAAA,IACL,aAAAV;AAAA,IACA,WAAAH;AAAA,IACA,OAAAC;AAAA,EAAA;AAEJ,GAEagB,IAAc,MAAM;AAC/B,QAAM,EAAE,aAAAZ,GAAa,WAAAL,GAAW,OAAAC,EAAA,IAAUY,EAAA;AAC1C,SAAO;AAAA,IACL,aAAAR;AAAA,IACA,WAAAL;AAAA,IACA,OAAAC;AAAA,EAAA;AAEJ,GAEaiB,IAAe,MAAM;AAChC,QAAM,EAAE,cAAAZ,GAAc,WAAAN,GAAW,OAAAC,EAAA,IAAUY,EAAA;AAC3C,SAAO;AAAA,IACL,cAAAP;AAAA,IACA,WAAAN;AAAA,IACA,OAAAC;AAAA,EAAA;AAEJ,GAEakB,IAAsB,MAAM;AACvC,QAAM,EAAE,qBAAAf,GAAqB,WAAAJ,GAAW,OAAAC,EAAA,IAAUY,EAAA;AAClD,SAAO;AAAA,IACL,qBAAAT;AAAA,IACA,WAAAJ;AAAA,IACA,OAAAC;AAAA,EAAA;AAEJ,GAEamB,IAAgB,MAAM;AACjC,QAAM,EAAE,eAAAX,GAAe,WAAAT,GAAW,OAAAC,EAAA,IAAUY,EAAA;AAC5C,SAAO;AAAA,IACL,eAAAJ;AAAA,IACA,WAAAT;AAAA,IACA,OAAAC;AAAA,EAAA;AAEJ,GCnGaoB,IAAkB,MAItB,IAMIC,IAAW,MAAM;AAC5B,QAAM,EAAE,QAAAC,GAAQ,eAAAC,GAAe,gBAAAC,GAAgB,YAAAC,GAAY,WAAAC,EAAA,IACzDC,EAAA,GAGIC,IAAYC;AAAA,IAChB,OAAOC,GAAmBC,GAAiBC,MAAyB;AAClE,UAAI;AACF,cAAMN,EAAUI,GAAWC,GAAWC,CAAM;AAAA,MAC9C,SAAShC,GAAO;AACd,sBAAQ,MAAM,aAAaA,CAAK,GAC1BA;AAAA,MACR;AAAA,IACF;AAAA,IACA,CAAC0B,CAAS;AAAA,EAAA;AAGZ,SAAO;AAAA,IACL,QAAAJ;AAAA,IACA,eAAAC;AAAA,IACA,gBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,WAAAG;AAAA,IACA,SAASN,EAAO,SAAS;AAAA,EAAA;AAE7B;"}