Compare commits

...

115 Commits

Author SHA1 Message Date
a08c609caa Merge branch 'dev' into feature/yj-layoutSetup 2025-04-18 09:24:53 +09:00
김민식
21dcdfb3ef 다국어 수정 2025-04-17 14:22:58 +09:00
김민식
29ccf72c5e 수동으로 방위설정 안되던 버그 수정 2025-04-17 14:13:05 +09:00
김민식
4c219ddce9 validation 방식 수정 2025-04-17 14:12:50 +09:00
김민식
ed721f36d0 Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into qcast-pub 2025-04-17 14:12:16 +09:00
김민식
30414568e0 다국어 추가 2025-04-17 14:11:55 +09:00
06812b77af Merge branch 'dev' into feature/yj-layoutSetup 2025-04-16 17:17:50 +09:00
김민식
2897dc26e3 Orientation에서 nextstep시 compas 매개변수 추가 2025-04-11 16:41:28 +09:00
김민식
08a29aec26 cvrCheck, snowCheck 수정 2025-04-10 14:23:43 +09:00
김민식
a742fc1f9c Merge remote-tracking branch 'origin/qcast-pub' into feature/yj-layoutSetup
# Conflicts:
#	src/hooks/module/useModuleTrestle.js
2025-04-10 13:55:13 +09:00
김민식
cf900c3e92 lenBase -> length 로 수정 2025-04-10 13:54:05 +09:00
김민식
e2b8bc19b1 lenBase 버그 수정 2025-04-10 13:33:42 +09:00
김민식
14aa4227f4 Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into qcast-pub 2025-04-10 13:24:41 +09:00
김민식
af63891df2 지붕재 수정시 모듈.가대 정보 초기화 2025-04-10 13:24:29 +09:00
070e9d933f api 오류 시 처리 추가 2025-04-10 11:36:44 +09:00
e67fc749f4 마우스 휠 줌 이벤트 보정 2025-04-10 10:55:00 +09:00
김민식
adf9febc8c Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into feature/yj-layoutSetup 2025-04-10 10:54:29 +09:00
김민식
089ffed7af 키 명 수정 2025-04-10 10:54:21 +09:00
김민식
990de88caf 키 값 수정 2025-04-10 10:51:59 +09:00
d53d7f4220 Merge branch 'dev' into feature/yj-layoutSetup 2025-04-10 10:48:13 +09:00
김민식
134becaa93 중복코드 제거 2025-04-10 10:47:00 +09:00
김민식
74b3c6dac7 처마력 커버 설치여부 , 적설방지금구설치 여부 값 추가 2025-04-10 10:46:01 +09:00
76693640cf Merge branch 'dev' into feature/yj-layoutSetup 2025-04-09 17:39:13 +09:00
defebb21d7 chore: 내부 개발서버용 실행 스크립트 추가 2025-04-09 17:20:05 +09:00
c869e9d5a3 육지붕 수정 2025-04-09 16:56:43 +09:00
김민식
e71c655d05 Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into feature/yj-layoutSetup 2025-04-09 14:36:18 +09:00
김민식
29e8ca25a5 BasicSetting 하단 버튼 리펙터링 2025-04-09 14:35:59 +09:00
0673567900 Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into feature/yj-layoutSetup 2025-04-09 14:13:58 +09:00
c42e244f24 좌표가 음수일때 보정 로직 추가 2025-04-09 14:13:55 +09:00
김민식
e940884312 육지붕일때 moduleSelectionData 에 margin 추가 2025-04-09 13:34:34 +09:00
115544edb4 번역추가 2025-04-09 11:04:10 +09:00
김민식
9e9bd8f9c4 withDraggable spinner 추가 2025-04-09 10:39:57 +09:00
2da7ea0c78 Merge branch 'dev' into feature/yj-layoutSetup 2025-04-08 17:43:46 +09:00
00a201704b trestleDetail 작업 2025-04-08 17:43:19 +09:00
김민식
597aaa6d42 orientation module validation 추가 2025-04-08 16:14:57 +09:00
김민식
468980abbc roofConstruction 첫번째 trestleDetail null로 들어가는 버그 수정 2025-04-08 15:54:31 +09:00
김민식
91ccfcb20e DB에서 불러온 값 roof에 적용 2025-04-08 15:16:44 +09:00
김민식
c35f3c1adb moduleSelectionData trestleDetail 없는 버그 수정 2025-04-08 14:19:03 +09:00
김민식
468c7fda6f moduleSelectionData 수정 2025-04-08 13:03:23 +09:00
김민식
9976ff59d6 Merge remote-tracking branch 'origin/qcast-pub' into feature/yj-layoutSetup 2025-04-07 18:22:01 +09:00
김민식
f548506179 moduleSelectionData 수정 2025-04-07 18:21:31 +09:00
d6d626f2d7 양단 케이블 파라미터 추가 2025-04-07 14:35:23 +09:00
c0cbcd18a2 Merge branch 'dev' into feature/yj-layoutSetup 2025-04-04 16:58:07 +09:00
김민식
f3a0504d0b Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into qcast-pub 2025-04-04 13:21:11 +09:00
b8f05a6ff0 fix: promise.all 형태로 변경 2025-04-04 13:15:21 +09:00
0a493884c6 Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into feature/yj-layoutSetup 2025-04-04 12:48:58 +09:00
김민식
a316664b20 addRoof, index 데이터 추가 2025-04-04 12:47:50 +09:00
804911af3e 모듈 혼합 수 동적 대응 2025-04-04 12:38:49 +09:00
김민식
59f9377cc9 trestleDetail 호출시 trestle 데이터 추가 2025-04-04 12:28:42 +09:00
김민식
15cb2cf270 roofIndex 추가 2025-04-04 11:32:32 +09:00
김민식
1cad8eaf76 Merge remote-tracking branch 'origin/qcast-pub' into feature/yj-layoutSetup 2025-04-04 10:58:38 +09:00
김민식
9400ee7707 trestle 데이터 버그 수정 2025-04-04 10:58:02 +09:00
22f8cd3fa7 모듈 선택 초기화 수정 2025-04-04 10:18:52 +09:00
e872df680d 모듈 설치면 초기화 기능 2025-04-03 17:09:17 +09:00
김민식
02a0e4a67f Merge remote-tracking branch 'origin/qcast-pub' into feature/yj-layoutSetup 2025-04-03 16:32:13 +09:00
김민식
d524b33f56 모듈 관련 데이터 수정시 roofs 데이터 초기화 버그 수정 2025-04-03 16:31:12 +09:00
e7b50ca642 Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into feature/module-grouping
# Conflicts:
#	src/locales/ja.json
2025-04-03 16:30:36 +09:00
3f40725647 3중 멀티모듈 대응 2025-04-03 16:28:58 +09:00
aa2685e558 레이아웃설치 수정 2025-04-03 14:33:54 +09:00
f32e772141 모듈 표 추가 2025-04-03 13:36:46 +09:00
7d76929689 고도화 작업 레이아웃 모듈 설치 기능 2025-04-03 11:23:37 +09:00
김민식
6c6e5845ef 적설량, 풍속 등 수정했을때 설정한 roof 초기화 2025-04-03 10:22:48 +09:00
김민식
001143954e QSelectbox value 없을때 title 부분 수정 2025-04-03 10:22:14 +09:00
265593f6dd 모듈 그룹화 작업중 2025-04-02 17:36:25 +09:00
김민식
ce7c90eb6f Merge branch 'feature/yj-layoutSetup' of https://git.hanasys.jp/qcast3/qcast-front into feature/yj-layoutSetup
# Conflicts:
#	src/components/floor-plan/modal/basic/BasicSetting.jsx
#	src/components/floor-plan/modal/basic/step/Trestle.jsx
2025-04-02 17:04:29 +09:00
2e60e848c8 basicsetting 수정 2025-04-02 17:01:37 +09:00
김민식
51aaf342fa Merge remote-tracking branch 'origin/qcast-pub' into feature/yj-layoutSetup
# Conflicts:
#	src/components/floor-plan/modal/basic/BasicSetting.jsx
2025-04-02 16:57:48 +09:00
김민식
82632b962e Trestle 데이터 추가 2025-04-02 16:55:23 +09:00
8c33611440 Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts:
#	src/components/floor-plan/modal/basic/BasicSetting.jsx
2025-04-02 15:21:15 +09:00
김민식
d8e43b0d81 BasicSetting 버그 수정 2025-04-02 15:19:00 +09:00
cb87d6cd23 Merge branch 'dev' into feature/yj-layoutSetup 2025-04-02 14:51:54 +09:00
김민식
8ba79d6a06 Merge remote-tracking branch 'origin/qcast-pub' into dev 2025-04-02 14:50:45 +09:00
김민식
ba06fde9cc useModuleTrestle 추가 2025-04-02 14:50:20 +09:00
1588b8cda7 Merge branch 'dev' into feature/yj-layoutSetup 2025-04-02 14:48:26 +09:00
김민식
9c1df779e4 Merge remote-tracking branch 'origin/qcast-pub' into dev 2025-04-02 14:47:53 +09:00
김민식
2dbbd3a957 roofAtom 추가 2025-04-02 14:47:21 +09:00
김민식
d165267ec1 🚨chore: Sync Sass 2025-04-02 14:47:09 +09:00
da8e0856cb Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts:
#	src/components/floor-plan/modal/basic/BasicSetting.jsx
#	src/locales/ja.json
2025-04-02 14:46:08 +09:00
김민식
78ce43969a Merge remote-tracking branch 'origin/qcast-pub' into dev 2025-04-02 14:23:23 +09:00
김민식
fe10ecf476 PlacementShapeSetting merge 2025-04-02 14:22:15 +09:00
김민식
b16174ec0d Merge remote-tracking branch 'origin/qcast-pub' into dev
# Conflicts:
#	src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
#	src/locales/ja.json
2025-04-02 14:08:21 +09:00
김민식
964d9bdcc7 basicsetting 로직 수정 2025-04-02 13:56:03 +09:00
d6b9634a89 레이아웃 설치 validate 추가 2025-04-01 17:18:38 +09:00
87ef010ae6 레이아웃 문구 추가 2025-04-01 15:40:20 +09:00
7d37deb048 모듈 설치 페이지 변경 2025-04-01 15:31:12 +09:00
97ca91aa29 Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts:
#	src/hooks/module/useModuleBasicSetting.js
2025-04-01 13:26:08 +09:00
09e985e9b5 Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts:
#	src/locales/ja.json
#	src/locales/ko.json
2025-03-31 14:57:32 +09:00
826739fb0e 혼합 가능 여부 확인 validate 추가 2025-03-31 10:44:56 +09:00
482b6b5477 수동 설치 혼합일 경우 설치 여부 확인 2025-03-31 10:20:45 +09:00
2bb1b71a0b 레이아웃 설치 작업 2025-03-28 09:40:19 +09:00
b88299b78d Merge branch 'dev' into feature/yj-layoutSetup 2025-03-27 14:11:40 +09:00
63d8ae092c 레이아웃 모듈 설치 validate 추가 2025-03-27 14:11:23 +09:00
7fcaaece53 Merge branch 'dev' into feature/yj-layoutSetup 2025-03-25 16:08:16 +09:00
yjnoh
5597f8ad70 지붕라인 색칠하기 2025-03-25 15:48:18 +09:00
yjnoh
a7e9aba26c Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts:
#	src/locales/ja.json
#	src/locales/ko.json
2025-03-25 15:09:40 +09:00
yjnoh
c631c6344e 레이아웃 설치 작업중 2025-03-24 17:07:19 +09:00
yjnoh
0ec917b09f 레이어 팝업 수정 2025-03-24 14:07:14 +09:00
yjnoh
dc8f033e9f validation 수정 2025-03-24 10:49:56 +09:00
yjnoh
943fd16e4b 클릭시 배치면 데이터 validation 추가 2025-03-24 10:23:35 +09:00
yjnoh
70c706341e Merge branch 'dev' into feature/yj-layoutSetup 2025-03-24 09:35:53 +09:00
yjnoh
c704207d2f 레이아웃설치 validation 2025-03-24 09:35:21 +09:00
yjnoh
9285caf422 Merge branch 'dev' into feature/yj-layoutSetup
# Conflicts:
#	src/locales/ja.json
2025-03-21 15:55:58 +09:00
yjnoh
ad14bf091f Merge branch 'dev' into dev-yj-layoutSetup 2025-03-19 17:49:28 +09:00
yjnoh
c34a7fc54d 수동시 치조 여부에 따라 모듈 가운데 흡착 2025-03-19 17:49:17 +09:00
yjnoh
9bb72bfa3a 그림자 제외 처리 2025-03-19 13:38:35 +09:00
yjnoh
8ea6f43ddb Merge branch 'dev' into dev-yj-layoutSetup
# Conflicts:
#	src/hooks/module/useModuleBasicSetting.js
#	src/locales/ja.json
#	src/locales/ko.json
2025-03-19 13:38:16 +09:00
yjnoh
8a5bd9f505 단수배치 작업 2025-03-18 15:44:41 +09:00
yjnoh
63db694efa 단수지정배치 작업중 2025-03-17 18:36:39 +09:00
yjnoh
15ff2989f4 Merge branch 'dev' into dev-yj-layoutSetup 2025-03-17 15:03:27 +09:00
yjnoh
83b27582f7 레이아웃 작업 2025-03-17 15:01:25 +09:00
yjnoh
9e66b3ef7d 레이아웃 설치 동서남북 작업 2025-03-17 11:33:44 +09:00
yjnoh
ae2171c633 레이아웃 설치 2025-03-14 18:35:13 +09:00
yjnoh
f9766a7d21 Merge branch 'dev' into dev-yj-layoutSetup
# Conflicts:
#	src/components/floor-plan/modal/basic/BasicSetting.jsx
#	src/hooks/module/useModuleBasicSetting.js
2025-03-14 18:22:24 +09:00
yjnoh
83038a7c81 Merge branch 'dev' into dev-yj-layoutSetup 2025-03-12 17:27:25 +09:00
yjnoh
3df466a717 레이아웃 설치 데모 작업 2025-03-12 16:44:41 +09:00
24 changed files with 3646 additions and 742 deletions

View File

@ -39,7 +39,7 @@ export default function QSelectBox({
if (showKey !== '' && !value) {
//value showKey
// return options[0][showKey]
return title
return title !== '' ? title : getMessage('selectbox.title')
} else if (showKey !== '' && value) {
//value sourceKey targetKey

View File

@ -1,109 +1,89 @@
import { useMessage } from '@/hooks/useMessage'
import { POLYGON_TYPE } from '@/common/common'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useContext, useEffect, useRef, useState } from 'react'
import Module from '@/components/floor-plan/modal/basic/step/Module'
import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchModule'
import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation'
import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement'
import Placement from '@/components/floor-plan/modal/basic/step/Placement'
import { useRecoilValue, useRecoilState } from 'recoil'
import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState } from '@/store/canvasAtom'
import { usePopup } from '@/hooks/usePopup'
import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { useEvent } from '@/hooks/useEvent'
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
import { addedRoofsState, corridorDimensionSelector, basicSettingState } from '@/store/settingAtom'
import { isObjectNotEmpty } from '@/util/common-utils'
import Swal from 'sweetalert2'
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
import { useMasterController } from '@/hooks/common/useMasterController'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { useModuleSelection } from '@/hooks/module/useModuleSelection'
import { useOrientation } from '@/hooks/module/useOrientation'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import {
canvasState,
checkedModuleState,
currentCanvasPlanState,
isManualModuleLayoutSetupState,
isManualModuleSetupState,
toggleManualSetupModeState,
} from '@/store/canvasAtom'
import { loginUserStore } from '@/store/commonAtom'
import { currentCanvasPlanState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
import { roofsState } from '@/store/roofAtom'
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { addedRoofsState, basicSettingState } from '@/store/settingAtom'
import { isObjectNotEmpty } from '@/util/common-utils'
import { useEffect, useRef, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import Swal from 'sweetalert2'
import Trestle from './step/Trestle'
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const [tabNum, setTabNum] = useState(1)
const canvasSetting = useRecoilValue(canvasSettingState)
const orientationRef = useRef(null)
const { initEvent } = useEvent()
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
const addedRoofs = useRecoilValue(addedRoofsState)
const [isManualModuleLayoutSetup, setIsManualModuleLayoutSetup] = useRecoilState(isManualModuleLayoutSetupState)
const trestleRef = useRef(null)
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
const loginUserState = useRecoilValue(loginUserStore)
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
const canvas = useRecoilValue(canvasState)
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 })
const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState)
const [roofs, setRoofs] = useState(addedRoofs)
const [manualSetupMode, setManualSetupMode] = useRecoilState(toggleManualSetupModeState)
const [layoutSetup, setLayoutSetup] = useState([{}])
const {
moduleSelectionInitParams,
selectedModules,
roughnessCodes,
windSpeedCodes,
managementState,
setManagementState,
moduleList,
setSelectedModules,
selectedSurfaceType,
setSelectedSurfaceType,
installHeight,
setInstallHeight,
standardWindSpeed,
setStandardWindSpeed,
verticalSnowCover,
setVerticalSnowCover,
handleChangeModule,
handleChangeSurfaceType,
handleChangeWindSpeed,
handleChangeInstallHeight,
handleChangeVerticalSnowCover,
} = useModuleSelection({ addedRoofs })
const { nextStep, compasDeg, setCompasDeg } = useOrientation()
const { trigger: orientationTrigger } = useCanvasPopupStatusController(1)
const { trigger: trestleTrigger } = useCanvasPopupStatusController(2)
const { trigger: placementTrigger } = useCanvasPopupStatusController(3)
const [roofsStore, setRoofsStore] = useRecoilState(roofsState)
// const { initEvent } = useContext(EventContext)
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(tabNum)
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup, manualModuleLayoutSetup, restoreModuleInstArea } =
useModuleBasicSetting(tabNum)
const { updateObjectDate } = useMasterController()
const handleBtnNextStep = () => {
if (tabNum === 1) {
orientationRef.current.handleNextStep()
} else if (tabNum === 2) {
if (basicSetting.roofSizeSet !== '3') {
if (!isObjectNotEmpty(moduleSelectionData.module)) {
Swal.fire({
title: getMessage('module.not.found'),
icon: 'warning',
})
return
}
if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) {
Swal.fire({
title: getMessage('construction.length.difference'),
icon: 'warning',
})
return
}
//
updateObjectDataApi({
objectNo: currentCanvasPlan.objectNo, //_no
standardWindSpeedId: moduleSelectionData.common.stdWindSpeed, //
verticalSnowCover: moduleSelectionData.common.stdSnowLd, //
surfaceType: moduleSelectionData.common.illuminationTpNm, //
installHeight: moduleSelectionData.common.instHt, //
userId: loginUserState.userId, //
})
} else {
if (!isObjectNotEmpty(moduleSelectionData.module)) {
Swal.fire({
title: getMessage('module.not.found'),
icon: 'warning',
})
return
}
}
}
setTabNum(tabNum + 1)
}
const placementRef = {
isChidori: useRef('false'),
setupLocation: useRef('eaves'),
isMaxSetup: useRef('false'),
}
const placementFlatRef = {
setupLocation: useRef('south'),
}
const handleManualModuleSetup = () => {
setIsManualModuleSetup(!isManualModuleSetup)
}
const updateObjectDataApi = async (params) => {
const res = await updateObjectDate(params)
}
useEffect(() => {
const moduleTabNum = basicSetting.roofSizeSet != 3 ? 3 : 2
let hasModules = canvas
.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
@ -111,23 +91,42 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
if (hasModules) {
orientationRef.current.handleNextStep()
setTabNum(3)
setTabNum(moduleTabNum)
}
}, [])
//
const handleClosePopup = (id) => {
if (tabNum == 3) {
if (isManualModuleSetup) {
setIsManualModuleSetup(false)
}
useEffect(() => {
if (roofsStore && addedRoofs) {
setRoofs(
addedRoofs.map((roof, index) => {
return {
...roof,
...roofsStore[index]?.addRoof,
construction: roofsStore[index]?.construction,
trestle: roofsStore[index]?.trestle,
trestleDetail: roofsStore[index]?.trestleDetail,
}
}),
)
setModuleSelectionData({
...moduleSelectionData,
roofConstructions: roofsStore.map((roof) => {
return {
roofIndex: roof.roofIndex,
addRoof: roof.addRoof,
construction: roof.construction,
trestle: roof.trestle,
trestleDetail: roof.trestleDetail,
}
}),
})
}
setIsClosePopup({ close: true, id: id })
}
}, [roofsStore, addedRoofs])
useEffect(() => {
if (basicSetting.roofSizeSet !== '3') {
manualModuleSetup(placementRef)
manualModuleSetup()
} else {
manualFlatroofModuleSetup(placementFlatRef)
}
@ -140,55 +139,222 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
setIsManualModuleSetup(false)
}, [checkedModules])
useEffect(() => {
if (basicSetting.roofSizeSet !== '3') {
if (manualSetupMode.indexOf('manualSetup') > -1) {
manualModuleSetup()
} else if (manualSetupMode.indexOf('manualLayoutSetup') > -1) {
manualModuleLayoutSetup(layoutSetup)
} else if (manualSetupMode.indexOf('off') > -1) {
manualModuleSetup()
manualModuleLayoutSetup(layoutSetup)
}
} else {
manualFlatroofModuleSetup(placementFlatRef)
}
if (isClosePopup.close) {
closePopup(isClosePopup.id)
}
}, [manualSetupMode, isClosePopup])
useEffect(() => {
if (isManualModuleLayoutSetup) {
manualModuleLayoutSetup(layoutSetup)
}
}, [layoutSetup])
useEffect(() => {
setIsManualModuleSetup(false)
setIsManualModuleLayoutSetup(false)
setManualSetupMode(`off`)
}, [checkedModules])
const handleBtnNextStep = () => {
if (tabNum === 1) {
orientationRef.current.handleNextStep()
setAddedRoofs(roofs)
// setTabNum(tabNum + 1)
return
} else if (tabNum === 2) {
if (basicSetting.roofSizeSet !== '3') {
// if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) {
// Swal.fire({
// title: getMessage('construction.length.difference'),
// icon: 'warning',
// })
// return
// }
trestleRef.current.isComplete().then((res) => {
if (!res) return
})
//
} else {
if (!isObjectNotEmpty(moduleSelectionData.module)) {
Swal.fire({
title: getMessage('module.not.found'),
icon: 'warning',
})
return
}
setTabNum(tabNum + 1)
}
}
}
const placementFlatRef = {
setupLocation: useRef('south'),
}
const handleManualModuleSetup = () => {
setManualSetupMode(`manualSetup_${!isManualModuleSetup}`)
setIsManualModuleSetup(!isManualModuleSetup)
}
const handleManualModuleLayoutSetup = () => {
setManualSetupMode(`manualLayoutSetup_${!isManualModuleLayoutSetup}`)
setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup)
}
const updateObjectDataApi = async (params) => {
const res = await updateObjectDate(params)
}
//
const handleClosePopup = (id) => {
if (tabNum == 3) {
if (isManualModuleSetup) {
setIsManualModuleSetup(false)
}
if (isManualModuleLayoutSetup) {
setIsManualModuleLayoutSetup(false)
}
}
setIsClosePopup({ close: true, id: id })
}
const orientationProps = {
roofs,
setRoofs,
tabNum,
setTabNum,
compasDeg, //
setCompasDeg,
moduleSelectionInitParams,
selectedModules,
moduleSelectionData,
setModuleSelectionData,
roughnessCodes, //
windSpeedCodes, //
managementState,
setManagementState,
moduleList, //
setSelectedModules,
selectedSurfaceType,
setSelectedSurfaceType,
installHeight, //
setInstallHeight,
standardWindSpeed, //
setStandardWindSpeed,
verticalSnowCover, //
setVerticalSnowCover,
currentCanvasPlan,
loginUserState,
handleChangeModule,
handleChangeSurfaceType,
handleChangeWindSpeed,
handleChangeInstallHeight,
handleChangeVerticalSnowCover,
orientationTrigger,
nextStep,
updateObjectDataApi,
}
const trestleProps = {
roofs,
setRoofs,
setRoofsStore,
tabNum,
setTabNum,
moduleSelectionData,
setModuleSelectionData,
trestleTrigger,
}
const placementProps = {}
return (
<WithDraggable isShow={true} pos={pos} className="lx-2">
<WithDraggable isShow={true} pos={pos} className={basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' ? 'll' : 'lx-2'}>
<WithDraggable.Header title={getMessage('plan.menu.module.circuit.setting.default')} onClose={() => handleClosePopup(id)} />
<WithDraggable.Body>
<div className="roof-module-tab">
<div className={`module-tab-bx act`}>{getMessage('modal.module.basic.setting.orientation.setting')}</div>
<span className={`tab-arr ${tabNum !== 1 ? 'act' : ''}`}></span>
<div className={`module-tab-bx ${tabNum !== 1 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.setting')}</div>
<span className={`tab-arr ${tabNum === 3 ? 'act' : ''}`}></span>
<div className={`module-tab-bx ${tabNum === 3 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.placement')}</div>
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && (
<>
<div className={`module-tab-bx ${tabNum !== 1 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.setting')}</div>
<span className={`tab-arr ${tabNum === 3 ? 'act' : ''}`}></span>
<div className={`module-tab-bx ${tabNum === 3 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.placement')}</div>
</>
)}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && (
<>
<div className={`module-tab-bx ${tabNum === 2 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.placement')}</div>
</>
)}
</div>
{tabNum === 1 && <Orientation ref={orientationRef} tabNum={tabNum} setTabNum={setTabNum} />}
{tabNum === 1 && <Orientation ref={orientationRef} {...orientationProps} />}
{/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && <Module setTabNum={setTabNum} />}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && <Placement setTabNum={setTabNum} ref={placementRef} />}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && <Trestle ref={trestleRef} {...trestleProps} />}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && (
<Placement setTabNum={setTabNum} layoutSetup={layoutSetup} setLayoutSetup={setLayoutSetup} />
)}
{/*배치면 초기설정 - 입력방법: 육지붕*/}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && <PitchModule setTabNum={setTabNum} />}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && (
{/* {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && <PitchModule setTabNum={setTabNum} />} */}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && (
<PitchPlacement setTabNum={setTabNum} ref={placementFlatRef} />
)}
<div className="grid-btn-wrap">
{tabNum !== 1 && (
<button className="btn-frame modal mr5" onClick={() => setTabNum(tabNum - 1)}>
{getMessage('modal.module.basic.setting.prev')}
</button>
)}
{/*{tabNum !== 3 && <button className="btn-frame modal act mr5">{getMessage('modal.common.save')}</button>}*/}
{tabNum !== 3 && (
<button className="btn-frame modal" onClick={handleBtnNextStep}>
Next
</button>
)}
{tabNum === 3 && (
{/* {tabNum === 1 && <button className="btn-frame modal mr5">{getMessage('modal.common.save')}</button>} */}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && (
<>
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && (
{tabNum !== 1 && (
<button className="btn-frame modal mr5" onClick={() => setTabNum(tabNum - 1)}>
{getMessage('modal.module.basic.setting.prev')}
</button>
)}
{tabNum !== 3 && (
<button className="btn-frame modal" onClick={handleBtnNextStep}>
Next
</button>
)}
{tabNum === 3 && (
<>
<button className={`btn-frame modal mr5 ${isManualModuleLayoutSetup ? 'act' : ''}`} onClick={handleManualModuleLayoutSetup}>
{getMessage('modal.module.basic.setting.row.batch')}
</button>
<button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
{getMessage('modal.module.basic.setting.passivity.placement')}
</button>
<button className="btn-frame modal act" onClick={() => autoModuleSetup(placementRef)}>
<button className="btn-frame modal act" onClick={() => autoModuleSetup()}>
{getMessage('modal.module.basic.setting.auto.placement')}
</button>
</>
)}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && (
</>
)}
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && (
<>
{tabNum === 1 && (
<button className="btn-frame modal" onClick={handleBtnNextStep}>
Next
</button>
)}
{tabNum === 2 && (
<>
<button className="btn-frame modal mr5" onClick={() => setTabNum(tabNum - 1)}>
{getMessage('modal.module.basic.setting.prev')}
</button>
<button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
{getMessage('modal.module.basic.setting.passivity.placement')}
</button>

View File

@ -1,115 +1,466 @@
import { forwardRef, useContext, useEffect, useImperativeHandle, useState } from 'react'
import { forwardRef, use, useContext, useEffect, useImperativeHandle, useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { useOrientation } from '@/hooks/module/useOrientation'
import { getDegreeInOrientation } from '@/util/canvas-util'
import { numberCheck } from '@/util/common-utils'
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
import { addedRoofsState, basicSettingState } from '@/store/settingAtom'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import QSelectBox from '@/components/common/select/QSelectBox'
import { roofsState } from '@/store/roofAtom'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import Swal from 'sweetalert2'
export const Orientation = forwardRef(({ tabNum }, ref) => {
export const Orientation = forwardRef((props, ref) => {
const { getMessage } = useMessage()
const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController(1)
const { nextStep, compasDeg, setCompasDeg } = useOrientation()
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
const basicSetting = useRecoilValue(basicSettingState)
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) //
const [roofsStore, setRoofsStore] = useRecoilState(roofsState)
const [roofTab, setRoofTab] = useState(0) //
const {
roofs,
setRoofs,
tabNum,
setTabNum,
compasDeg,
setCompasDeg,
moduleSelectionInitParams,
selectedModules,
roughnessCodes,
windSpeedCodes,
managementState,
setManagementState,
moduleList,
moduleSelectionData,
setModuleSelectionData,
setSelectedModules,
selectedSurfaceType,
setSelectedSurfaceType,
installHeight,
setInstallHeight,
standardWindSpeed,
setStandardWindSpeed,
verticalSnowCover,
setVerticalSnowCover,
orientationTrigger,
nextStep,
currentCanvasPlan,
loginUserState,
updateObjectDataApi,
} = props
const [inputCompasDeg, setInputCompasDeg] = useState(compasDeg ?? 0)
const [inputInstallHeight, setInputInstallHeight] = useState('0')
const [inputMargin, setInputMargin] = useState('0')
const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState('0')
const [inputRoughness, setInputRoughness] = useState(selectedSurfaceType)
const [inputStandardWindSpeed, setInputStandardWindSpeed] = useState(standardWindSpeed)
const { restoreModuleInstArea } = useModuleBasicSetting()
const moduleData = {
header: [
{ name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' },
{
name: `${getMessage('height')} (mm)`,
prop: 'height',
},
{ name: `${getMessage('width')} (mm)`, prop: 'width' },
{ name: `${getMessage('output')} (W)`, prop: 'output' },
],
}
useEffect(() => {
if (basicSetting.roofSizeSet == '3') {
restoreModuleInstArea()
}
}, [])
useEffect(() => {
if (moduleSelectionData?.common) {
setInputMargin(moduleSelectionData?.common?.margin)
}
}, [moduleSelectionData])
useEffect(() => {
if (selectedModules) {
setSelectedModules(moduleList.find((module) => module.itemId === selectedModules.itemId))
}
}, [selectedModules])
useEffect(() => {
if (selectedSurfaceType) {
setInputRoughness(roughnessCodes.find((code) => code.clCode === managementState?.surfaceTypeValue))
}
}, [selectedSurfaceType])
useEffect(() => {
if (standardWindSpeed) setInputStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === managementState?.standardWindSpeedId))
}, [standardWindSpeed])
useEffect(() => {
if (managementState?.installHeight && managementState?.installHeight) {
setSelectedSurfaceType(roughnessCodes.find((code) => code.clCode === managementState?.surfaceTypeValue))
setInputInstallHeight(managementState?.installHeight)
setStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === managementState?.standardWindSpeedId))
setInputVerticalSnowCover(managementState?.verticalSnowCover)
}
}, [managementState])
useImperativeHandle(ref, () => ({
handleNextStep,
}))
const handleNextStep = () => {
nextStep()
canvasPopupStatusTrigger(compasDeg)
if (isComplete()) {
const common = {
illuminationTp: inputRoughness.clCode,
illuminationTpNm: inputRoughness.clCodeNm,
instHt: inputInstallHeight,
stdWindSpeed: inputStandardWindSpeed?.clCode,
stdSnowLd: inputVerticalSnowCover,
saleStoreNorthFlg: managementState?.saleStoreNorthFlg,
moduleTpCd: selectedModules.itemTp,
moduleItemId: selectedModules.itemId,
margin: inputMargin,
}
setCompasDeg(inputCompasDeg)
setInstallHeight(inputInstallHeight)
setVerticalSnowCover(inputVerticalSnowCover)
setSelectedSurfaceType(inputRoughness)
setStandardWindSpeed(inputStandardWindSpeed)
nextStep(inputCompasDeg)
setManagementState({
...managementState,
installHeight: inputInstallHeight,
verticalSnowCover: inputVerticalSnowCover,
standardWindSpeedId: inputStandardWindSpeed?.clCode,
surfaceType: inputRoughness.clCodeNm,
surfaceTypeValue: inputRoughness.clCode,
})
setModuleSelectionData({
...moduleSelectionData,
module: {
...selectedModules,
},
common,
})
orientationTrigger({
compasDeg: inputCompasDeg,
common: common,
module: {
...selectedModules,
},
margin: inputMargin,
})
updateObjectDataApi({
objectNo: currentCanvasPlan.objectNo, //_no
standardWindSpeedId: inputStandardWindSpeed?.clCode, //
verticalSnowCover: inputVerticalSnowCover, //
surfaceType: inputRoughness.clCodeNm, //
installHeight: inputInstallHeight, //
userId: loginUserState.userId, //
})
setTabNum(2)
} else {
if (!selectedModules || !selectedModules.itemId) {
Swal.fire({
title: getMessage('module.not.found'),
icon: 'warning',
})
return
}
}
}
useEffect(() => {
checkDegree(compasDeg)
}, [compasDeg])
const checkDegree = (e) => {
if (e === '-0' || e === '-') {
setCompasDeg('-')
setInputCompasDeg('-')
return
}
if (e === '0-') {
setCompasDeg('-0')
setInputCompasDeg('-0')
return
}
if (Number(e) >= -180 && Number(e) <= 180) {
if (numberCheck(Number(e))) {
setCompasDeg(Number(e))
setInputCompasDeg(Number(e))
}
} else {
setCompasDeg(compasDeg)
setInputCompasDeg(compasDeg)
}
}
const isComplete = () => {
if (!selectedModules || !selectedModules.itemId) return false
if (basicSetting && basicSetting.roofSizeSet !== '3') {
if (inputInstallHeight <= 0) {
return false
}
if (+inputVerticalSnowCover <= 0) {
return false
}
if (!inputStandardWindSpeed) return false
if (!inputRoughness) return false
}
return true
}
const handleChangeModule = (e) => {
resetRoofs()
setSelectedModules(e)
}
const handleChangeRoughness = (e) => {
resetRoofs()
setInputRoughness(e)
}
const handleChangeInstallHeight = (e) => {
resetRoofs()
setInputInstallHeight(e)
}
const handleChangeStandardWindSpeed = (e) => {
resetRoofs()
setInputStandardWindSpeed(e)
}
const handleChangeVerticalSnowCover = (e) => {
resetRoofs()
setInputVerticalSnowCover(e)
}
const resetRoofs = () => {
const newRoofs = addedRoofs.map((roof) => {
return {
...roof,
trestle: {
lengthBase: null,
trestleMkrCd: null,
constMthdCd: null,
constTp: null,
roofBaseCd: null,
roofPchBase: null,
},
addRoof: {
...roof.addRoof,
lengthBase: null,
eavesMargin: null,
kerabaMargin: null,
ridgeMargin: null,
},
construction: {
constTp: null,
cvrYn: 'N',
snowGdPossYn: 'N',
cvrChecked: false,
snowGdChecked: false,
},
}
})
// setRoofs(newRoofs)
// setAddedRoofs(newRoofs)
setRoofsStore(newRoofs)
}
return (
<>
<div className="properties-setting-wrap">
<div className="outline-wrap">
<div className="guide">{getMessage('modal.module.basic.setting.orientation.setting.info')}</div>
<div className="roof-module-compas">
<div className="compas-box">
<div className="compas-box-inner">
{Array.from({ length: 180 / 15 }).map((dot, index) => (
<div
key={index}
className={`circle ${getDegreeInOrientation(compasDeg) === -1 * (-15 * index + 180) || (index === 0 && compasDeg >= 172 && index === 0 && compasDeg <= 180) || (compasDeg === -180 && index === 0) ? 'act' : ''}`}
onClick={() => {
if (index === 0) {
setCompasDeg(180)
return
}
setCompasDeg(-1 * (-15 * index + 180))
}}
>
{index === 0 && <i>180°</i>}
{index === 6 && <i>-90°</i>}
<div className="roof-module-inner">
<div className="compas-wrapper">
<div className="guide">{getMessage('modal.module.basic.setting.orientation.setting.info')}</div>
<div className="roof-module-compas">
<div className="compas-box">
<div className="compas-box-inner">
{Array.from({ length: 180 / 15 }).map((dot, index) => (
<div
key={index}
className={`circle ${getDegreeInOrientation(inputCompasDeg) === -1 * (-15 * index + 180) || (index === 0 && inputCompasDeg >= 172 && index === 0 && inputCompasDeg <= 180) || (inputCompasDeg === -180 && index === 0) ? 'act' : ''}`}
onClick={() => {
if (index === 0) {
setInputCompasDeg(180)
return
}
setInputCompasDeg(-1 * (-15 * index + 180))
}}
>
{index === 0 && <i>180°</i>}
{index === 6 && <i>-90°</i>}
</div>
))}
{Array.from({ length: 180 / 15 }).map((dot, index) => (
<div
key={index}
className={`circle ${inputCompasDeg !== 180 && getDegreeInOrientation(inputCompasDeg) === 15 * index ? 'act' : ''}`}
onClick={() => setInputCompasDeg(15 * index)}
>
{index === 0 && <i>0°</i>}
{index === 6 && <i>90°</i>}
</div>
))}
<div className="compas">
<div className="compas-arr" style={{ transform: `rotate(${getDegreeInOrientation(inputCompasDeg)}deg)` }}></div>
</div>
</div>
))}
{Array.from({ length: 180 / 15 }).map((dot, index) => (
<div
key={index}
className={`circle ${compasDeg !== 180 && getDegreeInOrientation(compasDeg) === 15 * index ? 'act' : ''}`}
onClick={() => setCompasDeg(15 * index)}
>
{index === 0 && <i>0°</i>}
{index === 6 && <i>90°</i>}
</div>
</div>
<div className="center-wrap">
<div className="outline-form">
<div className="d-check-box pop mr10">
<input type="checkbox" id="ch99" checked={hasAnglePassivity} onChange={() => setHasAnglePassivity(!hasAnglePassivity)} />
<label htmlFor="ch99">{getMessage('modal.module.basic.setting.orientation.setting.angle.passivity')}</label>
</div>
))}
<div className="compas">
<div className="compas-arr" style={{ transform: `rotate(${getDegreeInOrientation(compasDeg)}deg)` }}></div>
<div className="input-grid mr10" style={{ width: '60px' }}>
<input
type="text"
className="input-origin block"
value={inputCompasDeg}
readOnly={!hasAnglePassivity}
placeholder={0}
onChange={(e) => checkDegree(e.target.value)}
/>
</div>
<span className="thin">°</span>
<span className="thin"> -180 180 </span>
</div>
</div>
</div>
</div>
<div className="center-wrap">
<div className="d-check-box pop">
<input type="checkbox" id="ch99" checked={hasAnglePassivity} onChange={() => setHasAnglePassivity(!hasAnglePassivity)} />
<label htmlFor="ch99">{getMessage('modal.module.basic.setting.orientation.setting.angle.passivity')}-180 180</label>
</div>
<div className="outline-form">
<div className="input-grid mr10" style={{ width: '160px' }}>
<input
type="text"
className="input-origin block"
value={compasDeg}
readOnly={!hasAnglePassivity}
placeholder={0}
onChange={
(e) => checkDegree(e.target.value)
// setCompasDeg(
// e.target.value === '-' || (e.target.value !== '' && parseInt(e.target.value) <= 180 && parseInt(e.target.value) >= -180)
// ? e.target.value
// : 0,
// )
}
/>
<div className="compas-table-wrap">
<div className="compas-table-box mb10">
<div className="outline-form mb10">
<span>{getMessage('modal.module.basic.setting.module.setting')}</span>
<div className="grid-select">
{moduleList && (
<QSelectBox
options={moduleList}
value={selectedModules}
targetKey={'itemId'}
sourceKey={'itemId'}
showKey={'itemNm'}
onChange={(e) => handleChangeModule(e)}
/>
)}
</div>
</div>
<div className="roof-module-table">
<table>
<thead>
<tr>
{moduleData.header.map((header) => {
return (
<th key={header.prop} style={{ width: header.width ? header.width + 'px' : '' }}>
{header.name}
</th>
)
})}
</tr>
</thead>
<tbody>
{Array.from({ length: 3 }).map((_, index) => {
return selectedModules && selectedModules?.itemList && selectedModules?.itemList?.length >= index + 1 ? (
<tr key={index}>
<td>
<div className="color-wrap">
<span
className="color-box"
style={{
backgroundColor: selectedModules.itemList[index].color,
}}
></span>
<span className="name">{selectedModules.itemList[index].itemNm}</span>
</div>
</td>
<td className="al-r">{Number(selectedModules.itemList[index].shortAxis).toFixed(0)}</td>
<td className="al-r">{Number(selectedModules.itemList[index].longAxis).toFixed(0)}</td>
<td className="al-r">{Number(selectedModules.itemList[index].wpOut).toFixed(0)}</td>
</tr>
) : (
<tr key={index}>
<td>
<div className="color-wrap"></div>
</td>
<td className="al-r"></td>
<td className="al-r"></td>
<td className="al-r"></td>
</tr>
)
})}
</tbody>
</table>
</div>
{basicSetting && basicSetting.roofSizeSet == '3' && (
<div className="outline-form mt15">
<span>{getMessage('modal.module.basic.setting.module.placement.area')}</span>
<div className="input-grid mr10" style={{ width: '60px' }}>
<input type="text" className="input-origin block" value={inputMargin} onChange={(e) => setInputMargin(e.target.value)} />
</div>
<span className="thin">m</span>
</div>
)}
</div>
<span className="thin">°</span>
{basicSetting && basicSetting.roofSizeSet != '3' && (
<div className="compas-table-box">
<div className="compas-grid-table">
<div className="outline-form">
<span>{getMessage('modal.module.basic.setting.module.surface.type')}</span>
<div className="grid-select">
{roughnessCodes.length > 0 && managementState && (
<QSelectBox
options={roughnessCodes}
value={inputRoughness}
targetKey={'clCode'}
sourceKey={'clCode'}
showKey={'clCodeNm'}
onChange={(e) => handleChangeRoughness(e)}
/>
)}
</div>
</div>
<div className="outline-form">
<span>{getMessage('modal.module.basic.setting.module.fitting.height')}</span>
<div className="input-grid mr10">
<input
type="text"
className="input-origin block"
value={inputInstallHeight}
onChange={(e) => handleChangeInstallHeight(e.target.value)}
/>
</div>
<span className="thin">m</span>
</div>
<div className="outline-form">
<span>{getMessage('modal.module.basic.setting.module.standard.wind.speed')}</span>
<div className="grid-select">
{windSpeedCodes.length > 0 && managementState && (
<QSelectBox
title={''}
options={windSpeedCodes}
value={inputStandardWindSpeed}
targetKey={'clCode'}
sourceKey={'clCode'}
showKey={'clCodeNm'}
onChange={(e) => handleChangeStandardWindSpeed(e)}
/>
)}
</div>
</div>
<div className="outline-form">
<span>{getMessage('modal.module.basic.setting.module.standard.snowfall.amount')}</span>
<div className="input-grid mr10">
<input
type="text"
className="input-origin block"
value={inputVerticalSnowCover}
onChange={(e) => handleChangeVerticalSnowCover(e.target.value)}
/>
</div>
<span className="thin">cm</span>
</div>
</div>
</div>
)}
</div>
</div>
</div>

View File

@ -1,29 +1,43 @@
import { forwardRef, useEffect, useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { checkedModuleState, currentCanvasPlanState, isManualModuleSetupState } from '@/store/canvasAtom'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import {
checkedModuleState,
isManualModuleLayoutSetupState,
isManualModuleSetupState,
moduleRowColArrayState,
moduleSetupOptionState,
toggleManualSetupModeState,
} from '@/store/canvasAtom'
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils'
const Placement = forwardRef((props, refs) => {
const { getMessage } = useMessage()
const [isChidori, setIsChidori] = useState(false)
const [useTab, setUseTab] = useState(true)
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
const [setupLocation, setSetupLocation] = useState('eaves')
const [isMaxSetup, setIsMaxSetup] = useState('false')
const [selectedItems, setSelectedItems] = useState({})
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState)
const setCheckedModules = useSetRecoilState(checkedModuleState)
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
const { makeModuleInitArea } = useModuleBasicSetting(3)
const { makeModuleInitArea, roofOutlineColor } = useModuleBasicSetting(3)
const [isMultiModule, setIsMultiModule] = useState(false)
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
//
const setIsManualModuleSetup = useSetRecoilState(isManualModuleSetupState)
const setIsManualModuleLayoutSetup = useSetRecoilState(isManualModuleLayoutSetupState)
const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState)
const [moduleSetupOption, setModuleSetupOption] = useRecoilState(moduleSetupOptionState) //
const resetModuleSetupOption = useResetRecoilState(moduleSetupOptionState)
const [colspan, setColspan] = useState(1)
const [moduleRowColArray, setModuleRowColArray] = useRecoilState(moduleRowColArrayState)
//
useEffect(() => {
@ -36,13 +50,24 @@ const Placement = forwardRef((props, refs) => {
makeModuleInitArea(moduleSelectionData)
}
if (moduleSelectionData.module.itemList.length > 1) {
setColspan(2)
}
return () => {
refs.isChidori.current = 'false'
refs.setupLocation.current = 'eaves'
// refs.isChidori.current = 'false'
// refs.setupLocation.current = 'eaves'
setIsManualModuleSetup(false)
setIsManualModuleLayoutSetup(false)
setManualSetupMode('off')
resetModuleSetupOption()
}
}, [])
useEffect(() => {
console.log('moduleRowColArray', moduleRowColArray)
}, [moduleRowColArray])
//
useEffect(() => {
if (isObjectNotEmpty(moduleSelectionData)) {
@ -56,8 +81,10 @@ const Placement = forwardRef((props, refs) => {
initCheckedModule = { ...initCheckedModule, [obj.itemId]: true }
}
})
setSelectedItems(initCheckedModule)
setSelectedModules(moduleSelectionData.module)
props.setLayoutSetup(moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0, checked: true })))
}
//
@ -82,59 +109,75 @@ const Placement = forwardRef((props, refs) => {
header: [
{ type: 'check', name: '', prop: 'check', width: 70 },
{ type: 'color-box', name: getMessage('module'), prop: 'module' },
{ type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 },
{ type: 'text', name: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn'), prop: 'mixAsgYn', width: 50 },
{ type: 'text', name: `単数`, prop: 'rows', width: 60 },
{ type: 'text', name: `熱水`, prop: 'cols', width: 60 },
],
rows: [],
}
const handleChangeChidori = (e) => {
const bool = e.target.value === 'true' ? true : false
setIsChidori(bool)
refs.isChidori.current = e.target.value
setModuleSetupOption({ ...moduleSetupOption, isChidori: bool })
//
setIsManualModuleSetup(false)
setIsManualModuleLayoutSetup(false)
setManualSetupMode('off')
}
const handleSetupLocation = (e) => {
setSetupLocation(e.target.value)
refs.setupLocation.current = e.target.value
}
setModuleSetupOption({ ...moduleSetupOption, setupLocation: e.target.value })
const handleMaxSetup = (e) => {
if (e.target.checked) {
setIsMaxSetup('true')
refs.isMaxSetup.current = 'true'
} else {
setIsMaxSetup('false')
refs.isMaxSetup.current = 'false'
}
//
setIsManualModuleSetup(false)
setIsManualModuleLayoutSetup(false)
setManualSetupMode('off')
}
//
const handleSelectedItem = (e) => {
const handleSelectedItem = (e, itemId) => {
setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked })
const newLayoutSetup = [...props.layoutSetup]
props.layoutSetup.forEach((item, index) => {
if (item.moduleId === itemId) {
newLayoutSetup[index] = { ...props.layoutSetup[index], checked: e.target.checked }
}
})
props.setLayoutSetup(newLayoutSetup)
}
const handleLayoutSetup = (e, itemId, index) => {
const newLayoutSetup = [...props.layoutSetup]
newLayoutSetup[index] = {
...newLayoutSetup[index],
moduleId: itemId,
[e.target.name]: Number(e.target.value),
}
props.setLayoutSetup(newLayoutSetup)
}
return (
<>
<div className="module-table-flex-wrap mb10">
<div className="module-table-flex-wrap">
<div className="module-table-box">
<div className="module-table-inner">
<div className="roof-module-table">
<table>
<thead>
<tr>
{moduleData.header.map((data) => (
<th key={data.prop} style={{ width: data.width ? data.width : '' }}>
{data.type === 'check' ? (
<div className="d-check-box no-text pop">
<input type="checkbox" id="ch01" disabled />
<label htmlFor="ch01"></label>
</div>
) : (
data.name
)}
</th>
))}
</tr>
{moduleData.header.map((data) => (
<th key={data.prop} style={{ width: data.width ? data.width : '' }}>
{data.type === 'check' ? (
<div className="d-check-box no-text pop">
<input type="checkbox" id="ch01" disabled />
<label htmlFor="ch01"></label>
</div>
) : (
data.name
)}
</th>
))}
</thead>
<tbody>
{selectedModules.itemList &&
@ -147,7 +190,7 @@ const Placement = forwardRef((props, refs) => {
id={item.itemId}
name={item.itemId}
checked={selectedItems[item.itemId]}
onChange={handleSelectedItem}
onChange={(e) => handleSelectedItem(e, item.itemId)}
/>
<label htmlFor={item.itemId}></label>
</div>
@ -158,93 +201,174 @@ const Placement = forwardRef((props, refs) => {
<span className="name">{item.itemNm}</span>
</div>
</td>
<td className="al-r">{item.wpOut}</td>
<td className="al-c">
<div className="color-wrap">
<span className="name">{item.mixAsgYn}</span>
</div>
</td>
<td className="al-r">
<div className="input-grid">
<input
type="text"
className="input-origin block"
name="row"
value={props.layoutSetup[index]?.row ?? 1}
defaultValue={0}
onChange={(e) => handleLayoutSetup(e, item.itemId, index)}
/>
</div>
</td>
<td className="al-r">
<div className="input-grid">
<input
type="text"
className="input-origin block"
name="col"
value={props.layoutSetup[index]?.col ?? 1}
defaultValue={0}
onChange={(e) => handleLayoutSetup(e, item.itemId, index)}
/>
</div>
</td>
</tr>
))}
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div className="module-table-box">
<div className="module-table-box non-flex">
<div className="module-table-inner">
<div className="self-table-tit">{getMessage('modal.module.basic.setting.module.placement.select.fitting.type')}</div>
<div className="module-self-table">
<div className="self-table-item">
<div className="self-item-th">{getMessage('modal.module.basic.setting.module.placement.waterfowl.arrangement')}</div>
<div className="self-item-td">
<div className="pop-form-radio">
<div className="d-check-radio pop">
<input
type="radio"
name="radio01"
id="ra01"
checked={isChidori}
disabled={isChidoriNotAble}
value={'true'}
onChange={(e) => handleChangeChidori(e)}
/>
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.module.placement.do')}</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio02" id="ra02" checked={!isChidori} value={'false'} onChange={(e) => handleChangeChidori(e)} />
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.module.placement.do.not')}</label>
</div>
</div>
</div>
</div>
<div className="self-table-item">
<div className="self-item-th">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}</div>
<div className="self-item-td">
<div className="pop-form-radio">
<div className="d-check-radio pop">
<input
type="radio"
name="radio03"
id="ra03"
checked={setupLocation === 'center'}
value={'center'}
onChange={handleSetupLocation}
disabled={isMultiModule}
/>
<label htmlFor="ra03">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.center')}</label>
</div>
<div className="d-check-radio pop">
<input
type="radio"
name="radio04"
id="ra04"
checked={setupLocation === 'eaves'}
value={'eaves'}
onChange={handleSetupLocation}
/>
<label htmlFor="ra04">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.eaves')}</label>
</div>
<div className="d-check-radio pop">
<input
type="radio"
name="radio05"
id="ra05"
checked={setupLocation === 'ridge'}
value={'ridge'}
onChange={handleSetupLocation}
disabled={isMultiModule}
/>
<label htmlFor="ra05">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.ridge')}</label>
</div>
</div>
</div>
</div>
</div>
<div className="self-table-flx">
{/* <div className="d-check-box pop">
<input type="checkbox" id="ch04" checked={isMaxSetup === 'true'} value={'true'} onChange={handleMaxSetup} />
<label htmlFor="ch04">{getMessage('modal.module.basic.setting.module.placement.maximum')}</label>
</div> */}
<div className="roof-module-table">
<table>
<thead>
<tr>
<th>{getMessage('modal.module.basic.setting.module.placement.waterfowl.arrangement')}</th>
<th>{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div className="hexagonal-radio-wrap">
<div className="d-check-radio pop mb10">
<input
type="radio"
name="radio02"
id="ra03"
checked={moduleSetupOption.isChidori}
disabled={isChidoriNotAble}
value={'true'}
onChange={(e) => handleChangeChidori(e)}
/>
<label htmlFor="ra03">{getMessage('modal.module.basic.setting.module.placement.do')}</label>
</div>
<div className="d-check-radio pop">
<input
type="radio"
name="radio02"
id="ra04"
checked={!moduleSetupOption.isChidori}
value={'false'}
onChange={(e) => handleChangeChidori(e)}
/>
<label htmlFor="ra04">{getMessage('modal.module.basic.setting.module.placement.do.not')}</label>
</div>
</div>
</td>
<td>
<div className="hexagonal-radio-wrap">
<div className="d-check-radio pop mb10">
<input
type="radio"
name="radio03"
id="ra05"
checked={moduleSetupOption.setupLocation === 'eaves'}
value={'eaves'}
onChange={handleSetupLocation}
/>
<label htmlFor="ra05">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.eaves')}</label>
</div>
<div className="d-check-radio pop">
<input
type="radio"
name="radio03"
id="ra06"
checked={moduleSetupOption.setupLocation === 'ridge'}
value={'ridge'}
onChange={handleSetupLocation}
disabled={isMultiModule}
/>
<label htmlFor="ra06">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.ridge')}</label>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div className="hide-check-guide">
{getMessage('modal.module.basic.setting.module.placement.max.size.check')}
<button className={`arr ${!useTab ? 'act' : ''}`} onClick={() => setUseTab(!useTab)}></button>
</div>
<div className={`module-table-box mt10 ${useTab ? 'hide' : ''}`}>
<div className="module-table-inner">
<div className="roof-module-table">
<table className="">
<thead>
<tr>
<th rowSpan={2} style={{ width: '22%' }}></th>
{selectedModules &&
selectedModules.itemList.map((item) => (
<th colSpan={colspan}>
<div className="color-wrap">
<span className="color-box" style={{ backgroundColor: item.color }}></span>
<span className="name">{item.itemNm}</span>
</div>
</th>
))}
</tr>
<tr>
{selectedModules.itemList.map((item) => (
<>
<th>{getMessage('modal.module.basic.setting.module.placement.max.row')}</th>
{colspan > 1 && <th>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>}
</>
))}
</tr>
</thead>
<tbody>
{moduleSelectionData.roofConstructions.map((item, index) => (
<tr>
<td>
<div className="color-wrap">
<span className="color-box" style={{ backgroundColor: roofOutlineColor(item.addRoof?.index) }}></span>
<span className="name">{item.addRoof?.roofMatlNmJp}</span>
</div>
</td>
{moduleRowColArray[index]?.map((item) => (
<>
<td className="al-c">{item.moduleMaxRows}</td>
{colspan > 1 && <td className="al-c">{item.mixModuleMaxRows}</td>}
</>
))}
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</>
)
})

View File

@ -0,0 +1,727 @@
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { useModuleTrestle } from '@/hooks/module/useModuleTrestle'
import { useMessage } from '@/hooks/useMessage'
import { currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
import { roofsState } from '@/store/roofAtom'
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
import { forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import Swal from 'sweetalert2'
const Trestle = forwardRef((props, ref) => {
const { tabNum, setTabNum, trestleTrigger, roofs, setRoofs, moduleSelectionData, setModuleSelectionData, setRoofsStore } = props
const { getMessage } = useMessage()
// const [selectedTrestle, setSelectedTrestle] = useState()
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const [selectedRoof, setSelectedRoof] = useState(null)
const {
trestleState,
trestleDetail,
dispatch,
raftBaseList,
trestleList,
constMthdList,
roofBaseList,
constructionList,
eavesMargin,
ridgeMargin,
kerabaMargin,
setEavesMargin,
setRidgeMargin,
setKerabaMargin,
lengthBase,
setLengthBase,
hajebichi,
setHajebichi,
cvrYn,
cvrChecked,
snowGdPossYn,
snowGdChecked,
setCvrYn,
setCvrChecked,
setSnowGdPossYn,
setSnowGdChecked,
} = useModuleTrestle({
selectedRoof,
})
const selectedModules = useRecoilValue(selectedModuleState) //
// const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
const [selectedRaftBase, setSelectedRaftBase] = useState(null)
const [selectedTrestle, setSelectedTrestle] = useState(null)
const [selectedConstMthd, setSelectedConstMthd] = useState(null)
const [selectedConstruction, setSelectedConstruction] = useState(null)
const [selectedRoofBase, setSelectedRoofBase] = useState(null)
const { managementState } = useContext(GlobalDataContext)
const { restoreModuleInstArea } = useModuleBasicSetting()
const [flag, setFlag] = useState(false)
const tempModuleSelectionData = useRef(null)
useEffect(() => {
if (roofs && !selectedRoof) {
setSelectedRoof(roofs[0])
}
//
restoreModuleInstArea()
}, [roofs])
useEffect(() => {
if (flag && moduleSelectionData) {
if (JSON.stringify(tempModuleSelectionData.current) === JSON.stringify(moduleSelectionData)) {
setTabNum(tabNum + 1)
}
}
}, [flag, moduleSelectionData])
useEffect(() => {
if (selectedRoof) {
if (moduleSelectionData?.roofConstructions?.length >= selectedRoof.index + 1) {
const { construction, trestle, trestleDetail } = moduleSelectionData?.roofConstructions[selectedRoof.index]
dispatch({
type: 'SET_INITIALIZE',
roof: { common: moduleSelectionData.common, module: moduleSelectionData.module, construction, trestle, trestleDetail, ...selectedRoof },
})
} else {
dispatch({ type: 'SET_INITIALIZE', roof: { ...selectedRoof, common: moduleSelectionData.common, module: moduleSelectionData.module } })
}
}
}, [selectedRoof])
useEffect(() => {
if (raftBaseList.length > 0) {
setSelectedRaftBase(raftBaseList.find((raft) => raft.clCode === trestleState?.raftBaseCd) ?? null)
} else {
setSelectedRaftBase(null)
}
}, [raftBaseList])
useEffect(() => {
if (trestleList.length > 0) {
setSelectedTrestle(trestleList.find((trestle) => trestle.trestleMkrCd === trestleState?.trestleMkrCd) ?? null)
} else {
setSelectedTrestle(null)
}
}, [trestleList])
useEffect(() => {
if (roofBaseList.length > 0) {
setSelectedRoofBase(roofBaseList.find((roofBase) => roofBase.roofBaseCd === trestleState?.roofBaseCd) ?? null)
} else {
setSelectedRoofBase(null)
}
}, [roofBaseList])
useEffect(() => {
if (constMthdList.length > 0) {
setSelectedConstMthd(constMthdList.find((constMthd) => constMthd.constMthdCd === trestleState?.constMthdCd) ?? null)
} else {
setSelectedConstMthd(null)
}
}, [constMthdList])
useEffect(() => {
if (constructionList.length > 0) {
setSelectedConstruction(constructionList.find((construction) => construction.constTp === trestleState?.construction?.constTp) ?? null)
} else {
setSelectedConstruction(null)
}
}, [constructionList])
const getConstructionState = (index) => {
if (constructionList && constructionList.length > 0) {
if (constructionList[index].constPossYn === 'Y') {
if (trestleState && trestleState.constTp === constructionList[index].constTp) {
return 'blue'
}
return 'white'
}
return 'no-click'
}
return 'no-click'
}
const onChangeRaftBase = (e) => {
setSelectedRaftBase(e)
dispatch({
type: 'SET_RAFT_BASE',
roof: {
moduleTpCd: selectedModules.itemTp ?? '',
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
raftBaseCd: e.clCode,
},
})
}
const onChangeTrestleMaker = (e) => {
setSelectedTrestle(e)
dispatch({
type: 'SET_TRESTLE_MAKER',
roof: {
moduleTpCd: selectedModules.itemTp ?? '',
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
raftBaseCd: selectedRaftBase?.clCode,
trestleMkrCd: e.trestleMkrCd,
},
})
}
const onChangeConstMthd = (e) => {
setSelectedConstMthd(e)
dispatch({
type: 'SET_CONST_MTHD',
roof: {
moduleTpCd: selectedModules.itemTp ?? '',
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
raftBaseCd: selectedRaftBase?.clCode,
trestleMkrCd: selectedTrestle.trestleMkrCd,
constMthdCd: e.constMthdCd,
},
})
}
const onChangeRoofBase = (e) => {
setSelectedRoofBase(e)
dispatch({
type: 'SET_ROOF_BASE',
roof: {
moduleTpCd: selectedModules.itemTp ?? '',
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
raftBaseCd: selectedRaftBase?.clCode,
trestleMkrCd: selectedTrestle.trestleMkrCd,
constMthdCd: selectedConstMthd.constMthdCd,
roofBaseCd: e.roofBaseCd,
illuminationTp: managementState?.surfaceTypeValue ?? '',
instHt: managementState?.installHeight ?? '',
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
stdSnowLd: managementState?.verticalSnowCover ?? '',
inclCd: selectedRoof?.pitch ?? 0,
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
},
})
}
const handleConstruction = (index) => {
if (constructionList[index]?.constPossYn === 'Y') {
dispatch({
type: 'SET_CONSTRUCTION',
roof: {
moduleTpCd: selectedModules.itemTp ?? '',
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
raftBaseCd: selectedRaftBase?.clCode,
trestleMkrCd: selectedTrestle.trestleMkrCd,
constMthdCd: selectedConstMthd.constMthdCd,
roofBaseCd: selectedRoofBase.roofBaseCd,
illuminationTp: managementState?.surfaceTypeValue ?? '',
instHt: managementState?.installHeight ?? '',
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
stdSnowLd: +managementState?.verticalSnowCover ?? '',
inclCd: selectedRoof?.pitch ?? 0,
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
constTp: constructionList[index].constTp,
snowGdPossYn: constructionList[index].snowGdPossYn,
cvrYn: constructionList[index].cvrYn,
mixMatlNo: selectedModules.mixMatlNo,
workingWidth: selectedRoof?.length?.toString() ?? '',
},
})
setCvrYn(constructionList[index].cvrYn)
setSnowGdPossYn(constructionList[index].snowGdPossYn)
setCvrChecked(false)
setSnowGdChecked(false)
}
}
const handleChangeRoofMaterial = (index) => {
const newAddedRoofs = roofs.map((roof, i) => {
if (i === selectedRoof.index) {
return {
...selectedRoof,
hajebichi,
lenBase: lengthBase,
eavesMargin,
ridgeMargin,
kerabaMargin,
roofIndex: selectedRoof.index,
trestle: {
hajebichi: hajebichi,
length: lengthBase,
...selectedRaftBase,
...selectedTrestle,
...selectedConstMthd,
...selectedRoofBase,
},
construction: {
...constructionList.find((data) => data.constTp === trestleState.constTp),
cvrYn: cvrYn,
snowGdPossYn: snowGdPossYn,
cvrChecked: cvrChecked,
snowGdChecked: snowGdChecked,
},
trestleDetail: trestleDetail,
}
}
return roof
})
setRoofs(newAddedRoofs)
setSelectedRoof(newAddedRoofs[index])
}
const isComplete = async () => {
const newAddedRoofs = roofs.map((roof, i) => {
if (i === selectedRoof?.index) {
return {
...selectedRoof,
length: lengthBase,
eavesMargin,
ridgeMargin,
kerabaMargin,
roofIndex: roof.index,
trestle: {
length: lengthBase,
hajebichi: hajebichi,
...selectedRaftBase,
...selectedTrestle,
...selectedConstMthd,
...selectedRoofBase,
},
construction: {
...constructionList.find((data) => data.constTp === trestleState.constTp),
cvrYn,
snowGdPossYn,
cvrChecked,
snowGdChecked,
setupCover: cvrChecked,
setupSnowCover: snowGdChecked,
},
trestleDetail: trestleDetail,
}
}
return roof
})
let result = true
console.log(newAddedRoofs)
for (let i = 0; i < newAddedRoofs.length; i++) {
const roof = newAddedRoofs[i]
if (!roof.trestle?.trestleMkrCd) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error1', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
if (!roof.trestle?.constMthdCd) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error2', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
if (!roof.trestle?.roofBaseCd) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error3', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
if (!roof.construction?.constTp) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error4', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
if (roof.lenAuth === 'C') {
if (!roof.trestle?.length) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error5', [roof.nameJp]), // L .
icon: 'warning',
})
result = false
return false
}
}
if (['C', 'R'].includes(roof.raftAuth)) {
if (!roof?.raftBaseCd) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error6', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
}
if (['C', 'R'].includes(roof.roofPchAuth)) {
if (!roof?.roofPchBase) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error7', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
}
if (!roof?.eavesMargin || !roof?.ridgeMargin || !roof?.kerabaMargin) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error8', [roof.nameJp]), // .
icon: 'warning',
})
result = false
return false
}
if (roof.trestle.trestleMkrCd !== 'NO_DATA') {
//
if (roof.trestleDetail?.eaveIntvl > roof.eavesMargin) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error9', [roof.trestleDetail?.eaveIntvl, roof.nameJp]), // {0}mm .
icon: 'warning',
})
result = false
return false
}
if (roof.trestleDetail?.ridgeIntvl > roof.ridgeMargin) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error10', [roof.trestleDetail?.ridgeIntvl, roof.nameJp]), // {0}mm .
icon: 'warning',
})
result = false
return false
}
if (roof.trestleDetail?.kerabaIntvl > roof.kerabaMargin) {
Swal.fire({
title: getMessage('modal.module.basic.settting.module.error11', [roof.trestleDetail?.kerabaIntvl, roof.nameJp]), // {0}mm .
icon: 'warning',
})
result = false
return false
}
}
}
if (result) {
const newRoofs = newAddedRoofs.map((roof) => {
const { addRoof, construction, trestle, trestleDetail, roofConstructions, ...rest } = roof
return rest
})
setModuleSelectionData({
...moduleSelectionData,
roofConstructions: newAddedRoofs.map((roof, index) => ({
roofIndex: newRoofs[index].index,
trestle: roof.trestle,
addRoof: newRoofs[index],
construction: roof.construction,
trestleDetail: roof.trestleDetail,
})),
})
setFlag(true)
tempModuleSelectionData.current = {
...moduleSelectionData,
roofConstructions: newAddedRoofs.map((roof, index) => ({
roofIndex: newRoofs[index].index,
trestle: roof.trestle,
addRoof: newRoofs[index],
construction: roof.construction,
trestleDetail: roof.trestleDetail,
})),
}
const updatePromises = [
// new Promise((resolve) => {
// resolve()
// }),
new Promise((resolve) => {
setRoofs(newRoofs)
resolve()
}),
new Promise((resolve) => {
const roofConstruction = newAddedRoofs.map((roof, index) => ({
roofIndex: newRoofs[index].index,
addRoof: newRoofs[index],
trestle: {
...roof.trestle,
raftBaseCd: roof.raftBaseCd,
},
construction: {
// ...constructionList.find((construction) => newAddedRoofs[index].construction.constTp === construction.constTp),
...roof.construction,
roofIndex: roof.index,
selectedIndex: roof.index,
},
trestleDetail: roof.trestleDetail,
}))
trestleTrigger({
roofConstruction,
})
setRoofsStore(roofConstruction)
resolve()
}),
]
await Promise.all(updatePromises)
return true
}
return false
}
const onMarginCheck = (target, data) => {}
useImperativeHandle(ref, () => ({
isComplete,
}))
return (
<div className="roof-module-tab2-overflow">
<div className="module-table-box mb10">
<div className="module-box-tab">
{roofs &&
roofs.map((roof, index) => (
<button
key={index}
className={`module-btn ${selectedRoof?.index === index ? 'act' : ''}`}
onClick={() => (roof ? handleChangeRoofMaterial(index) : null)}
>
{roof !== undefined ? `${roof.nameJp} (${currentAngleType === 'slope' ? roof.pitch : roof.angle}${pitchText})` : '-'}
</button>
))}
</div>
<div className="module-table-inner">
<div className="module-table-flex-wrap tab2">
<div className="module-flex-item">
<div className="eaves-keraba-table">
{selectedRoof && selectedRoof.lenAuth === 'C' && (
<>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">L</div>
<div className="eaves-keraba-td">
<div className="grid-select">
<input
type="text"
className="input-origin block"
value={lengthBase}
onChange={(e) => setLengthBase(e.target.value)}
disabled={selectedRoof.lenAuth === 'R'}
/>
</div>
</div>
</div>
</>
)}
{selectedRoof && ['C', 'R'].includes(selectedRoof.raftAuth) && (
<>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.rafter.margin')}</div>
<div className="eaves-keraba-td">
<div className="grid-select">
{raftBaseList.length > 0 && (
<QSelectBox
options={raftBaseList}
value={selectedRaftBase}
sourceKey={'clCode'}
targetKey={'clCode'}
showKey={'clCodeNm'}
disabled={selectedRoof.raftAuth === 'R'}
onChange={(e) => onChangeRaftBase(e)}
/>
)}
</div>
</div>
</div>
</>
)}
{selectedRoof && ['C', 'R'].includes(selectedRoof.roofPchAuth) && (
<>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.hajebichi')}</div>
<div className="eaves-keraba-td">
<div className="grid-select">
<input
type="text"
className="input-origin block"
disabled={selectedRoof.roofPchAuth === 'R'}
onChange={(e) => setHajebichi(e.target.value)}
value={hajebichi}
/>
</div>
</div>
</div>
</>
)}
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.trestle.maker')}</div>
<div className="eaves-keraba-td">
<div className="grid-select">
{trestleList && (
<QSelectBox
title={getMessage('selectbox.title')}
options={trestleList}
value={selectedTrestle}
sourceKey={'trestleMkrCd'}
targetKey={'trestleMkrCd'}
showKey={'trestleMkrCdJp'}
onChange={(e) => onChangeTrestleMaker(e)}
/>
)}
</div>
</div>
</div>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.construction.method')}</div>
<div className="eaves-keraba-td">
<div className="grid-select">
{constMthdList && (
<QSelectBox
title={getMessage('selectbox.title')}
options={constMthdList}
value={selectedConstMthd}
sourceKey={'constMthdCd'}
targetKey={'constMthdCd'}
showKey={'constMthdCdJp'}
onChange={(e) => onChangeConstMthd(e)}
/>
)}
</div>
</div>
</div>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.under.roof')}</div>
<div className="eaves-keraba-td">
<div className="grid-select">
{roofBaseList && (
<QSelectBox
title={getMessage('selectbox.title')}
options={roofBaseList}
sourceKey={'roofBaseCd'}
targetKey={'roofBaseCd'}
showKey={'roofBaseCdJp'}
value={selectedRoofBase}
onChange={(e) => onChangeRoofBase(e)}
/>
)}
</div>
</div>
</div>
</div>
</div>
<div className="module-flex-item non-flex">
<div className="flex-item-btn-wrap">
<button className={`btn-frame roof ${getConstructionState(0)}`} onClick={() => handleConstruction(0)}>
{getMessage('modal.module.basic.setting.module.standard.construction')}(I)
</button>
<button className={`btn-frame roof ${getConstructionState(3)}`} onClick={() => handleConstruction(3)}>
{getMessage('modal.module.basic.setting.module.multiple.construction')}
</button>
<button className={`btn-frame roof ${getConstructionState(1)}`} onClick={() => handleConstruction(1)}>
{getMessage('modal.module.basic.setting.module.standard.construction')}
</button>
<button className={`btn-frame roof ${getConstructionState(4)}`} onClick={() => handleConstruction(4)}>
{getMessage('modal.module.basic.setting.module.multiple.construction')}(II)
</button>
<button className={`btn-frame roof ${getConstructionState(2)}`} onClick={() => handleConstruction(2)}>
{getMessage('modal.module.basic.setting.module.enforce.construction')}
</button>
</div>
<div className="grid-check-form-flex">
<div className="d-check-box pop">
<input
type="checkbox"
id={`ch01`}
disabled={!cvrYn || cvrYn === 'N'}
checked={cvrChecked || false}
// onChange={() => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, cvrChecked: !trestleState.cvrChecked } })}
onChange={() => setCvrChecked(!cvrChecked)}
/>
<label htmlFor={`ch01`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
</div>
<div className="d-check-box pop">
<input
type="checkbox"
id={`ch02`}
disabled={!snowGdPossYn || snowGdPossYn === 'N'}
checked={snowGdChecked || false}
// onChange={() => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, snowGdChecked: !trestleState.snowGdChecked } })}
onChange={() => setSnowGdChecked(!snowGdChecked)}
/>
<label htmlFor={`ch02`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
</div>
</div>
</div>
</div>
<div className="module-area mt10">
<div className="module-area-title">{getMessage('modal.module.basic.setting.module.placement.area')}</div>
<div className="outline-form mr15">
<span>{getMessage('modal.module.basic.setting.module.placement.area.eaves')}</span>
<div className="input-grid mr10">
<input
type="text"
className="input-origin block"
value={eavesMargin ?? 0}
// onChange={(e) => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, eavesMargin: e.target.value } })}
onChange={(e) => setEavesMargin(+e.target.value)}
/>
</div>
<span className="thin">mm</span>
</div>
<div className="outline-form mr15">
<span>{getMessage('modal.module.basic.setting.module.placement.area.ridge')}</span>
<div className="input-grid mr10">
<input
type="text"
className="input-origin block"
value={ridgeMargin ?? 0}
// onChange={(e) => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, ridgeMargin: e.target.value } })}
onChange={(e) => setRidgeMargin(+e.target.value)}
/>
</div>
<span className="thin">mm</span>
</div>
<div className="outline-form ">
<span>{getMessage('modal.module.basic.setting.module.placement.area.keraba')}</span>
<div className="input-grid mr10">
<input
type="text"
className="input-origin block"
value={kerabaMargin ?? 0}
// onChange={(e) => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, kerabaMargin: e.target.value } })}
onChange={(e) => setKerabaMargin(+e.target.value)}
/>
</div>
<span className="thin">mm</span>
</div>
</div>
</div>
</div>
<div className="module-bottom">
<div className="module-table-box ">
<div className="warning-guide">
<div className="warning">
{getMessage('modal.module.basic.setting.module.setting.info1')}
<br />
{getMessage('modal.module.basic.setting.module.setting.info2')}
</div>
</div>
</div>
</div>
</div>
)
})
export default Trestle

View File

@ -33,14 +33,6 @@ const PitchPlacement = forwardRef((props, refs) => {
setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked })
}
const moduleData = {
header: [
{ type: 'check', name: '', prop: 'check', width: 70 },
{ type: 'color-box', name: getMessage('module'), prop: 'module' },
{ type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 },
],
}
//
useEffect(() => {
const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key])
@ -105,87 +97,91 @@ const PitchPlacement = forwardRef((props, refs) => {
return (
<>
<div className="module-table-box mb10">
<div className="module-table-inner">
<div className="roof-module-table">
<table>
<thead>
<tr>
{moduleData.header.map((data) => (
<th key={data.prop} style={{ width: data.width ? data.width : '' }}>
{data.type === 'check' ? (
<div className="d-check-box no-text pop">
<input type="checkbox" id="ch01" disabled />
<label htmlFor="ch01"></label>
</div>
) : (
data.name
)}
<div className="hexagonal-flex-wrap">
<div className="module-table-box ">
<div className="module-table-inner">
<div className="roof-module-table">
<table>
<thead>
<tr>
<th style={{ width: '70px' }}>
<div className="d-check-box no-text pop">
<input type="checkbox" id="ch01" disabled />
<label htmlFor="ch01"></label>
</div>
</th>
))}
</tr>
</thead>
<tbody>
{selectedModules.itemList &&
selectedModules.itemList.map((item, index) => (
<tr key={index}>
<td className="al-c">
<div className="d-check-box no-text pop">
<input
type="checkbox"
id={item.itemId}
name={item.itemId}
checked={selectedItems[item.itemId]}
onChange={handleSelectedItem}
/>
<label htmlFor={item.itemId}></label>
</div>
</td>
<td>
<div className="color-wrap">
<span className="color-box" style={{ backgroundColor: item.color }}></span>
<span className="name">{item.itemNm}</span>
</div>
</td>
<td className="al-r">{item.wpOut}</td>
</tr>
))}
</tbody>
</table>
<th>{getMessage('module')}</th>
</tr>
</thead>
<tbody>
{selectedModules.itemList &&
selectedModules.itemList.map((item, index) => (
<tr key={index}>
<td className="al-c">
<div className="d-check-box no-text pop">
<input
type="checkbox"
id={item.itemId}
name={item.itemId}
checked={selectedItems[item.itemId]}
onChange={handleSelectedItem}
/>
<label htmlFor={item.itemId}></label>
</div>
</td>
<td>
<div className="color-wrap">
<span className="color-box" style={{ backgroundColor: item.color }}></span>
<span className="name">{item.itemNm}</span>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
</div>
<div className="module-table-box mb10">
<div className="module-table-inner">
<div className="hexagonal-wrap">
<div className="hexagonal-item">
<div className="bold-font">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting')}</div>
</div>
<div className="hexagonal-item">
<div className="pop-form-radio">
<div className="d-check-radio pop">
<input
type="radio"
name="radio01"
id="ra01"
value={'south'}
defaultChecked={setupLocation === 'south'}
onClick={handleSetupLocation}
/>
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
</div>
<div className="d-check-radio pop">
<input
type="radio"
name="radio01"
id="ra02"
value={'excreta'}
defaultChecked={setupLocation === 'excreta'}
onClick={handleSetupLocation}
/>
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
</div>
</div>
<div className="module-table-box non-flex">
<div className="module-table-inner">
<div className="roof-module-table">
<table>
<thead>
<tr>
<th>{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting')}</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div className="hexagonal-radio-wrap">
<div className="d-check-radio pop mb10">
<input
type="radio"
name="radio01"
id="ra01"
value={'south'}
defaultChecked={setupLocation === 'south'}
onClick={handleSetupLocation}
/>
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
</div>
<div className="d-check-radio pop">
<input
type="radio"
name="radio01"
id="ra02"
value={'excreta'}
defaultChecked={setupLocation === 'excreta'}
onClick={handleSetupLocation}
/>
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>

View File

@ -100,7 +100,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
]
return (
<WithDraggable isShow={true} pos={pos} className="lrr" style={{ visibility: isHidden ? 'hidden' : 'visible' }}>
<WithDraggable isShow={true} pos={pos} className="lrr" isHidden={isHidden}>
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.object')} onClose={() => closePopup(id)} />
<WithDraggable.Body>
<div className="modal-btn-wrap">

View File

@ -46,7 +46,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
const { setSurfaceShapePattern } = useRoofFn()
const canvas = useRecoilValue(canvasState)
const roofDisplay = useRecoilValue(roofDisplaySelector)
const { saveCanvas } = usePlan()
const roofRef = {
roofCd: useRef(null),
@ -55,7 +54,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
rafter: useRef(null),
hajebichi: useRef(null),
}
const { saveCanvas } = usePlan()
/**
* 치수 입력방법(복시도입력/실측값입력/육지붕)
*/
@ -263,8 +262,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
<WithDraggable isShow={true} pos={pos} className="ll">
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.initial.setting')} />
<WithDraggable.Body>
<div className="left-bar modal-handle"></div>
<div className="right-bar modal-handle"></div>
<div className="placement-table">
<table>
<colgroup>

View File

@ -1,6 +1,6 @@
'use client'
import { useRecoilState, useRecoilValue } from 'recoil'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import useSWRMutation from 'swr/mutation'
import { useAxios } from '../useAxios'
import { unescapeString } from '@/util/common-utils'
@ -10,6 +10,8 @@ import { canvasState, currentCanvasPlanState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
import { useCircuitTrestle } from '../useCirCuitTrestle'
import { useEffect } from 'react'
import { addedRoofsState } from '@/store/settingAtom'
import { roofsState } from '@/store/roofAtom'
/**
* 캔버스 팝업 상태 관리
@ -19,13 +21,14 @@ import { useEffect } from 'react'
export function useCanvasPopupStatusController(param = 1) {
const popupType = parseInt(param)
const [compasDeg, setCompasDeg] = useRecoilState(compasDegAtom)
const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState)
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState)
const setCompasDeg = useSetRecoilState(compasDegAtom)
const setModuleSelectionDataStore = useSetRecoilState(moduleSelectionDataState)
const setSelectedModules = useSetRecoilState(selectedModuleState)
const { get, promiseGet, getFetcher, postFetcher } = useAxios()
const canvas = useRecoilValue(canvasState)
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
const [roofs, setRoofs] = useRecoilState(roofsState)
/**
* 팝업 상태 조회
* @param {number} popupTypeParam
@ -53,19 +56,27 @@ export function useCanvasPopupStatusController(param = 1) {
const handleModuleSelectionTotal = async () => {
for (let i = 1; i < 3; i++) {
const result = await getModuleSelection(i)
console.log('🚀 ~ handleModuleSelectionTotal ~ result:', result)
if (!result.objectNo) return
if (i === 1) {
setCompasDeg(result.popupStatus)
if (result.popupStatus && unescapeString(result.popupStatus)) {
const data = JSON.parse(unescapeString(result.popupStatus))
if (data?.compasDeg) setCompasDeg(data.compasDeg)
if (data?.module) setSelectedModules(data.module)
setModuleSelectionDataStore(data)
}
} else if (i === 2) {
const data = JSON.parse(unescapeString(result.popupStatus))
setModuleSelectionDataStore(data)
const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
roofSurfaceList.forEach((surface) => {
surface.modules = modules.filter((module) => module.surfaceId === surface.id)
})
if (data.module) setSelectedModules(data.module)
if (data.roofConstruction) {
setRoofs(data.roofConstruction)
// setManagementState({ ...managementState, roofs: data.roofConstruction.map((roof) => roof.construction.managementState) })
}
// if (data?.module) setManagementState(data.common.managementState)
}
}
}
@ -80,7 +91,8 @@ export function useCanvasPopupStatusController(param = 1) {
objectNo: currentCanvasPlan.objectNo,
planNo: parseInt(currentCanvasPlan.planNo),
popupType: popupType.toString(),
popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'),
// popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'),
popupStatus: JSON.stringify(arg).replace(/"/g, '\"'),
}
postFetcher(`/api/v1/canvas-popup-status`, params)
},

File diff suppressed because it is too large Load Diff

View File

@ -13,22 +13,19 @@ import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
export function useModuleSelection(props) {
const canvas = useRecoilValue(canvasState)
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록
const [moduleList, setModuleList] = useState([{}]) //모듈 목록
const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도
const [installHeight, setInstallHeight] = useState() //설치 높이
const [standardWindSpeed, setStandardWindSpeed] = useState({}) //기준풍속
const [verticalSnowCover, setVerticalSnowCover] = useState() //수직적설량
const [installHeight, setInstallHeight] = useState(managementState?.installHeight) //설치 높이
const [standardWindSpeed, setStandardWindSpeed] = useState() //기준풍속
const [verticalSnowCover, setVerticalSnowCover] = useState(managementState?.verticalSnowCover) //수직적설량
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
const [margin, setMargin] = useState(100)
const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
const { getModuleTypeItemList } = useMasterController()
const { findCommonCode } = useCommonCode()
const resetStatisticsData = useResetRecoilState(moduleStatisticsState)
const { restoreModuleInstArea } = useModuleBasicSetting()
const bindInitData = () => {
@ -95,7 +92,7 @@ export function useModuleSelection(props) {
getModuleData(roofsIds)
//모듈설치면 초기화
restoreModuleInstArea()
// restoreModuleInstArea()
resetStatisticsData()
}, [])
@ -184,14 +181,6 @@ export function useModuleSelection(props) {
})
}
useEffect(() => {
// console.log('installHeight', installHeight)
}, [installHeight])
useEffect(() => {
// console.log('verticalSnowCover', verticalSnowCover)
}, [verticalSnowCover])
//TODO: 설치높이, 기준적설량 debounce 적용해서 추가해야됨
// useEffect(() => {
@ -226,11 +215,17 @@ export function useModuleSelection(props) {
roughnessCodes,
windSpeedCodes,
managementState,
setManagementState,
moduleList,
setSelectedModules,
selectedSurfaceType,
setSelectedSurfaceType,
installHeight,
setInstallHeight,
standardWindSpeed,
setStandardWindSpeed,
verticalSnowCover,
setVerticalSnowCover,
handleChangeModule,
handleChangeSurfaceType,
handleChangeWindSpeed,

View File

@ -0,0 +1,288 @@
import { use, useContext, useEffect, useReducer, useState } from 'react'
import { useCommonCode } from '../common/useCommonCode'
import { useMasterController } from '../common/useMasterController'
import { selectedModuleState } from '@/store/selectedModuleOptions'
import { useRecoilState, useRecoilValue } from 'recoil'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { popSpinnerState } from '@/store/popupAtom'
const RAFT_BASE_CODE = '203800'
const trestleReducer = (state, action) => {
switch (action.type) {
case 'SET_RAFT_BASE':
case 'SET_TRESTLE_MAKER':
case 'SET_CONST_MTHD':
case 'SET_ROOF_BASE':
case 'SET_CONSTRUCTION':
case 'SET_TRESTLE_DETAIL':
return {
...action.roof,
}
case 'SET_INITIALIZE':
return {
moduleTpCd: action.roof.module?.itemTp ?? '',
roofMatlCd: action.roof?.roofMatlCd ?? '',
hajebichi: action.roof?.hajebichi ?? 0,
raftBaseCd: action.roof?.raftBaseCd ?? null,
trestleMkrCd: action.roof.trestle?.trestleMkrCd ?? null,
constMthdCd: action.roof.trestle?.constMthdCd ?? null,
constTp: action.roof.construction?.constTp ?? null,
roofBaseCd: action.roof.trestle?.roofBaseCd ?? null,
workingWidth: action.roof.workingWidth ?? 0,
lengthBase: action.roof?.length ?? 0,
illuminationTp: action.roof.common?.illuminationTp ?? null,
instHt: action.roof.common?.instHt ?? null,
stdWindSpeed: action.roof.common?.stdWindSpeed ?? null,
stdSnowLd: action.roof.common?.stdSnowLd ?? null,
inclCd: action.roof?.pitch ?? null,
roofPitch: action.roof?.roofPchBase ?? 0,
eavesMargin: action.roof?.eavesMargin ?? null,
ridgeMargin: action.roof?.ridgeMargin ?? null,
kerabaMargin: action.roof?.kerabaMargin ?? null,
}
default:
return state
}
}
export function useModuleTrestle(props) {
const { selectedRoof } = props
const { findCommonCode } = useCommonCode()
const [raftBaseList, setRaftBaseList] = useState([])
const [trestleList, setTrestleList] = useState([])
const [constMthdList, setConstMthdList] = useState([])
const [roofBaseList, setRoofBaseList] = useState([])
const [constructionList, setConstructionList] = useState([])
const { getTrestleList, getConstructionList, getTrestleDetailList } = useMasterController()
const [lengthBase, setLengthBase] = useState(0)
const [hajebichi, setHajebichi] = useState(0)
const [cvrYn, setCvrYn] = useState('N')
const [cvrChecked, setCvrChecked] = useState(false)
const [snowGdPossYn, setSnowGdPossYn] = useState('N')
const [snowGdChecked, setSnowGdChecked] = useState(false)
const [eavesMargin, setEavesMargin] = useState(0)
const [ridgeMargin, setRidgeMargin] = useState(0)
const [kerabaMargin, setKerabaMargin] = useState(0)
const [trestleState, dispatch] = useReducer(trestleReducer, null)
const [trestleDetail, setTrestleDetail] = useState(null)
const [popSpinnerStore, setPopSpinnerStore] = useRecoilState(popSpinnerState)
useEffect(() => {
const raftCodeList = findCommonCode(RAFT_BASE_CODE)
setRaftBaseList(raftCodeList)
setTrestleList([])
setConstMthdList([])
setRoofBaseList([])
setConstructionList([])
// setEavesMargin(selectedRoof?.addRoof?.eavesMargin ?? 0)
// setRidgeMargin(selectedRoof?.addRoof?.ridgeMargin ?? 0)
// setKerabaMargin(selectedRoof?.addRoof?.kerabaMargin ?? 0)
setHajebichi(selectedRoof?.hajebichi ?? 0)
setEavesMargin(selectedRoof?.eavesMargin ?? 0)
setRidgeMargin(selectedRoof?.ridgeMargin ?? 0)
setKerabaMargin(selectedRoof?.kerabaMargin ?? 0)
setLengthBase(Math.round(selectedRoof?.length ?? 0))
setCvrYn(selectedRoof?.construction?.cvrYn ?? 'N')
setCvrChecked(selectedRoof?.construction?.cvrChecked ?? false)
setSnowGdPossYn(selectedRoof?.construction?.snowGdPossYn ?? 'N')
setSnowGdChecked(selectedRoof?.construction?.snowGdChecked ?? false)
setTrestleDetail(selectedRoof?.trestleDetail)
}, [selectedRoof])
useEffect(() => {
if (trestleState) {
handleSetTrestleList()
if (!trestleState?.trestleMkrCd) {
setConstMthdList([])
setRoofBaseList([])
setConstructionList([])
setTrestleDetail(null)
return
}
handleSetConstMthdList()
if (!trestleState?.constMthdCd) {
setRoofBaseList([])
setConstructionList([])
setTrestleDetail(null)
return
}
handleSetRoofBaseList()
if (!trestleState?.roofBaseCd) {
setConstructionList([])
setTrestleDetail(null)
return
}
handleSetConstructionList()
if (!trestleState?.constTp) {
setTrestleDetail(null)
return
}
if (!trestleState?.eavesMargin) {
handleSetTrestleDetailData()
}
}
}, [trestleState])
const handleSetTrestleList = () => {
setPopSpinnerStore(true)
getTrestleList({
moduleTpCd: trestleState?.moduleTpCd ?? '',
roofMatlCd: trestleState?.roofMatlCd ?? '',
raftBaseCd: trestleState?.raftBaseCd ?? '',
})
.then((res) => {
if (res?.data) setTrestleList(res.data)
setPopSpinnerStore(false)
})
.catch((e) => {
setPopSpinnerStore(false)
})
}
const handleSetConstMthdList = () => {
setPopSpinnerStore(true)
getTrestleList({
moduleTpCd: trestleState?.moduleTpCd ?? '',
roofMatlCd: trestleState?.roofMatlCd ?? '',
raftBaseCd: trestleState?.raftBaseCd ?? '',
trestleMkrCd: trestleState?.trestleMkrCd ?? '',
})
.then((res) => {
if (res?.data) setConstMthdList(res.data)
setPopSpinnerStore(false)
})
.catch((e) => {
setPopSpinnerStore(false)
})
}
const handleSetRoofBaseList = () => {
setPopSpinnerStore(true)
getTrestleList({
moduleTpCd: trestleState?.moduleTpCd ?? '',
roofMatlCd: trestleState?.roofMatlCd ?? '',
raftBaseCd: trestleState?.raftBaseCd ?? '',
trestleMkrCd: trestleState?.trestleMkrCd ?? '',
constMthdCd: trestleState?.constMthdCd ?? '',
})
.then((res) => {
if (res?.data) setRoofBaseList(res.data)
setPopSpinnerStore(false)
})
.catch((e) => {
setPopSpinnerStore(false)
})
}
const handleSetConstructionList = () => {
setPopSpinnerStore(true)
getConstructionList({
moduleTpCd: trestleState?.moduleTpCd ?? '',
roofMatlCd: trestleState?.roofMatlCd ?? '',
trestleMkrCd: trestleState?.trestleMkrCd ?? '',
constMthdCd: trestleState?.constMthdCd ?? '',
roofBaseCd: trestleState?.roofBaseCd ?? '',
illuminationTp: trestleState.illuminationTp ?? '',
instHt: trestleState.instHt ?? '',
stdWindSpeed: trestleState.stdWindSpeed ?? '',
stdSnowLd: trestleState.stdSnowLd ?? '',
inclCd: trestleState.inclCd ?? '',
raftBaseCd: trestleState.raftBaseCd ?? '',
roofPitch: Math.round(trestleState.roofPitch) ?? '',
})
.then((res) => {
if (res?.data) setConstructionList(res.data)
setPopSpinnerStore(false)
})
.catch((e) => {
setPopSpinnerStore(false)
})
}
const handleSetTrestleDetailData = () => {
setPopSpinnerStore(true)
getTrestleDetailList([
{
moduleTpCd: trestleState.moduleTpCd ?? '',
roofMatlCd: trestleState.roofMatlCd ?? '',
trestleMkrCd: trestleState.trestleMkrCd ?? '',
constMthdCd: trestleState.constMthdCd ?? '',
roofBaseCd: trestleState.roofBaseCd ?? '',
illuminationTp: trestleState.illuminationTp ?? '',
instHt: trestleState.instHt ?? '',
stdWindSpeed: trestleState.stdWindSpeed ?? '',
stdSnowLd: trestleState.stdSnowLd ?? '',
inclCd: trestleState.inclCd ?? '',
constTp: trestleState.constTp ?? '',
mixMatlNo: trestleState.mixMatlNo ?? '',
roofPitch: trestleState.roofPitch ?? '',
workingWidth: trestleState.workingWidth ?? '',
},
])
.then((res) => {
if (res.length > 0) {
if (!res[0].data) return
setEavesMargin(res[0].data.eaveIntvl)
setRidgeMargin(res[0].data.ridgeIntvl)
setKerabaMargin(res[0].data.kerabaIntvl)
setTrestleDetail(res[0].data)
// dispatch({
// type: 'SET_TRESTLE_DETAIL',
// roof: {
// ...trestleState,
// eavesMargin: res[0].data.eaveIntvl,
// ridgeMargin: res[0].data.ridgeIntvl,
// kerabaMargin: res[0].data.kerabaIntvl,
// },
// })
}
setPopSpinnerStore(false)
})
.catch((e) => {
setPopSpinnerStore(false)
})
}
return {
trestleState,
trestleDetail,
dispatch,
raftBaseList,
trestleList,
constMthdList,
roofBaseList,
constructionList,
handleSetTrestleList,
handleSetConstMthdList,
handleSetRoofBaseList,
handleSetConstructionList,
handleSetTrestleDetailData,
lengthBase,
setLengthBase,
hajebichi,
setHajebichi,
cvrYn,
cvrChecked,
snowGdPossYn,
snowGdChecked,
eavesMargin,
ridgeMargin,
kerabaMargin,
setEavesMargin,
setRidgeMargin,
setKerabaMargin,
setCvrYn,
setCvrChecked,
setSnowGdPossYn,
setSnowGdChecked,
}
}

View File

@ -22,8 +22,8 @@ export function useOrientation() {
})
}, [])*/
const nextStep = () => {
if (isNaN(compasDeg)) {
const nextStep = (compas = compasDeg) => {
if (isNaN(compas)) {
setCompasDeg(0)
}
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
@ -36,7 +36,7 @@ export function useOrientation() {
roofs.forEach((roof) => {
roof.set({
moduleCompass: isNaN(compasDeg) ? 0 : compasDeg,
moduleCompass: isNaN(compas) ? 0 : compas,
})
drawDirectionArrow(roof)
})

View File

@ -371,11 +371,16 @@ export const useTrestle = () => {
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
//C1C2C3인 경우
let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo)
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === leftRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === leftRowsInfo.rowsInfo[1].count
rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
newLeftRowsInfo.rowsInfo.every((row, index) => {
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
return rackRowCount === row.count
})
)
}
})?.value.racks
@ -388,11 +393,15 @@ export const useTrestle = () => {
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo)
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === rightRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === rightRowsInfo.rowsInfo[1].count
rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
newRightRowsInfo.rowsInfo.every((row, index) => {
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
return rackRowCount === row.count
})
)
}
})?.value.racks
@ -405,11 +414,15 @@ export const useTrestle = () => {
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
let newCenterRowsInfo = normalizeModules(rack.value.moduleTpCd, centerRowsInfo)
return (
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === centerRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === centerRowsInfo.rowsInfo[1].count
rack.value.moduleTpCd === newCenterRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newCenterRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
newCenterRowsInfo.rowsInfo.every((row, index) => {
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
return rackRowCount === row.count
})
)
}
})?.value.racks
@ -500,11 +513,15 @@ export const useTrestle = () => {
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo)
return (
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === leftRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === leftRowsInfo.rowsInfo[1].count
rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
newLeftRowsInfo.rowsInfo.every((row, index) => {
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
return rackRowCount === row.count
})
)
}
})?.value.racks
@ -576,11 +593,16 @@ export const useTrestle = () => {
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
)
} else {
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo)
return (
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
Number(rack.value.moduleTpRows1) === rightRowsInfo.rowsInfo[0].count &&
Number(rack.value.moduleTpRows2) === rightRowsInfo.rowsInfo[1].count
rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp &&
rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
newRightRowsInfo.rowsInfo.every((row, index) => {
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
return rackRowCount === row.count
})
)
}
})?.value.racks
@ -635,6 +657,31 @@ export const useTrestle = () => {
return { moduleTotalTp, rowsInfo }
}
function normalizeModules(rackTpCd, data) {
// rackTpCd를 숫자를 기준으로 자른다.
const allModules = rackTpCd.match(/[A-Za-z]+\d+/g) || [] // 모든 모듈 유형
// 현재 존재하는 모듈 유형을 추출
const existingModules = data.rowsInfo.map((row) => row.moduleTpCd)
const result = { ...data, rowsInfo: [...data.rowsInfo] }
// 없는 모듈을 추가 (count: 0)
allModules.forEach((module) => {
if (!existingModules.includes(module)) {
result.rowsInfo.push({ moduleTpCd: module, count: 0 })
}
})
// rowsInfo를 C1, C2, C3 순서로 정렬
result.rowsInfo.sort((a, b) => allModules.indexOf(a.moduleTpCd) - allModules.indexOf(b.moduleTpCd))
// moduleTotalTp를 C1C2C3로 설정
result.moduleTotalTp = allModules.join('')
return result
}
// itemList 조회 후 estimateParam에 저장
const getEstimateData = async () => {
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
@ -661,13 +708,18 @@ export const useTrestle = () => {
})
// trestles 배열에서 null인 경우 제거
const params = { trestles, pcses, modules }
const dblCblTotCnt = getTotalConnectCableCnt()
const params = { trestles, pcses, modules, dblCblTotCnt }
//견적서 itemList 조회
const { data, data2, result } = await getQuotationItem(params)
if (result.resultCode === 'E') {
swalFire({ text: result.resultMsg, icon: 'error' })
clear()
setViewCircuitNumberTexts(true)
setIsGlobalLoading(false)
return
}
@ -2129,12 +2181,13 @@ export const useTrestle = () => {
const visited = new Set()
const width = Math.floor(moduleExample.width)
const height = Math.floor(moduleExample.height)
const horizonPadding = 0 // 가로 패딩
const verticalPadding = 0 // 세로 패딩
const horizonPadding = 3 // 가로 패딩
const verticalPadding = 7 // 세로 패딩
function isAdjacent(p1, p2) {
const dx = Math.abs(p1.x - p2.x)
const dy = Math.abs(p1.y - p2.y)
return (
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
@ -2166,6 +2219,128 @@ export const useTrestle = () => {
return groups
}
function areConnected(m1, m2, surface) {
/*const m1Fill = m1.fill
const m2Fill = m2.fill
m1.set({ fill: 'red' })
m2.set({ fill: 'blue' })
canvas.renderAll()*/
let sizes = []
const { width: currentWidth, height: currentHeight, moduleInfo: currentModuleInfo } = m1
const { width: neighborWidth, height: neighborHeight, moduleInfo: neighborModuleInfo } = m2
const { moduleTpCd: currentModuleTpCd } = currentModuleInfo
const { moduleTpCd: neighborModuleTpCd } = neighborModuleInfo
const { x: m1X, y: m1Y } = m1.getCenterPoint()
const { x: m2X, y: m2Y } = m2.getCenterPoint()
sizes.push({ width: currentWidth, height: currentHeight })
if (currentModuleTpCd !== neighborModuleTpCd) {
sizes.push({ width: neighborWidth, height: neighborHeight })
}
/*m1.set({ fill: m1Fill })
m2.set({ fill: m2Fill })
canvas.renderAll()*/
return sizes.some(({ width, height }) => {
let maxX
let maxY
let halfMaxX
let halfMaxY
const { direction, trestleDetail } = surface
const { moduleIntvlHor, moduleIntvlVer } = trestleDetail
if (direction === 'south' || direction === 'north') {
maxX = width + moduleIntvlHor / 10
maxY = height + moduleIntvlVer / 10
halfMaxX = moduleIntvlHor / 10
halfMaxY = moduleIntvlVer / 10
if (currentModuleTpCd !== neighborModuleTpCd) {
maxX = currentWidth / 2 + neighborWidth / 2 + moduleIntvlHor / 10
maxY = currentHeight / 2 + neighborHeight / 2 + moduleIntvlVer / 10
}
// console.log(maxX, maxY, halfMaxX, halfMaxY)
if (Math.abs(m1X - m2X) < 1) {
return Math.abs(Math.abs(m1Y - m2Y) - maxY) < 1
} else if (Math.abs(m1Y - m2Y) < 1) {
return Math.abs(Math.abs(m1X - m2X) - maxX) < 1
}
return (
(Math.abs(m1X - m2X) < maxX - moduleIntvlHor / 10 && Math.abs(m1Y - m2Y) < maxY - moduleIntvlVer / 10) ||
(Math.abs(Math.abs(m1X - m2X) - maxX / 2) < halfMaxX + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxY) < halfMaxY + 1) ||
(Math.abs(Math.abs(m1X - m2X) - maxX) < halfMaxX + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxY / 2) < halfMaxY + 1)
)
} else if (direction === 'east' || direction === 'west') {
maxX = height + moduleIntvlHor / 10
maxY = width + moduleIntvlVer / 10
halfMaxX = moduleIntvlVer / 10
halfMaxY = moduleIntvlHor / 10
if (currentModuleTpCd !== neighborModuleTpCd) {
maxX = currentHeight / 2 + neighborHeight / 2 + moduleIntvlVer / 10
maxY = currentWidth / 2 + neighborWidth / 2 + moduleIntvlHor / 10
}
if (Math.abs(m1X - m2X) < 1) {
return Math.abs(Math.abs(m1Y - m2Y) - maxX) < 1
} else if (Math.abs(m1Y - m2Y) < 1) {
return Math.abs(Math.abs(m1X - m2X) - maxY) < 1
}
return (
(Math.abs(m1X - m2X) <= maxY - moduleIntvlVer / 10 && Math.abs(m1Y - m2Y) <= maxX - moduleIntvlHor / 10) ||
(Math.abs(Math.abs(m1X - m2X) - maxY / 2) < halfMaxY + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxX) < halfMaxX + 1) ||
(Math.abs(Math.abs(m1X - m2X) - maxY) < halfMaxY + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxX / 2) < halfMaxX + 1)
)
}
})
}
// 25-04-02 추가
// 그룹화
function groupPoints(modules, surface) {
const groups = []
const visited = new Set()
for (const point of modules) {
const { x: pointX, y: pointY } = point.getCenterPoint()
const key = `${pointX},${pointY}`
if (visited.has(key)) continue
const queue = [point]
const group = []
while (queue.length > 0) {
const current = queue.shift()
const { x: currentX, y: currentY } = current.getCenterPoint()
const currentKey = `${currentX},${currentY}`
if (visited.has(currentKey)) continue
visited.add(currentKey)
group.push(current)
for (const neighbor of modules) {
const { x: neighborX, y: neighborY } = neighbor.getCenterPoint()
const neighborKey = `${neighborX},${neighborY}`
if (!visited.has(neighborKey) && areConnected(current, neighbor, surface)) {
queue.push(neighbor)
}
}
}
groups.push(group)
}
return groups
}
// 각도에 따른 길이 반환
function getTrestleLength(length, degree) {
if (roofSizeSet !== 1) {
@ -2863,5 +3038,82 @@ export const useTrestle = () => {
return surfaces.every((surface) => surface.isComplete)
}
return { apply, getTrestleParams, clear, setViewCircuitNumberTexts, getEstimateData, setAllModuleSurfaceIsComplete, isAllComplete }
const groupByType = (originArr = []) => {
const grouped = {}
const newArr = [...originArr]
// 타입별로 객체들을 분류
for (const item of newArr) {
if (!grouped[item.circuitNumber]) {
grouped[item.circuitNumber] = []
}
grouped[item.circuitNumber].push(item)
}
// 객체를 배열로 변환
return Object.values(grouped)
}
function groupByCircuitAndSurface(arr) {
const circuitGroups = {}
for (const item of arr) {
const { circuitNumber, surfaceId } = item
if (!circuitGroups[circuitNumber]) {
circuitGroups[circuitNumber] = new Map()
}
const surfaceMap = circuitGroups[circuitNumber]
const key = surfaceId
if (!surfaceMap.has(key)) {
surfaceMap.set(key, [])
}
surfaceMap.get(key).push(item)
}
// 결과: circuitNumber별 surface 그룹 수
const result = {}
for (const [circuit, surfaceMap] of Object.entries(circuitGroups)) {
result[circuit] = surfaceMap.size
}
return result
}
// 양단 케이블 구하는 공식
const getTotalConnectCableCnt = () => {
let cnt = 0
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
surfaces.forEach((surface) => {
const modules = surface.modules
const groups = groupByType(modules)
groups.forEach((group) => {
const result = groupPoints(group, surface)
cnt += result.length - 1
})
})
const groupByCircuitAndSurfaceCnt = groupByCircuitAndSurface(modules)
Object.keys(groupByCircuitAndSurfaceCnt).forEach((key) => {
cnt += groupByCircuitAndSurfaceCnt[key] - 1
})
return cnt
}
return {
apply,
getTrestleParams,
clear,
setViewCircuitNumberTexts,
getEstimateData,
setAllModuleSurfaceIsComplete,
isAllComplete,
groupCoordinates,
groupPoints,
}
}

View File

@ -123,6 +123,7 @@ export function useCanvasSetting(executeEffect = true) {
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */
const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */
const { trigger: orientationTrigger } = useCanvasPopupStatusController(1)
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */
@ -526,7 +527,10 @@ export function useCanvasSetting(executeEffect = true) {
/** 모듈 선택 데이터 초기화 */
resetModuleSelectionData()
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
//1번 초기화
orientationTrigger({ compasDeg: 0, common: {}, module: {} })
//2번 초기화
moduleSelectedDataTrigger({ roofConstructions: [] })
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
if (!isModuleExist) {
resetSelectedModules()

View File

@ -29,6 +29,7 @@ import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupSta
import { outerLinePointsState } from '@/store/outerLineAtom'
import { QcastContext } from '@/app/QcastProvider'
import { usePlan } from '@/hooks/usePlan'
import { roofsState } from '@/store/roofAtom'
export function useRoofAllocationSetting(id) {
const canvas = useRecoilValue(canvasState)
@ -55,7 +56,7 @@ export function useRoofAllocationSetting(id) {
const { setIsGlobalLoading } = useContext(QcastContext)
const { setSurfaceShapePattern } = useRoofFn()
const { saveCanvas } = usePlan()
const [roofsStore, setRoofsStore] = useRecoilState(roofsState)
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
const resetPoints = useResetRecoilState(outerLinePointsState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
@ -267,6 +268,8 @@ export function useRoofAllocationSetting(id) {
newRoofList[0].selected = true
}
setCurrentRoofList(newRoofList)
setRoofsStore(newRoofList)
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
}
/**
@ -307,12 +310,14 @@ export function useRoofAllocationSetting(id) {
setRoofList(newRoofList)
setRoofMaterials(newRoofList)
setRoofsStore(newRoofList)
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
drawDirectionArrow(currentObject)
modifyModuleSelectionData()
closeAll()
basicSettingSave()
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
}
/**
@ -421,7 +426,7 @@ export function useRoofAllocationSetting(id) {
})
setRoofMaterials(newRoofList)
setRoofsStore(newRoofList)
/** 외곽선 삭제 */
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
removeTargets.forEach((obj) => {
@ -445,7 +450,8 @@ export function useRoofAllocationSetting(id) {
})
/** 모듈 선택 데이터 초기화 */
modifyModuleSelectionData()
// modifyModuleSelectionData()
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
}
/**
@ -563,7 +569,7 @@ export function useRoofAllocationSetting(id) {
* 모듈 선택에서 선택한 데이터 초기화
*/
const modifyModuleSelectionData = () => {
if (moduleSelectionData.roofConstructions.length > 0) {
if (moduleSelectionData.roofConstructions?.length > 0) {
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: [] })
moduleSelectedDataTrigger({ ...moduleSelectionData, roofConstructions: [] })
}

View File

@ -31,7 +31,7 @@ export function useCircuitTrestle(executeEffect = false) {
const { getMessage } = useMessage()
useEffect(() => {
if (Object.keys(selectedModules).length > 0 && executeEffect) setModuleStatisticsData()
if (selectedModules && Object.keys(selectedModules).length > 0 && executeEffect) setModuleStatisticsData()
}, [selectedModules])
const getOptYn = () => {

View File

@ -77,10 +77,10 @@ export function useEvent() {
setCanvasZoom(Number((zoom * 100).toFixed(0)))
// 마우스 위치 기준으로 확대/축소
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom)
canvas.requestRenderAll()
canvas.zoomToPoint(new fabric.Point(opt.e.offsetX, opt.e.offsetY), zoom)
canvas.calcOffset()
canvas.setViewportTransform(canvas.viewportTransform)
canvas.requestRenderAll()
// 이벤트의 기본 동작 방지 (스크롤 방지)
opt.e.preventDefault()

View File

@ -114,6 +114,17 @@
"modal.module.basic.setting.module.eaves.bar.fitting": "軒カバーの設置",
"modal.module.basic.setting.module.blind.metal.fitting": "落雪防止金具設置",
"modal.module.basic.setting.module.select": "モジュール/架台選択",
"modal.module.basic.settting.module.error1": "架台メーカーを選択してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error2": "工法を選択してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error3": "屋根の下を選択してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error4": "施工法を選択してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error5": "L を選択してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error6": "垂木の間隔を入力してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error7": "下在ビーチを入力してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error8": "モジュール配置領域の値を入力してください。(屋根材: {0})(JA)",
"modal.module.basic.settting.module.error9": "軒側の値は{0} mm以上でなければなりません。(屋根材: {1})(JA)",
"modal.module.basic.settting.module.error10": "吊下側の値は{0} mm以上でなければなりません。(屋根材: {1})(JA)",
"modal.module.basic.settting.module.error11": "ケラバ側の値は{0} mm以上でなければなりません。(屋根材: {1})(JA)",
"modal.module.basic.setting.module.placement": "モジュールの配置",
"modal.module.basic.setting.module.placement.select.fitting.type": "設置形態を選択してください。",
"modal.module.basic.setting.module.placement.waterfowl.arrangement": "千鳥配置",
@ -128,9 +139,9 @@
"modal.module.basic.setting.module.placement.arrangement.standard.eaves": "軒側",
"modal.module.basic.setting.module.placement.arrangement.standard.ridge": "棟側",
"modal.module.basic.setting.module.placement.maximum": "最大配置",
"modal.module.basic.setting.pitch.module.placement.standard.setting": "配置基準設定",
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "南向き設置",
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "指定した辺を基準に設置",
"modal.module.basic.setting.pitch.module.placement.standard.setting": "配置基準設定",
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "南向き設置",
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "指定した辺を基準に設置する",
"modal.module.basic.setting.pitch.module.allocation.setting": "割り当て設定",
"modal.module.basic.setting.pitch.module.allocation.setting.info": "※配置パネルの種類が1種類の場合のみ使用できます。",
"modal.module.basic.setting.pitch.module.row.amount": "単数",
@ -138,6 +149,7 @@
"modal.module.basic.setting.pitch.module.column.amount": "列数",
"modal.module.basic.setting.pitch.module.column.margin": "左右間隔",
"modal.module.basic.setting.prev": "前に戻る",
"modal.module.basic.setting.row.batch": "単数指定配置",
"modal.module.basic.setting.passivity.placement": "手動配置",
"modal.module.basic.setting.auto.placement": "自動配置",
"plan.menu.module.circuit.setting.circuit.trestle.setting": "回路設定",
@ -603,7 +615,7 @@
"myinfo.message.password.error": "パスワードが間違っています。",
"login": "ログイン",
"login.auto.page.text": "自動ログイン中です。",
"login.fail": "アカウントが存在しないか、パスワードが間違っています。",
"login.fail": "계정이 없거나 비밀번호가 잘못되었습니다.",
"login.id.save": "ID保存",
"login.id.placeholder": "IDを入力してください。",
"login.password.placeholder": "パスワードを入力してください。",
@ -1047,12 +1059,19 @@
"outerLine.property.fix": "外壁線の属性設定 を完了しますか?",
"outerLine.property.close": "外壁線の属性設定 を終了しますか?",
"want.to.complete.auxiliary.creation": "補助線の作成を完了しますか?",
"module.layout.setup.has.zero.value": "モジュールの列、行を入力してください.",
"modal.placement.initial.setting.plan.drawing.only.number": "(※数字は[半角]入力のみ可能です。)",
"wall.line.not.found": "外壁がありません",
"roof.line.not.found": "屋根形状がありません",
"roof.material.can.not.delete": "割り当てられた配置面があります。",
"chidory.can.not.install": "千鳥配置できない工法です。",
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다. (JA)",
"module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다. (JA)",
"roofAllocation.not.found": "할당할 지붕이 없습니다. (JA)"
"module.layout.setup.max.count": "モジュールの最大段数は{0}、最大列数は{1}です。 (JA)",
"module.layout.setup.max.count.multiple": "モジュール{0}の最大段数は{1}、最大列数は{2}です。 (JA)",
"roofAllocation.not.found": "割り当てる屋根がありません。 (JA)",
"modal.module.basic.setting.module.placement.max.size.check": "屋根材別モジュールの最大単数。混合最大単数を確認してください。 (JA)",
"modal.module.basic.setting.module.placement.max.row": "最大 単数(JA)",
"modal.module.basic.setting.module.placement.max.rows.multiple": "混合単数(JA)",
"modal.module.basic.setting.module.placement.mix.asg.yn.error": "混合インストール不可能なモジュールです。 (JA)",
"modal.module.basic.setting.module.placement.mix.asg.yn": "ミックス. (JA)",
"modal.module.basic.setting.layoutpassivity.placement": "layout配置 (JA)"
}

View File

@ -114,6 +114,17 @@
"modal.module.basic.setting.module.eaves.bar.fitting": "처마커버설치",
"modal.module.basic.setting.module.blind.metal.fitting": "적설방지금구설치",
"modal.module.basic.setting.module.select": "모듈/가대 선택",
"modal.module.basic.settting.module.error1": "가대메이커를 선택해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error2": "공법를 선택해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error3": "지붕밑바탕을 선택해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error4": "시공법을 선택해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error5": "L 을 입력해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error6": "서까래 간격을 입력해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error7": "하제비치를 입력해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error8": "모듈 배치 영역 값을 입력해주세요.(지붕재: {0})",
"modal.module.basic.settting.module.error9": "처마쪽 값은 {0}mm 이상이어야 합니다.(지붕재: {1})",
"modal.module.basic.settting.module.error10": "용마루쪽 값은 {0}mm 이상이어야 합니다.(지붕재: {1})",
"modal.module.basic.settting.module.error11": "케라바쪽 값은 {0}mm 이상이어야 합니다.(지붕재: {1})",
"modal.module.basic.setting.module.placement": "모듈 배치",
"modal.module.basic.setting.module.placement.select.fitting.type": "설치형태를 선택합니다.",
"modal.module.basic.setting.module.placement.waterfowl.arrangement": "물떼새 배치",
@ -128,6 +139,7 @@
"modal.module.basic.setting.module.placement.arrangement.standard.eaves": "처마쪽",
"modal.module.basic.setting.module.placement.arrangement.standard.ridge": "용마루쪽",
"modal.module.basic.setting.module.placement.maximum": "최대배치",
"modal.module.basic.setting.module.placement.margin.check1": "가대메이커를 선택해주세요.",
"modal.module.basic.setting.pitch.module.placement.standard.setting": "배치기준 설정",
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "남향설치",
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "지정한 변을 기준으로 설치",
@ -1048,6 +1060,7 @@
"outerLine.property.fix": "외벽선 속성 설정을 완료하시겠습니까?",
"outerLine.property.close": "외벽선 속성 설정을 종료하시겠습니까?",
"want.to.complete.auxiliary.creation": "보조선 작성을 완료하시겠습니까?",
"module.layout.setup.has.zero.value": "모듈의 열, 행을 입력해 주세요.",
"modal.placement.initial.setting.plan.drawing.only.number": "(※ 숫자는 [반각]입력만 가능합니다.)",
"wall.line.not.found": "외벽선이 없습니다.",
"roof.line.not.found": "지붕형상이 없습니다.",
@ -1055,5 +1068,11 @@
"chidory.can.not.install": "치조 불가 공법입니다.",
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.",
"module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.",
"roofAllocation.not.found": "할당할 지붕이 없습니다."
"roofAllocation.not.found": "할당할 지붕이 없습니다.",
"modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈의 최대 단수. 혼합 최대 단수를 확인하십시오.",
"modal.module.basic.setting.module.placement.max.row": "최대 단수",
"modal.module.basic.setting.module.placement.max.rows.multiple": "혼합 단수",
"modal.module.basic.setting.module.placement.mix.asg.yn.error": "혼합 설치 불가능한 모듈입니다.",
"modal.module.basic.setting.module.placement.mix.asg.yn": "혼합",
"modal.module.basic.setting.layoutpassivity.placement": "레이아웃 배치"
}

View File

@ -384,3 +384,27 @@ export const isManualModuleSetupState = atom({
key: 'isManualModuleSetupState',
default: false,
})
export const isManualModuleLayoutSetupState = atom({
key: 'isManualModuleLayoutSetupState',
default: false,
})
export const moduleSetupOptionState = atom({
key: 'moduleSetupOptionState',
default: {
isChidori: false, //치조 안함
setupLocation: 'eaves', //처마
},
})
export const toggleManualSetupModeState = atom({
key: 'toggleManualSetupModeState',
default: '',
})
export const moduleRowColArrayState = atom({
key: 'moduleRowColArrayState',
default: [],
dangerouslyAllowMutability: true,
})

7
src/store/roofAtom.js Normal file
View File

@ -0,0 +1,7 @@
import { atom } from 'recoil'
export const roofsState = atom({
key: 'roofs',
default: null,
dangerouslyAllowMutability: true,
})

View File

@ -2,7 +2,7 @@ import { atom } from 'recoil'
export const selectedModuleState = atom({
key: 'selectedModuleState',
default: [],
default: null,
dangerouslyAllowMutability: true,
})

View File

@ -383,7 +383,7 @@ button{
}
}
&::-webkit-scrollbar {
width: 2px;
width: 5px;
background-color: transparent;
}