|
@@ -250,10 +261,10 @@ export default function Module({ setTabNum }) {
diff --git a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx
index 22554a11..edd631d0 100644
--- a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx
+++ b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx
@@ -9,7 +9,15 @@ import { isObjectNotEmpty } from '@/util/common-utils'
import QSelectBox from '@/components/common/select/QSelectBox'
import { addedRoofsState } from '@/store/settingAtom'
-export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
+export default function ModuleTabContents({
+ tabIndex,
+ addRoof,
+ setAddedRoofs,
+ roofTab,
+ tempModuleSelectionData,
+ setTempModuleSelectionData,
+ moduleSelectionInitParams,
+}) {
const { getMessage } = useMessage()
const [roofMaterial, setRoofMaterial] = useState(addRoof) //지붕재`
@@ -37,7 +45,7 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
const [constructionParams, setConstructionParams] = useState({}) //공법 관련 api호출 파라메터
const [roofBaseParams, setRoofBaseParams] = useState({}) //지붕밑바탕 관련 api호출 파라메터
- const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
+ // const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
const { getTrestleList, getConstructionList } = useMasterController()
@@ -61,15 +69,73 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
const hajebichiRef = useRef()
const lengthRef = useRef()
+ const originalModuleSelectionData = useRef(moduleSelectionData)
+
+ //서까래간격 변경
+ const handleChangeRaftBase = (option) => {
+ setSelectedRaftBase(option)
+ setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode }) //가대메이커
+ setConstMthdList([]) //공법 초기화
+ setRoofBaseList([]) //지붕밑바탕 초기화
+ setConstructionList([]) //공법 초기화
+ }
+
+ //지붕밑바탕변경
+
+ //처마력바 체크
+ const handleCvrChecked = () => {
+ setCvrChecked(!cvrChecked)
+ setSelectedConstruction({ ...selectedConstruction, setupCover: !cvrChecked })
+ }
+
+ //눈막이금구 체크
+ const handleSnowGdChecked = () => {
+ setSnowGdChecked(!snowGdChecked)
+ setSelectedConstruction({ ...selectedConstruction, setupSnowCover: !snowGdChecked })
+ }
+
+ const getConstructionListData = async (params) => {
+ if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
+ const optionsList = await getConstructionList(params)
+ setConstructionList(optionsList.data)
+ }
+ }
+
useEffect(() => {
setHajebichi(addRoof.hajebichi)
setLengthBase(addRoof.lenBase)
+
+ // 202600 경사도
+ const raftCodeList = findCommonCode('203800')
+ //서까래 코드
+ raftCodeList.forEach((obj) => {
+ obj.name = obj.clCodeNm
+ obj.id = obj.clCode
+ })
+ setRaftCodes(raftCodeList)
}, [])
+ //리코일에 데이터가 담기는 시점에 시작
+ useEffect(() => {
+ if (
+ moduleSelectionData.roofConstructions.length > 0 &&
+ isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex].trestle) &&
+ isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex].construction)
+ ) {
+ setModuleConstructionSelectionData(moduleSelectionData.roofConstructions[tabIndex])
+ }
+ }, [moduleSelectionData])
+
+ useEffect(() => {
+ if (isObjectNotEmpty(moduleConstructionSelectionData)) {
+ setIsExistData(true)
+ }
+ }, [moduleConstructionSelectionData])
+
//높이를 변경하면 addRoofs에 적용
useEffect(() => {
- //가대 조회 api 파라메터
- setTrestleParams({ ...trestleParams, workingWidth: lengthBase })
+ // //가대 조회 api 파라메터
+ // setTrestleParams({ ...trestleParams, workingWidth: lengthBase })
const copyAddRoof = { ...addRoof }
copyAddRoof.length = Number(lengthBase)
@@ -90,29 +156,69 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
}, [hajebichi])
useEffect(() => {
- if (moduleSelectionData.roofConstructions.length > 0) {
- setModuleConstructionSelectionData(moduleSelectionData.roofConstructions[roofTab])
+ if (isExistData) {
+ setConstructionListParams({
+ ...moduleSelectionInitParams,
+ ...roofBaseParams,
+ roofBaseCd: selectedRoofBase.roofBaseCd,
+ inclCd: addRoof.pitch,
+ roofPitch: hajebichiRef.current ? hajebichiRef.current.value : 0,
+ raftBaseCd: addRoof.raftBaseCd,
+ })
}
- }, [moduleSelectionData])
+ }, [selectedRoofBase])
- //서까래간격 변경
- const handleChangeRaftBase = (option) => {
- setSelectedRaftBase(option)
- setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode }) //가대메이커
- setConstMthdList([]) //공법 초기화
- setRoofBaseList([]) //지붕밑바탕 초기화
- setConstructionList([]) //공법 초기화
- }
+ useEffect(() => {
+ if (
+ isExistData &&
+ constructionList.length > 0 &&
+ isObjectNotEmpty(moduleConstructionSelectionData?.construction) &&
+ moduleConstructionSelectionData?.construction.hasOwnProperty('constPossYn') ///키가 있으면
+ ) {
+ const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
+ const construction = constructionList[selectedIndex]
+ if (construction.constPossYn === 'Y') {
+ handleConstruction(selectedIndex)
+ }
+ }
+ }, [constructionList])
- //가대메이커 변경
+ //모듈 변경
+ useEffect(() => {
+ //lengbase는 무조건 있다고 가정 하고 최초에 실행 방지
+ if (selectedModules) {
+ //가대메이커 파라메터 만들기
+ setTrestleParams({
+ moduleTpCd: selectedModules.itemTp,
+ roofMatlCd: addRoof.roofMatlCd,
+ raftBaseCd: addRoof.raftBaseCd,
+ workingWidth: lengthBase,
+ })
+ }
+ }, [selectedModules])
+
+ //가대메이커 api 호출
+ useEffect(() => {
+ if (isObjectNotEmpty(trestleParams)) {
+ getModuleOptionsListData(trestleParams, 'trestle')
+ }
+ }, [trestleParams])
+
+ //가대메이커 변경 함수
const handleChangeTrestle = (option) => {
setSelectedTrestle(option) //선택값 저장
setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' })
- setConstMthdList([]) //공법 초기화
- setRoofBaseList([]) //지붕밑바탕 초기화
- setConstructionList([]) //공법 초기화
+ // setConstMthdList([]) //공법 초기화
+ // setRoofBaseList([]) //지붕밑바탕 초기화
+ // setConstructionList([]) //공법 초기화
}
+ useEffect(() => {
+ if (isObjectNotEmpty(constructionParams)) {
+ getModuleOptionsListData(constructionParams, 'construction')
+ }
+ }, [constructionParams])
+
//공법 변경
const handleChangeConstMthd = (option) => {
setSelectedConstMthd(option) //선택된값 저장
@@ -121,24 +227,37 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
trestleMkrCd: selectedTrestle.trestleMkrCd,
constMthdCd: option.constMthdCd,
roofBaseCd: '',
- roofPitch: hajebichiRef.current ? hajebichiRef.current.value : '',
})
- setRoofBaseList([]) //지붕밑바탕 초기화
- setConstructionList([]) //공법 초기화
}
- //지붕밑바탕변경
+ useEffect(() => {
+ if (isObjectNotEmpty(roofBaseParams)) {
+ getModuleOptionsListData(roofBaseParams, 'roofBase')
+ }
+ }, [roofBaseParams])
+
const handleChangeRoofBase = (option) => {
- // if (option) {
setConstructionListParams({
...moduleSelectionInitParams,
- ...roofBaseParams,
+ trestleMkrCd: selectedTrestle.trestleMkrCd,
+ constMthdCd: selectedConstMthd.constMthdCd,
roofBaseCd: option.roofBaseCd,
inclCd: addRoof.pitch,
+ roofPitch: hajebichiRef.current ? hajebichiRef.current.value : 0,
+ raftBaseCd: addRoof.raftBaseCd,
+ roofMatlCd: addRoof.roofMatlCd,
})
setSelectedRoofBase(option)
}
+ //공법 리스트 변경 함수
+ useEffect(() => {
+ if (isObjectNotEmpty(constructionListParams)) {
+ getConstructionListData(constructionListParams)
+ }
+ }, [constructionListParams])
+
+ //공법 선택 함수
const handleConstruction = (index) => {
if (index > -1) {
const isPossibleIndex = constructionRef.current
@@ -160,6 +279,9 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
selectedConstruction.setupSnowCover = false //눈막이금구 설치 여부
selectedConstruction.selectedIndex = index
+ setCvrYn(selectedConstruction.cvrYn)
+ setSnowGdPossYn(selectedConstruction.snowGdPossYn)
+
//기존에 선택된 데이터가 있으면 체크한다
if (moduleConstructionSelectionData && moduleConstructionSelectionData.construction) {
selectedConstruction.setupCover = moduleConstructionSelectionData.construction.setupCover
@@ -168,8 +290,6 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
setSnowGdChecked(selectedConstruction.setupSnowCover)
}
- setCvrYn(selectedConstruction.cvrYn)
- setSnowGdPossYn(selectedConstruction.snowGdPossYn)
setSelectedConstruction(selectedConstruction)
} else {
constructionRef.current.forEach((ref) => {
@@ -178,178 +298,128 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
}
}
- const handleCvrChecked = () => {
- setCvrChecked(!cvrChecked)
- setSelectedConstruction({ ...selectedConstruction, setupCover: !cvrChecked })
- }
-
- const handleSnowGdChecked = () => {
- setSnowGdChecked(!snowGdChecked)
- setSelectedConstruction({ ...selectedConstruction, setupSnowCover: !snowGdChecked })
- }
-
- const getModuleOptionsListData = async (params) => {
- const optionsList = await getTrestleList(params)
-
- if (optionsList.data.length > 0) {
- if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd === null) {
- setTrestleList(optionsList.data)
- if (isExistData) {
- setSelectedTrestle({ ...moduleConstructionSelectionData?.trestle })
- } else {
- setConstMthdList([])
- setRoofBaseList([])
- }
- }
-
- if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd === null) {
- setConstMthdList(optionsList.data)
- if (isExistData) {
- setSelectedConstMthd({ ...moduleConstructionSelectionData?.trestle })
- } else {
- setRoofBaseList([])
- }
- }
-
- if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd) {
- setRoofBaseList(optionsList.data)
- if (isExistData) {
- setSelectedRoofBase({ ...moduleConstructionSelectionData?.trestle })
- }
- }
- }
- }
-
- const getConstructionListData = async (params) => {
- if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
- const optionsList = await getConstructionList(params)
- setConstructionList(optionsList.data)
- }
- }
-
+ //공법 선택시 이후 프로세스
useEffect(() => {
if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
- const newRoofConstructions = {
- roofIndex: roofTab,
- addRoof: addRoof,
- trestle: selectedRoofBase,
- construction: selectedConstruction,
- }
+ if (tabIndex === roofTab) {
+ const common = { ...moduleSelectionInitParams }
+ const module = { ...selectedModules }
+ const newRoofConstructions = {
+ roofIndex: tabIndex,
+ addRoof: addRoof,
+ trestle: selectedRoofBase,
+ construction: selectedConstruction,
+ }
- const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === roofTab)
+ console.log('newRoofConstructions', newRoofConstructions)
+ console.log('roofTab', roofTab)
- if (index > -1) {
- const newArray = [
- ...tempModuleSelectionData.roofConstructions.slice(0, index),
- newRoofConstructions,
- ...tempModuleSelectionData.roofConstructions.slice(index + 1),
- ]
- setTempModuleSelectionData({ roofConstructions: newArray })
- } else {
- setTempModuleSelectionData({ roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }] })
+ const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === tabIndex)
+
+ if (index > -1) {
+ const newArray = [
+ ...tempModuleSelectionData.roofConstructions.slice(0, index),
+ newRoofConstructions,
+ ...tempModuleSelectionData.roofConstructions.slice(index + 1),
+ ]
+ setTempModuleSelectionData({ common: common, module: module, roofConstructions: newArray })
+ } else {
+ setTempModuleSelectionData({
+ common: common,
+ module: module,
+ roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }],
+ })
+ }
}
}
}, [selectedConstruction])
- useEffect(() => {
- if (isExistData) {
- setConstructionListParams({
- ...moduleSelectionInitParams,
- ...roofBaseParams,
- roofBaseCd: selectedRoofBase.roofBaseCd,
- inclCd: addRoof.pitch,
- })
- }
- }, [selectedRoofBase])
+ const getModuleOptionsListData = async (params, type) => {
+ const optionsList = await getTrestleList(params)
- useEffect(() => {
- console.log('moduleConstructionSelectionData', moduleConstructionSelectionData)
-
- if (
- isExistData &&
- constructionList.length > 0 &&
- isObjectNotEmpty(moduleConstructionSelectionData?.construction) &&
- moduleConstructionSelectionData?.construction.hasOwnProperty('constPossYn') ///키가 있으면
- ) {
- const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
- const construction = constructionList[selectedIndex]
- if (construction.constPossYn === 'Y') {
- handleConstruction(selectedIndex)
- }
- }
- }, [constructionList])
-
- useEffect(() => {
- if (isObjectNotEmpty(moduleSelectionData) && isObjectNotEmpty(moduleSelectionData.module)) {
- setSelectedModules(moduleSelectionData.module)
- }
- }, [moduleSelectionData])
-
- useEffect(() => {
- // 202600 경사도
- const raftCodeList = findCommonCode('203800')
- //서까래 코드
- raftCodeList.forEach((obj) => {
- obj.name = obj.clCodeNm
- obj.id = obj.clCode
- })
- setRaftCodes(raftCodeList)
- }, [])
-
- useEffect(() => {
- //물건 상세의 데이터를 가지고 초기화 데이터를 만든다
- if (
- moduleSelectionInitParams.illuminationTp &&
- moduleSelectionInitParams.instHt &&
- moduleSelectionInitParams.stdSnowLd &&
- moduleSelectionInitParams.stdWindSpeed
- ) {
- const isModuleLoaded = moduleSelectionInitParams.hasOwnProperty('moduleTpCd') //모듈컬럼이 있으면 모듈을 변경했다는 내용
- if (isModuleLoaded) {
- setTrestleParams({
- moduleTpCd: moduleSelectionInitParams.moduleTpCd,
- roofMatlCd: addRoof.roofMatlCd,
- raftBaseCd: addRoof.raftBaseCd,
- workingWidth: lengthBase,
- })
- setConstructionList([])
-
- if (isObjectNotEmpty(moduleConstructionSelectionData)) {
- //기존에 데이터가 있으면 파라메터를 넣는다
- setConstructionParams({ ...moduleConstructionSelectionData.trestle, constMthdCd: '', roofBaseCd: '' })
- setRoofBaseParams({ ...moduleConstructionSelectionData.trestle, roofBaseCd: '' })
-
- setIsExistData(true)
+ if (optionsList.data.length > 0) {
+ if (type === 'trestle') {
+ setTrestleList(optionsList.data)
+ if (isExistData) {
+ // setSelectedTrestle({ ...moduleConstructionSelectionData?.trestle })
+ handleChangeTrestle(moduleConstructionSelectionData?.trestle)
+ } else {
+ setConstMthdList([])
+ setRoofBaseList([])
+ }
+ } else if (type === 'construction') {
+ setConstMthdList(optionsList.data)
+ if (isExistData) {
+ handleChangeConstMthd(moduleConstructionSelectionData?.trestle)
+ } else {
+ setRoofBaseList([])
+ }
+ } else if (type === 'roofBase') {
+ setRoofBaseList(optionsList.data)
+ if (isExistData) {
+ handleChangeRoofBase(moduleConstructionSelectionData?.trestle)
}
}
}
+ }
- setTempModuleSelectionData({ common: moduleSelectionInitParams, module: selectedModules })
+ useEffect(() => {
+ console.log('originalModuleSelectionData', originalModuleSelectionData)
+ console.log('moduleSelectionInitParams', moduleSelectionInitParams)
+
+ // console.log('moduleSelectionInitParams', moduleSelectionInitParams)
+ // setSelectedTrestle({})
+ // setSelectedConstMthd({})
+ // setSelectedRoofBase({})
+ // setModuleSelectionData({
+ // ...moduleSelectionData,
+ // roofConstructions: [],
+ // })
}, [moduleSelectionInitParams])
- useEffect(() => {
- if (isObjectNotEmpty(trestleParams)) {
- getModuleOptionsListData(trestleParams)
- }
- }, [trestleParams])
+ // useEffect(() => {
+ // useEffect(() => {
+ // console.log('moduleSelectionInitParams', moduleSelectionInitParams)
- useEffect(() => {
- if (isObjectNotEmpty(constructionParams)) {
- getModuleOptionsListData(constructionParams)
- }
- }, [constructionParams])
+ // //물건 상세의 데이터를 가지고 초기화 데이터를 만든다
+ // if (
+ // moduleSelectionInitParams.illuminationTp &&
+ // moduleSelectionInitParams.instHt &&
+ // moduleSelectionInitParams.stdSnowLd &&
+ // moduleSelectionInitParams.stdWindSpeed
+ // ) {
+ // const isModuleLoaded = moduleSelectionInitParams.hasOwnProperty('moduleTpCd') //모듈컬럼이 있으면 모듈을 변경했다는 내용
- useEffect(() => {
- if (isObjectNotEmpty(roofBaseParams)) {
- getModuleOptionsListData(roofBaseParams)
- }
- }, [roofBaseParams])
+ // //모듈 이름이 있고 모듈이 선택되어있다면
+ // if (isModuleLoaded && moduleSelectionInitParams.moduleTpCd) {
+ // setTrestleParams({
+ // moduleTpCd: moduleSelectionInitParams.moduleTpCd,
+ // roofMatlCd: addRoof.roofMatlCd,
+ // raftBaseCd: addRoof.raftBaseCd,
+ // workingWidth: lengthBase,
+ // })
+ // // setConstructionList([])
- useEffect(() => {
- if (isObjectNotEmpty(constructionListParams)) {
- getConstructionListData(constructionListParams)
- }
- }, [constructionListParams])
+ // if (isObjectNotEmpty(moduleConstructionSelectionData)) {
+ // //기존에 데이터가 있으면 파라메터를 넣는다
+ // setConstructionParams({ ...moduleConstructionSelectionData.trestle, constMthdCd: '', roofBaseCd: '' })
+ // setRoofBaseParams({ ...moduleConstructionSelectionData.trestle, roofBaseCd: '' })
+
+ // setIsExistData(true)
+ // }
+ // }
+ // }
+
+ // setTempModuleSelectionData({ common: moduleSelectionInitParams, module: selectedModules })
+ // }, [])
+
+ // useEffect(() => {
+ // console.log('roofBaseParams', roofBaseParams)
+
+ // if (isObjectNotEmpty(roofBaseParams)) {
+ // getModuleOptionsListData(roofBaseParams)
+ // }
+ // }, [roofBaseParams])
// useEffect(() => {
// if (isObjectNotEmpty(tempModuleSelectionData)) {
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js
index bc0569d3..53966ee7 100644
--- a/src/hooks/module/useModuleBasicSetting.js
+++ b/src/hooks/module/useModuleBasicSetting.js
@@ -615,7 +615,7 @@ export function useModuleBasicSetting() {
for (let i = 0; i <= totalWidth; i++) {
leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0
- if (isChidori) {
+ if (isChidori && !isMaxSetup) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
}
@@ -716,7 +716,7 @@ export function useModuleBasicSetting() {
for (let j = 0; j < totalHeight; j++) {
leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0
- if (isChidori) {
+ if (isChidori && !isMaxSetup) {
chidoriLength = i % 2 === 0 ? 0 : height / 2
}
@@ -827,7 +827,7 @@ export function useModuleBasicSetting() {
for (let i = 0; i < diffRightEndPoint; i++) {
leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0
- if (isChidori) {
+ if (isChidori && !isMaxSetup) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
}
@@ -927,7 +927,7 @@ export function useModuleBasicSetting() {
leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0
- if (isChidori) {
+ if (isChidori && !isMaxSetup) {
chidoriLength = i % 2 === 0 ? 0 : height / 2 - intvHor
}
diff --git a/src/hooks/module/useModuleSelection.js b/src/hooks/module/useModuleSelection.js
index 2cf6e509..22d1f88f 100644
--- a/src/hooks/module/useModuleSelection.js
+++ b/src/hooks/module/useModuleSelection.js
@@ -3,8 +3,8 @@ import { useContext, useEffect, useState } from 'react'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { useMasterController } from '@/hooks/common/useMasterController'
import { useCommonCode } from '@/hooks/common/useCommonCode'
-
import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { isObjectNotEmpty } from '@/util/common-utils'
export function useModuleSelection(props) {
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
@@ -30,6 +30,8 @@ export function useModuleSelection(props) {
setSelectedSurfaceType(managementState?.surfaceType)
}
+ const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
+
//탭별 파라메터 초기화
useEffect(() => {
bindInitData()
@@ -94,6 +96,13 @@ export function useModuleSelection(props) {
}
}
+ //데이터가 있으면 모듈 자동 선택
+ useEffect(() => {
+ if (moduleList.length > 0 && isObjectNotEmpty(moduleSelectionData.module)) {
+ handleChangeModule(moduleSelectionData.module)
+ }
+ }, [moduleList])
+
const handleChangeModule = (option) => {
//선택된 모듈
setSelectedModules(option) //선택값 저장
|