@bwg-ui/core 1.1.20 → 1.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{BwgDownload-CF_Zo2oU.js → BwgDownload-COsACbpJ.js} +3 -3
- package/dist/chunks/{BwgDownload-CF_Zo2oU.js.map → BwgDownload-COsACbpJ.js.map} +1 -1
- package/dist/chunks/{BwgDownload-DvCaLWCL.cjs → BwgDownload-i6w7ZD-i.cjs} +2 -2
- package/dist/chunks/{BwgDownload-DvCaLWCL.cjs.map → BwgDownload-i6w7ZD-i.cjs.map} +1 -1
- package/dist/chunks/{SSOHandler-Cr04mtMm.js → SSOHandler-BHJ5NexT.js} +4 -4
- package/dist/chunks/{SSOHandler-Cr04mtMm.js.map → SSOHandler-BHJ5NexT.js.map} +1 -1
- package/dist/chunks/{SSOHandler-C7echUZs.cjs → SSOHandler-BtrmIPzQ.cjs} +2 -2
- package/dist/chunks/{SSOHandler-C7echUZs.cjs.map → SSOHandler-BtrmIPzQ.cjs.map} +1 -1
- package/dist/chunks/{SearchBoxContext-C2ECWG9l.js → SearchBoxContext-BxJN-x3-.js} +2 -2
- package/dist/chunks/{SearchBoxContext-C2ECWG9l.js.map → SearchBoxContext-BxJN-x3-.js.map} +1 -1
- package/dist/chunks/{SearchBoxContext-aMXi2JmO.cjs → SearchBoxContext-DnQGaRgo.cjs} +2 -2
- package/dist/chunks/{SearchBoxContext-aMXi2JmO.cjs.map → SearchBoxContext-DnQGaRgo.cjs.map} +1 -1
- package/dist/chunks/{ViewContainer-DI7hvDi-.cjs → ViewContainer-HSyLfryI.cjs} +2 -2
- package/dist/chunks/{ViewContainer-DI7hvDi-.cjs.map → ViewContainer-HSyLfryI.cjs.map} +1 -1
- package/dist/chunks/{ViewContainer-DxhY26m3.js → ViewContainer-x2yzKkIG.js} +2 -2
- package/dist/chunks/{ViewContainer-DxhY26m3.js.map → ViewContainer-x2yzKkIG.js.map} +1 -1
- package/dist/chunks/apiUtils-CudW_FKE.cjs +3 -0
- package/dist/chunks/apiUtils-CudW_FKE.cjs.map +1 -0
- package/dist/chunks/apiUtils-DfPv_gmI.js +2064 -0
- package/dist/chunks/apiUtils-DfPv_gmI.js.map +1 -0
- package/dist/chunks/{codeStore-kuUEfWSS.js → codeStore-DefmZVgs.js} +2 -2
- package/dist/chunks/{codeStore-kuUEfWSS.js.map → codeStore-DefmZVgs.js.map} +1 -1
- package/dist/chunks/{codeStore-WWRT65Zk.cjs → codeStore-pQbDqWkZ.cjs} +2 -2
- package/dist/chunks/{codeStore-WWRT65Zk.cjs.map → codeStore-pQbDqWkZ.cjs.map} +1 -1
- package/dist/chunks/{favoriteStore-DdGoghEn.cjs → favoriteStore-BXBziAgB.cjs} +2 -2
- package/dist/chunks/{favoriteStore-DdGoghEn.cjs.map → favoriteStore-BXBziAgB.cjs.map} +1 -1
- package/dist/chunks/{favoriteStore-D40XfOmq.js → favoriteStore-DAPC01iF.js} +2 -2
- package/dist/chunks/{favoriteStore-D40XfOmq.js.map → favoriteStore-DAPC01iF.js.map} +1 -1
- package/dist/chunks/{popupStore-DKpp0bmC.cjs → popupStore-BV632k5p.cjs} +2 -2
- package/dist/chunks/{popupStore-DKpp0bmC.cjs.map → popupStore-BV632k5p.cjs.map} +1 -1
- package/dist/chunks/{popupStore-axohgTV-.js → popupStore-CcQg9AvK.js} +2 -2
- package/dist/chunks/{popupStore-axohgTV-.js.map → popupStore-CcQg9AvK.js.map} +1 -1
- package/dist/chunks/{usePopup-Dftb7Bbl.js → usePopup-Cw5xsOaH.js} +3 -3
- package/dist/chunks/{usePopup-Dftb7Bbl.js.map → usePopup-Cw5xsOaH.js.map} +1 -1
- package/dist/chunks/{usePopup-DYnRe9Th.cjs → usePopup-DoVGuobp.cjs} +2 -2
- package/dist/chunks/{usePopup-DYnRe9Th.cjs.map → usePopup-DoVGuobp.cjs.map} +1 -1
- package/dist/components/common/index.cjs +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/core/index.cjs +1 -1
- package/dist/components/core/index.js +1 -1
- package/dist/components/layout/index.cjs +1 -1
- package/dist/components/layout/index.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +9 -9
- package/dist/provider/index.cjs +1 -1
- package/dist/provider/index.js +2 -2
- package/dist/stores/index.cjs +1 -1
- package/dist/stores/index.js +6 -6
- package/dist/utils/commonUtils.d.ts +0 -6
- package/dist/utils/commonUtils.d.ts.map +1 -1
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunks/apiUtils-BRaXRbjE.js +0 -1428
- package/dist/chunks/apiUtils-BRaXRbjE.js.map +0 -1
- package/dist/chunks/apiUtils-DL43X2ta.cjs +0 -3
- package/dist/chunks/apiUtils-DL43X2ta.cjs.map +0 -1
- package/dist/chunks/core-D7JhyoYH.cjs +0 -2
- package/dist/chunks/core-D7JhyoYH.cjs.map +0 -1
- package/dist/chunks/core-DLGhqegD.js +0 -514
- package/dist/chunks/core-DLGhqegD.js.map +0 -1
- package/dist/chunks/enc-base64-96WlVdPN.js +0 -102
- package/dist/chunks/enc-base64-96WlVdPN.js.map +0 -1
- package/dist/chunks/enc-base64-b9mIy966.cjs +0 -2
- package/dist/chunks/enc-base64-b9mIy966.cjs.map +0 -1
- package/dist/chunks/sha256-BMg1y0Py.js +0 -79
- package/dist/chunks/sha256-BMg1y0Py.js.map +0 -1
- package/dist/chunks/sha256-BxdSMFca.cjs +0 -2
- package/dist/chunks/sha256-BxdSMFca.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as u } from "./jsx-runtime-Dpn_P65e.js";
|
|
2
2
|
import { useEffect as m, createContext as i, useContext as l, useRef as x } from "react";
|
|
3
|
-
import { al as f } from "./apiUtils-
|
|
3
|
+
import { al as f } from "./apiUtils-DfPv_gmI.js";
|
|
4
4
|
const n = {
|
|
5
5
|
// 권한 관련
|
|
6
6
|
AUTH_BTNS: "SCMSIGN00202",
|
|
@@ -85,4 +85,4 @@ export {
|
|
|
85
85
|
D as e,
|
|
86
86
|
M as u
|
|
87
87
|
};
|
|
88
|
-
//# sourceMappingURL=SearchBoxContext-
|
|
88
|
+
//# sourceMappingURL=SearchBoxContext-BxJN-x3-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBoxContext-
|
|
1
|
+
{"version":3,"file":"SearchBoxContext-BxJN-x3-.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,2 +1,2 @@
|
|
|
1
|
-
"use strict";const a=require("./jsx-runtime-CeSfJrVB.cjs"),c=require("react"),v=require("./apiUtils-
|
|
2
|
-
//# sourceMappingURL=SearchBoxContext-
|
|
1
|
+
"use strict";const a=require("./jsx-runtime-CeSfJrVB.cjs"),c=require("react"),v=require("./apiUtils-CudW_FKE.cjs"),u={AUTH_BTNS:"SCMSIGN00202",AUTH_MENU:"SCMSIGN00201",SRCH_CODE:"SCMSIGN00301",SRCH_POPU:"SCMPOPU00101",AUTH_BMRK:"SCMBMRK00101"},S=c.createContext(null),x=({children:o,serviceCodes:e={}})=>{c.useEffect(()=>{v.setServiceCodeOverrides(e)},[e]);const i={serviceCodes:e,getServiceCode:r=>{if(e[r]&&e[r].trim()!=="")return console.log(`🔧 Provider 설정 사용: ${r} = ${e[r]}`),e[r];const s=u[r];return console.log(`🔧 기본값 사용: ${r} = ${s}`),s}};return a.jsxRuntimeExports.jsx(S.Provider,{value:i,children:o})},n=()=>{const o=c.useContext(S);if(!o)throw new Error("useServiceCode must be used within a ServiceCodeProvider");return o},g=o=>{const{getServiceCode:e}=n();return e(o)},m=()=>{const{getServiceCode:o}=n(),e={};for(const t of Object.keys(u))e[t]=o(t);return e},f=()=>{const{getServiceCode:o}=n();console.log("🔧 bwg-core 서비스코드 설정:"),console.log("📋 Provider 설정 > 기본값 순서로 확인");for(const e of Object.keys(u)){const t=o(e);console.log(` ${e}: ${t}`)}},l=c.createContext(null),P=({children:o})=>{const e=c.useRef(null),C={searchBoxRef:e,getFormData:()=>e.current?.getFormData()||{},setFormData:d=>{e.current?.setFormData(d)},resetForm:()=>{e.current?.resetForm()},validateForm:async()=>await e.current?.validateForm()||{success:!1,error:null}};return a.jsxRuntimeExports.jsx(l.Provider,{value:C,children:o})},F=()=>{const o=c.useContext(l);if(!o)throw new Error("useSearchBox must be used within a SearchBoxProvider");return o};exports.SearchBoxProvider=P;exports.ServiceCodeProvider=x;exports.useAllServiceCodes=m;exports.useLogServiceCodeConfig=f;exports.useSearchBox=F;exports.useServiceCode=n;exports.useServiceCodeValue=g;
|
|
2
|
+
//# sourceMappingURL=SearchBoxContext-DnQGaRgo.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBoxContext-
|
|
1
|
+
{"version":3,"file":"SearchBoxContext-DnQGaRgo.cjs","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":"mHAUMA,EAAwB,CAE5B,UAAW,eACX,UAAW,eACX,UAAW,eAGX,UAAW,eAGX,UAAW,cACb,EAGMC,EAAqBC,EAAAA,cAA6C,IAAI,EA0D/DC,EAA0D,CAAC,CACtE,SAAAC,EACA,aAAAC,EAAe,CAAA,CACjB,IAAM,CAEJC,EAAAA,UAAU,IAAM,CACdC,EAAAA,wBAAwBF,CAAY,CACtC,EAAG,CAACA,CAAY,CAAC,EAgBjB,MAAMG,EAAuC,CAC3C,aAAAH,EACA,eAfsBI,GAAgC,CAEtD,GAAIJ,EAAaI,CAAG,GAAKJ,EAAaI,CAAG,EAAG,KAAA,IAAW,GACrD,eAAQ,IAAI,sBAAsBA,CAAG,MAAMJ,EAAaI,CAAG,CAAC,EAAE,EACvDJ,EAAaI,CAAG,EAIzB,MAAMC,EAAeV,EAAsBS,CAAG,EAC9C,eAAQ,IAAI,cAAcA,CAAG,MAAMC,CAAY,EAAE,EAC1CA,CACT,CAIE,EAGF,+BACGT,EAAmB,SAAnB,CAA4B,MAAOO,EACjC,SAAAJ,EACH,CAEJ,EAWaO,EAAiB,IAA8B,CAC1D,MAAMC,EAAUC,EAAAA,WAAWZ,CAAkB,EAC7C,GAAI,CAACW,EACH,MAAM,IAAI,MAAM,0DAA0D,EAE5E,OAAOA,CACT,EAcaE,EAAuBL,GAAgC,CAClE,KAAM,CAAE,eAAAM,CAAA,EAAmBJ,EAAA,EAC3B,OAAOI,EAAeN,CAAG,CAC3B,EAaaO,EAAqB,IAAsC,CACtE,KAAM,CAAE,eAAAD,CAAA,EAAmBJ,EAAA,EACrBM,EAAS,CAAA,EAEf,UAAWR,KAAO,OAAO,KAAKT,CAAqB,EACjDiB,EAAOR,CAAG,EAAIM,EAAeN,CAAG,EAGlC,OAAOQ,CACT,EAYaC,EAA0B,IAAY,CACjD,KAAM,CAAE,eAAAH,CAAA,EAAmBJ,EAAA,EAE3B,QAAQ,IAAI,uBAAuB,EACnC,QAAQ,IAAI,6BAA6B,EAEzC,UAAWF,KAAO,OAAO,KAAKT,CAAqB,EAAuB,CACxE,MAAMmB,EAAQJ,EAAeN,CAAG,EAChC,QAAQ,IAAI,KAAKA,CAAG,KAAKU,CAAK,EAAE,CAClC,CACF,ECpLMC,EAAmBlB,EAAAA,cAA2C,IAAI,EAQ3DmB,EAAsD,CAAC,CAClE,SAAAjB,CACF,IAAM,CACJ,MAAMkB,EAAeC,EAAAA,OAAqB,IAAI,EAuBxCJ,EAA8B,CAClC,aAAAG,EACA,YAvBkB,IACXA,EAAa,SAAS,YAAA,GAAiB,CAAA,EAuB9C,YApBmBE,GAAc,CACjCF,EAAa,SAAS,YAAYE,CAAI,CACxC,EAmBE,UAjBgB,IAAM,CACtBF,EAAa,SAAS,UAAA,CACxB,EAgBE,aAdmB,SAEhB,MAAMA,EAAa,SAAS,gBAAmB,CAC9C,QAAS,GACT,MAAO,IAAA,CAUX,EAGF,OACEG,EAAAA,kBAAAA,IAACL,EAAiB,SAAjB,CAA0B,MAAAD,EACxB,SAAAf,CAAA,CACH,CAEJ,EAGasB,EAAe,IAAM,CAChC,MAAMd,EAAUC,EAAAA,WAAWO,CAAgB,EAC3C,GAAI,CAACR,EACH,MAAM,IAAI,MAAM,sDAAsD,EAExE,OAAOA,CACT"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";const e=require("./jsx-runtime-CeSfJrVB.cjs"),g=require("./ScreenProtectContext-CVuXrJm6.cjs"),n=require("react"),b=require("./AuthContext-CXng9fj0.cjs"),E=require("./apiUtils-
|
|
1
|
+
"use strict";const e=require("./jsx-runtime-CeSfJrVB.cjs"),g=require("./ScreenProtectContext-CVuXrJm6.cjs"),n=require("react"),b=require("./AuthContext-CXng9fj0.cjs"),E=require("./apiUtils-CudW_FKE.cjs"),o=require("antd"),R=require("react-router-dom"),h=require("@ant-design/icons");class w extends n.Component{constructor(r){super(r),this.resetError=()=>{this.setState({hasError:!1,error:void 0,errorInfo:void 0})},this.state={hasError:!1}}static getDerivedStateFromError(r){return{hasError:!0,error:r}}componentDidCatch(r,s){console.error("ErrorBound caught an error:",r,s),this.setState({error:r,errorInfo:s})}render(){return this.state.hasError?this.props.fallback?this.props.fallback:e.jsxRuntimeExports.jsxs("div",{style:{padding:"40px 20px",textAlign:"center",backgroundColor:"#fafafa",display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center"},children:[e.jsxRuntimeExports.jsx(o.Result,{status:"error",title:"컴포넌트 로딩 중 오류가 발생했습니다",subTitle:this.state.error?`오류 내용: ${this.state.error.message}`:"알 수 없는 오류가 발생했습니다",extra:[e.jsxRuntimeExports.jsx(o.Button,{type:"primary",icon:e.jsxRuntimeExports.jsx(h.ReloadOutlined,{}),onClick:this.resetError,style:{marginRight:8},children:"다시 시도"},"retry")]}),this.state.error&&e.jsxRuntimeExports.jsxs("details",{style:{marginTop:"20px",textAlign:"left",maxWidth:"600px",backgroundColor:"#fff",padding:"16px",borderRadius:"6px",border:"1px solid #d9d9d9"},children:[e.jsxRuntimeExports.jsx("summary",{style:{cursor:"pointer",fontWeight:"bold"},children:"오류 상세 정보"}),e.jsxRuntimeExports.jsx("pre",{style:{marginTop:"8px",fontSize:"12px",color:"#666",whiteSpace:"pre-wrap",wordBreak:"break-word"},children:this.state.error.stack})]})]}):this.props.children}}const v=t=>({position:"absolute",inset:0,visibility:t?"visible":"hidden",opacity:t?1:0,transition:"opacity 0.2s ease-in-out",pointerEvents:t?"auto":"none"}),C=({once:t=!0})=>{const{lock:r}=g.useLock(),s=n.useRef(!1);return n.useEffect(()=>{t&&s.current||(s.current=!0,r())},[t,r]),null},S=({isActive:t,flagged:r,tabKey:s,onUnlock:i,children:l})=>{const a=n.useRef(null),[x,d]=n.useState(!1),c=n.useCallback(u=>{a.current=u,d(!!u)},[]),m=v(t);return e.jsxRuntimeExports.jsx("div",{ref:c,style:m,children:x?e.jsxRuntimeExports.jsxs(g.ScreenProtectProvider,{idleMs:Number.POSITIVE_INFINITY,persistLocked:!1,overlayScope:"scoped",overlayPosition:"absolute",eventTarget:a.current,overlayId:`tab-overlay-${s}`,onUnlock:async()=>(i(),!0),children:[t&&r?e.jsxRuntimeExports.jsx(C,{once:!0}):null,l]}):l})},j="bwg-dot-line-wave-v4";function k(){if(typeof document>"u"||document.getElementById(j))return;const t=document.createElement("style");t.id=j,t.textContent=`
|
|
2
2
|
.bwg-dotline {
|
|
3
3
|
display: inline-flex;
|
|
4
4
|
align-items: center;
|
|
@@ -33,4 +33,4 @@
|
|
|
33
33
|
.bwg-dotline .dot { animation: none; }
|
|
34
34
|
}
|
|
35
35
|
`,document.head.appendChild(t)}const P=({colors:t=["#DAD3FF","#B3A6FF","#9380FF","#816BFA"],count:r,size:s=12,gap:i=10,amp:l=16,speedMs:a=900,direction:x="ltr",phase:d=.7})=>{n.useEffect(()=>{k()},[]);const c=r??t.length,m=Array.from({length:c}),u={"--bwg-size":`${s}px`,"--bwg-gap":`${i}px`,"--bwg-amp":`${l}px`,"--bwg-speed":`${a}ms`},f=a/c*d;return e.jsxRuntimeExports.jsx("span",{className:"bwg-dotline",role:"img","aria-label":"loading",style:u,children:m.map((B,p)=>e.jsxRuntimeExports.jsx("span",{className:"dot",style:{backgroundColor:t[p%t.length],animationDelay:x==="ltr"?`${p*f}ms`:`${(c-1-p)*f}ms`}},p))})},y=({spin:t=null,text:r="인증중..."})=>{const{busy:s}=b.useAuth();return t??s?e.jsxRuntimeExports.jsxs("div",{style:{position:"fixed",height:"100vh",left:0,right:0,top:0,display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"center",gap:8,padding:"8px 12px",background:"rgba(0,0,0,0.6)",color:"#fff",zIndex:1e4},"aria-live":"polite","aria-busy":"true",role:"status",children:[e.jsxRuntimeExports.jsx(o.Spin,{indicator:e.jsxRuntimeExports.jsx(P,{colors:["#DAD3FF","#B3A6FF","#9380FF","#816BFA"],size:12,gap:10,amp:16,speedMs:900,phase:.75,direction:"ltr"})}),e.jsxRuntimeExports.jsx("span",{className:"bwg-spin-txt",style:{marginTop:"15px"},children:r})]}):null},I=()=>{const{reauthWithPin:t}=b.useAuth();return e.jsxRuntimeExports.jsx(g.ScreenProtectProvider,{idleMs:30*6e4,onUnlock:async r=>E.isLocal?!0:!!r&&await t(r),children:e.jsxRuntimeExports.jsx(o.ConfigProvider,{getPopupContainer:()=>document.getElementById("app-shell")||document.body,children:e.jsxRuntimeExports.jsxs("div",{id:"app-shell",children:[e.jsxRuntimeExports.jsx(y,{}),e.jsxRuntimeExports.jsx(R.Outlet,{})]})})})},T=()=>e.jsxRuntimeExports.jsxs("div",{children:[e.jsxRuntimeExports.jsx(y,{}),e.jsxRuntimeExports.jsx(R.Outlet,{})]}),D=({isActive:t,instance:r,params:s})=>{const{activeMenuId:i,closeTab:l}=E.useMenuViewStore(),a=()=>{i&&l(i)};return r?e.jsxRuntimeExports.jsx("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",visibility:t?"visible":"hidden",opacity:t?1:0,transition:"opacity 0.2s ease-in-out",pointerEvents:t?"auto":"none"},children:e.jsxRuntimeExports.jsx(w,{children:e.jsxRuntimeExports.jsx(n.Suspense,{fallback:null,children:r&&n.createElement(r,{params:s})})})}):e.jsxRuntimeExports.jsx("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",display:"flex",justifyContent:"center",alignItems:"center",visibility:t?"visible":"hidden",opacity:t?1:0,transition:"opacity 0.2s ease-in-out",pointerEvents:t?"auto":"none"},children:e.jsxRuntimeExports.jsx("div",{style:{width:500,maxWidth:"90%",background:"#fff",borderRadius:16,boxShadow:"0 8px 30px rgba(0,0,0,0.05)",padding:24},children:e.jsxRuntimeExports.jsx(o.Result,{icon:e.jsxRuntimeExports.jsx(h.ExclamationCircleTwoTone,{twoToneColor:"#69b1ff"}),status:"warning",title:"등록된 메뉴 정보가 없거나 유효한 메뉴가 아닙니다.",subTitle:e.jsxRuntimeExports.jsx(o.Typography.Text,{type:"secondary",children:"자세한 내용은 관리자에게 문의바랍니다."}),extra:e.jsxRuntimeExports.jsx(o.Space,{children:e.jsxRuntimeExports.jsx(o.Button,{icon:e.jsxRuntimeExports.jsx(h.CloseOutlined,{}),onClick:a,children:"탭 닫기"})})})})})},F=n.memo(D);exports.ErrorBound=w;exports.PrivateProtectedOverlay=S;exports.ProgressOverlay=y;exports.ProtectedLayout=I;exports.PublicLayout=T;exports.ViewContainer=F;
|
|
36
|
-
//# sourceMappingURL=ViewContainer-
|
|
36
|
+
//# sourceMappingURL=ViewContainer-HSyLfryI.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewContainer-DI7hvDi-.cjs","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
|
+
{"version":3,"file":"ViewContainer-HSyLfryI.cjs","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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"}
|
|
@@ -2,7 +2,7 @@ import { j as e } from "./jsx-runtime-Dpn_P65e.js";
|
|
|
2
2
|
import { S as m, u as E } from "./ScreenProtectContext-3my4PHFa.js";
|
|
3
3
|
import k, { Component as C, useRef as f, useState as S, useCallback as T, useEffect as g, memo as F, Suspense as I } from "react";
|
|
4
4
|
import { u as y } from "./AuthContext-Ei2P-z4d.js";
|
|
5
|
-
import { a8 as D, aH as P } from "./apiUtils-
|
|
5
|
+
import { a8 as D, aH as P } from "./apiUtils-DfPv_gmI.js";
|
|
6
6
|
import { Result as b, Button as w, Spin as R, ConfigProvider as B, Space as L, Typography as $ } from "antd";
|
|
7
7
|
import { Outlet as j } from "react-router-dom";
|
|
8
8
|
import { ReloadOutlined as z, CloseOutlined as N, ExclamationCircleTwoTone as O } from "@ant-design/icons";
|
|
@@ -323,4 +323,4 @@ export {
|
|
|
323
323
|
te as b,
|
|
324
324
|
re as c
|
|
325
325
|
};
|
|
326
|
-
//# sourceMappingURL=ViewContainer-
|
|
326
|
+
//# sourceMappingURL=ViewContainer-x2yzKkIG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewContainer-DxhY26m3.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
|
+
{"version":3,"file":"ViewContainer-x2yzKkIG.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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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";const le=require("axios"),A=require("dayjs"),N=require("antd"),re=require("zustand");var W=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function k(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function fr(e){if(Object.prototype.hasOwnProperty.call(e,"__esModule"))return e;var r=e.default;if(typeof r=="function"){var t=function n(){var a=!1;try{a=this instanceof n}catch{}return a?Reflect.construct(r,arguments,this.constructor):r.apply(this,arguments)};t.prototype=r.prototype}else t={};return Object.defineProperty(t,"__esModule",{value:!0}),Object.keys(e).forEach(function(n){var a=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,a.get?a:{enumerable:!0,get:function(){return e[n]}})}),t}const Le={AUTH_BTNS:"SCMSIGN00202",AUTH_MENU:"SCMSIGN00201",SRCH_CODE:"SCMSIGN00301",SRCH_POPU:"SCMPOPU00101",AUTH_BMRK:"SCMBMRK00101"};let Y={};function Ae(e){Y=e,console.log("🔧 Provider 서비스코드 오버라이드 설정:",e)}function ne(e){return Y[e]&&Y[e].trim()!==""?Y[e]:Le[e]}function de(){const e={};for(const r of Object.keys(Le))e[r]=ne(r);return e}function Be(){console.log("🔧 bwg-core 서비스코드 설정:"),console.log("📋 Provider 설정 > 기본값 순서로 확인");const e=de();for(const[r,t]of Object.entries(e)){const n=Y[r]?"Provider 설정":"기본값";console.log(` ${r}: ${t} (${n})`)}}const hr=Object.freeze(Object.defineProperty({__proto__:null,getAllServiceCodes:de,getServiceCode:ne,logServiceCodeConfig:Be,setServiceCodeOverrides:Ae},Symbol.toStringTag,{value:"Module"}));(void 0).DEV;function gr(e,r){let t;try{t=e()}catch{return}return{getItem:a=>{var i;const f=g=>g===null?null:JSON.parse(g,void 0),w=(i=t.getItem(a))!=null?i:null;return w instanceof Promise?w.then(f):f(w)},setItem:(a,i)=>t.setItem(a,JSON.stringify(i,void 0)),removeItem:a=>t.removeItem(a)}}const ce=e=>r=>{try{const t=e(r);return t instanceof Promise?t:{then(n){return ce(n)(t)},catch(n){return this}}}catch(t){return{then(n){return this},catch(n){return ce(n)(t)}}}},mr=(e,r)=>(t,n,a)=>{let i={storage:gr(()=>localStorage),partialize:o=>o,version:0,merge:(o,d)=>({...d,...o}),...r},f=!1;const w=new Set,g=new Set;let S=i.storage;if(!S)return e((...o)=>{console.warn(`[zustand persist middleware] Unable to update item '${i.name}', the given storage is currently unavailable.`),t(...o)},n,a);const y=()=>{const o=i.partialize({...n()});return S.setItem(i.name,{state:o,version:i.version})},p=a.setState;a.setState=(o,d)=>(p(o,d),y());const l=e((...o)=>(t(...o),y()),n,a);a.getInitialState=()=>l;let u;const h=()=>{var o,d;if(!S)return;f=!1,w.forEach(s=>{var c;return s((c=n())!=null?c:l)});const _=((d=i.onRehydrateStorage)==null?void 0:d.call(i,(o=n())!=null?o:l))||void 0;return ce(S.getItem.bind(S))(i.name).then(s=>{if(s)if(typeof s.version=="number"&&s.version!==i.version){if(i.migrate){const c=i.migrate(s.state,s.version);return c instanceof Promise?c.then(m=>[!0,m]):[!0,c]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return[!1,s.state];return[!1,void 0]}).then(s=>{var c;const[m,v]=s;if(u=i.merge(v,(c=n())!=null?c:l),t(u,!0),m)return y()}).then(()=>{_?.(u,void 0),u=n(),f=!0,g.forEach(s=>s(u))}).catch(s=>{_?.(void 0,s)})};return a.persist={setOptions:o=>{i={...i,...o},o.storage&&(S=o.storage)},clearStorage:()=>{S?.removeItem(i.name)},getOptions:()=>i,rehydrate:()=>h(),hasHydrated:()=>f,onHydrate:o=>(w.add(o),()=>{w.delete(o)}),onFinishHydration:o=>(g.add(o),()=>{g.delete(o)})},i.skipHydration||h(),u||l},ke=mr,E=re.create()(ke((e,r)=>({user:null,isLoggedIn:!1,login:t=>{e({user:t,isLoggedIn:!0}),console.log("사용자 로그인:",t)},logout:()=>{e({user:null,isLoggedIn:!1}),console.log("사용자 로그아웃")},updateUser:t=>{const n=r().user;n&&e({user:{...n,...t}})}}),{name:"user-storage",partialize:e=>({user:e.user,isLoggedIn:e.isLoggedIn})})),Re=()=>E.getState().user?.crprCd||null,fe=()=>E.getState().user?.userId||null,he=()=>E.getState().user?.userNm||null,Ye=()=>E.getState().user?.userDvsn||null,Fe=()=>E.getState().user?.emplNo||null,ge=()=>E.getState().user?.dprtCd||null,me=()=>E.getState().user?.dprtNm||null,H=()=>E.getState().user?.roleList||null,He=e=>{const r=H();return r?r.includes(e):!1},ze=e=>{const r=H();return r?e.some(t=>r.includes(t)):!1},je=e=>{const r=H();return r?e.every(t=>r.includes(t)):!1},qe=()=>E.getState().isLoggedIn,z=()=>E.getState().user,We=()=>z()!==null,Ge=()=>{const e=he(),r=fe();return e||r||null},Ke=()=>{const e=me(),r=ge();return e||(r?String(r):null)},pr=Object.freeze(Object.defineProperty({__proto__:null,getCrprCd:Re,getDepartmentInfo:Ke,getDisplayName:Ge,getDprtCd:ge,getDprtNm:me,getEmplNo:Fe,getRoleList:H,getUserDvsn:Ye,getUserId:fe,getUserInfo:z,getUserNm:he,hasAllRoles:je,hasAnyRole:ze,hasRole:He,hasUserInfo:We,isLoggedIn:qe},Symbol.toStringTag,{value:"Module"})),ue={DEFAULT_PRNT_GBCD:1},vr=e=>e&&typeof e=="object"&&typeof e.menuId=="string"&&typeof e.menuNm=="string"&&typeof e.crprCd=="string",Ie=e=>Array.isArray(e)&&e.every(vr);let ae=[],xe=[];const yr=e=>{if(e&&typeof e=="object"){const r=e;if(r.menus&&Ie(r.menus))return r.menus;if(Ie(e))return e}return console.warn("⚠️ 메뉴 응답이 비어있거나 예상과 다릅니다."),[]},Sr=(e,r)=>!!r&&e.crprCd===r.crprCd&&e.userId===r.userId&&(e.prntGbcd??ue.DEFAULT_PRNT_GBCD)===(r.prntGbcd??ue.DEFAULT_PRNT_GBCD),wr=e=>{if(ae.length===e.length&&ae.every((i,f)=>i.menuId===e[f]?.menuId&&i.menuPrntId===e[f]?.menuPrntId))return xe;if(!e.length)return[];const r=new Map,t=[];e.forEach(i=>i?.menuId&&r.set(i.menuId,{...i,children:[]})),e.forEach(i=>{const f=r.get(i.menuId);f&&(i.menuPrntId&&i.menuPrntId!==""&&i.menuPrntId!=="-"?r.get(i.menuPrntId)?.children?.push(f):t.push(f))});const n=i=>i.sort((f,w)=>(f?.menuNo??0)-(w?.menuNo??0)).map(f=>({...f,children:f.children&&f.children.length?n(f.children):void 0})),a=n(t);return ae=[...e],xe=a,a},Ve=re.create((e,r)=>({menuList:[],flatMenuList:[],isLoading:!1,error:null,_lastFetchParams:null,fetchMenu:async({crprCd:t,userId:n,prntGbcd:a})=>{const i={crprCd:t,userId:n,prntGbcd:a??ue.DEFAULT_PRNT_GBCD};if(Sr(i,r()._lastFetchParams)){console.log("✅ 중복 fetch 차단",i);return}e({isLoading:!0,error:null,_lastFetchParams:i});try{const f=await L(ne("AUTH_MENU"),i),w=yr(f),g=wr(w);e({flatMenuList:w,menuList:g,isLoading:!1,error:null})}catch(f){e({isLoading:!1,error:f?.message??"메뉴 로드 실패"})}},clearMenu:()=>{e({menuList:[],flatMenuList:[],error:null,_lastFetchParams:null})},findMenuById:t=>{const{flatMenuList:n}=r();return n.find(a=>a.menuId===t)??null}})),ie={MAX_TABS:15},pe=re.create((e,r)=>({activeMenuId:null,activeMenuItem:null,activeDetailItem:null,tabs:[],sidebarCollapsed:!1,maxTabs:ie.MAX_TABS,tabProtectFlag:{},tabParams:{},componentLabelMap:{},openTabFromMenu:(t,n)=>{const{tabs:a,activeMenuId:i}=r(),f=a.find(g=>g.key===t.menuId),w=a.find(g=>g.key===t.menuId);if(f)w!=null?(e({activeMenuId:t.menuId,activeMenuItem:t}),r().setTabParams(t.menuId,n||{}),t?.prsnInfoYn==="Y"&&r().setProtectFlagForKey(t.menuId)):N.message.warning("유효하지 않은 메뉴정보입니다.");else{if(a.length>ie.MAX_TABS){console.warn("❌ 최대 탭 개수를 초과했습니다."),N.message.warning(`최대 ${ie.MAX_TABS}개의 탭만 열 수 있습니다.
|
|
2
|
+
기존 탭을 닫고 다시 시도해주세요.`);return}const g={key:t.menuId,label:t.menuNm,gubun:"M",menuItem:t,closable:!0};e({tabs:[...a,g],activeMenuId:t.menuId,activeMenuItem:t}),r().setTabParams(t.menuId,n||{}),t?.prsnInfoYn==="Y"&&r().setProtectFlagForKey(t.menuId)}},openTabByMenuId:(t,n)=>{const a=Ve.getState().findMenuById(t);a?r().openTabFromMenu(a,n):N.message.warning("메뉴 ID를 찾을 수 없습니다.")},openDetailView:(t,n,a)=>{const{tabs:i,activeMenuId:f}=r();if(i.find(g=>g.key===t.viewId))r().focusTab(t.viewId);else{const g={key:t.viewId,label:t.viewLabel,gubun:"C",componentItem:{scrnPath:n,prsnInfoYn:a,prntInfo:t.prntInfo},closable:!0};e({tabs:[...i,g],activeMenuId:t.viewId,activeDetailItem:t}),r().setTabParams(t.viewId,t.viewParams||{})}},closeTab:t=>{const{tabs:n,activeMenuId:a}=r();n.find(w=>w.key===t);const i=n.filter(w=>w.key!==t);let f=a;if(a===t){const w=n.findIndex(g=>g.key===t);f=i.length?i[Math.min(w,i.length-1)]?.key??null:null}e({tabs:i}),f&&r().focusTab(f)},focusTab:t=>{const{tabs:n}=r(),a=n.find(i=>i.key===t);if(a){const i=a.gubun==="C"?{viewId:a.key,viewLabel:a.label,prntInfo:a.componentItem?.prntInfo}:null;a.menuItem?.prsnInfoYn==="Y"?(e({activeMenuId:t,activeMenuItem:a.menuItem,activeDetailItem:i}),console.log("✅ 탭 포커스 (개인정보) - activeMenuItem:",a.menuItem),r().setProtectFlagForKey(t)):(e({activeMenuId:t,activeMenuItem:a.menuItem,activeDetailItem:i}),r().clearProtectFlagForKey(t))}else e({activeMenuId:t,activeMenuItem:null,activeDetailItem:null}),console.warn("❌ 탭을 찾을 수 없음:",t)},closeAllTabs:()=>e({tabs:[],activeMenuId:null,activeMenuItem:null,activeDetailItem:null}),toggleSidebar:()=>e(t=>({sidebarCollapsed:!t.sidebarCollapsed})),reorderTabs:t=>e(n=>{const a=new Map(n.tabs.map(i=>[i.key,i]));return{tabs:t.map(i=>a.get(i)).filter(Boolean)}}),setProtectFlagForKey:t=>e(n=>({tabProtectFlag:{...n.tabProtectFlag,[t]:!0}})),clearProtectFlagForKey:t=>e(n=>{const a={...n.tabProtectFlag};return delete a[t],{tabProtectFlag:a}}),setTabParams:(t,n)=>e(a=>{const i=a.tabParams[t]||{},f={...n||{}};return Object.keys(i).length===Object.keys(f).length&&Object.keys(f).every(g=>i[g]===f[g])?a:{tabParams:{...a.tabParams,[t]:f}}}),setComponentLabelMap:(t,n)=>e({componentLabelMap:t})})),ee=re.create(e=>({requestCount:0,loading:!1,showLoading:()=>e(r=>{const t=r.requestCount+1;return{requestCount:t,loading:t>0}}),hideLoading:()=>e(r=>{const t=Math.max(0,r.requestCount-1);return{requestCount:t,loading:t>0}})}));var G={exports:{}};function _r(e){throw new Error('Could not dynamically require "'+e+'". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.')}var K={exports:{}};const Mr={},Cr=Object.freeze(Object.defineProperty({__proto__:null,default:Mr},Symbol.toStringTag,{value:"Module"})),br=fr(Cr);var Tr=K.exports,De;function Je(){return De||(De=1,(function(e,r){(function(t,n){e.exports=n()})(Tr,function(){var t=t||(function(n,a){var i;if(typeof window<"u"&&window.crypto&&(i=window.crypto),typeof self<"u"&&self.crypto&&(i=self.crypto),typeof globalThis<"u"&&globalThis.crypto&&(i=globalThis.crypto),!i&&typeof window<"u"&&window.msCrypto&&(i=window.msCrypto),!i&&typeof W<"u"&&W.crypto&&(i=W.crypto),!i&&typeof _r=="function")try{i=br}catch{}var f=function(){if(i){if(typeof i.getRandomValues=="function")try{return i.getRandomValues(new Uint32Array(1))[0]}catch{}if(typeof i.randomBytes=="function")try{return i.randomBytes(4).readInt32LE()}catch{}}throw new Error("Native crypto module could not be used to get secure random number.")},w=Object.create||(function(){function s(){}return function(c){var m;return s.prototype=c,m=new s,s.prototype=null,m}})(),g={},S=g.lib={},y=S.Base=(function(){return{extend:function(s){var c=w(this);return s&&c.mixIn(s),(!c.hasOwnProperty("init")||this.init===c.init)&&(c.init=function(){c.$super.init.apply(this,arguments)}),c.init.prototype=c,c.$super=this,c},create:function(){var s=this.extend();return s.init.apply(s,arguments),s},init:function(){},mixIn:function(s){for(var c in s)s.hasOwnProperty(c)&&(this[c]=s[c]);s.hasOwnProperty("toString")&&(this.toString=s.toString)},clone:function(){return this.init.prototype.extend(this)}}})(),p=S.WordArray=y.extend({init:function(s,c){s=this.words=s||[],c!=a?this.sigBytes=c:this.sigBytes=s.length*4},toString:function(s){return(s||u).stringify(this)},concat:function(s){var c=this.words,m=s.words,v=this.sigBytes,M=s.sigBytes;if(this.clamp(),v%4)for(var C=0;C<M;C++){var b=m[C>>>2]>>>24-C%4*8&255;c[v+C>>>2]|=b<<24-(v+C)%4*8}else for(var T=0;T<M;T+=4)c[v+T>>>2]=m[T>>>2];return this.sigBytes+=M,this},clamp:function(){var s=this.words,c=this.sigBytes;s[c>>>2]&=4294967295<<32-c%4*8,s.length=n.ceil(c/4)},clone:function(){var s=y.clone.call(this);return s.words=this.words.slice(0),s},random:function(s){for(var c=[],m=0;m<s;m+=4)c.push(f());return new p.init(c,s)}}),l=g.enc={},u=l.Hex={stringify:function(s){for(var c=s.words,m=s.sigBytes,v=[],M=0;M<m;M++){var C=c[M>>>2]>>>24-M%4*8&255;v.push((C>>>4).toString(16)),v.push((C&15).toString(16))}return v.join("")},parse:function(s){for(var c=s.length,m=[],v=0;v<c;v+=2)m[v>>>3]|=parseInt(s.substr(v,2),16)<<24-v%8*4;return new p.init(m,c/2)}},h=l.Latin1={stringify:function(s){for(var c=s.words,m=s.sigBytes,v=[],M=0;M<m;M++){var C=c[M>>>2]>>>24-M%4*8&255;v.push(String.fromCharCode(C))}return v.join("")},parse:function(s){for(var c=s.length,m=[],v=0;v<c;v++)m[v>>>2]|=(s.charCodeAt(v)&255)<<24-v%4*8;return new p.init(m,c)}},o=l.Utf8={stringify:function(s){try{return decodeURIComponent(escape(h.stringify(s)))}catch{throw new Error("Malformed UTF-8 data")}},parse:function(s){return h.parse(unescape(encodeURIComponent(s)))}},d=S.BufferedBlockAlgorithm=y.extend({reset:function(){this._data=new p.init,this._nDataBytes=0},_append:function(s){typeof s=="string"&&(s=o.parse(s)),this._data.concat(s),this._nDataBytes+=s.sigBytes},_process:function(s){var c,m=this._data,v=m.words,M=m.sigBytes,C=this.blockSize,b=C*4,T=M/b;s?T=n.ceil(T):T=n.max((T|0)-this._minBufferSize,0);var x=T*C,D=n.min(x*4,M);if(x){for(var R=0;R<x;R+=C)this._doProcessBlock(v,R);c=v.splice(0,x),m.sigBytes-=D}return new p.init(c,D)},clone:function(){var s=y.clone.call(this);return s._data=this._data.clone(),s},_minBufferSize:0});S.Hasher=d.extend({cfg:y.extend(),init:function(s){this.cfg=this.cfg.extend(s),this.reset()},reset:function(){d.reset.call(this),this._doReset()},update:function(s){return this._append(s),this._process(),this},finalize:function(s){s&&this._append(s);var c=this._doFinalize();return c},blockSize:16,_createHelper:function(s){return function(c,m){return new s.init(m).finalize(c)}},_createHmacHelper:function(s){return function(c,m){return new _.HMAC.init(s,m).finalize(c)}}});var _=g.algo={};return g})(Math);return t})})(K)),K.exports}var Ir=G.exports,Ee;function xr(){return Ee||(Ee=1,(function(e,r){(function(t,n){e.exports=n(Je())})(Ir,function(t){return(function(n){var a=t,i=a.lib,f=i.WordArray,w=i.Hasher,g=a.algo,S=[],y=[];(function(){function u(_){for(var s=n.sqrt(_),c=2;c<=s;c++)if(!(_%c))return!1;return!0}function h(_){return(_-(_|0))*4294967296|0}for(var o=2,d=0;d<64;)u(o)&&(d<8&&(S[d]=h(n.pow(o,1/2))),y[d]=h(n.pow(o,1/3)),d++),o++})();var p=[],l=g.SHA256=w.extend({_doReset:function(){this._hash=new f.init(S.slice(0))},_doProcessBlock:function(u,h){for(var o=this._hash.words,d=o[0],_=o[1],s=o[2],c=o[3],m=o[4],v=o[5],M=o[6],C=o[7],b=0;b<64;b++){if(b<16)p[b]=u[h+b]|0;else{var T=p[b-15],x=(T<<25|T>>>7)^(T<<14|T>>>18)^T>>>3,D=p[b-2],R=(D<<15|D>>>17)^(D<<13|D>>>19)^D>>>10;p[b]=x+p[b-7]+R+p[b-16]}var ir=m&v^~m&M,cr=d&_^d&s^_&s,ur=(d<<30|d>>>2)^(d<<19|d>>>13)^(d<<10|d>>>22),lr=(m<<26|m>>>6)^(m<<21|m>>>11)^(m<<7|m>>>25),Te=C+lr+ir+y[b]+p[b],dr=ur+cr;C=M,M=v,v=m,m=c+Te|0,c=s,s=_,_=d,d=Te+dr|0}o[0]=o[0]+d|0,o[1]=o[1]+_|0,o[2]=o[2]+s|0,o[3]=o[3]+c|0,o[4]=o[4]+m|0,o[5]=o[5]+v|0,o[6]=o[6]+M|0,o[7]=o[7]+C|0},_doFinalize:function(){var u=this._data,h=u.words,o=this._nDataBytes*8,d=u.sigBytes*8;return h[d>>>5]|=128<<24-d%32,h[(d+64>>>9<<4)+14]=n.floor(o/4294967296),h[(d+64>>>9<<4)+15]=o,u.sigBytes=h.length*4,this._process(),this._hash},clone:function(){var u=w.clone.call(this);return u._hash=this._hash.clone(),u}});a.SHA256=w._createHelper(l),a.HmacSHA256=w._createHmacHelper(l)})(Math),t.SHA256})})(G)),G.exports}var Dr=xr();const Er=k(Dr);var V={exports:{}},Or=V.exports,Oe;function Nr(){return Oe||(Oe=1,(function(e,r){(function(t,n){e.exports=n(Je())})(Or,function(t){return(function(){var n=t,a=n.lib,i=a.WordArray,f=n.enc;f.Base64={stringify:function(g){var S=g.words,y=g.sigBytes,p=this._map;g.clamp();for(var l=[],u=0;u<y;u+=3)for(var h=S[u>>>2]>>>24-u%4*8&255,o=S[u+1>>>2]>>>24-(u+1)%4*8&255,d=S[u+2>>>2]>>>24-(u+2)%4*8&255,_=h<<16|o<<8|d,s=0;s<4&&u+s*.75<y;s++)l.push(p.charAt(_>>>6*(3-s)&63));var c=p.charAt(64);if(c)for(;l.length%4;)l.push(c);return l.join("")},parse:function(g){var S=g.length,y=this._map,p=this._reverseMap;if(!p){p=this._reverseMap=[];for(var l=0;l<y.length;l++)p[y.charCodeAt(l)]=l}var u=y.charAt(64);if(u){var h=g.indexOf(u);h!==-1&&(S=h)}return w(g,S,p)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="};function w(g,S,y){for(var p=[],l=0,u=0;u<S;u++)if(u%4){var h=y[g.charCodeAt(u-1)]<<u%4*2,o=y[g.charCodeAt(u)]>>>6-u%4*2,d=h|o;p[l>>>2]|=d<<24-l%4*8,l++}return i.create(p,l)}})(),t.enc.Base64})})(V)),V.exports}var Ur=Nr();const Pr=k(Ur);var J={exports:{}},$r=J.exports,Ne;function Lr(){return Ne||(Ne=1,(function(e,r){(function(t,n){e.exports=n(A)})($r,(function(t){function n(f){return f&&typeof f=="object"&&"default"in f?f:{default:f}}var a=n(t),i={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(f){return f+"일"},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(f){return f<12?"오전":"오후"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇 초",m:"1분",mm:"%d분",h:"한 시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한 달",MM:"%d달",y:"일 년",yy:"%d년"}};return a.default.locale(i,null,!0),i}))})(J)),J.exports}Lr();var X={exports:{}},Ar=X.exports,Ue;function Br(){return Ue||(Ue=1,(function(e,r){(function(t,n){e.exports=n()})(Ar,(function(){return function(t,n,a){t=t||{};var i=n.prototype,f={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 w(S,y,p,l){return i.fromToBase(S,y,p,l)}a.en.relativeTime=f,i.fromToBase=function(S,y,p,l,u){for(var h,o,d,_=p.$locale().relativeTime||f,s=t.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"}],c=s.length,m=0;m<c;m+=1){var v=s[m];v.d&&(h=l?a(S).diff(p,v.d,!0):p.diff(S,v.d,!0));var M=(t.rounding||Math.round)(Math.abs(h));if(d=h>0,M<=v.r||!v.r){M<=1&&m>0&&(v=s[m-1]);var C=_[v.l];u&&(M=u(""+M)),o=typeof C=="string"?C.replace("%d",M):C(M,y,v.l,d);break}}if(y)return o;var b=d?_.future:_.past;return typeof b=="function"?b(o):b.replace("%s",o)},i.to=function(S,y){return w(S,y,this,!0)},i.from=function(S,y){return w(S,y,this)};var g=function(S){return S.$u?a.utc():a()};i.toNow=function(S){return this.to(g(this),S)},i.fromNow=function(S){return this.from(g(this),S)}}}))})(X)),X.exports}var kr=Br();const Rr=k(kr);var Z={exports:{}},Yr=Z.exports,Pe;function Fr(){return Pe||(Pe=1,(function(e,r){(function(t,n){e.exports=n()})(Yr,(function(){var t={year:0,month:1,day:2,hour:3,minute:4,second:5},n={};return function(a,i,f){var w,g=function(l,u,h){h===void 0&&(h={});var o=new Date(l),d=(function(_,s){s===void 0&&(s={});var c=s.timeZoneName||"short",m=_+"|"+c,v=n[m];return v||(v=new Intl.DateTimeFormat("en-US",{hour12:!1,timeZone:_,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",timeZoneName:c}),n[m]=v),v})(u,h);return d.formatToParts(o)},S=function(l,u){for(var h=g(l,u),o=[],d=0;d<h.length;d+=1){var _=h[d],s=_.type,c=_.value,m=t[s];m>=0&&(o[m]=parseInt(c,10))}var v=o[3],M=v===24?0:v,C=o[0]+"-"+o[1]+"-"+o[2]+" "+M+":"+o[4]+":"+o[5]+":000",b=+l;return(f.utc(C).valueOf()-(b-=b%1e3))/6e4},y=i.prototype;y.tz=function(l,u){l===void 0&&(l=w);var h,o=this.utcOffset(),d=this.toDate(),_=d.toLocaleString("en-US",{timeZone:l}),s=Math.round((d-new Date(_))/1e3/60),c=15*-Math.round(d.getTimezoneOffset()/15)-s;if(!Number(c))h=this.utcOffset(0,u);else if(h=f(_,{locale:this.$L}).$set("millisecond",this.$ms).utcOffset(c,!0),u){var m=h.utcOffset();h=h.add(o-m,"minute")}return h.$x.$timezone=l,h},y.offsetName=function(l){var u=this.$x.$timezone||f.tz.guess(),h=g(this.valueOf(),u,{timeZoneName:l}).find((function(o){return o.type.toLowerCase()==="timezonename"}));return h&&h.value};var p=y.startOf;y.startOf=function(l,u){if(!this.$x||!this.$x.$timezone)return p.call(this,l,u);var h=f(this.format("YYYY-MM-DD HH:mm:ss:SSS"),{locale:this.$L});return p.call(h,l,u).tz(this.$x.$timezone,!0)},f.tz=function(l,u,h){var o=h&&u,d=h||u||w,_=S(+f(),d);if(typeof l!="string")return f(l).tz(d);var s=(function(M,C,b){var T=M-60*C*1e3,x=S(T,b);if(C===x)return[T,C];var D=S(T-=60*(x-C)*1e3,b);return x===D?[T,x]:[M-60*Math.min(x,D)*1e3,Math.max(x,D)]})(f.utc(l,o).valueOf(),_,d),c=s[0],m=s[1],v=f(c).utcOffset(m);return v.$x.$timezone=d,v},f.tz.guess=function(){return Intl.DateTimeFormat().resolvedOptions().timeZone},f.tz.setDefault=function(l){w=l}}}))})(Z)),Z.exports}var Hr=Fr();const zr=k(Hr);var Q={exports:{}},jr=Q.exports,$e;function qr(){return $e||($e=1,(function(e,r){(function(t,n){e.exports=n()})(jr,(function(){var t="minute",n=/[+-]\d\d(?::?\d\d)?/g,a=/([+-]|\d\d)/g;return function(i,f,w){var g=f.prototype;w.utc=function(o){var d={date:o,utc:!0,args:arguments};return new f(d)},g.utc=function(o){var d=w(this.toDate(),{locale:this.$L,utc:!0});return o?d.add(this.utcOffset(),t):d},g.local=function(){return w(this.toDate(),{locale:this.$L,utc:!1})};var S=g.parse;g.parse=function(o){o.utc&&(this.$u=!0),this.$utils().u(o.$offset)||(this.$offset=o.$offset),S.call(this,o)};var y=g.init;g.init=function(){if(this.$u){var o=this.$d;this.$y=o.getUTCFullYear(),this.$M=o.getUTCMonth(),this.$D=o.getUTCDate(),this.$W=o.getUTCDay(),this.$H=o.getUTCHours(),this.$m=o.getUTCMinutes(),this.$s=o.getUTCSeconds(),this.$ms=o.getUTCMilliseconds()}else y.call(this)};var p=g.utcOffset;g.utcOffset=function(o,d){var _=this.$utils().u;if(_(o))return this.$u?0:_(this.$offset)?p.call(this):this.$offset;if(typeof o=="string"&&(o=(function(v){v===void 0&&(v="");var M=v.match(n);if(!M)return null;var C=(""+M[0]).match(a)||["-",0,0],b=C[0],T=60*+C[1]+ +C[2];return T===0?0:b==="+"?T:-T})(o),o===null))return this;var s=Math.abs(o)<=16?60*o:o,c=this;if(d)return c.$offset=s,c.$u=o===0,c;if(o!==0){var m=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();(c=this.local().add(s+m,t)).$offset=s,c.$x.$localOffset=m}else c=this.utc();return c};var l=g.format;g.format=function(o){var d=o||(this.$u?"YYYY-MM-DDTHH:mm:ss[Z]":"");return l.call(this,d)},g.valueOf=function(){var o=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*o},g.isUTC=function(){return!!this.$u},g.toISOString=function(){return this.toDate().toISOString()},g.toString=function(){return this.toDate().toUTCString()};var u=g.toDate;g.toDate=function(o){return o==="s"&&this.$offset?w(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate():u.call(this)};var h=g.diff;g.diff=function(o,d,_){if(o&&this.$u===o.$u)return h.call(this,o,d,_);var s=this.local(),c=w(o).local();return h.call(s,c,d,_)}}}))})(Q)),Q.exports}var Wr=qr();const Gr=k(Wr),Xe="ui_theme",Ze=e=>typeof e=="string",Qe=e=>typeof e=="number"&&!isNaN(e),et=e=>typeof e=="boolean",tt=e=>typeof e=="function",rt=e=>e!==null&&typeof e=="object",nt=e=>Array.isArray(e),ot=e=>e===null,st=e=>e===void 0,at=e=>e==null,it=(e,r)=>{let t=0;return(...n)=>{const a=Date.now();a-t>=r&&(t=a,e(...n))}},ct=(e,r)=>{let t;return(...n)=>{clearTimeout(t),t=setTimeout(()=>e(...n),r)}},ut=async e=>{try{return await navigator.clipboard.writeText(e),!0}catch(r){return console.error("Error copying to clipboard:",r),!1}},j=()=>{const e=window.innerWidth;return e<768?"mobile":e<1024?"tablet":"desktop"},lt=()=>j()==="mobile",dt=()=>j()==="tablet",ft=()=>j()==="desktop",ht=()=>"#"+Math.floor(Math.random()*16777215).toString(16),q=e=>!e||e.length===0,gt=e=>[...new Set(e)],mt=e=>{if(!q(e))return Math.max(...e)},pt=e=>{if(!q(e))return Math.min(...e)},vt=e=>{if(!q(e))return e.reduce((r,t)=>r+t,0)/e.length},yt=e=>e.reduce((r,t)=>r+t,0),St=(e,r)=>e.filter(r).length,wt=e=>[...e].reverse(),_t=e=>{const r=new Set,t=new Set;return e.forEach(n=>{r.has(n)?t.add(n):r.add(n)}),Array.from(t)},Mt=(e,r)=>Math.random()*(r-e)+e,Ct=(e,r,t)=>Math.min(Math.max(e,r),t),bt=(e,r=0)=>Math.round(e*Math.pow(10,r))/Math.pow(10,r),Tt=(e,r)=>{try{sessionStorage.setItem(e,JSON.stringify(r))}catch(t){console.error("Error saving to sessionStorage:",t)}},It=(e,r)=>{try{const t=sessionStorage.getItem(e);return t?JSON.parse(t):r||null}catch(t){return console.error("Error reading from sessionStorage:",t),r||null}},xt=e=>{try{sessionStorage.removeItem(e)}catch(r){console.error("Error removing from sessionStorage:",r)}},Dt=()=>{try{sessionStorage.clear()}catch(e){console.error("Error clearing sessionStorage:",e)}},Et=(e,r,t=30)=>{const n=new Date;n.setTime(n.getTime()+t*24*60*60*1e3),document.cookie=`${e}=${r};expires=${n.toUTCString()};path=/`},Ot=e=>{const r=e+"=",t=document.cookie.split(";");for(let n=0;n<t.length;n++){let a=t[n];for(;a.charAt(0)===" ";)a=a.substring(1,a.length);if(a.indexOf(r)===0)return a.substring(r.length,a.length)}return null},Nt=e=>{document.cookie=`${e}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`},ve=e=>typeof e!="string"?!e:e.trim().length===0,Ut=(e,r)=>ve(e)?r:e||"",Pt=e=>e.replace(/-([a-z])/g,r=>r[1].toUpperCase()),$t=e=>/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e),Lt=e=>{try{return new URL(e),!0}catch{return!1}},At=(e,r,t=" ")=>e.padStart(r,t),Bt=(e,r,t=" ")=>e.padEnd(r,t),ye=(e,r="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")=>{let t="";for(let n=0;n<e;n++)t+=r.charAt(Math.floor(Math.random()*r.length));return t},Kr=()=>"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){const r=Math.random()*16|0;return(e==="x"?r:r&3|8).toString(16)}),Se=(e=32)=>{const t=Kr().replace(/-/g,"");return e>=32?t+ye(e-32,"0123456789abcdef"):t.substring(0,e)};async function kt(e){return Er(e).toString(Pr)}A.extend(Rr);A.extend(Gr);A.extend(zr);A.locale("ko");const Rt=()=>A(),Yt=(e="YYYY-MM-DD")=>A().format(e),Vr=Object.freeze(Object.defineProperty({__proto__:null,THEME_COOKIE_NAME:Xe,arrAverage:vt,arrCount:St,arrMax:mt,arrMin:pt,arrReverse:wt,arrSum:yt,arrUnique:gt,clamp:Ct,clearSessionStorage:Dt,copyToClipboard:ut,debounce:ct,deleteCookie:Nt,duplicates:_t,encryptSha256:kt,generateRandomColor:ht,generateRandomString:ye,generateUID:Se,getCookie:Ot,getCurrentDate:Rt,getCurrentDateString:Yt,getDeviceType:j,getSessionStorage:It,isArray:nt,isBoolean:et,isDesktop:ft,isEmpty:ve,isEmptyArray:q,isFunction:tt,isMobile:lt,isNull:ot,isNullOrUndefined:at,isNumber:Qe,isObject:rt,isSafeEmpty:Ut,isString:Ze,isTablet:dt,isUndefined:st,isValidEmail:$t,isValidUrl:Lt,padLeft:At,padRight:Bt,random:Mt,removeSessionStorage:xt,round:bt,setCookie:Et,setSessionStorage:Tt,throttle:it,toCamelCase:Pt},Symbol.toStringTag,{value:"Module"})),$=(()=>{try{if((void 0).DEV)return!0}catch{}return!1})();let Ft=[],Ht=[];function zt(e){e.devHosts&&(Ft=e.devHosts),e.prodHosts&&(Ht=e.prodHosts)}function jt(){if(typeof window<"u"&&window.location)return window.location.hostname}const we=(()=>{const e=jt();return!!(e&&Ft.includes(e))})(),_e=(()=>{const e=jt();return!!(e&&Ht.includes(e))})();function qt(){return $?"X":we?"D":_e?"P":"X"}const Jr=Object.freeze(Object.defineProperty({__proto__:null,configureEnvUtils:zt,getEnvCode:qt,isDev:we,isLocal:$,isProd:_e},Symbol.toStringTag,{value:"Module"})),O={duration:4.5,placement:"topRight"};class B{constructor(){}static getInstance(){return B.instance||(B.instance=new B),B.instance}showBwgError(r){const{message:t,description:n,duration:a=O.duration,placement:i=O.placement}=r;N.notification.error({message:`${t}`,description:n||"오류가 발생했습니다. 다시 시도해주세요.",duration:a,placement:i,style:{borderLeft:"4px solid #ff4d4f",backgroundColor:"#fff2f0"}})}showSuccess(r,t,n){N.notification.success({message:`${r}`,description:t,duration:n||O.duration,placement:O.placement})}showInfo(r,t,n){N.notification.info({message:`${r}`,description:t,duration:n||O.duration,placement:O.placement})}showWarning(r,t,n){N.notification.warning({message:`${r}`,description:t,duration:n||O.duration,placement:O.placement})}showError(r,t,n){N.notification.error({message:`${r}`,description:t,duration:n||O.duration,placement:O.placement})}destroy(){N.notification.destroy()}close(r){N.notification.destroy()}}const P=B.getInstance(),Me=e=>{P.showBwgError(e)},Wt=(e,r,t)=>{P.showSuccess(e,r,t)},Ce=(e,r,t)=>{P.showInfo(e,r,t)},be=(e,r,t)=>{P.showWarning(e,r,t)},Gt=(e,r,t)=>{P.showError(e,r,t)},Kt=()=>{P.destroy()},Vt=e=>{P.close(e)},Xr=Object.freeze(Object.defineProperty({__proto__:null,closeNotification:Vt,destroyNotifications:Kt,notiBwgError:Me,notiError:Gt,notiInfo:Ce,notiSuccess:Wt,notiWarning:be,notificationService:P},Symbol.toStringTag,{value:"Module"}));let U=null;const oe=async e=>{if(U===null)if(e===void 0)try{let t=(await le.get("/api/ip")).data.trim();t=t.replace(/\s+/g,""),U=t}catch(r){console.warn("IP 가져오기 실패:",r),U="unknown"}else U=e},Jt=()=>U,Xt=async()=>(console.log("IP 검증 비활성화됨 (성능 최적화)"),U||"unknown");class I extends Error{constructor(r,t,n,a,i){super(r),this.name="ApiError",this.detailMsg=t,this.response=n,this.msgCd=a,this.errorType=i,Error.captureStackTrace&&Error.captureStackTrace(this,I)}}const te={method:"POST",timeout:3e4,withCredentials:!0,showLoading:!0,showError:!0,retryCount:0,retryDelay:1e3},F=le.create({timeout:te.timeout,withCredentials:te.withCredentials,headers:{"Content-Type":"application/json; charset=utf-8",Accept:"application/json; charset=utf-8"}});F.interceptors.request.use(e=>{e.showLoading&&ee.getState().showLoading();let r="UNKNOWN",t="UNKNOWN";new Date().getTime();try{e.data&&e.data.header?(r=e.data.header.trxCd||"UNKNOWN",t=e.data.header.guid||"UNKNOWN"):e.params&&e.params.header&&(r=e.params.header.trxCd||"UNKNOWN",t=e.params.header.guid||"UNKNOWN")}catch(a){console.warn("trxCd/guid 추출 실패:",a)}e.trxCd=r,e.guid=t,e.requestStartTime=Date.now(),console.log(`🚀 API 요청 시작 [거래코드: ${r} / GUID: ${t}]`);const n=localStorage.getItem("accessToken");return n&&(e.headers.Authorization=`Bearer ${n}`),e.headers["Content-Type"]="application/json; charset=UTF-8",e.headers.Accept="application/json; charset=UTF-8",e},e=>(console.error("❌ 요청 인터셉터 에러:",e),Promise.reject(e)));F.interceptors.response.use(e=>{e.config.showLoading&&ee.getState().hideLoading();let r="UNKNOWN",t="UNKNOWN";const n=new Date().getTime();try{e.config.trxCd&&(r=e.config.trxCd),e.config.guid?t=e.config.guid:e.data&&e.data.header&&e.data.header.trxCd?(r=e.data.header.trxCd,t=e.data.header.guid||"UNKNOWN"):e.config.data&&e.config.data.header?(r=e.config.data.header.trxCd||"UNKNOWN",t=e.config.data.header.guid||"UNKNOWN"):e.config.params&&e.config.params.header&&(r=e.config.params.header.trxCd||"UNKNOWN",t=e.config.params.header.guid||"UNKNOWN")}catch(i){console.warn("trxCd/guid 추출 실패:",i)}let a=0;return e.config.requestStartTime&&(a=n-e.config.requestStartTime),console.log(`✅ API 응답 성공 [거래코드: ${r} / GUID : ${t}] - (소요시간: ${a}ms)`),e},async e=>{if(e.config&&e.config.showLoading&&ee.getState().hideLoading(),console.error("❌ API 응답 에러:",e),$&&console.error("🚨 Error Details:",{message:e.message,status:e.response?.status,statusText:e.response?.statusText,data:e.response?.data,config:{url:e.config?.url,method:e.config?.method,baseURL:e.config?.baseURL}}),e.response?.status===401){const r=localStorage.getItem("refreshToken");if(r)try{const t=await le.post("/auth/refresh",{refreshToken:r});if(t.data.accessToken){localStorage.setItem("accessToken",t.data.accessToken);const n=e.config;if(n)return n.headers.Authorization=`Bearer ${t.data.accessToken}`,F(n)}}catch{localStorage.removeItem("accessToken"),localStorage.removeItem("refreshToken"),window.location.href="/login"}}return Promise.reject(e)});const se=()=>Se(),L=async(e,r,t)=>{try{const n={...te,...t},{activeMenuId:a}=pe.getState();if(U===null){const p=Date.now();await oe();const l=Date.now();console.log(`[INFO] IP 조회 소요시간: ${l-p}ms`)}const i={method:n.method,url:"/api/service",timeout:n.timeout,withCredentials:n.withCredentials,showLoading:n.showLoading};n.headers&&(i.headers=n.headers);const f=U||"unknown",w=__APP_CD__,g=__SYS_CD__,S={header:{trxCd:e,guid:se(),userInfo:z(),clientIp:f,domainId:"DEFAULT",appCd:w,sysCd:g,screenId:a},data:r};$&&console.log("__BWG_LOCAL__ 테스트 입니다. ",$),n.method==="GET"?i.params=S||n.params:(i.data=S||n.data,n.params&&(i.params=n.params));let y;for(let p=0;p<=(n.retryCount||0);p++)try{const l=await F(i);if(l.data.header?.resCd==0){for(const u in l.data)if(u!=="header")return l.data[u];return{}}else{const u=l.data.header,h=u?.msgs?.basicMsg||"요청 처리 중 오류가 발생했습니다.",o=u?.msgs?.detailMsgs||h,d=u?.msgCd,_=u?.msgs?.type;throw new I(h,o,l,d,_)}}catch(l){if(l.isAxiosError&&l.response){const u=l,h=u.response,o=h.data,d=o?.header?.msgs?.basicMsg||u.message||"서버에서 오류가 발생했습니다.",_=o?.header?.msgs?.detailMsgs||(typeof h.data=="string"?h.data:JSON.stringify(h.data))||d,s=o?.header?.msgCd,c=o?.header?.msgs?.type;y=new I(d,_,h,s,c)}else y=l;if(l.isAxiosError&&Qt(l)&&p<(n.retryCount||0)){await er(n.retryDelay||1e3);continue}break}if(y){if(n.showError){const p=y instanceof I?y.message:"요청 처리 중 오류가 발생했습니다.",l=y instanceof I?y.msgCd:"요청 처리 중 오류가 발생했습니다.",u=y instanceof I?y.detailMsg:y.message,h=y instanceof I?y.errorType:"";l?.startsWith("BXM")?Me({message:p,description:u,duration:5}):h=="I"?Ce(p,u,5):be(p,u,5)}throw y}throw new Error("알 수 없는 API 오류가 발생했습니다.")}catch(n){throw console.error("callService 최종 에러:",n),n}},Zt=async(e,r,t,n)=>{try{const a={...te,...n},{activeMenuId:i}=pe.getState();if(U===null){const l=Date.now();await oe();const u=Date.now();console.log(`[INFO] IP 조회 소요시간: ${u-l}ms`)}const f={method:a.method,url:"/api/"+e+"/service",timeout:a.timeout,withCredentials:a.withCredentials,showLoading:a.showLoading};a.headers&&(f.headers=a.headers);const w=U||"unknown",g=__APP_CD__,S=__SYS_CD__,y={header:{trxCd:r,guid:se(),userInfo:z(),clientIp:w,domainId:"DEFAULT",appCd:g,sysCd:S,screenId:i},data:t};$&&console.log("__BWG_LOCAL__ 테스트 입니다. ",$),a.method==="GET"?f.params=y||a.params:(f.data=y||a.data,a.params&&(f.params=a.params));let p;for(let l=0;l<=(a.retryCount||0);l++)try{const u=await F(f);if(u.data.header?.resCd==0){for(const h in u.data)if(h!=="header")return u.data[h];return{}}else{const h=u.data.header,o=h?.msgs?.basicMsg||"요청 처리 중 오류가 발생했습니다.",d=h?.msgs?.detailMsgs||o,_=h?.msgCd,s=h?.msgs?.type;throw new I(o,d,u,_,s)}}catch(u){if(u.isAxiosError&&u.response){const h=u,o=h.response,d=o.data,_=d?.header?.msgs?.basicMsg||h.message||"서버에서 오류가 발생했습니다.",s=d?.header?.msgs?.detailMsgs||(typeof o.data=="string"?o.data:JSON.stringify(o.data))||_,c=d?.header?.msgCd,m=d?.header?.msgs?.type;p=new I(_,s,o,c,m)}else p=u;if(u.isAxiosError&&Qt(u)&&l<(a.retryCount||0)){await er(a.retryDelay||1e3);continue}break}if(p){if(a.showError){const l=p instanceof I?p.message:"요청 처리 중 오류가 발생했습니다.",u=p instanceof I?p.msgCd:"요청 처리 중 오류가 발생했습니다.",h=p instanceof I?p.detailMsg:p.message,o=p instanceof I?p.errorType:"";u?.startsWith("BXM")?showBwgError({message:l,description:h,duration:5}):o=="I"?showInfo(l,h,5):showWarning(l,h,5)}throw p}throw new Error("알 수 없는 API 오류가 발생했습니다.")}catch(a){throw console.error("callService 최종 에러:",a),a}},Qt=e=>!e.response||e.response.status>=500&&e.response.status<600,er=e=>new Promise(r=>setTimeout(r,e)),tr=(e,r,t)=>L(e,r,{...t,method:"GET"}),rr=(e,r,t)=>L(e,r,{...t,method:"POST"}),nr=(e,r,t)=>L(e,r,{...t,method:"PUT"}),or=(e,r,t)=>L(e,r,{...t,method:"DELETE"}),sr=(e,r,t)=>L(e,r,{...t,method:"PATCH"}),ar=async(e,r,t)=>{try{const n=await fetch("/api/permissions",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({userId:e,menuId:r,popupId:t})});if(!n.ok)throw new Error(`권한 확인 실패: ${n.status}`);return await n.json()}catch(n){throw console.error("권한 확인 서비스 오류:",n),n}},Zr=Object.freeze(Object.defineProperty({__proto__:null,ApiError:I,apiDelete:or,apiGet:tr,apiPatch:sr,apiPost:rr,apiPut:nr,callService:L,callService_SYSCD:Zt,getClientIp:Jt,getGuid:se,getPermissionService:ar,setClientIp:oe,verifyClientIp:Xt},Symbol.toStringTag,{value:"Module"}));exports.ApiError=I;exports.THEME_COOKIE_NAME=Xe;exports.apiDelete=or;exports.apiGet=tr;exports.apiPatch=sr;exports.apiPost=rr;exports.apiPut=nr;exports.apiUtilsModule=Zr;exports.arrAverage=vt;exports.arrCount=St;exports.arrMax=mt;exports.arrMin=pt;exports.arrReverse=wt;exports.arrSum=yt;exports.arrUnique=gt;exports.callService=L;exports.callService_SYSCD=Zt;exports.clamp=Ct;exports.clearSessionStorage=Dt;exports.closeNotification=Vt;exports.commonUtilsModule=Vr;exports.commonjsGlobal=W;exports.configureEnvUtils=zt;exports.copyToClipboard=ut;exports.debounce=ct;exports.deleteCookie=Nt;exports.destroyNotifications=Kt;exports.duplicates=_t;exports.encryptSha256=kt;exports.envUtilsModule=Jr;exports.generateRandomColor=ht;exports.generateRandomString=ye;exports.generateUID=Se;exports.getAllServiceCodes=de;exports.getClientIp=Jt;exports.getCookie=Ot;exports.getCrprCd=Re;exports.getCurrentDate=Rt;exports.getCurrentDateString=Yt;exports.getDefaultExportFromCjs=k;exports.getDepartmentInfo=Ke;exports.getDeviceType=j;exports.getDisplayName=Ge;exports.getDprtCd=ge;exports.getDprtNm=me;exports.getEmplNo=Fe;exports.getEnvCode=qt;exports.getGuid=se;exports.getPermissionService=ar;exports.getRoleList=H;exports.getServiceCode=ne;exports.getSessionStorage=It;exports.getUserDvsn=Ye;exports.getUserId=fe;exports.getUserInfo=z;exports.getUserNm=he;exports.hasAllRoles=je;exports.hasAnyRole=ze;exports.hasRole=He;exports.hasUserInfo=We;exports.isArray=nt;exports.isBoolean=et;exports.isDesktop=ft;exports.isDev=we;exports.isEmpty=ve;exports.isEmptyArray=q;exports.isFunction=tt;exports.isLocal=$;exports.isLoggedIn=qe;exports.isMobile=lt;exports.isNull=ot;exports.isNullOrUndefined=at;exports.isNumber=Qe;exports.isObject=rt;exports.isProd=_e;exports.isSafeEmpty=Ut;exports.isString=Ze;exports.isTablet=dt;exports.isUndefined=st;exports.isValidEmail=$t;exports.isValidUrl=Lt;exports.logServiceCodeConfig=Be;exports.notiBwgError=Me;exports.notiError=Gt;exports.notiInfo=Ce;exports.notiSuccess=Wt;exports.notiWarning=be;exports.notificationService=P;exports.notificationUtilsModule=Xr;exports.padLeft=At;exports.padRight=Bt;exports.persist=ke;exports.random=Mt;exports.removeSessionStorage=xt;exports.round=bt;exports.serviceConfigModule=hr;exports.setClientIp=oe;exports.setCookie=Et;exports.setServiceCodeOverrides=Ae;exports.setSessionStorage=Tt;exports.throttle=it;exports.toCamelCase=Pt;exports.useLoadingStore=ee;exports.useMenuModelStore=Ve;exports.useMenuViewStore=pe;exports.useUserStore=E;exports.userUtilsModule=pr;exports.verifyClientIp=Xt;
|
|
3
|
+
//# sourceMappingURL=apiUtils-CudW_FKE.cjs.map
|