@@ -1076,7 +1185,6 @@ export default function Estimate({}) {
- {/* */}
- {/* */}
{
if (canvas) {
canvas?.clear() // 캔버스를 초기화합니다.
- if (selectedPlan?.canvasStatus) {
- canvas?.loadFromJSON(JSON.parse(selectedPlan.canvasStatus), function () {
+ if (currentCanvasPlan?.canvasStatus && floorPlanState.objectNo === currentCanvasPlan.objectNo) {
+ canvas?.loadFromJSON(JSON.parse(currentCanvasPlan.canvasStatus), function () {
canvasLoadInit() //config된 상태로 캔버스 객체를 그린다
canvas?.renderAll() // 캔버스를 다시 그립니다.
})
@@ -39,7 +43,11 @@ export default function CanvasFrame() {
useEffect(() => {
loadCanvas()
- }, [selectedPlan, canvas])
+ }, [currentCanvasPlan, canvas])
+
+ useEffect(() => {
+ setIsGlobalLoading(false)
+ }, [])
return (
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx
index ba2994c0..bc1a4007 100644
--- a/src/components/floor-plan/CanvasLayout.jsx
+++ b/src/components/floor-plan/CanvasLayout.jsx
@@ -30,22 +30,22 @@ export default function CanvasLayout({ children }) {
- {plans.map((plan) => (
+ {plans.map((plan, index) => (
-
+
>
)}
diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx
index 0769af0a..eb9f3047 100644
--- a/src/components/floor-plan/FloorPlan.jsx
+++ b/src/components/floor-plan/FloorPlan.jsx
@@ -1,37 +1,53 @@
'use client'
import { useEffect } from 'react'
-//import { useRecoilState } from 'recoil'
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { usePopup } from '@/hooks/usePopup'
-//import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
-//import { correntObjectNoState } from '@/store/settingAtom'
import '@/styles/contents.scss'
+import { notFound, useSearchParams } from 'next/navigation'
+import { useRecoilState } from 'recoil'
+import { correntObjectNoState } from '@/store/settingAtom'
export default function FloorPlan({ children }) {
- //const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext)
- //const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState)
+ const [correntObjectNo, setCurrentObjectNo] = useRecoilState(correntObjectNoState)
+ const searchParams = useSearchParams()
+ const objectNo = searchParams.get('objectNo')
+ const pid = searchParams.get('pid')
+
const { closeAll } = usePopup()
const { menuNumber, setMenuNumber } = useCanvasMenu()
- const { fetchSettings } = useCanvasSetting()
+ const { fetchSettings, fetchBasicSettings } = useCanvasSetting()
+
+ // URL 파라미터에서 objectNo 설정
+ useEffect(() => {
+ if (!objectNo) {
+ notFound()
+ }
+ setCurrentObjectNo(objectNo)
+ }, [objectNo, setCurrentObjectNo])
+
+ // 설정 데이터 fetch
+ useEffect(() => {
+ if (!correntObjectNo) return // correntObjectNo가 없으면 실행하지 않음
+
+ if(menuNumber === null) {
+ setMenuNumber(1)
+ }
+ fetchSettings()
+ fetchBasicSettings()
+
+ return () => {
+ closeAll()
+ }
+ }, [correntObjectNo])
const modalProps = {
menuNumber,
setMenuNumber,
}
- useEffect(() => {
- ///setCorrentObjectNo(floorPlanState.objectNo)
- //console.log('FloorPlan objectNo ', floorPlanState.objectNo, correntObjectNo)
- setMenuNumber(1)
- fetchSettings()
- return () => {
- closeAll()
- }
- }, [])
-
return (
<>
diff --git a/src/components/floor-plan/modal/Slope.jsx b/src/components/floor-plan/modal/Slope.jsx
index 42b8be64..58ccec4d 100644
--- a/src/components/floor-plan/modal/Slope.jsx
+++ b/src/components/floor-plan/modal/Slope.jsx
@@ -15,7 +15,7 @@ export default function Slope({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('plan.menu.placement.surface.slope.setting')}
+
)
diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx
index 609ff975..b85d76c6 100644
--- a/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx
+++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryDrawing.jsx
@@ -126,7 +126,7 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('modal.auxiliary.drawing')}
+
)
diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx
index 07fc9e46..e0f3522b 100644
--- a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx
+++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx
@@ -46,7 +46,7 @@ export default function AuxiliaryEdit(props) {
return (
-
+
{getMessage(type === 'copy' ? 'modal.auxiliary.copy' : 'modal.auxiliary.move')}
+
)
diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx
index e984be57..1afdd7ec 100644
--- a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx
+++ b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx
@@ -14,7 +14,7 @@ export default function AuxiliarySize(props) {
return (
-
+
{getMessage('modal.auxiliary.size.edit')}
+
)
diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx
index 392c1eda..89560025 100644
--- a/src/components/floor-plan/modal/basic/BasicSetting.jsx
+++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx
@@ -11,6 +11,11 @@ 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 } from '@/store/selectedModuleOptions'
+import { addedRoofsState } from '@/store/settingAtom'
+import { isObjectNotEmpty } from '@/util/common-utils'
+import Swal from 'sweetalert2'
+import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
const { getMessage } = useMessage()
@@ -20,13 +25,32 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
const orientationRef = useRef(null)
const { initEvent } = useEvent()
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
+ const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
+ const addedRoofs = useRecoilValue(addedRoofsState)
// const { initEvent } = useContext(EventContext)
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting()
const handleBtnNextStep = () => {
if (tabNum === 1) {
orientationRef.current.handleNextStep()
+ } else if (tabNum === 2) {
+ 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
+ }
}
+
setTabNum(tabNum + 1)
}
@@ -51,7 +75,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('plan.menu.module.circuit.setting.default')}
closePopup(id)}>
닫기
@@ -115,6 +139,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
)}
+
)
diff --git a/src/components/floor-plan/modal/basic/step/Module.jsx b/src/components/floor-plan/modal/basic/step/Module.jsx
index 78189124..eb4f0177 100644
--- a/src/components/floor-plan/modal/basic/step/Module.jsx
+++ b/src/components/floor-plan/modal/basic/step/Module.jsx
@@ -1,28 +1,31 @@
-import { useEffect, useState, useReducer } from 'react'
+import { useEffect, useState, useReducer, useRef } from 'react'
import { useRecoilValue, useRecoilState } from 'recoil'
import { addedRoofsState } from '@/store/settingAtom'
-import { canvasSettingState, pitchSelector } from '@/store/canvasAtom'
+import { currentCanvasPlanState } from '@/store/canvasAtom'
import { useMessage } from '@/hooks/useMessage'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useModuleSelection } from '@/hooks/module/useModuleSelection'
import ModuleTabContents from './ModuleTabContents'
-import { useDebounceCallback, useDebounceValue } from 'usehooks-ts'
+import { useDebounceValue } from 'usehooks-ts'
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
+import { isObjectNotEmpty } from '@/util/common-utils'
export default function Module({ setTabNum }) {
const { getMessage } = useMessage()
- const addedRoofs = useRecoilValue(addedRoofsState) //지붕재 선택
+ const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) //지붕재 선택
const [roofTab, setRoofTab] = useState(0) //지붕재 탭
const {
moduleSelectionInitParams,
selectedModules,
- raftCodes,
roughnessCodes,
windSpeedCodes,
managementState,
moduleList,
+ selectedSurfaceType,
installHeight,
+ standardWindSpeed,
verticalSnowCover,
handleChangeModule,
handleChangeSurfaceType,
@@ -31,8 +34,8 @@ export default function Module({ setTabNum }) {
handleChangeVerticalSnowCover,
} = useModuleSelection({ addedRoofs })
- const [inputInstallHeight, setInputInstallHeight] = useState(installHeight)
- const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState(verticalSnowCover)
+ const [inputInstallHeight, setInputInstallHeight] = useState()
+ const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState()
const [debouncedInstallHeight] = useDebounceValue(inputInstallHeight, 500)
const [debouncedVerticalSnowCover] = useDebounceValue(inputVerticalSnowCover, 500)
@@ -44,18 +47,38 @@ export default function Module({ setTabNum }) {
}, moduleSelectionData)
useEffect(() => {
- handleChangeInstallHeight(debouncedInstallHeight)
+ if (installHeight) {
+ setInputInstallHeight(installHeight)
+ }
+ if (verticalSnowCover) {
+ setInputVerticalSnowCover(verticalSnowCover)
+ }
+ }, [installHeight, verticalSnowCover])
+
+ useEffect(() => {
+ if (tempModuleSelectionData.roofConstructions.length > 0) {
+ if (tempModuleSelectionData.common.moduleItemId && isObjectNotEmpty(tempModuleSelectionData.module)) {
+ //저장된 temp데이터가 지붕재(addedRoofs) 개수와 같으면 모듈 선택 저장
+ if (tempModuleSelectionData.roofConstructions.length === addedRoofs.length) {
+ setModuleSelectionData(tempModuleSelectionData)
+ moduleSelectedDataTrigger(tempModuleSelectionData)
+ }
+ }
+ }
+ }, [tempModuleSelectionData])
+
+ useEffect(() => {
+ if (debouncedInstallHeight) {
+ handleChangeInstallHeight(debouncedInstallHeight)
+ }
}, [debouncedInstallHeight])
useEffect(() => {
- handleChangeVerticalSnowCover(debouncedVerticalSnowCover)
+ if (debouncedVerticalSnowCover) {
+ handleChangeVerticalSnowCover(debouncedVerticalSnowCover)
+ }
}, [debouncedVerticalSnowCover])
- useEffect(() => {
- setInputInstallHeight(installHeight)
- setInputVerticalSnowCover(verticalSnowCover)
- }, [installHeight, verticalSnowCover])
-
const moduleData = {
header: [
{ name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' },
@@ -69,16 +92,12 @@ export default function Module({ setTabNum }) {
rows: [],
}
- useEffect(() => {}, [roofTab])
-
- useEffect(() => {
- console.log('moduleSelectionData', moduleSelectionData)
- }, [])
-
const handleRoofTab = (tab) => {
setRoofTab(tab)
}
+ const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
+
return (
<>
@@ -114,21 +133,20 @@ export default function Module({ setTabNum }) {
- {selectedModules.itemList &&
- selectedModules.itemList.map((row) => (
- <>
-
- |
-
-
- {row.itemNm}
-
- |
- {Number(row.shortAxis).toFixed(0)} |
- {Number(row.longAxis).toFixed(0)} |
- {Number(row.wpOut).toFixed(0)} |
-
- >
+ {selectedModules &&
+ selectedModules.itemList &&
+ selectedModules.itemList.map((row, index) => (
+
+ |
+
+
+ {row.itemNm}
+
+ |
+ {Number(row.shortAxis).toFixed(0)} |
+ {Number(row.longAxis).toFixed(0)} |
+ {Number(row.wpOut).toFixed(0)} |
+
))}
@@ -232,11 +250,10 @@ export default function Module({ setTabNum }) {
diff --git a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx
index 7fcbc0bb..ad48695e 100644
--- a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx
+++ b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx
@@ -1,288 +1,42 @@
-import { useEffect, useState, useRef } from 'react'
-import { useRecoilValue } from 'recoil'
-import { pitchTextSelector } from '@/store/canvasAtom'
+import { useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
-import { useMasterController } from '@/hooks/common/useMasterController'
-import { useCommonCode } from '@/hooks/common/useCommonCode'
-import { moduleSelectionInitParamsState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils'
import QSelectBox from '@/components/common/select/QSelectBox'
+import { useModuleTabContents } from '@/hooks/module/useModuleTabContents'
-export default function ModuleTabContents({
- addRoof,
- roofTab,
- moduleConstructionSelectionData,
- setModuleSelectionData,
- tempModuleSelectionData,
- setTempModuleSelectionData,
-}) {
+export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
const { getMessage } = useMessage()
const [roofMaterial, setRoofMaterial] = useState(addRoof) //지붕재`
- const globalPitchText = useRecoilValue(pitchTextSelector) //피치 텍스트
- const { findCommonCode } = useCommonCode()
- const [raftCodes, setRaftCodes] = useState([]) //가대 목록
- const [trestleList, setTrestleList] = useState([])
- const [constMthdList, setConstMthdList] = useState([])
- const [roofBaseList, setRoofBaseList] = useState([])
- const [constructionList, setConstructionList] = useState([{}]) //공법 목록
-
- const [selectedRaftBase, setSelectedRaftBase] = useState({}) //선택된 가대
- const [selectedTrestle, setSelectedTrestle] = useState({}) //선택된 가대
- const [selectedConstMthd, setSelectedConstMthd] = useState({}) //선택된 공법
- const [selectedRoofBase, setSelectedRoofBase] = useState({}) //선택된 지붕밑바탕
- const [selectedConstruction, setSelectedConstruction] = useState({}) //선택된 공법
- const [constructionListParams, setConstructionListParams] = useState({})
-
- const [trestleParams, setTrestleParams] = useState({}) //서까래, 가대메이커,공법,지붕밑바탕 관련 api호출 파라메터
- const [constructionParams, setConstructionParams] = useState({}) //공법 관련 api호출 파라메터
- const [roofBaseParams, setRoofBaseParams] = useState({}) //지붕밑바탕 관련 api호출 파라메터
-
- const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
-
- const { getTrestleList, getConstructionList } = useMasterController()
-
- const constructionRef = useRef([])
- const [cvrYn, setCvrYn] = useState('N')
- const [snowGdPossYn, setSnowGdPossYn] = useState('N')
-
- const [cvrChecked, setCvrChecked] = useState(false)
- const [snowGdChecked, setSnowGdChecked] = useState(false)
-
- const [isExistData, setIsExistData] = useState(false)
-
- //서까래간격 변경
- const handleChangeRaftBase = (option) => {
- setSelectedRaftBase(option)
- setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode })
-
- setTrestleList([]) //가대메이커
- setConstMthdList([]) //공법 초기화
- setRoofBaseList([]) //지붕밑바탕 초기화
- setConstructionList([]) //공법 초기화
- }
-
- //가대메이커 변경
- const handleChangeTrestle = (option) => {
- setSelectedTrestle(option) //선택값 저장
- setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' })
- setConstMthdList([]) //공법 초기화
- setRoofBaseList([]) //지붕밑바탕 초기화
- setConstructionList([]) //공법 초기화
- }
-
- //공법 변경
- const handleChangeConstMthd = (option) => {
- setSelectedConstMthd(option) //선택된값 저장
- setRoofBaseParams({ ...trestleParams, trestleMkrCd: selectedTrestle.trestleMkrCd, constMthdCd: option.constMthdCd, roofBaseCd: '' })
- setConstructionList([]) //공법 초기화
- }
-
- //지붕밑바탕변경
- const handleChangeRoofBase = (option) => {
- // if (option) {
- setConstructionListParams({
- ...moduleSelectionInitParams,
- ...roofBaseParams,
- roofBaseCd: option.roofBaseCd,
- inclCd: addRoof.pitch,
- })
- setSelectedRoofBase(option)
- }
-
- const getModuleOptionsListData = async (params) => {
- const optionsList = await getTrestleList(params)
-
- if (optionsList.data.length > 0) {
- if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd === null) {
- setTrestleList(optionsList.data)
- if (isExistData) {
- setSelectedTrestle({ ...moduleConstructionSelectionData.trestle })
- } else {
- setConstMthdList([])
- setRoofBaseList([])
- }
- }
-
- if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd === null) {
- setConstMthdList(optionsList.data)
- if (isExistData) {
- setSelectedConstMthd({ ...moduleConstructionSelectionData.trestle })
- } else {
- setRoofBaseList([])
- }
- }
-
- if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd) {
- setRoofBaseList(optionsList.data)
- if (isExistData) {
- setSelectedRoofBase({ ...moduleConstructionSelectionData.trestle })
- }
- }
- }
- }
-
- const getConstructionListData = async (params) => {
- if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
- const optionsList = await getConstructionList(params)
- setConstructionList(optionsList.data)
- }
- }
-
- const handleConstruction = (index) => {
- if (index > -1) {
- const isPossibleIndex = constructionRef.current
- .map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1))
- .filter((index) => index !== -1)
-
- isPossibleIndex.forEach((index) => {
- if (constructionRef.current[index].classList.contains('blue')) {
- constructionRef.current[index].classList.remove('blue')
- constructionRef.current[index].classList.add('white')
- }
- })
- constructionRef.current[index].classList.remove('white')
- constructionRef.current[index].classList.add('blue')
-
- const selectedConstruction = constructionList[index]
- selectedConstruction.roofIndex = roofTab
- selectedConstruction.setupCover = false //처마력바 설치 여부
- selectedConstruction.setupSnowCover = false //눈막이금구 설치 여부
- selectedConstruction.selectedIndex = index
-
- setCvrYn(selectedConstruction.cvrYn)
- setSnowGdPossYn(selectedConstruction.snowGdPossYn)
- setSelectedConstruction(selectedConstruction)
- } else {
- constructionRef.current.forEach((ref) => {
- ref.classList.remove('blue')
- })
- }
- }
-
- useEffect(() => {
- if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
- const newRoofConstructions = {
- roofIndex: roofTab,
- addRoof: addRoof,
- trestle: selectedRoofBase,
- construction: selectedConstruction,
- }
- const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === roofTab)
-
- if (index > -1) {
- const newArray = [
- ...tempModuleSelectionData.roofConstructions.slice(0, index),
- newRoofConstructions,
- ...tempModuleSelectionData.roofConstructions.slice(index + 1),
- ]
- setTempModuleSelectionData({ roofConstructions: newArray })
- } else {
- setTempModuleSelectionData({ roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }] })
- }
- }
- }, [selectedConstruction])
-
- const handleCvrChecked = () => {
- setCvrChecked(!cvrChecked)
- }
-
- const handleSnowGdChecked = () => {
- setSnowGdChecked(!snowGdChecked)
- }
-
- useEffect(() => {
- setSelectedConstruction({ ...selectedConstruction, setupCover: cvrChecked })
- }, [cvrChecked])
-
- useEffect(() => {
- setSelectedConstruction({ ...selectedConstruction, setupSnowCover: snowGdChecked })
- }, [snowGdChecked])
-
- useEffect(() => {
- if (isExistData) {
- setConstructionListParams({
- ...moduleSelectionInitParams,
- ...roofBaseParams,
- roofBaseCd: selectedRoofBase.roofBaseCd,
- inclCd: addRoof.pitch,
- })
- }
- }, [selectedRoofBase])
-
- useEffect(() => {
- if (isExistData && constructionList.length > 0) {
- const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
- handleConstruction(selectedIndex)
- }
- }, [constructionList])
-
- useEffect(() => {
- // 202600 경사도
- const raftCodeList = findCommonCode('203800')
- //서까래 코드
- raftCodeList.forEach((obj) => {
- obj.name = obj.clCodeNm
- obj.id = obj.clCode
- })
- setRaftCodes(raftCodeList)
- }, [])
-
- useEffect(() => {
- //물건 상세의 데이터를 가지고 초기화 데이터를 만든다
- if (
- moduleSelectionInitParams.illuminationTp &&
- moduleSelectionInitParams.instHt &&
- moduleSelectionInitParams.stdSnowLd &&
- moduleSelectionInitParams.stdWindSpeed
- ) {
- const isModuleLoaded = moduleSelectionInitParams.hasOwnProperty('moduleTpCd') //모듈컬럼이 있으면 모듈을 변경했다는 내용
- if (isModuleLoaded) {
- setTrestleParams({ moduleTpCd: moduleSelectionInitParams.moduleTpCd, roofMatlCd: addRoof.roofMatlCd, raftBaseCd: addRoof.raftBaseCd })
- setConstructionList([])
-
- if (isObjectNotEmpty(moduleConstructionSelectionData)) {
- setConstructionParams({ ...moduleConstructionSelectionData.trestle, constMthdCd: '', roofBaseCd: '' })
- setRoofBaseParams({ ...moduleConstructionSelectionData.trestle, roofBaseCd: '' })
- setCvrChecked(moduleConstructionSelectionData.construction.setupCover)
- setSnowGdChecked(moduleConstructionSelectionData.construction.setupSnowCover)
- setIsExistData(true)
- }
- }
- }
-
- setTempModuleSelectionData({ common: moduleSelectionInitParams })
- }, [moduleSelectionInitParams])
-
- useEffect(() => {
- if (isObjectNotEmpty(trestleParams)) {
- getModuleOptionsListData(trestleParams)
- }
- }, [trestleParams])
-
- useEffect(() => {
- if (isObjectNotEmpty(constructionParams)) {
- getModuleOptionsListData(constructionParams)
- }
- }, [constructionParams])
-
- useEffect(() => {
- if (isObjectNotEmpty(roofBaseParams)) {
- getModuleOptionsListData(roofBaseParams)
- }
- }, [roofBaseParams])
-
- useEffect(() => {
- if (isObjectNotEmpty(constructionListParams)) {
- getConstructionListData(constructionListParams)
- }
- }, [constructionListParams])
-
- useEffect(() => {
- if (isObjectNotEmpty(tempModuleSelectionData)) {
- setModuleSelectionData(tempModuleSelectionData)
- }
- }, [tempModuleSelectionData])
+ const {
+ raftCodes,
+ trestleList,
+ constMthdList,
+ roofBaseList,
+ constructionList,
+ globalPitchText,
+ selectedTrestle,
+ selectedConstMthd,
+ selectedRoofBase,
+ constructionRef,
+ cvrYn,
+ cvrChecked,
+ snowGdPossYn,
+ snowGdChecked,
+ lengthBase,
+ hajebichi,
+ lengthRef,
+ hajebichiRef,
+ setLengthBase,
+ setHajebichi,
+ handleChangeRaftBase,
+ handleChangeTrestle,
+ handleChangeConstMthd,
+ handleChangeRoofBase,
+ handleConstruction,
+ handleCvrChecked,
+ handleSnowGdChecked,
+ } = useModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData })
return (
<>
@@ -300,21 +54,21 @@ export default function ModuleTabContents({
<>
L
-
-
+
+ setLengthBase(e.target.value)}
+ disabled={roofMaterial.lenAuth === 'R' ? true : false}
+ ref={lengthRef}
+ />
>
)}
+
+
{roofMaterial && ['C', 'R'].includes(roofMaterial.raftAuth) && (
<>
{getMessage('modal.module.basic.setting.module.rafter.margin')}
@@ -335,22 +89,21 @@ export default function ModuleTabContents({
>
)}
+
+
{roofMaterial && ['C', 'R'].includes(roofMaterial.roofPchAuth) && (
<>
- {getMessage('modal.module.basic.setting.module.rafter.margin')}
+ {getMessage('modal.module.basic.setting.module.hajebichi')}
diff --git a/src/components/floor-plan/modal/basic/step/Orientation.jsx b/src/components/floor-plan/modal/basic/step/Orientation.jsx
index 4b100514..590c9d46 100644
--- a/src/components/floor-plan/modal/basic/step/Orientation.jsx
+++ b/src/components/floor-plan/modal/basic/step/Orientation.jsx
@@ -1,12 +1,15 @@
-import { forwardRef, useImperativeHandle, useState } from 'react'
+import { forwardRef, 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'
export const Orientation = forwardRef(({ tabNum }, ref) => {
const { getMessage } = useMessage()
+ const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController(1)
+
const { nextStep, compasDeg, setCompasDeg } = useOrientation()
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
@@ -17,8 +20,13 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
const handleNextStep = () => {
nextStep()
+ canvasPopupStatusTrigger(compasDeg)
}
+ useEffect(() => {
+ checkDegree(compasDeg)
+ }, [compasDeg])
+
const checkDegree = (e) => {
if (numberCheck(Number(e)) && Number(e) >= -180 && Number(e) <= 180) {
setCompasDeg(Number(e))
@@ -30,7 +38,6 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
return (
<>
- {getMessage('modal.module.basic.setting.orientation.setting')}
{getMessage('modal.module.basic.setting.orientation.setting.info')}
@@ -64,7 +71,7 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
- setHasAnglePassivity(!hasAnglePassivity)} />
+ setHasAnglePassivity(!hasAnglePassivity)} />
@@ -73,7 +80,7 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
type="text"
className="input-origin block"
value={compasDeg}
- readOnly={hasAnglePassivity}
+ readOnly={!hasAnglePassivity}
placeholder={0}
onChange={
(e) => checkDegree(e.target.value)
diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx
index 8e48a42c..4938b1e9 100644
--- a/src/components/floor-plan/modal/basic/step/Placement.jsx
+++ b/src/components/floor-plan/modal/basic/step/Placement.jsx
@@ -1,14 +1,17 @@
import { forwardRef, useEffect, useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
-import { checkedModuleState } from '@/store/canvasAtom'
-import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil'
-import { selectedModuleState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { checkedModuleState, currentCanvasPlanState } from '@/store/canvasAtom'
+import { useRecoilValue, useSetRecoilState } from 'recoil'
+import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { useModulePlace } from '@/hooks/module/useModulePlace'
const Placement = forwardRef((props, refs) => {
const { getMessage } = useMessage()
- const [isChidori, setIsChidori] = useState('false')
+ const [isChidori, setIsChidori] = useState(false)
+ const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
+ const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
+
const [setupLocation, setSetupLocation] = useState('center')
const [isMaxSetup, setIsMaxSetup] = useState('false')
const [selectedItems, setSelectedItems] = useState({})
@@ -21,9 +24,13 @@ const Placement = forwardRef((props, refs) => {
//모듈 배치면 생성
useEffect(() => {
- console.log('🚀 ~ Placement ~ moduleSelectionData:', moduleSelectionData)
- console.log('🚀 ~ Placement ~ selectedModules:', selectedModules)
- makeModuleInstArea()
+ if (moduleSelectionData) {
+ //1개라도 치도리 불가가 있으면 치도리 불가
+ const isChidroriValue = moduleSelectionData.roofConstructions.some((item) => item.construction.plvrYn === 'N')
+ if (isChidroriValue) {
+ setIsChidoriNotAble(true)
+ }
+ }
}, [])
//체크된 모듈 데이터
@@ -45,10 +52,15 @@ const Placement = forwardRef((props, refs) => {
}
const handleChangeChidori = (e) => {
- setIsChidori(e.target.value)
+ const bool = e.target.value === 'true' ? true : false
+ setIsChidori(bool)
refs.isChidori.current = e.target.value
}
+ useEffect(() => {
+ console.log('isChidori', isChidori)
+ }, [isChidori])
+
const handleSetupLocation = (e) => {
setSetupLocation(e.target.value)
refs.setupLocation.current = e.target.value
@@ -127,19 +139,19 @@ const Placement = forwardRef((props, refs) => {
diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx
index 38ae2e89..b4d13d20 100644
--- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx
+++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx
@@ -6,20 +6,21 @@ import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import PassivityCircuitAllocation from './step/type/PassivityCircuitAllocation'
-import { useAxios } from '@/hooks/useAxios'
import { useMasterController } from '@/hooks/common/useMasterController'
-import { get } from 'react-hook-form'
import { correntObjectNoState } from '@/store/settingAtom'
import { useRecoilValue } from 'recoil'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
-
import { useRecoilState } from 'recoil'
-import { powerConditionalState } from '@/store/circuitTrestleAtom'
+import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, selectedModelsState, seriesState } from '@/store/circuitTrestleAtom'
import { POLYGON_TYPE } from '@/common/common'
import { useSwal } from '@/hooks/useSwal'
import { canvasState } from '@/store/canvasAtom'
import { useTrestle } from '@/hooks/module/useTrestle'
+import { selectedModuleState } from '@/store/selectedModuleOptions'
+import { v4 as uuidv4 } from 'uuid'
+
+import { stepUpListDataState } from '@/store/circuitTrestleAtom'
const ALLOCATION_TYPE = {
AUTO: 'auto',
@@ -28,62 +29,455 @@ const ALLOCATION_TYPE = {
export default function CircuitTrestleSetting({ id }) {
const { getMessage } = useMessage()
const { closePopup } = usePopup()
- // 탭 번호 1: 파워 컨디셔너 선택(+수동 설정)
- // 탭 번호 2: 회로 할당
+ const { apply } = useTrestle()
+ const { swalFire } = useSwal()
+ const canvas = useRecoilValue(canvasState)
+
+ const [makers, setMakers] = useRecoilState(makersState)
+ const [selectedMaker, setSelectedMaker] = useRecoilState(selectedMakerState)
+ const [series, setSeries] = useRecoilState(seriesState)
+ const [models, setModels] = useRecoilState(modelsState)
+ const [selectedModels, setSelectedModels] = useRecoilState(selectedModelsState)
+ const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
+
const [tabNum, setTabNum] = useState(1)
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
-
- const [makers, setMakers] = useState([])
- const [series, setSeries] = useState([])
- const [models, setModels] = useState([])
- const [selectedMaker, setSelectedMaker] = useState(null)
- const [selectedModels, setSelectedModels] = useState(null)
- const [selectedSeries, setSelectedSeries] = useState(null)
- const correntObjectNo = useRecoilValue(correntObjectNoState)
- const { getPcsMakerList } = useMasterController()
+ const [circuitAllocationType, setCircuitAllocationType] = useState(1)
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
- const { apply } = useTrestle()
+ const selectedModules = useRecoilValue(selectedModuleState)
+ const { getPcsAutoRecommendList, getPcsVoltageChk } = useMasterController()
+
+ // 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가
+ const [selectedStepUpValues, setSelectedStepUpValues] = useState({})
+ const [getStepUpSelections, setGetStepUpSelections] = useState(null)
+
+ const [stepUpListData, setStepUpListData] = useRecoilState(stepUpListDataState)
useEffect(() => {
- // console.log(canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE))
- // if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE).length === 0) {
- // swalFire({
- // title: '모듈을 배치해주세요.',
- // type: 'alert',
- // confirmFn: () => {
- // closePopup(id)
- // },
- // })
- // }
+ if (!managementState) {
+ setManagementState(managementStateLoaded)
+ }
}, [])
- // useEffect(() => {
- // console.log('🚀 ~ CircuitTrestleSetting ~ series:', series)
- // const selectedSeries = series.filter((s) => s.selectd).map((s) => s.pcsSerCd)
- // if (selectedSeries.length > 0) {
- // getPcsMakerList(selectedSeries).then((res) => {
- // setModels(res.data)
- // })
- // }
- // }, [series])
- // 회로 할당 유형
- const [circuitAllocationType, setCircuitAllocationType] = useState(1)
+ useEffect(() => {
+ if (allocationType === ALLOCATION_TYPE.PASSIVITY && tabNum === 2) {
+ const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
+ canvas.remove(...notAllocationModules)
+ canvas.renderAll()
+ }
+ }, [tabNum])
+
+ useEffect(() => {
+ console.log('stepUpListData >>> ', stepUpListData)
+ }, [stepUpListData])
+
+ const onAutoRecommend = () => {
+ if (series.filter((s) => s.selected).length === 0) {
+ swalFire({
+ title: '시리즈를 선택해 주세요.',
+ type: 'alert',
+ })
+ return
+ }
+
+ const params = {
+ ...getOptYn(),
+ useModuleItemList: getUseModuleItemList(),
+ roofSurfaceList: getRoofSurfaceList(),
+ pcsItemList: getPcsItemList(),
+ }
+
+ if (selectedModels.length === 0) {
+ getPcsAutoRecommendList(params).then((res) => {
+ if (res.data?.pcsItemList) {
+ const itemList = models.filter((model) => {
+ return res.data?.pcsItemList.map((item) => item.itemId).includes(model.itemId)
+ })
+ const selectedModels = itemList.map((model) => {
+ return {
+ ...model,
+ id: uuidv4(),
+ }
+ })
+ const pcsVoltageChkParams = {
+ ...getOptYn(),
+ useModuleItemList: getUseModuleItemList(),
+ roofSurfaceList: getRoofSurfaceList(),
+ pcsItemList: getPcsItemList(),
+ }
+ setSelectedModels(selectedModels)
+ getPcsVoltageChk(pcsVoltageChkParams).then((res) => {
+ setTabNum(2)
+ })
+ } else {
+ // 데이터가 없는 경우 오류 메시지 확인 필요
+ if (res.result.resultCode === 'E') {
+ swalFire({
+ title: res.result.resultMsg,
+ type: 'alert',
+ })
+ } else {
+ swalFire({
+ title: '파워컨디셔너를 추가해 주세요.',
+ type: 'alert',
+ })
+ }
+ }
+ })
+ } else {
+ getPcsVoltageChk(params).then((res) => {
+ setTabNum(2)
+ })
+ }
+ }
+
+ const getOptYn = () => {
+ return {
+ maxConnYn: pcsCheck.max ? 'Y' : 'N',
+ smpCirYn: pcsCheck.division ? 'Y' : 'N',
+ coldZoneYn: managementState?.coldRegionFlg === '1' ? 'Y' : 'N',
+ }
+ }
+
+ const getPcsItemList = () => {
+ return models.map((model) => {
+ return {
+ itemId: model.itemId,
+ pcsMkrCd: model.pcsMkrCd,
+ pcsSerCd: model.pcsSerCd,
+ }
+ })
+ }
+
+ const getUseModuleItemList = () => {
+ return selectedModules.itemList.map((m) => {
+ return {
+ itemId: m.itemId,
+ mixMatlNo: m.mixMatlNo,
+ }
+ })
+ }
+
+ const getRoofSurfaceList = () => {
+ return canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
+ .map((obj) => {
+ getModuleList(obj)
+ return {
+ roofSurfaceId: obj.id,
+ roofSurface: canvas
+ .getObjects()
+ .filter((o) => o.id === obj.parentId)[0]
+ .directionText.replace(/[0-9]/g, ''),
+ roofSurfaceIncl: canvas.getObjects().filter((o) => o.id === obj.parentId)[0].roofMaterial.pitch,
+ moduleList: getModuleList(obj).map((module) => {
+ return {
+ itemId: module.moduleInfo.itemId,
+ circuit: module.circuitNumber ? module.circuitNumber : null,
+ pcsItemId: module.circuit ? module.circuit?.pcsItemId : null,
+ }
+ }),
+ }
+ })
+ }
+
+ const getModuleList = (surface) => {
+ let moduleList = []
+ let [xObj, yObj] = [{}, {}]
+ let [xPoints, yPoints] = [[], []]
+ surface.modules.forEach((module) => {
+ if (!xObj[module.left]) {
+ xObj[module.left] = module.left
+ xPoints.push(module.left)
+ }
+ if (!yObj[module.top]) {
+ yObj[module.top] = module.top
+ yPoints.push(module.top)
+ }
+ })
+ switch (surface.direction) {
+ case 'south':
+ xPoints.sort((a, b) => a - b)
+ yPoints.sort((a, b) => b - a)
+ yPoints.forEach((y, index) => {
+ let temp = surface.modules.filter((m) => m.top === y)
+ if (index % 2 === 0) {
+ temp.sort((a, b) => a.left - b.left)
+ } else {
+ temp.sort((a, b) => b.left - a.left)
+ }
+ moduleList = [...moduleList, ...temp]
+ })
+ break
+ case 'north':
+ xPoints.sort((a, b) => b - a)
+ yPoints.sort((a, b) => a - b)
+ yPoints.forEach((y, index) => {
+ let temp = surface.modules.filter((m) => m.top === y)
+ if (index % 2 === 0) {
+ temp.sort((a, b) => b.left - a.left)
+ } else {
+ temp.sort((a, b) => a.left - b.left)
+ }
+ moduleList = [...moduleList, ...temp]
+ })
+ break
+ case 'west':
+ xPoints.sort((a, b) => a - b)
+ yPoints.sort((a, b) => a - b)
+ xPoints.forEach((x, index) => {
+ let temp = surface.modules.filter((m) => m.left === x)
+ if (index % 2 === 0) {
+ temp.sort((a, b) => a.top - b.top)
+ } else {
+ temp.sort((a, b) => b.top - a.top)
+ }
+ moduleList = [...moduleList, ...temp]
+ })
+ break
+ case 'east':
+ xPoints.sort((a, b) => b - a)
+ yPoints.sort((a, b) => b - a)
+ xPoints.forEach((x, index) => {
+ let temp = surface.modules.filter((m) => m.left === x)
+ if (index % 2 === 0) {
+ temp.sort((a, b) => b.top - a.top)
+ } else {
+ temp.sort((a, b) => a.top - b.top)
+ }
+ moduleList = [...moduleList, ...temp]
+ })
+ break
+ default:
+ return []
+ }
+ return moduleList
+ }
+
+ const onAutoAllocation = () => {
+ let moduleStdQty = 0
+ let moduleMaxQty = 0
+ const selectedModels = models.filter((m) => m.selected)
+
+ if (selectedModels.length === 0) {
+ onAutoRecommend()
+ } else {
+ moduleStdQty = selectedModels.reduce((acc, model) => {
+ return acc + parseInt(model.moduleStdQty)
+ }, 0)
+ moduleMaxQty = selectedModels.reduce((acc, model) => {
+ return acc + parseInt(model.moduleMaxQty)
+ }, 0)
+ }
+ // const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
+ // const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
+
+ // if (placementModules.length > target) {
+ // swalFire({
+ // title: '배치가능 매수를 초과합니다. 파워컨디셔너를 다시 선택해 주세요.',
+ // type: 'alert',
+ // })
+ // return
+ // }
+
+ // setAllocationType(ALLOCATION_TYPE.AUTO)
+ // setTabNum(2)
+ }
+
+ const onPassivityAllocation = () => {
+ if (selectedModels.length === 0) {
+ const params = {
+ ...getOptYn(),
+ useModuleItemList: getUseModuleItemList(),
+ roofSurfaceList: getRoofSurfaceList(),
+ pcsItemList: getPcsItemList(),
+ }
+
+ getPcsAutoRecommendList(params).then((res) => {
+ if (res.data?.pcsItemList) {
+ const itemList = models.filter((model) => {
+ return res.data?.pcsItemList.map((item) => item.itemId).includes(model.itemId)
+ })
+ const selectedModels = itemList.map((model) => {
+ return {
+ ...model,
+ id: uuidv4(),
+ }
+ })
+ const PcsVoltageChkParams = {
+ ...getOptYn(),
+ useModuleItemList: getUseModuleItemList(),
+ roofSurfaceList: getRoofSurfaceList(),
+ pcsItemList: getPcsItemList(),
+ }
+ setSelectedModels(selectedModels)
+ getPcsVoltageChk(PcsVoltageChkParams).then((res) => {})
+ } else {
+ swalFire({
+ title: '파워컨디셔너를 추가해 주세요.',
+ type: 'alert',
+ })
+ }
+ })
+ } else if (pcsCheck.max) {
+ const moduleStdQty = selectedModels.reduce((acc, model) => {
+ return acc + parseInt(model.moduleStdQty)
+ }, 0)
+ const moduleMaxQty = selectedModels.reduce((acc, model) => {
+ return acc + parseInt(model.moduleMaxQty)
+ }, 0)
+
+ const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
+ const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
+
+ if (placementModules.length > target) {
+ swalFire({
+ title: '배치가능 매수를 초과합니다. 파워컨디셔너를 다시 선택해 주세요.',
+ type: 'alert',
+ })
+ return
+ }
+ }
+
+ setAllocationType(ALLOCATION_TYPE.PASSIVITY)
+ }
+
+ // StepUp에서 선택된 값들을 처리하는 함수 수정
+ const handleStepUpValuesSelected = (selectionData) => {
+ const { gooodsNo } = selectionData
+
+ setSelectedStepUpValues((prev) => ({
+ ...prev,
+ [gooodsNo]: selectionData,
+ }))
+ }
+
+ // StepUp 컴포넌트 초기화 핸들러
+ const handleStepUpInitialize = (getCurrentSelections) => {
+ setGetStepUpSelections(() => getCurrentSelections)
+ }
+
+ // apply 함수 수정
+ const onApply = () => {
+ // 현재 선택된 값들 가져오기
+ const currentSelections = getStepUpSelections ? getStepUpSelections() : {}
+
+ console.log('currentSelections >>> ', currentSelections)
+
+ // 실제 선택된 값이 있는지 더 정확하게 확인
+ const hasSelections = Object.values(currentSelections).some((stepUpConfig) => Object.values(stepUpConfig).length > 0)
+
+ console.log('hasSelections >>> ', hasSelections)
+
+ if (!hasSelections) {
+ swalFire({
+ title: '승압 설정값을 선택해주세요.1',
+ type: 'alert',
+ })
+ return
+ }
+
+ // 선택된 값들 로그
+ console.log('Applying StepUp configurations:', currentSelections)
+
+ // StepUp 컴포넌트로부터 stepUpListData 받아오기
+ //const stepUpData = getStepUpSelections().stepUpListData
+ //console.log('stepUpData >>> ', stepUpData)
+ // stepUpListData를 Recoil state에 저장
+ // setStepUpListData(stepUpData)
+
+ // 선택된 값들을 배열로 변환하여 처리
+ const configurations = Object.values(currentSelections)
+ .map((stepUpConfig) => {
+ const firstConfig = Object.values(stepUpConfig)[0] // 첫 번째 설정만 사용
+ return {
+ pcsInfo: firstConfig.pcsInfo,
+ allocation: firstConfig.allocation,
+ }
+ })
+ .filter((config) => config.pcsInfo && config.allocation) // 유효한 설정만 필터링
+
+ console.log('Processed configurations:', configurations)
+
+ // stepUpListData를 Recoil state에 저장
+ setStepUpListData(configurations)
+
+ // 기존 apply 로직 실행 전에 필요한 데이터가 모두 있는지 확인
+ if (configurations.length > 0) {
+ apply()
+ } else {
+ swalFire({
+ title: '승압 설정값을 선택해주세요.2',
+ type: 'alert',
+ })
+ }
+ }
+
+ const onClickPrev = () => {
+ setAllocationType(ALLOCATION_TYPE.AUTO)
+ swalFire({
+ text: '할당한 회로 번호가 초기화됩니다.',
+ type: 'alert',
+ icon: 'warning',
+ confirmFn: () => {
+ const circuitModules = canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id))
+ canvas.remove(...circuitModules.map((module) => module.circuit))
+ circuitModules.forEach((obj) => {
+ obj.circuit = null
+ obj.pcsItemId = null
+ })
+ },
+ })
+ }
const powerConditionalSelectProps = {
tabNum,
setTabNum,
+ makers,
+ setMakers,
+ selectedMaker,
+ setSelectedMaker,
+ series,
+ setSeries,
+ models,
+ setModels,
+ selectedModels,
+ setSelectedModels,
+ managementState,
}
- const circuitProps = {
+
+ const passivityProps = {
tabNum,
setTabNum,
+ pcsCheck,
+ selectedModels,
+ setSelectedModels,
+ getOptYn,
+ getUseModuleItemList,
+ getRoofSurfaceList,
+ }
+
+ const stepUpProps = {
+ tabNum,
+ setTabNum,
+ models,
+ setModels,
circuitAllocationType,
setCircuitAllocationType,
+ getOptYn, // 옵션 Y/N
+ getUseModuleItemList, // 사용된 모듈아이템 List
+ getRoofSurfaceList, // 지붕면 목록
+ getPcsItemList, // PCS 아이템 목록
+ onValuesSelected: handleStepUpValuesSelected, // 선택된 값들을 처리하는 함수
}
return (
-
+
{getMessage('modal.circuit.trestle.setting')}
closePopup(id)}>
닫기
@@ -98,14 +492,14 @@ export default function CircuitTrestleSetting({ id }) {
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && }
- {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && }
- {tabNum === 2 && }
+ {tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && }
+ {tabNum === 2 && }
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && (
- setTabNum(2)}>
+ onAutoAllocation()}>
{getMessage('modal.circuit.trestle.setting.circuit.allocation.auto')}
- setAllocationType(ALLOCATION_TYPE.PASSIVITY)}>
+ onPassivityAllocation()}>
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}
@@ -125,12 +519,14 @@ export default function CircuitTrestleSetting({ id }) {
setTabNum(1)}>
{getMessage('modal.common.prev')}
- apply()}>
+ {/* apply()}> */}
+
{getMessage('modal.common.save')}({getMessage('modal.circuit.trestle.setting.circuit.allocation')})
)}
+
)
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx
index 420a2e35..407c5e34 100644
--- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx
+++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx
@@ -1,36 +1,43 @@
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useMasterController } from '@/hooks/common/useMasterController'
-import { useEvent } from '@/hooks/useEvent'
import { useMessage } from '@/hooks/useMessage'
-import { makerState, modelState, seriesState } from '@/store/circuitTrestleAtom'
+import { useSwal } from '@/hooks/useSwal'
+import { pcsCheckState } from '@/store/circuitTrestleAtom'
import { globalLocaleStore } from '@/store/localeAtom'
-import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
+import { selectedModuleState } from '@/store/selectedModuleOptions'
+import { isNullOrUndefined } from '@/util/common-utils'
import { useContext, useEffect, useState } from 'react'
import { useRecoilState } from 'recoil'
import { useRecoilValue } from 'recoil'
import { v4 as uuidv4 } from 'uuid'
-const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
-
export default function PowerConditionalSelect(props) {
- let { tabNum, setTabNum } = props
- const [makerData, setMakerData] = useRecoilState(makerState)
- const [makers, setMakers] = useState(makerData.makers)
- const [selectedMaker, setSelectedMaker] = useState(makerData.selectedMaker)
- const [series, setSeries] = useRecoilState(seriesState)
- const [seriesList, setSeriesList] = useState(series.series)
- const [selectedSeries, setSelectedSeries] = useState(series.selectedSeries)
- const model = useRecoilValue(modelState)
- const [models, setModels] = useState(model.models)
- const [selectedModels, setSelectedModels] = useState(model.selectedModels)
- const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
+ let {
+ tabNum,
+ setTabNum,
+ makers,
+ setMakers,
+ selectedMaker,
+ setSelectedMaker,
+ series,
+ setSeries,
+ models,
+ setModels,
+ selectedModels,
+ setSelectedModels,
+ managementState,
+ } = props
+ const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
+
const { getMessage } = useMessage()
const [selectedRow, setSelectedRow] = useState(null)
const globalLocale = useRecoilValue(globalLocaleStore)
const { getPcsMakerList, getPcsModelList } = useMasterController()
const selectedModules = useRecoilValue(selectedModuleState)
+ const { swalFire } = useSwal()
const modelHeader = [
+ { name: getMessage('시리즈'), width: '15%', prop: 'pcsSerNm', type: 'color-box' },
{ name: getMessage('명칭'), width: '15%', prop: 'itemNm', type: 'color-box' },
{
name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.rated.output')} (kW)`,
@@ -57,86 +64,115 @@ export default function PowerConditionalSelect(props) {
useEffect(() => {
if (makers.length === 0) {
getPcsMakerList().then((res) => {
+ console.log('getPcsMakerList', res.data)
setMakers(res.data)
})
}
- if (!managementState) {
- console.log('🚀 ~ useEffect ~ managementState:', managementState)
- setManagementState(managementStateLoaded)
- }
- // promiseGet({ url: `/api/object/${correntObjectNo}/detail` }).then((res) => {
- // console.log('🚀 ~ useEffect ~ /api/object/${correntObjectNo}/detail:', res)
- // // coldRegionFlg-한랭지사양, conType// 계약조건(잉여~,전량)
- // })
}, [])
- useEffect(() => {
- console.log('🚀 ~ PowerConditionalSelect ~ selectedMaker:', selectedMaker)
- if (selectedMaker) {
- setSelectedModels([])
- getPcsMakerList(selectedMaker).then((res) => {
- setSeriesList(
- res.data.map((series) => {
- return { ...series, selected: false }
- }),
- )
+ const checkValidation = () => {
+ const checkedSeries = series.filter((s) => s.selected)
+ if (checkedSeries.length === 0) {
+ swalFire({
+ title: 'PCS 시리즈를 선택해 주세요.',
+ icon: 'warning',
})
+ return false
+ } else if (checkedSeries.length === 1) {
+ if (checkedSeries[0].pcsMkrMultiType === 'SINGLE-P' && checkedSeries[0].pcsSerParallelYn === 'Y') {
+ swalFire({
+ title: '병설은 단독으로 안 됨',
+ icon: 'warning',
+ })
+ }
+ return false
}
- }, [selectedMaker])
+ return true
+ }
- useEffect(() => {
- console.log('🚀 ~ useEffect ~ seriesList:', seriesList)
- if (seriesList.filter((series) => series.selected).length === 0) return
- const pcsMkrCd = seriesList.filter((series) => series.selected)[0]?.pcsMkrCd
- const pcsSerList = seriesList
- .filter((series) => series.selected)
- .map((series) => {
- return { pcsSerCd: series.pcsSerCd }
- })
+ const onCheckSeries = (data) => {
+ console.log('data', data)
+ const copySeries = series.map((s) => {
+ return {
+ ...s,
+ selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.selected,
+ }
+ })
+ setSeries(copySeries)
+ console.log('copySeries', copySeries)
+ handleSetmodels(copySeries.filter((s) => s.selected))
+ }
+
+ const handleSetmodels = (selectedSeries) => {
+ console.log('series', selectedSeries)
+ if (selectedSeries.length === 0) {
+ setModels([])
+ setSelectedModels([])
+ return
+ }
+ const pcsMkrCd = selectedSeries[0]?.pcsMkrCd
+ const pcsSerList = selectedSeries.map((series) => {
+ return { pcsSerCd: series.pcsSerCd }
+ })
const moduleItemList = selectedModules.itemList?.map((module) => {
return {
itemId: module.itemId,
mixMatlNo: module.mixMatlNo,
}
})
- console.log('🚀 ~ useEffect ~ moduleItemList:', selectedModules)
getPcsModelList({ pcsMkrCd, pcsSerList, moduleItemList }).then((res) => {
- if (res?.result.code === 200) {
- console.log('🚀 ~ useEffect ~ res:', res.data)
+ if (res?.result.code === 200 && res?.data) {
setModels(
res.data.map((model) => {
return {
...model,
+ moduleStdQty: parseInt(model.moduleStdQty),
+ moduleMaxQty: parseInt(model.moduleMaxQty),
code: uuidv4(),
- selected: false,
}
}),
)
+ } else {
+ setModels([])
+ setSelectedModels([])
}
})
- }, [seriesList])
-
- const onCheckSeries = (series) => {
- setSeriesList((prev) => prev.map((s) => ({ ...s, selected: s.pcsSerCd === series.pcsSerCd ? !s.selected : s.selected })))
}
const onAddSelectedModel = () => {
- setSelectedModels([...selectedModels, selectedRow])
+ if (selectedRow === null) return
+ if (selectedModels.length === 3) {
+ swalFire({
+ title: '최대 3개까지 선택할 수 있습니다.',
+ icon: 'warning',
+ })
+
+ return
+ }
+ setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4() }])
setSelectedRow(null)
}
- useEffect(() => {
- const selectedModelsIds = selectedModels.map((model) => model.itemId)
+ const onRemoveSelectedModel = (model) => {
+ setSelectedModels(selectedModels.filter((m) => m.id !== model.id))
+ }
+
+ const onChangeMaker = (option) => {
+ if (option) {
+ setModels([])
+ setSelectedMaker(option)
+
+ getPcsMakerList(option).then((res) => {
+ console.log('getPcsMakerList(series)', res.data)
+ setSeries(
+ res.data.map((series) => {
+ return { ...series, selected: false }
+ }),
+ )
+ })
+ }
+ }
- setModels(
- models.map((model) => {
- return {
- ...model,
- selected: selectedModelsIds.includes(model.itemId) === selectedRow.itemId ? true : false,
- }
- }),
- )
- }, [selectedModels])
return (
<>
@@ -151,19 +187,19 @@ export default function PowerConditionalSelect(props) {
sourceKey="pcsMkrCd"
targetKey="pcsMkrCd"
value={selectedMaker}
- onChange={(option) => setSelectedMaker(option)}
+ onChange={(option) => onChangeMaker(option)}
/>
- {managementState?.conType === '1' && (
+ {managementState?.coldRegionFlg === '1' && (
{getMessage('modal.circuit.trestle.setting.power.conditional.select.cold.region')}
)}
@@ -206,7 +240,7 @@ export default function PowerConditionalSelect(props) {
{selectedModels?.map((model) => (
- {model.itemNm}
+ {model.itemNm} onRemoveSelectedModel(model)}>
))}
@@ -214,11 +248,11 @@ export default function PowerConditionalSelect(props) {
-
+ setPcsCheck({ ...pcsCheck, division: !pcsCheck.division })} />
-
+ setPcsCheck({ ...pcsCheck, max: !pcsCheck.max })} />
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx
index 8bb39d4e..b098f409 100644
--- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx
+++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx
@@ -1,133 +1,416 @@
-import { useState } from 'react'
-import { useRecoilValue } from 'recoil'
+import { GlobalDataContext } from '@/app/GlobalDataProvider'
+import QSelectBox from '@/components/common/select/QSelectBox'
+import { useMessage } from '@/hooks/useMessage'
+import { canvasState } from '@/store/canvasAtom'
+import { modelState, pcsCheckState } from '@/store/circuitTrestleAtom'
+import { selectedModuleState } from '@/store/selectedModuleOptions'
+import { useContext, useEffect, useState } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
-import { useMessage } from '@/hooks/useMessage'
-import QSelectBox from '@/components/common/select/QSelectBox'
+import { useMasterController } from '@/hooks/common/useMasterController'
-const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
-
-export default function StepUp({}) {
+export default function StepUp(props) {
const { getMessage } = useMessage()
const [moduleTab, setModuleTab] = useState(1)
+ const [moduleTabs, setModuleTabs] = useState({})
const [arrayLength, setArrayLength] = useState(3) //module-table-inner의 반복 개수
+ const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
+ const { models } = props
+ const { getPcsVoltageStepUpList, getPcsAutoRecommendList } = useMasterController()
+ const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
+ const canvas = useRecoilValue(canvasState)
+ const selectedModules = useRecoilValue(selectedModuleState)
+ const [stepUpListData, setStepUpListData] = useState([])
+ const [optCodes, setOptCodes] = useState([])
- useCanvasPopupStatusController(6)
- const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore)
- if (Object.keys(canvasPopupStatusState[6]).length !== 0) {
+ const [selectedRows, setSelectedRows] = useState({})
+ const [isManualSelection, setIsManualSelection] = useState({})
+
+ // 선택된 값들을 저장할 상태 추가
+ const [selectedValues, setSelectedValues] = useState({})
+
+ // useCanvasPopupStatusController(6)
+ // const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore)
+ // if (Object.keys(canvasPopupStatusState[6]).length !== 0) {
+ // console.log('🚀 ~ useEffect ~ canvasPopupStatusState :', canvasPopupStatusState)
+ // }
+
+ useEffect(() => {
+ // PCS 승압설정 정보 조회
+ fetchStepUpData()
+ }, [])
+
+ // PCS 승압설정 정보 조회
+ const fetchStepUpData = async () => {
+ try {
+ const params = {
+ useYn: props.getOptYn(), // 옵션 Y/N
+ useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List
+ roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록
+ pcsItemList: props.getPcsItemList(), // PCS 아이템 목록
+ }
+
+ // PCS 승압설정 정보 조회
+ const res = await getPcsVoltageStepUpList(params)
+
+ if (res?.result.code === 200 && res?.data) {
+ const dataArray = Array.isArray(res.data) ? res.data : [res.data]
+ const stepUpListData = formatStepUpListData(dataArray)
+
+ // PCS 승압설정 정보 SET
+ setStepUpListData(stepUpListData)
+
+ // PCS 옵션 조회
+ const formattedOptCodes = formatOptionCodes(res.data.optionList)
+ setOptCodes(formattedOptCodes)
+ }
+ } catch (error) {
+ console.error('Error fetching step up data:', error)
+ }
}
+ // PCS 옵션 조회
+ const formatOptionCodes = (optionList = []) => {
+ return optionList?.map((opt) => ({
+ code: opt.pcsOptCd ? opt.pcsOptCd : '',
+ name: opt.pcsOptNm ? opt.pcsOptNm : '',
+ nameJp: opt.pcsOptNmJp ? opt.pcsOptNmJp : '',
+ }))
+ }
+
+ // // PCS 승압설정 정보 포맷
+ // const formatStepUpListData = (dataArray = []) => {
+ // return dataArray?.map((stepUps) => ({
+ // ...stepUps,
+ // optionList: formatOptionList(stepUps.optionList),
+ // pcsItemList: formatPcsItemList(stepUps.pcsItemList),
+ // selectedPcsItem: formatPcsItemList(stepUps.pcsItemList),
+ // }))
+ // }
+
+ // PCS 승압설정 정보 포맷 후 추천 값 저장
+ const formatStepUpListData = (dataArray = []) => {
+ const formattedData = dataArray?.map((stepUps) => ({
+ ...stepUps,
+ optionList: formatOptionList(stepUps.optionList),
+ pcsItemList: formatPcsItemList(stepUps.pcsItemList),
+ selectedPcsItem: formatPcsItemList(stepUps.pcsItemList),
+ }))
+
+ // 초기 추천 값들을 selectedValues에 저장
+ const initialSelectedValues = {}
+ formattedData.forEach((stepUp) => {
+ stepUp.pcsItemList.forEach((pcsItem, pcsIdx) => {
+ const pcsKey = `${stepUp.id}_${pcsIdx}`
+
+ // 추천 값(rmdYn === 'Y') 찾기
+ const recommendedRow = pcsItem.serQtyList.find((item) => item.rmdYn === 'Y')
+ if (recommendedRow) {
+ const selectionData = {
+ stepUpId: pcsItem.goodsNo,
+ pcsInfo: {
+ itemId: pcsItem.itemId,
+ goodsNo: pcsItem.goodsNo,
+ pcsMkrCd: pcsItem.pcsMkrCd,
+ pcsSerCd: pcsItem.pcsSerCd,
+ },
+ allocation: {
+ serQty: recommendedRow.serQty,
+ paralQty: recommendedRow.paralQty,
+ },
+ }
+
+ initialSelectedValues[stepUp.id] = {
+ ...initialSelectedValues[stepUp.id],
+ [pcsKey]: selectionData,
+ }
+ }
+ })
+ })
+
+ setSelectedValues(initialSelectedValues)
+
+ return formattedData
+ }
+
+ // PCS 옵션 포맷
+ const formatOptionList = (optionList = []) => {
+ return optionList?.map((option) => ({
+ pcsOptCd: option.pcsOptCd ? option.pcsOptCd : '',
+ pcsOptNm: option.pcsOptNm ? option.pcsOptNm : '',
+ pcsOptNmJp: option.pcsOptNmJp ? option.pcsOptNmJp : '',
+ }))
+ }
+
+ // PCS 아이템 포맷
+ const formatPcsItemList = (pcsItemList = []) => {
+ return pcsItemList?.map((item) => ({
+ goodsNo: item.goodsNo ? item.goodsNo : '',
+ itemId: item.itemId ? item.itemId : '',
+ itemNm: item.itemNm ? item.itemNm : '',
+ pcsMkrCd: item.pcsMkrCd ? item.pcsMkrCd : '',
+ pcsSerCd: item.pcsSerCd ? item.pcsSerCd : '',
+ connList: formatConnList(item.connList),
+ serQtyList: formatSerQtyList(item.serQtyList),
+ }))
+ }
+
+ // PCS 연결 포맷
+ const formatConnList = (connList = []) => {
+ if (!connList) return [] // null인 경우 빈 배열 반환
+
+ return connList?.map((conn) => ({
+ connAllowCur: conn.connAllowCur ? conn.connAllowCur : 0,
+ connMaxParalCnt: conn.connMaxParalCnt ? conn.connMaxParalCnt : 0,
+ goodsNo: conn.goodsNo ? conn.goodsNo : '',
+ itemId: conn.itemId ? conn.itemId : '',
+ itemNm: conn.itemNm ? conn.itemNm : '',
+ vstuParalCnt: conn.vstuParalCnt ? conn.vstuParalCnt : 0,
+ }))
+ }
+
+ // PCS 시리즈 포맷
+ const formatSerQtyList = (serQtyList = []) => {
+ return serQtyList?.map((qty) => ({
+ serQty: qty.serQty ? qty.serQty : 0,
+ paralQty: qty.paralQty ? qty.paralQty : 0,
+ rmdYn: qty.rmdYn ? qty.rmdYn : 'N',
+ usePossYn: qty.usePossYn ? qty.usePossYn : 'Y',
+ }))
+ }
+
+ // 각 모듈의 탭을 변경하는 함수
+ const handleTabChange = (goodsNo, idx, tabNumber) => {
+ setModuleTabs((prev) => ({
+ ...prev,
+ [`${goodsNo}_${idx}`]: tabNumber,
+ }))
+ }
+
+ // 행 선택 핸들러 함수 추가
+ const handleRowClick = (goodsNo, pcsIdx, serQtyIdx, serQty, paralQty) => {
+ const rowKey = `${goodsNo}_${pcsIdx}_${serQtyIdx}`
+ const pcsKey = `${goodsNo}_${pcsIdx}`
+
+ console.log('goodsNo >> ', goodsNo, serQty, paralQty)
+
+ // 현재 선택된 PCS 아이템 정보 가져오기
+ const pcsItem = stepUpListData.find((stepUp) => stepUp.pcsItemList.find((item) => item.goodsNo === goodsNo))?.pcsItemList[pcsIdx]
+
+ if (!pcsItem) {
+ console.error('PCS item not found:', { goodsNo, pcsIdx })
+ return
+ }
+
+ // 선택된 값들 업데이트 - 더 자세한 정보 포함
+ const selectionData = {
+ goodsNo: goodsNo,
+ pcsInfo: {
+ itemId: pcsItem?.itemId,
+ goodsNo: pcsItem?.goodsNo,
+ pcsMkrCd: pcsItem?.pcsMkrCd,
+ pcsSerCd: pcsItem?.pcsSerCd,
+ },
+ allocation: {
+ serQty: serQty,
+ paralQty: paralQty,
+ },
+ }
+
+ // 선택된 값들 업데이트
+ setSelectedValues((prev) => ({
+ ...prev,
+ [goodsNo]: {
+ ...prev[goodsNo],
+ [pcsKey]: selectionData,
+ },
+ }))
+
+ // 부모 컴포넌트에 선택된 값들 전달
+ if (props.onValuesSelected) {
+ props.onValuesSelected(selectionData)
+ }
+
+ setSelectedRows((prev) => {
+ // 현재 stepUpId에 대한 선택 상태가 없으면 빈 객체로 초기화
+ const currentStepUpSelections = prev[goodsNo] || {}
+
+ // 이미 선택된 행을 다시 클릭하는 경우, 선택을 해제하지 않음
+ if (currentStepUpSelections[pcsKey] === rowKey) {
+ return prev
+ }
+
+ return {
+ ...prev,
+ [goodsNo]: {
+ ...currentStepUpSelections,
+ [pcsKey]: rowKey,
+ },
+ }
+ })
+
+ // 수동 선택 상태를 업데이트하되, 기존 추천 선택은 유지
+ setIsManualSelection((prev) => ({
+ ...prev,
+ [goodsNo]: {
+ ...prev[goodsNo],
+ [pcsKey]: true,
+ },
+ }))
+ }
+
+ // 현재 선택된 값들을 가져오는 함수 추가
+ const getCurrentSelections = () => {
+ return selectedValues
+ }
+
+ // props로 getCurrentSelections 함수 전달
+ useEffect(() => {
+ if (props.onInitialize) {
+ props.onInitialize(getCurrentSelections)
+ }
+ }, [])
+
+ // stepUpListData가 변경될 때마다 업데이트하는 useEffect
+ useEffect(() => {
+ if (props.onInitialize) {
+ // onInitialize를 props에서 가져옴
+ props.onInitialize(() => ({
+ ...getCurrentSelections(),
+ stepUpListData, // stepUpListData를 포함하여 반환
+ }))
+ }
+ }, [stepUpListData])
+
return (
<>
{/* 3개일때 className = by-max */}
-
- {Array.from({ length: arrayLength }).map((_, idx) => (
-
-
- HQJP-KA55-5
-
-
-
-
- | {getMessage('modal.circuit.trestle.setting.step.up.allocation.serial.amount')} |
- {getMessage('modal.circuit.trestle.setting.step.up.allocation.total.amount')} |
-
-
-
-
- | 10 |
- 0 |
-
-
- | 10 |
- 0 |
-
-
- | 10 |
- 0 |
-
-
- | 10 |
- 0 |
-
-
- | 10 |
- 0 |
-
-
- | 10 |
- 0 |
-
-
-
+ {stepUpListData.map((stepUp, index) => (
+
+ {stepUp?.pcsItemList.map((_, idx) => (
+
+
+ {stepUp.pcsItemList[idx].goodsNo}
+
+
+
+
+ | {getMessage('modal.circuit.trestle.setting.step.up.allocation.serial.amount')} |
+ {getMessage('modal.circuit.trestle.setting.step.up.allocation.total.amount')} |
+
+
+
+ {stepUp.pcsItemList[idx].serQtyList.map((item, serQtyIdx) => {
+ const rowKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}_${serQtyIdx}`
+ const pcsKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}`
+ return (
+ handleRowClick(stepUp.pcsItemList[idx].goodsNo, idx, serQtyIdx, item.serQty, item.paralQty)}
+ style={{ cursor: 'pointer' }}
+ >
+ | {item.serQty} |
+ {item.paralQty} |
+
+ )
+ })}
+
+
+
+
+
+ handleTabChange(stepUp.pcsItemList[idx].goodsNo, idx, 1)}
+ >
+ {getMessage('modal.circuit.trestle.setting.step.up.allocation.connected')}
+
+ handleTabChange(stepUp.pcsItemList[idx].goodsNo, idx, 2)}
+ >
+ {getMessage('modal.circuit.trestle.setting.step.up.allocation.option')}
+
+
+
+ {(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 1 && (
+
+
+
+
+
+ | {getMessage('modal.circuit.trestle.setting.power.conditional.select.name')} |
+ {getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')} |
+ {getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')} |
+
+
+
+
+ |
+ {stepUp.pcsItemList[idx].connList?.[0]?.goodsNo ? stepUp.pcsItemList[idx].connList?.[0]?.goodsNo : '-'}
+ |
+
+ {stepUp.pcsItemList[idx].connList?.[0]?.connMaxParalCnt
+ ? (stepUp.pcsItemList[idx].connList?.[0]?.connMaxParalCnt ?? '-')
+ : '-'}
+ |
+
+ {stepUp.pcsItemList[idx].connList?.[0]?.vstuParalCnt ? stepUp.pcsItemList[idx].connList?.[0]?.vstuParalCnt : '-'}
+ |
+
+
+
+
+
+ )}
+ {(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 2 && (
+
+
+
+
+
+ {/* | 名称 |
+ 昇圧回路数 | */}
+ {getMessage('modal.circuit.trestle.setting.power.conditional.select.name')} |
+ {getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')} |
+
+
+
+
+ | - |
+ - |
+
+
+
+
+
+ )}
-
- setModuleTab(1)}>
- {getMessage('modal.circuit.trestle.setting.step.up.allocation.connected')}
-
- setModuleTab(2)}>
- {getMessage('modal.circuit.trestle.setting.step.up.allocation.option')}
-
-
-
- {moduleTab === 1 && (
-
-
-
-
-
- | {getMessage('modal.circuit.trestle.setting.power.conditional.select.name')} |
- {getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')} |
- {getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')} |
-
-
-
-
- | KTN-CBD4C |
- 4 |
- 0 |
-
-
-
-
-
- )}
- {moduleTab === 2 && (
-
-
-
-
-
- | 名称 |
- 昇圧回路数 |
-
-
-
-
- | - |
- - |
-
-
-
-
-
- )}
-
-
- ))}
-
+ ))}
+
+ ))}
{getMessage('modal.circuit.trestle.setting.step.up.allocation.select.monitor')}
-
-
-
+ {optCodes.length > 0 && (
+
+ {/* */}
+
+
+ )}
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx
index 7c01cd6c..a8cb2e7f 100644
--- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx
+++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx
@@ -1,35 +1,449 @@
+import { GlobalDataContext } from '@/app/GlobalDataProvider'
+import { POLYGON_TYPE } from '@/common/common'
+import { useMasterController } from '@/hooks/common/useMasterController'
import { useMessage } from '@/hooks/useMessage'
+import { useSwal } from '@/hooks/useSwal'
+import { canvasState } from '@/store/canvasAtom'
+import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
+import { selectedModuleState } from '@/store/selectedModuleOptions'
+import { useContext, useEffect, useState } from 'react'
+import { useRecoilValue } from 'recoil'
-export default function PassivityCircuitAllocation() {
+export default function PassivityCircuitAllocation(props) {
+ const {
+ tabNum,
+ setTabNum,
+ selectedModels,
+ getOptYn: getApiProps,
+ getUseModuleItemList: getSelectedModuleList,
+ getSelectModelList: getSelectModelList,
+ getRoofSurfaceList,
+ getModelList,
+ } = props
+ const { swalFire } = useSwal()
const { getMessage } = useMessage()
- const moduleData = {
- header: [
- { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' },
- { name: getMessage('modal.circuit.trestle.setting.circuit'), prop: 'circuit' },
- {
- name: getMessage('Q.TRON M-G2'),
- prop: 'moduleName',
- },
- {
- name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`,
- prop: 'powerGeneration',
- },
- ],
- rows: [
- {
- roofShape: { name: 'M 1' },
- circuit: { name: 'M 1' },
- moduleName: { name: '8' },
- powerGeneration: { name: '3,400' },
- },
- {
- roofShape: { name: 'M 1' },
- circuit: { name: 'M 1' },
- moduleName: { name: '8' },
- powerGeneration: { name: '3,400' },
- },
- ],
+ const canvas = useRecoilValue(canvasState)
+ const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
+ const selectedModules = useRecoilValue(selectedModuleState)
+ const moduleStatistics = useRecoilValue(moduleStatisticsState)
+ // const [totalWpout, setTotalWpout] = useState(0)
+ const [selectedPcs, setSelectedPcs] = useState(selectedModels[0])
+ // const { header, rows: row } = moduleStatistics
+ const [header, setHeader] = useState(moduleStatistics.header)
+ const [rows, setRows] = useState(moduleStatistics.rows)
+ const [footer, setFooter] = useState(['합계'])
+ const [circuitNumber, setCircuitNumber] = useState(1)
+ const [targetModules, setTargetModules] = useState([])
+ const { getPcsManualConfChk } = useMasterController()
+
+ useEffect(() => {
+ console.log('header, rows', header, rows)
+ console.log('selectedModels', selectedModels)
+ // setSurfaceInfo()
+ setTableData()
+ if (!managementState) {
+ setManagementState(managementStateLoaded)
+ }
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE)
+ .forEach((obj) => {
+ obj.on('mousedown', (e) => handleTargetModules(obj))
+ })
+
+ return () => {
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE)
+ .forEach((obj) => {
+ obj.set({ strokeWidth: 0.3 })
+ obj.off('mousedown')
+ })
+ canvas.renderAll()
+ }
+ }, [])
+
+ const handleTargetModules = (obj) => {
+ if (!Array.isArray(targetModules)) {
+ setTargetModules([])
+ return
+ }
+
+ setTargetModules((prev) => {
+ if (prev.includes(obj.id)) {
+ obj.set({ strokeWidth: 0.3 })
+ return prev.filter((o) => o !== obj.id)
+ } else {
+ obj.set({ strokeWidth: 2 })
+ return [...prev, obj.id]
+ }
+ })
+
+ canvas.renderAll()
}
+
+ const setSurfaceInfo = () => {
+ const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
+ // setHeaders([header[0], { name: '회로', prop: 'circuit' }, ...header.slice(1)])
+ setRows(
+ rows.map((row) => {
+ return {
+ ...row,
+ circuit: '',
+ }
+ }),
+ )
+ let totals = {}
+
+ rows.forEach((row) => {
+ if (header.length === 4) {
+ if (!totals[header[2].prop]) totals[header[2].prop] = 0
+ totals[header[2].prop] += +row[header[2].prop]
+ } else if (header.length === 5) {
+ if (!totals[header[2].prop]) totals[header[2].prop] = 0
+ totals[header[2].prop] += +row[header[2].prop]
+ if (!totals[header[3].prop]) totals[header[3].prop] = 0
+ totals[header[3]] += +row[header[3]]
+ }
+ })
+ setFooter([
+ ...['합계', ''],
+ ...Object.keys(totals).map((key) => {
+ return totals[key]
+ }),
+ Object.keys(totals).reduce((acc, key) => {
+ return acc + totals[key]
+ }, 0),
+ ])
+ // let totalWpout = 0
+ // const rows = surfaces.map((surface) => {
+ // let wpOut = 0
+ // let moduleInfo = {}
+ // surface.modules.forEach((module) => {
+ // wpOut += +module.moduleInfo.wpOut
+ // if (!moduleInfo[module.moduleInfo.itemId]) moduleInfo[module.moduleInfo.itemId] = 0
+ // moduleInfo[module.moduleInfo.itemId]++
+ // })
+ // totalWpout += wpOut
+ // console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module)
+ // return {
+ // roofShape: DIRECTION[surface.direction],
+ // powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
+ // ...moduleInfo,
+ // }
+ // })
+
+ // setTotalWpout(totalWpout)
+ // 지붕면 리스트 -> 지붕면에 있는 모듈 리스트 -> 발전량 총합 계산
+ // wpOut
+
+ // setModuleData({
+ // header: [
+ // { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' },
+ // { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' },
+ // ...selectedModules.itemList.map((module) => {
+ // return {
+ // name: module.itemNm,
+ // prop: module.itemId,
+ // }
+ // }),
+ // {
+ // name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`,
+ // prop: 'powerGeneration',
+ // },
+ // ],
+ // rows: rows,
+ // })
+ }
+
+ const handleCircuitNumberFix = () => {
+ if (!circuitNumber || circuitNumber === 0) {
+ swalFire({
+ text: '회로번호를 1 이상입력해주세요.',
+ type: 'alert',
+ icon: 'warning',
+ })
+ return
+ } else if (targetModules.length === 0) {
+ swalFire({
+ text: '모듈을 선택해주세요.',
+ type: 'alert',
+ icon: 'warning',
+ })
+ return
+ } else if (selectedModels.length > 1) {
+ const uniqueCircuitNumbers = [
+ ...new Set(
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuitNumber)
+ .map((obj) => obj.circuitNumber),
+ ),
+ ]
+
+ let result = false
+ uniqueCircuitNumbers.forEach((number) => {
+ if (
+ number.split('-')[1] === circuitNumber + ')' &&
+ number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1)
+ ) {
+ result = true
+ }
+ })
+ if (result) {
+ swalFire({
+ text: '회로 번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로 번호를 설정하십시오.',
+ type: 'alert',
+ icon: 'warning',
+ })
+ return
+ }
+ }
+
+ canvas.discardActiveObject()
+ canvas
+ .getObjects()
+ .filter((obj) => targetModules.includes(obj.id))
+ .forEach((obj) => {
+ const moduleCircuitText = new fabric.Text(getCircuitNumber(), {
+ left: obj.left + obj.width / 2,
+ top: obj.top + obj.height / 2,
+ fill: 'black',
+ fontSize: 20,
+ width: obj.width,
+ height: obj.height,
+ textAlign: 'center',
+ originX: 'center',
+ originY: 'center',
+ name: 'circuitNumber',
+ parentId: obj.id,
+ circuitInfo: selectedPcs,
+ })
+ obj.set({
+ strokeWidth: 0.3,
+ })
+ obj.pcsItemId = selectedPcs.itemId
+ obj.circuit = moduleCircuitText
+ obj.circuitNumber = getCircuitNumber()
+ canvas.add(moduleCircuitText)
+ })
+
+ const roofSurfaceList = canvas
+ .getObjects()
+ .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
+ .map((surface) => {
+ return {
+ roofSurfaceId: surface.id,
+ roofSurface: surface.direction,
+ roofSurfaceIncl: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
+ moduleList: surface.modules.map((module) => {
+ return {
+ itemId: module.moduleInfo.itemId,
+ circuit: module.circuitNumber,
+ pcsItemId: module.pcsItemId,
+ }
+ }),
+ }
+ })
+
+ const pcsItemList = selectedModels.map((model) => {
+ return {
+ pcsMkrCd: model.pcsMkrCd,
+ pcsSerCd: model.pcsSerCd,
+ itemId: model.itemId,
+ itemNm: model.itemNm,
+ goodsNo: model.goodsNo,
+ serQtyList: [
+ {
+ serQty: 0,
+ paralQty: 0,
+ rmdYn: 'Y',
+ usePossYn: 'Y',
+ roofSurfaceList: roofSurfaceList,
+ },
+ ],
+ }
+ })
+
+ const params = {
+ ...getApiProps(),
+ useModuleItemList: getSelectedModuleList(),
+ pcsItemList: pcsItemList,
+ }
+
+ getPcsManualConfChk(params).then((res) => {
+ if (res.resultCode === 'E') {
+ swalFire({
+ text: res.resultMsg,
+ type: 'alert',
+ icon: 'warning',
+ confirmFn: () => {
+ const circuitNumbers = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber' && targetModules.includes(obj.parentId))
+ canvas.remove(...circuitNumbers)
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'module' && targetModules.includes(obj.id))
+ .forEach((obj) => {
+ obj.pcsItemId = null
+ obj.circuit = null
+ obj.circuitNumber = null
+ })
+ canvas.renderAll()
+ },
+ })
+
+ return
+ }
+
+ setTargetModules([])
+ setCircuitNumber(+circuitNumber + 1)
+ setTableData()
+ })
+ }
+
+ const getCircuitNumber = () => {
+ if (selectedModels.length === 1) {
+ return `(${circuitNumber})`
+ } else {
+ return `(${selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1}-${circuitNumber})`
+ }
+ }
+
+ const setTableData = () => {
+ const tempHeader = [
+ { name: '지붕면', prop: 'name' },
+ { name: '회로', prop: 'circuit' },
+ ...selectedModules.itemList.map((module) => {
+ return {
+ name: module.itemNm,
+ prop: module.itemId,
+ }
+ }),
+ { name: '발전량(kW)', prop: 'wpOut' },
+ ]
+
+ const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
+ const surfaceIds = surfaces.map((surface) => surface.parentId)
+ const surfaceObjects = {}
+ const rows = surfaces.map((surface) => {
+ const moduleObject = {}
+ surfaceObjects[surface.id] = {
+ roofSurface: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].directionText,
+ circuit: '-',
+ amount: 0,
+ wpOut: 0,
+ circuits: {},
+ }
+
+ surface.modules.forEach((module) => {
+ if (!surfaceObjects[surface.id][module.moduleInfo.itemId]) {
+ // 지붕면에 모듈 존재 여부
+ surfaceObjects[surface.id][module.moduleInfo.itemId] = 0 // 모듈 초기화
+ }
+
+ surfaceObjects[surface.id][module.moduleInfo.itemId]++
+ surfaceObjects[surface.id].wpOut += +module.moduleInfo.wpOut
+ if (module.circuit) {
+ if (!surfaceObjects[surface.id].circuits[module.circuitNumber]) {
+ surfaceObjects[surface.id].circuits[module.circuitNumber] = {
+ circuit: module.circuitNumber,
+ wpOut: 0,
+ circuits: { wpOut: 0 },
+ }
+
+ if (!surfaceObjects[surface.id].circuits[module.circuitNumber].circuits[module.moduleInfo.itemId]) {
+ surfaceObjects[surface.id].circuits[module.circuitNumber].circuits[module.moduleInfo.itemId] = 0
+ }
+ }
+ surfaceObjects[surface.id].circuits[module.circuitNumber].circuits[module.moduleInfo.itemId]++
+ surfaceObjects[surface.id].circuits[module.circuitNumber].circuits.wpOut += +module.moduleInfo.wpOut
+ surfaceObjects[surface.id].wpOut -= +module.moduleInfo.wpOut
+ surfaceObjects[surface.id][module.moduleInfo.itemId]--
+ }
+ })
+ })
+ console.log('rows', rows)
+ console.log('surfaceObjects', surfaceObjects)
+ let tempRows = []
+ Object.keys(surfaceObjects).forEach((key) => {
+ let tempRow = {
+ name: surfaceObjects[key].roofSurface,
+ circuit: surfaceObjects[key].circuit,
+ wpOut: surfaceObjects[key].wpOut,
+ }
+ selectedModules.itemList.forEach((module) => {
+ tempRow[module.itemId] = surfaceObjects[key][module.itemId]
+ })
+ tempRows.push(tempRow)
+
+ Object.keys(surfaceObjects[key].circuits).forEach((circuit) => {
+ let row = {
+ name: surfaceObjects[key].roofSurface,
+ circuit: surfaceObjects[key].circuits[circuit].circuit,
+ wpOut: surfaceObjects[key].circuits[circuit].circuits.wpOut,
+ }
+ selectedModules.itemList.forEach((module) => {
+ row[module.itemId] = surfaceObjects[key].circuits[circuit].circuits[module.itemId]
+ })
+ tempRows.push(row)
+ })
+ })
+ const tempFooter = {
+ name: '총합',
+ circuit: '-',
+ wpOut: tempRows.reduce((acc, row) => acc + row.wpOut, 0),
+ }
+ selectedModules.itemList.forEach((module) => {
+ tempFooter[module.itemId] = tempRows.reduce((acc, row) => acc + row[module.itemId], 0)
+ })
+ console.log('tempHeader, tempRows, tempFooter', tempHeader, tempRows, tempFooter)
+ setHeader(tempHeader)
+ setRows(tempRows.filter((row) => row.wpOut !== 0))
+ setFooter(tempFooter)
+ }
+
+ const initSelectedPcsCircuitNumber = () => {
+ swalFire({
+ title: '선택된 파워 컨디셔너의 회로할당을 초기화합니다.',
+ type: 'confirm',
+ icon: 'warning',
+ confirmFn: () => {
+ const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module' && obj.circuit?.circuitInfo?.id === selectedPcs.id)
+ canvas.remove(...circuitModules.map((module) => module.circuit))
+ circuitModules.forEach((obj) => {
+ obj.circuit = null
+ obj.pcsItemId = null
+ })
+ setTargetModules([])
+
+ canvas.renderAll()
+ canvas.discardActiveObject()
+ },
+ })
+ }
+
+ const initAllPcsCircuitNumber = () => {
+ canvas.discardActiveObject()
+ swalFire({
+ title: '회로 할당의 설정을 초기화합니다.',
+ type: 'confirm',
+ icon: 'warning',
+ confirmFn: () => {
+ const circuitModules = canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id))
+ canvas.remove(...circuitModules.map((module) => module.circuit))
+ circuitModules.forEach((obj) => {
+ obj.circuit = null
+ obj.pcsItemId = null
+ })
+ setTargetModules([])
+
+ canvas.renderAll()
+ },
+ })
+ }
+
return (
<>
@@ -39,26 +453,35 @@ export default function PassivityCircuitAllocation() {
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.info')}
-
-
-
- {moduleData.header.map((header) => (
- | {header.name} |
+ {header && (
+
+
+
+ {header.map((header, index) => (
+ | {header.name} |
+ ))}
+
+
+
+ {rows.map((row, index) => (
+
+ {header.map((header, i) => (
+ |
+ {row[header.prop]}
+ |
+ ))}
+
))}
-
-
-
- {moduleData.rows.map((row, index) => (
-
- {moduleData.header.map((header) => (
- |
- {row[header.prop].name}
+ |
+ {header.map((header, i) => (
+ |
+ {footer[header.prop]}
|
))}
- ))}
-
-
+
+
+ )}
@@ -69,7 +492,27 @@ export default function PassivityCircuitAllocation() {
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional')}
@@ -92,16 +535,25 @@ export default function PassivityCircuitAllocation() {
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num')}
-
+ setCircuitNumber(e.target.value)}
+ />
- {getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix')}
+ handleCircuitNumberFix()}>
+ {getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix')}
+
-
+ initSelectedPcsCircuitNumber()}>
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset')}
-
+ initAllPcsCircuitNumber()}>
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset')}
diff --git a/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx b/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx
index 59c0ead4..1ec3684e 100644
--- a/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx
+++ b/src/components/floor-plan/modal/dimensionLine/DimensionLineSetting.jsx
@@ -85,7 +85,7 @@ export default function DimensionLineSetting(props) {
return (
-
+
{getMessage('contextmenu.display.edit')}
closePopup(id)}>
닫기
@@ -141,6 +141,7 @@ export default function DimensionLineSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/distance/Distance.jsx b/src/components/floor-plan/modal/distance/Distance.jsx
index ac65c1e5..d37302b6 100644
--- a/src/components/floor-plan/modal/distance/Distance.jsx
+++ b/src/components/floor-plan/modal/distance/Distance.jsx
@@ -18,7 +18,7 @@ export default function Distance(props) {
return (
-
+
{getMessage('modal.distance')}
closePopup(id)}>
닫기
@@ -68,6 +68,7 @@ export default function Distance(props) {
+
)
diff --git a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx
index 2b5a7079..56e88ba8 100644
--- a/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx
+++ b/src/components/floor-plan/modal/eavesGable/EavesGableEdit.jsx
@@ -40,7 +40,7 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('modal.eaves.gable.edit')}
closePopup(id)}>
닫기
@@ -62,6 +62,7 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
{type === TYPES.SHED && }
+
)
diff --git a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx
index 18eef849..14c40310 100644
--- a/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx
+++ b/src/components/floor-plan/modal/flowDirection/FlowDirectionSetting.jsx
@@ -65,7 +65,7 @@ export default function FlowDirectionSetting(props) {
return (
-
+
{getMessage('modal.shape.flow.direction.setting')}
closePopup(id)}>
닫기
@@ -176,6 +176,7 @@ export default function FlowDirectionSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx
index da41fdcf..c19f4c26 100644
--- a/src/components/floor-plan/modal/grid/DotLineGrid.jsx
+++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx
@@ -179,7 +179,7 @@ export default function DotLineGrid(props) {
return (
-
+
{getMessage('modal.canvas.setting.grid.dot.line.setting')}
+
)
}
diff --git a/src/components/floor-plan/modal/grid/GridCopy.jsx b/src/components/floor-plan/modal/grid/GridCopy.jsx
index 2f768406..0d34b3d4 100644
--- a/src/components/floor-plan/modal/grid/GridCopy.jsx
+++ b/src/components/floor-plan/modal/grid/GridCopy.jsx
@@ -22,7 +22,7 @@ export default function GridCopy(props) {
return (
-
+
{getMessage('modal.grid.copy')}
closePopup(id)}>
닫기
@@ -77,6 +77,7 @@ export default function GridCopy(props) {
+
)
diff --git a/src/components/floor-plan/modal/grid/GridMove.jsx b/src/components/floor-plan/modal/grid/GridMove.jsx
index f853f135..e28d8564 100644
--- a/src/components/floor-plan/modal/grid/GridMove.jsx
+++ b/src/components/floor-plan/modal/grid/GridMove.jsx
@@ -75,7 +75,7 @@ export default function GridMove(props) {
return (
-
+
{getMessage('modal.grid.move')}
닫기
@@ -156,6 +156,7 @@ export default function GridMove(props) {
+
)
diff --git a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx
index 13a00b06..1ad351eb 100644
--- a/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx
+++ b/src/components/floor-plan/modal/lineProperty/LinePropertySetting.jsx
@@ -52,7 +52,7 @@ export default function LinePropertySetting(props) {
return (
-
+
{getMessage('contextmenu.line.property.edit')}
handleClosePopup()}>
닫기
@@ -91,6 +91,7 @@ export default function LinePropertySetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx b/src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx
index 439e0748..b54d9bf4 100644
--- a/src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx
+++ b/src/components/floor-plan/modal/lineTypes/OuterLineWall.jsx
@@ -18,7 +18,11 @@ export default function OuterLineWall({ props }) {
className="input-origin block"
value={length1}
ref={length1Ref}
- onFocus={(e) => (length1Ref.current.value = '')}
+ onFocus={(e) => {
+ if (length1Ref.current.value === '0') {
+ length1Ref.current.value = ''
+ }
+ }}
onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
diff --git a/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx b/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx
index 3157fe51..62a0baaf 100644
--- a/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx
+++ b/src/components/floor-plan/modal/module/CircuitNumberEdit.jsx
@@ -16,7 +16,7 @@ export default function CircuitNumberEdit(props) {
return (
-
+
{getMessage('modal.module.circuit.number.edit')}
closePopup(id)}>
닫기
@@ -42,6 +42,7 @@ export default function CircuitNumberEdit(props) {
+
)
diff --git a/src/components/floor-plan/modal/module/PanelEdit.jsx b/src/components/floor-plan/modal/module/PanelEdit.jsx
index a6d1d4f9..8e1f9fac 100644
--- a/src/components/floor-plan/modal/module/PanelEdit.jsx
+++ b/src/components/floor-plan/modal/module/PanelEdit.jsx
@@ -84,7 +84,7 @@ export default function PanelEdit(props) {
return (
-
+
{getMessage([PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.COLUMN_MOVE].includes(type) ? 'modal.move.setting' : 'modal.copy.setting')}{' '}
@@ -139,6 +139,7 @@ export default function PanelEdit(props) {
+
)
diff --git a/src/components/floor-plan/modal/module/column/ColumnInsert.jsx b/src/components/floor-plan/modal/module/column/ColumnInsert.jsx
index 56f9a66c..03b5b4e0 100644
--- a/src/components/floor-plan/modal/module/column/ColumnInsert.jsx
+++ b/src/components/floor-plan/modal/module/column/ColumnInsert.jsx
@@ -26,7 +26,7 @@ export default function ColumnInsert(props) {
return (
-
+
{getMessage('modal.panel.column.insert')}
closePopup(id)}>
닫기
@@ -105,6 +105,7 @@ export default function ColumnInsert(props) {
+
)
diff --git a/src/components/floor-plan/modal/module/column/ColumnRemove.jsx b/src/components/floor-plan/modal/module/column/ColumnRemove.jsx
index a18d7982..95cdd942 100644
--- a/src/components/floor-plan/modal/module/column/ColumnRemove.jsx
+++ b/src/components/floor-plan/modal/module/column/ColumnRemove.jsx
@@ -29,7 +29,7 @@ export default function ColumnRemove(props) {
return (
-
+
{getMessage('modal.panel.column.remove')}
closePopup(id)}>
닫기
@@ -115,6 +115,7 @@ export default function ColumnRemove(props) {
+
)
diff --git a/src/components/floor-plan/modal/module/row/RowInsert.jsx b/src/components/floor-plan/modal/module/row/RowInsert.jsx
index 613fb180..fa3c2fff 100644
--- a/src/components/floor-plan/modal/module/row/RowInsert.jsx
+++ b/src/components/floor-plan/modal/module/row/RowInsert.jsx
@@ -26,7 +26,7 @@ export default function RowInsert(props) {
return (
-
+
{getMessage('modal.row.insert')}
closePopup(id)}>
닫기
@@ -105,6 +105,7 @@ export default function RowInsert(props) {
+
)
diff --git a/src/components/floor-plan/modal/module/row/RowRemove.jsx b/src/components/floor-plan/modal/module/row/RowRemove.jsx
index bb1f41cf..70c57c24 100644
--- a/src/components/floor-plan/modal/module/row/RowRemove.jsx
+++ b/src/components/floor-plan/modal/module/row/RowRemove.jsx
@@ -29,7 +29,7 @@ export default function RowRemove(props) {
return (
-
+
{getMessage('modal.row.remove')}
closePopup(id)}>
닫기
@@ -115,6 +115,7 @@ export default function RowRemove(props) {
+
)
diff --git a/src/components/floor-plan/modal/movement/MovementSetting.jsx b/src/components/floor-plan/modal/movement/MovementSetting.jsx
index 416afba8..057d7d37 100644
--- a/src/components/floor-plan/modal/movement/MovementSetting.jsx
+++ b/src/components/floor-plan/modal/movement/MovementSetting.jsx
@@ -18,7 +18,7 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('plan.menu.roof.cover.movement.shape.updown')}
closePopup(id)}>
닫기
@@ -33,7 +33,6 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
))}
- {getMessage('setting')}
{type === TYPE.FLOW_LINE && }
{type === TYPE.UP_DOWN && }
@@ -43,6 +42,7 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
+
)
diff --git a/src/components/floor-plan/modal/object/DormerOffset.jsx b/src/components/floor-plan/modal/object/DormerOffset.jsx
index 191a94ea..a1534891 100644
--- a/src/components/floor-plan/modal/object/DormerOffset.jsx
+++ b/src/components/floor-plan/modal/object/DormerOffset.jsx
@@ -42,7 +42,7 @@ export default function DormerOffset(props) {
return (
-
+
{title}
closePopup(id)}>
닫기
@@ -103,6 +103,7 @@ export default function DormerOffset(props) {
+
)
diff --git a/src/components/floor-plan/modal/object/ObjectSetting.jsx b/src/components/floor-plan/modal/object/ObjectSetting.jsx
index ee6ab256..69c4232c 100644
--- a/src/components/floor-plan/modal/object/ObjectSetting.jsx
+++ b/src/components/floor-plan/modal/object/ObjectSetting.jsx
@@ -77,7 +77,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('plan.menu.placement.surface.object')}
closePopup(id)}>
닫기
@@ -92,7 +92,6 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
))}
- {getMessage('setting')}
{buttonAct === 1 && }
{buttonAct === 2 && }
{buttonAct === 3 && }
@@ -109,6 +108,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
+
)
diff --git a/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx b/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx
index 015ace3e..815175ce 100644
--- a/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx
+++ b/src/components/floor-plan/modal/object/RoofMaterialSetting.jsx
@@ -23,7 +23,7 @@ export default function RoofMaterialSetting(props) {
return (
-
+
{getMessage('modal.roof.material.edit')}
closePopup(id)}>
닫기
@@ -39,6 +39,7 @@ export default function RoofMaterialSetting(props) {
{getMessage('modal.common.save')}
+
)
diff --git a/src/components/floor-plan/modal/object/SizeSetting.jsx b/src/components/floor-plan/modal/object/SizeSetting.jsx
index 3466e2ed..ebb925a6 100644
--- a/src/components/floor-plan/modal/object/SizeSetting.jsx
+++ b/src/components/floor-plan/modal/object/SizeSetting.jsx
@@ -47,7 +47,7 @@ export default function SizeSetting(props) {
return (
-
+
{getMessage('modal.size.setting')}
closePopup(id)}>
닫기
@@ -95,6 +95,7 @@ export default function SizeSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx
index 6c2c8d3f..86724267 100644
--- a/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx
+++ b/src/components/floor-plan/modal/outerlinesetting/PropertiesSetting.jsx
@@ -10,7 +10,7 @@ export default function PropertiesSetting(props) {
return (
-
+
{getMessage('modal.canvas.setting.wallline.properties.setting')}
closeModal(id)}>
닫기
@@ -38,6 +38,7 @@ export default function PropertiesSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx
index 70ff2150..c95c7c5a 100644
--- a/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx
+++ b/src/components/floor-plan/modal/outerlinesetting/WallLineSetting.jsx
@@ -116,7 +116,7 @@ export default function WallLineSetting(props) {
return (
-
+
{getMessage('modal.cover.outline.drawing')}
closePopup(id)}>
@@ -152,7 +152,6 @@ export default function WallLineSetting(props) {
- {getMessage('modal.cover.outline.setting')}
{type === OUTER_LINE_TYPE.OUTER_LINE ? (
) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
@@ -184,6 +183,7 @@ export default function WallLineSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx b/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx
index addc4cf8..2fbe78e9 100644
--- a/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx
+++ b/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx
@@ -3,6 +3,8 @@
import { useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
+import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
+import { useRecoilValue, useResetRecoilState } from 'recoil'
export default function PanelBatchStatistics() {
const { getMessage } = useMessage()
@@ -11,6 +13,7 @@ export default function PanelBatchStatistics() {
x: 0,
y: 30,
})
+ const { header, rows, footer } = useRecoilValue(moduleStatisticsState)
return (
@@ -21,14 +24,26 @@ export default function PanelBatchStatistics() {
- | {getMessage('modal.panel.batch.statistic.roof.shape')} |
- {getMessage('modal.panel.batch.statistic.power.generation.amount')} (kW) |
+ {header.map((item, index) => (
+ {item.name} |
+ ))}
+ {rows.map((row, index) => (
+
+ {header.map((item, i) => (
+ |
+ {typeof row[item.prop] === 'number' ? row[item.prop].toLocaleString('ko-KR', { maximumFractionDigits: 4 }) : row[item.prop]}
+ |
+ ))}
+
+ ))}
- | {getMessage('modal.panel.batch.statistic.total')} |
- 0.000 |
+ {footer.map((item, index) => (
+ {typeof item === 'number' ? item.toLocaleString('ko-KR', { maximumFractionDigits: 4 }) : item} |
+ // {item.amount} |
+ ))}
diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx
index 304d0169..71bed775 100644
--- a/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx
+++ b/src/components/floor-plan/modal/placementShape/PlacementShapeDrawing.jsx
@@ -123,7 +123,7 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('plan.menu.placement.surface.drawing')}
closePopup(id)}>
닫기
@@ -142,7 +142,6 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) {
))}
- {getMessage('setting')}
{buttonAct === 1 && }
{buttonAct === 2 && }
{buttonAct === 3 && }
@@ -155,10 +154,11 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) {
{getMessage('modal.cover.outline.rollback')}
- {getMessage('modal.cover.outline.fix')}
+ {getMessage('modal.placement.surface.drawing.fix')}
+
)
diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
index a9619c2f..1a5ea92a 100644
--- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
+++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
@@ -56,20 +56,24 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
]
// 데이터를 최초 한 번만 조회
- useEffect(() => {
- if (!basicSetting || !currentRoof || Object.keys(currentRoof).length === 0 || Object.keys(basicSetting).length === 0) return
- const raftCodeList = findCommonCode('203800')
- setRaftCodes(raftCodeList)
+ // useEffect(() => {
+ // if (!basicSetting || !currentRoof || Object.keys(currentRoof).length === 0 || Object.keys(basicSetting).length === 0) return
+ // const raftCodeList = findCommonCode('203800')
+ // setRaftCodes(raftCodeList)
+ // console.log('🚀 ~ useEffect ~ >>>>>>>>>>>>> raftCodeList 11 :', raftCodeList)
- if (addedRoofs[0].roofAngleSet && addedRoofs[0].roofAngleSet?.length > 0) {
- setCurrentRoof({ ...currentRoof, roofSizeSet: String(addedRoofs[0].roofSizeSet), roofAngleSet: addedRoofs[0].roofAngleSet })
- } else if (basicSetting.roofAngleSet && basicSetting.roofAngleSet?.length > 0) {
- setCurrentRoof({ ...currentRoof, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
- }
- }, [])
+ // if (addedRoofs[0].roofAngleSet && addedRoofs[0].roofAngleSet?.length > 0) {
+ // setCurrentRoof({ ...currentRoof, roofSizeSet: String(addedRoofs[0].roofSizeSet), roofAngleSet: addedRoofs[0].roofAngleSet })
+ // } else if (basicSetting.roofAngleSet && basicSetting.roofAngleSet?.length > 0) {
+ // setCurrentRoof({ ...currentRoof, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
+ // }
+ // }, [])
useEffect(() => {
if (addedRoofs.length > 0) {
+ const raftCodeList = findCommonCode('203800')
+ setRaftCodes(raftCodeList)
+
setCurrentRoof({ ...addedRoofs[0] })
}
}, [addedRoofs])
@@ -155,20 +159,20 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
...roofInfo,
},
//roofs: addedRoofs,
- roofsData: {
- roofApply: true,
- roofSeq: 0,
- roofMatlCd: currentRoof.roofMatlCd,
- roofWidth: currentRoof.width,
- roofHeight: currentRoof.length,
- roofHajebichi: currentRoof.hajebichi,
- roofGap: currentRoof.raft,
- roofLayout: currentRoof.layout,
- roofSizeSet: currentRoof.roofSizeSet,
- roofAngleSet: currentRoof.roofAngleSet,
- roofPitch: currentRoof.pitch,
- roofAngle: currentRoof.angle,
- },
+ // roofsData: {
+ // roofApply: true,
+ // roofSeq: 0,
+ // roofMatlCd: currentRoof.roofMatlCd,
+ // roofWidth: currentRoof.width,
+ // roofHeight: currentRoof.length,
+ // roofHajebichi: currentRoof.hajebichi,
+ // roofGap: currentRoof.raft,
+ // roofLayout: currentRoof.layout,
+ // roofSizeSet: currentRoof.roofSizeSet,
+ // roofAngleSet: currentRoof.roofAngleSet,
+ // roofPitch: currentRoof.pitch,
+ // roofAngle: currentRoof.angle,
+ // },
})
basicSettingSave()
@@ -177,7 +181,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
return (
-
+
{getMessage('plan.menu.placement.surface.initial.setting')}
closePopup(id)}>
닫기
@@ -256,7 +260,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
title={
currentRoof?.roofSizeSet === '3' ? getMessage('modal.placement.initial.setting.size.none.pitch') : currentRoof?.roofMatlNm
}
- ref={roofRef.roofCd}
+ //ref={roofRef.roofCd}
options={roofMaterials.map((roof) => {
return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp }
})}
@@ -338,13 +342,14 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
{currentRoof && ['C', 'R'].includes(currentRoof.raftAuth) && (
{getMessage('modal.placement.initial.setting.rafter')}
- {raftCodes.length > 0 && (
+ {raftCodes?.length > 0 && (
r.clCode === (currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft)).clCodeNm
+ raftCodes?.find((r) => r.clCode === (currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft))
+ .clCodeNm
}
value={currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft}
onChange={(e) => handleRafterChange(e.clCode)}
@@ -418,6 +423,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
{showSizeGuideModal && }
{showMaterialGuideModal && }
+
)
diff --git a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx
index 431e0f85..7fc56d57 100644
--- a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx
+++ b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx
@@ -242,7 +242,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
return (
-
+
{getMessage('plan.menu.placement.surface.arrangement')}
closePopup(id)}>
닫기
@@ -290,6 +290,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
+
)
diff --git a/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx
index edca1208..d9456bbd 100644
--- a/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx
+++ b/src/components/floor-plan/modal/roofAllocation/ActualSizeSetting.jsx
@@ -63,7 +63,7 @@ export default function ActualSizeSetting(props) {
return (
-
+
{getMessage('modal.actual.size.setting')}
closePopup(id)}>
닫기
@@ -116,6 +116,7 @@ export default function ActualSizeSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx
index e8942948..5bfad3e4 100644
--- a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx
+++ b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx
@@ -45,7 +45,7 @@ export default function ContextRoofAllocationSetting(props) {
return (
-
+
{getMessage('plan.menu.estimate.roof.alloc')}
closePopup(id)}>
닫기
@@ -79,133 +79,134 @@ export default function ContextRoofAllocationSetting(props) {
- {currentRoofList.map((roof, index) => {
- return (
-
-
-
-
-
-
-
-
-
- handleChangeRoofMaterial(e, index)}
- />
-
- {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}}
- {index !== 0 && onDeleteRoofMaterial(index)}>}
-
+ {currentRoofList.length > 0 &&
+ currentRoofList.map((roof, index) => {
+ return (
+
+
+
+
-
-
- {getMessage('slope')}
-
- {
- handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index)
- }}
- defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle}
- />
+
+
+
+
+ handleChangeRoofMaterial(e, index)}
+ />
+
+ {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}}
+ {index !== 0 && onDeleteRoofMaterial(index)}>}
- {pitchText}
-
- {(roof.widAuth || roof.lenAuth) && (
- {roof.widAuth && (
-
- W
-
-
-
+
+ {getMessage('slope')}
+
+ {
+ handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index)
+ }}
+ defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle}
+ />
- )}
- {roof.lenAuth && (
-
- )}
+ {pitchText}
+
- )}
- {(roof.raftAuth || roof.roofPchAuth) && (
-
- {roof.raftAuth && (
-
+ {(roof.widAuth || roof.lenAuth) && (
+
+ {roof.widAuth && (
- {getMessage('modal.placement.initial.setting.rafter')}
- {raftCodes.length > 0 && (
-
-
-
- )}
-
-
- )}
- {roof.roofPchAuth && (
-
-
- {getMessage('hajebichi')}
-
-
- )}
-
- )}
-
-
- {
- handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
- }}
- >
- {getMessage('modal.roof.alloc.select.parallel')}
-
-
- {
- handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
- }}
- >
- {getMessage('modal.roof.alloc.select.stairs')}
-
+ )}
+ {roof.lenAuth && (
+
+ )}
+
+ )}
+ {(roof.raftAuth || roof.roofPchAuth) && (
+
+ {roof.raftAuth && (
+
+
+ {getMessage('modal.placement.initial.setting.rafter')}
+ {raftCodes.length > 0 && (
+
+
+
+ )}
+
+
+ )}
+ {roof.roofPchAuth && (
+
+
+ {getMessage('hajebichi')}
+
+
+
+
+
+ )}
+
+ )}
+
+
+ {
+ handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
+ }}
+ >
+ {getMessage('modal.roof.alloc.select.parallel')}
+
+
+ {
+ handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
+ }}
+ >
+ {getMessage('modal.roof.alloc.select.stairs')}
+
+
-
- )
- })}
+ )
+ })}
@@ -213,6 +214,7 @@ export default function ContextRoofAllocationSetting(props) {
+
)
diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx
index 4118db79..0142a329 100644
--- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx
+++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx
@@ -49,7 +49,7 @@ export default function RoofAllocationSetting(props) {
{currentRoofList && (
<>
-
+
{getMessage('plan.menu.estimate.roof.alloc')}
closePopup(id)}>
닫기
@@ -235,6 +235,7 @@ export default function RoofAllocationSetting(props) {
>
)}
+
)
diff --git a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx
index 090eec0a..b47d2356 100644
--- a/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx
+++ b/src/components/floor-plan/modal/roofShape/RoofShapePassivitySetting.jsx
@@ -31,7 +31,7 @@ export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 }
return (
-
+
{getMessage('plan.menu.roof.cover.roof.shape.passivity.setting')}
closePopup(id)}>
닫기
@@ -67,6 +67,7 @@ export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 }
+
)
diff --git a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx
index b43bdd18..2a59cc91 100644
--- a/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx
+++ b/src/components/floor-plan/modal/roofShape/RoofShapeSetting.jsx
@@ -90,7 +90,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('modal.roof.shape.setting')}
closePopup(id)}>
닫기
@@ -108,7 +108,6 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
))}
- {getMessage('setting')}
{shapeNum === 1 && }
{(shapeNum === 2 || shapeNum === 3) && }
{shapeNum === 4 && }
@@ -120,6 +119,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
+
)
diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx
index f5e6e3ca..0ccd337a 100644
--- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx
+++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx
@@ -75,7 +75,7 @@ export default function SettingModal01(props) {
<>
-
+
{getMessage('modal.canvas.setting')}
closePopup(id, true)}>
닫기
@@ -100,6 +100,7 @@ export default function SettingModal01(props) {
{buttonAct === 2 && }
{buttonAct === 3 && }
+
>
diff --git a/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx b/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx
index 571741ed..9aae056b 100644
--- a/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx
+++ b/src/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting.jsx
@@ -192,7 +192,7 @@ export default function DimensionLineSetting(props) {
return (
-
+
{getMessage('modal.canvas.setting.font.plan.absorption.dimension.line')}
+
)
diff --git a/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx b/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx
index 0691046d..708897c0 100644
--- a/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx
+++ b/src/components/floor-plan/modal/setting01/planSize/PlanSizeSetting.jsx
@@ -57,7 +57,7 @@ export default function PlanSizeSetting(props) {
return (
-
+
{getMessage('modal.canvas.setting.font.plan.absorption.plan.size.setting')}
+
)
diff --git a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx
index 0edafff9..5e01918d 100644
--- a/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx
+++ b/src/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting.jsx
@@ -41,7 +41,7 @@ export default function WallLineOffsetSetting({ id, pos = { x: 50, y: 230 } }) {
return (
-
+
{getMessage('modal.wallline.offset.setting')}
closePopup(id)}>
닫기
@@ -66,6 +66,7 @@ export default function WallLineOffsetSetting({ id, pos = { x: 50, y: 230 } }) {
+
)
diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx
index 1a39e9e1..ab6b74b7 100644
--- a/src/components/header/Header.jsx
+++ b/src/components/header/Header.jsx
@@ -221,7 +221,7 @@ export default function Header(props) {
return (
<>
- {!isGlobalLoading && !(pathName.includes('login') || pathName.includes('join') || sessionState.pwdInitYn === 'N') && (
+ {!(pathName.includes('login') || pathName.includes('join') || sessionState.pwdInitYn === 'N') && (
diff --git a/src/components/main/MainContents.jsx b/src/components/main/MainContents.jsx
index 766d7efc..3c1e184b 100644
--- a/src/components/main/MainContents.jsx
+++ b/src/components/main/MainContents.jsx
@@ -10,12 +10,12 @@ import { useRecoilValue } from 'recoil'
import { useRouter } from 'next/navigation'
import { globalLocaleStore } from '@/store/localeAtom'
import { queryStringFormatter } from '@/util/common-utils'
-import MainSkeleton from '../ui/MainSkeleton'
import { useMainContentsController } from '@/hooks/main/useMainContentsController'
import { QcastContext } from '@/app/QcastProvider'
import { useSwal } from '@/hooks/useSwal'
import BoardDetailModal from '../community/modal/BoardDetailModal'
+import { handleFileDown } from '@/util/board-utils'
export default function MainContents() {
const { swalFire } = useSwal()
@@ -23,26 +23,53 @@ export default function MainContents() {
const { getMessage } = useMessage()
const router = useRouter()
const globalLocaleState = useRecoilValue(globalLocaleStore)
- const { promiseGet } = useAxios(globalLocaleState)
-
+ const { promiseGet, get } = useAxios(globalLocaleState)
//공지사항
const [recentNoticeList, setRecentNoticeList] = useState([])
//FAQ
const [recentFaqList, setRecentFaqList] = useState([])
- const { qcastState } = useContext(QcastContext)
+ const { qcastState, setIsGlobalLoading } = useContext(QcastContext)
const { fetchObjectList, initObjectList } = useMainContentsController()
+ //첨부파일
+ const [boardList, setBoardList] = useState([])
useEffect(() => {
fetchObjectList()
fetchNoticeList()
fetchFaqList()
+ //첨부파일 목록 호출
+ fetchArchiveList()
return () => {
initObjectList()
}
}, [])
+ //첨부파일 목록 호출
+ const fetchArchiveList = async () => {
+ const url = `/api/board/list`
+
+ const params = new URLSearchParams({
+ schNoticeTpCd: 'QC',
+ schNoticeClsCd: 'DOWN',
+ startRow: 1,
+ endRow: 2,
+ schMainYn: 'Y',
+ })
+
+ const apiUrl = `${url}?${params.toString()}`
+ const resultData = await get({ url: apiUrl })
+
+ if (resultData) {
+ if (resultData.result.code === 200) {
+ setBoardList(resultData.data)
+ } else {
+ alert(resultData.result.message)
+ }
+ }
+ }
+
//공지사항 호출
const fetchNoticeList = async () => {
try {
@@ -105,6 +132,7 @@ export default function MainContents() {
key={row.objectNo}
className="recently-item"
onClick={() => {
+ setIsGlobalLoading(true)
if (row.tempFlg === '0') {
router.push(`/management/stuff/detail?objectNo=${row.objectNo.toString()}`, { scroll: false })
} else {
@@ -114,7 +142,7 @@ export default function MainContents() {
>
{dayjs(row.lastEditDatetime).format('YYYY.MM.DD HH:mm:ss')}
- {row.tempFlg === '0' ? row.objectNo : getMessage('stuff.gridData.tempObjectNo')}
+ {row.tempFlg === '0' ? row.objectNo : getMessage('stuff.gridData.tempObjectNo')}
{row.objectName ? row.objectName : '-'}
{row.saleStoreName}
@@ -183,14 +211,19 @@ export default function MainContents() {
)}
-
- swalFire({ text: getMessage('main.content.alert.noFile'), type: 'alert' })}>
- {getMessage('main.content.download1')}
-
- swalFire({ text: getMessage('main.content.alert.noFile'), type: 'alert' })}>
- {getMessage('main.content.download2')}
-
-
+ {boardList.length > 0 ? (
+
+ {boardList?.map((board) => (
+ handleFileDown(board.noticeNo, 'Y')}>
+ {board.title}
+
+ ))}
+
+ ) : (
+
+ {getMessage('common.message.no.data')}
+
+ )}
diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx
index f55815fb..63d9ecad 100644
--- a/src/components/management/Stuff.jsx
+++ b/src/components/management/Stuff.jsx
@@ -15,12 +15,12 @@ import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json'
import QPagination from '../common/pagination/QPagination'
import { SessionContext } from '@/app/SessionProvider'
-
+import { useSwal } from '@/hooks/useSwal'
import { QcastContext } from '@/app/QcastProvider'
export default function Stuff() {
const { setIsGlobalLoading } = useContext(QcastContext)
-
+ const { swalFire } = useSwal()
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
const { session } = useContext(SessionContext)
const setAppMessageState = useSetRecoilState(appMessageStore)
@@ -41,20 +41,18 @@ export default function Stuff() {
//그리드 내부 복사버튼
const copyNo = async (value) => {
- // try {
- // await navigator.clipboard.writeText(value)
- // alert(getMessage('stuff.detail.header.successCopy'))
- // } catch (error) {
- // alert(getMessage('stuff.detail.header.failCopy'))
- // }
- // Navigator clipboard api needs a secure context (https)
if (navigator.clipboard && window.isSecureContext) {
+ console.log('trttt')
await navigator.clipboard
.writeText(value)
.then(() => {
- alert(getMessage('stuff.detail.header.successCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.successCopy'),
+ type: 'alert',
+ })
})
- .catch(() => {
+ .catch((e) => {
+ console.log(e)
alert(getMessage('stuff.detail.header.failCopy'))
})
} else {
@@ -71,7 +69,10 @@ export default function Stuff() {
try {
document.execCommand('copy')
- alert(getMessage('stuff.detail.header.successCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.successCopy'),
+ type: 'alert',
+ })
} catch (err) {
alert(getMessage('stuff.detail.header.failCopy'))
} finally {
@@ -122,7 +123,7 @@ export default function Stuff() {
type="button"
className="copy_ico"
onClick={() => {
- copyNo(params.value)
+ copyNo(params?.value)
}}
>
>
@@ -219,6 +220,9 @@ export default function Stuff() {
pageSize: stuffSearchParams?.pageSize ? stuffSearchParams.pageSize : 100,
}
+ if (!params.saleStoreId) {
+ params.saleStoreId = session.storeId
+ }
async function fetchData() {
const apiUrl = `/api/object/list?${queryStringFormatter(params)}`
await get({
@@ -271,6 +275,17 @@ export default function Stuff() {
stuffSearchParams.schSortType = defaultSortType
stuffSearchParams.pageNo = stuffSearchParams.pageNo
+ if (!stuffSearchParams.saleStoreId) {
+ stuffSearchParams.saleStoreId = session.storeId
+ }
+ if (stuffSearchParams.schMyDataCheck) {
+ if (session.storeLvl === '1') {
+ //schOtherSelSaleStoreId 초기화 schSelSaleStoreId 에 saleStoreId 담아서 보내기
+ stuffSearchParams.schOtherSelSaleStoreId = ''
+ stuffSearchParams.schSelSaleStoreId = session.storeId
+ }
+ }
+
async function fetchData() {
const apiUrl = `/api/object/list?${queryStringFormatter(stuffSearchParams)}`
await get({ url: apiUrl }).then((res) => {
@@ -301,6 +316,15 @@ export default function Stuff() {
stuffSearchParams.schSortType = defaultSortType
setPageNo(1)
+ if (!params.saleStoreId) {
+ stuffSearchParams.saleStoreId = session.storeId
+ }
+ if (stuffSearchParams.schMyDataCheck) {
+ //schOtherSelSaleStoreId 초기화 schSelSaleStoreId 에 saleStoreId 담아서 보내기
+ stuffSearchParams.schOtherSelSaleStoreId = ''
+ stuffSearchParams.schSelSaleStoreId = session.storeId
+ }
+
async function fetchData() {
const apiUrl = `/api/object/list?${queryStringFormatter(stuffSearchParams)}`
await get({ url: apiUrl }).then((res) => {
@@ -336,6 +360,7 @@ export default function Stuff() {
code: 'S',
pageNo: 1,
pageSize: 100,
+ schMyDataCheck: false,
}
setStuffSearch({
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx
index 15ea41fc..e4ef732c 100644
--- a/src/components/management/StuffDetail.jsx
+++ b/src/components/management/StuffDetail.jsx
@@ -4,7 +4,6 @@ import { useState, useEffect, useRef, useContext } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { Button } from '@nextui-org/react'
import Select, { components } from 'react-select'
-import Link from 'next/link'
import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom'
import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
@@ -289,10 +288,12 @@ export default function StuffDetail() {
display: 'none',
}
}
- // if (managementState?.createUser === 'T01' && session?.userId !== 'T01') {
- //createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 적용할지 미정!!!!!!!!
- //buttonStyle = { display: 'none' }
- // }
+ if (managementState?.createUser === 'T01') {
+ if (session.userId !== 'T01') {
+ // #474
+ buttonStyle = { display: 'none' }
+ }
+ }
return (
<>
@@ -301,9 +302,9 @@ export default function StuffDetail() {
type="button"
className="grid-btn"
onClick={() => {
- //mid:5(견적서), /pid:플랜번호
setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo })
setIsGlobalLoading(true)
+ setMenuNumber(5)
router.push(`/floor-plan/estimate/5?pid=${params.data.planNo}&objectNo=${params.data.objectNo}`)
}}
>
@@ -349,6 +350,10 @@ export default function StuffDetail() {
if (res?.data?.createUser === 'T01' && session?.userId !== 'T01') {
//createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기
setShowButton('none')
+ } else {
+ if (session.userId !== res?.data?.createUser) {
+ setShowButton('none')
+ }
}
if (isObjectNotEmpty(res.data)) {
let surfaceTypeValue
@@ -357,7 +362,7 @@ export default function StuffDetail() {
} else if (res.data.surfaceType === 'Ⅱ') {
surfaceTypeValue = '2'
}
- setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
+ setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue, firstFlag: 'Y' })
} else {
setManagementState({})
swalFire({
@@ -449,7 +454,6 @@ export default function StuffDetail() {
firstList = res
favList = res.filter((row) => row.priority !== 'B')
otherList = res.filter((row) => row.firstAgentYn === 'N')
-
setSaleStoreList(firstList)
setFavoriteStoreList(firstList)
setShowSaleStoreList(firstList)
@@ -526,6 +530,11 @@ export default function StuffDetail() {
get({ url: url }).then((res) => {
if (!isEmptyArray(res)) {
if (session?.storeId === 'T01') {
+ //즐겨찾기 구분 추가
+ res.map((row) => {
+ row.value = row.saleStoreId
+ row.label = row.saleStoreName
+ })
firstList = res.filter((row) => row.saleStoreLevel === '1')
firstList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
favList = firstList.filter((row) => row.saleStoreId === 'T01' || row.priority !== 'B')
@@ -648,7 +657,7 @@ export default function StuffDetail() {
//염해지역용아이템사용 saltAreaFlg 1이면 true
form.setValue('saltAreaFlg', managementState.saltAreaFlg === '1' ? true : false)
//설치높이
- let installHeight = managementState.installHeight ? managementState.installHeight.split('.')[0] : '0'
+ let installHeight = managementState.installHeight ? managementState.installHeight.split('.')[0] : ''
form.setValue('installHeight', installHeight)
//계약조건 null로 내려오면 0으로 디폴트셋팅
if (managementState.conType === null) {
@@ -984,7 +993,7 @@ export default function StuffDetail() {
form.setValue('saltAreaFlg', false)
}
- let installHeight = info.installHeight ? info.installHeight.split('.')[0] : '0'
+ let installHeight = info.installHeight ? info.installHeight.split('.')[0] : ''
form.setValue('installHeight', installHeight)
form.setValue('remarks', info.remarks)
@@ -1024,6 +1033,8 @@ export default function StuffDetail() {
const _objectNameOmit = watch('objectNameOmit')
// saleStoreId: '', //1차 판매점ID
const _saleStoreId = watch('saleStoreId')
+ // 2차 판매점명
+ const _otherSaleStoreId = watch('otherSaleStoreId')
// zipNo: '', //우편번호
const _zipNo = watch('zipNo')
// prefId: '', //도도부현
@@ -1042,6 +1053,7 @@ export default function StuffDetail() {
useEffect(() => {
if (editMode === 'NEW') {
const formData = form.getValues()
+
let errors = {}
if (!formData.receiveUser || formData.receiveUser.trim().length === 0) {
errors.receiveUser = true
@@ -1056,6 +1068,12 @@ export default function StuffDetail() {
errors.saleStoreId = true
}
+ if (session?.storeLvl === '2') {
+ if (!formData.otherSaleStoreId) {
+ errors.otherSaleStoreId = true
+ }
+ }
+
if (!formData.zipNo) {
errors.zipNo = true
}
@@ -1098,6 +1116,12 @@ export default function StuffDetail() {
errors.saleStoreId = true
}
+ if (session?.storeLvl === '2') {
+ if (!formData.otherSaleStoreId) {
+ errors.otherSaleStoreId = true
+ }
+ }
+
if (!formData.zipNo) {
errors.zipNo = true
}
@@ -1129,6 +1153,7 @@ export default function StuffDetail() {
_objectName,
_objectNameOmit,
_saleStoreId,
+ _otherSaleStoreId,
_zipNo,
_prefId,
_address,
@@ -1357,7 +1382,7 @@ export default function StuffDetail() {
//로그인이 2차점인데 otherSaleStoreId가 없으면 알럿
if (session.storeLvl !== '1') {
if (params.saleStoreLevel === '1') {
- return swalFire({ text: getMessage('stuff.detail.tempSave.message4'), type: 'alert' })
+ return swalFire({ text: getMessage('stuff.detail.tempSave.message3'), type: 'alert' })
}
}
@@ -1367,13 +1392,12 @@ export default function StuffDetail() {
setIsGlobalLoading(true)
//상세화면으로 전환
if (res.status === 201) {
+ setIsGlobalLoading(false)
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
swalFire({
text: getMessage('stuff.detail.save'),
type: 'alert',
confirmFn: () => {
- setIsGlobalLoading(false)
-
router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
},
})
@@ -1390,13 +1414,13 @@ export default function StuffDetail() {
setIsGlobalLoading(true)
if (res.status === 201) {
+ setIsGlobalLoading(false)
setFloorPlanObjectNo({ floorPlanObjectNo: res.data.objectNo })
swalFire({
text: getMessage('stuff.detail.save'),
type: 'alert',
confirmFn: () => {
- setIsGlobalLoading(false)
- router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
+ callDetailApi(objectNo)
},
})
}
@@ -1408,6 +1432,25 @@ export default function StuffDetail() {
}
}
+ const callDetailApi = async (objectNo) => {
+ await promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => {
+ if (res?.data?.createUser === 'T01' && session?.userId !== 'T01') {
+ setShowButton('none')
+ } else {
+ if (session.userId !== res?.data?.createUser) {
+ setShowButton('none')
+ }
+ }
+ let surfaceTypeValue
+ if (res.data.surfaceType === 'Ⅲ・Ⅳ') {
+ surfaceTypeValue = '3'
+ } else {
+ surfaceTypeValue = '2'
+ }
+ setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
+ })
+ }
+
// 임시저장
const onTempSave = async () => {
const formData = form.getValues()
@@ -1447,6 +1490,13 @@ export default function StuffDetail() {
params.saleStoreLevel = session.storeLvl
}
+ if (session.storeLvl !== '1') {
+ //로그인이 1차점이 아닌데 2차점을 안골라서 saleStoreLevel = 1로 셋팅되어있으면 알럿
+ if (params.saleStoreLevel === '1') {
+ return swalFire({ text: getMessage('stuff.detail.tempSave.message3'), type: 'alert' })
+ }
+ }
+
// 담당자 자리수 체크
if (params?.receiveUser !== '') {
if (params?.receiveUser.trim().length > 10) {
@@ -1460,11 +1510,11 @@ export default function StuffDetail() {
.then((res) => {
setIsGlobalLoading(true)
if (res.status === 201) {
+ setIsGlobalLoading(false)
swalFire({
text: getMessage('stuff.detail.tempSave.message1'),
type: 'alert',
confirmFn: () => {
- setIsGlobalLoading(false)
router.push(`/management/stuff/tempdetail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
},
})
@@ -1479,11 +1529,11 @@ export default function StuffDetail() {
.then((res) => {
setIsGlobalLoading(true)
if (res.status === 201) {
+ setIsGlobalLoading(false)
swalFire({
text: getMessage('stuff.detail.tempSave.message1'),
type: 'alert',
confirmFn: () => {
- setIsGlobalLoading(false)
router.push(`/management/stuff/tempdetail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
},
})
@@ -1511,7 +1561,7 @@ export default function StuffDetail() {
confirmFn: () => {
setFloorPlanObjectNo({ floorPlanObjectNo: '' })
del({ url: `/api/object/${objectNo}?${queryStringFormatter(delParams)}` })
- .then((res) => {
+ .then(() => {
setIsGlobalLoading(true)
setFloorPlanObjectNo({ floorPlanObjectNo: '' })
if (session.storeId === 'T01') {
@@ -1587,6 +1637,13 @@ export default function StuffDetail() {
// 그리드 더블 클릭 해당플랜의 도면작성 화면으로 이동
const getCellDoubleClicked = (params) => {
+ //#474정책
+ if (managementState.createUser === 'T01') {
+ if (session.userId !== 'T01') {
+ return false
+ }
+ }
+
if (params?.column?.colId !== 'estimateDate') {
if (params?.data?.planNo && params?.data?.objectNo) {
let objectNo = params?.data?.objectNo
@@ -1603,6 +1660,31 @@ export default function StuffDetail() {
}
}
+ const CustomOption = (props) => {
+ const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
+ const customClass = data.saleStoreId === 'T01' || data.priority !== 'B' ? 'special-option' : ''
+ // 기본 선택/호버 상태 적용
+ const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
+
+ return (
+
+ {data.label}
+
+ )
+ }
+
+ const CustomOption2 = (props) => {
+ const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
+ const customClass = data.priority !== 'B' ? 'special-option' : ''
+ // 기본 선택/호버 상태 적용
+ const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
+ return (
+
+ {data.label}
+
+ )
+ }
+
return (
<>
{(editMode === 'NEW' && (
@@ -1623,11 +1705,21 @@ export default function StuffDetail() {
{getMessage('stuff.detail.btn.save')}
)}
-
+ {/*
{getMessage('stuff.detail.btn.moveList')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.detail.btn.moveList')}
+
@@ -1760,6 +1852,7 @@ export default function StuffDetail() {
value={saleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
+ components={{ Option: CustomOption }}
>
@@ -1792,6 +1885,7 @@ export default function StuffDetail() {
value={showSaleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
+ // components={{ Option: CustomOption }}
>
@@ -1823,6 +1917,7 @@ export default function StuffDetail() {
value={showSaleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
+ // components={{ Option: CustomOption }}
>
@@ -1875,11 +1970,11 @@ export default function StuffDetail() {
? true
: false
}
- // isDisabled={otherSaleStoreList != null && otherSaleStoreList.length === 1 ? true : false}
isClearable={true}
value={otherSaleStoreList.filter(function (option) {
return option.saleStoreId === otherSelOptions
})}
+ components={{ Option: CustomOption2 }}
/>
@@ -2123,11 +2218,21 @@ export default function StuffDetail() {
{getMessage('stuff.detail.btn.save')}
)}
-
+ {/*
{getMessage('stuff.detail.btn.moveList')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.detail.btn.moveList')}
+
@@ -2142,11 +2247,21 @@ export default function StuffDetail() {
{managementState?.tempFlg === '0' ? (
<>
-
+ {/*
{getMessage('stuff.detail.btn.moveList')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.detail.btn.moveList')}
+
{getMessage('stuff.detail.btn.save')}
@@ -2167,11 +2282,21 @@ export default function StuffDetail() {
{getMessage('stuff.detail.btn.save')}
)}
-
+ {/*
{getMessage('stuff.detail.btn.moveList')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.detail.btn.moveList')}
+
>
)}
@@ -2296,7 +2421,7 @@ export default function StuffDetail() {
<>
@@ -2352,6 +2478,7 @@ export default function StuffDetail() {
value={showSaleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
+ // components={{ Option: CustomOption }}
/>
@@ -2386,6 +2513,7 @@ export default function StuffDetail() {
return option.saleStoreId
}
})}
+ // components={{ Option: CustomOption }}
/>
@@ -2425,19 +2553,22 @@ export default function StuffDetail() {
onChange={onSelectionChange2}
getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId}
- // isDisabled={
- // managementState?.tempFlg === '0'
- // ? true
- // : session?.storeLvl === '1' && form.watch('saleStoreId') != ''
- // ? false
- // : false
- // }
- isDisabled={managementState?.tempFlg === '0' ? true : false}
+ isDisabled={
+ managementState?.tempFlg === '0'
+ ? true
+ : session?.storeLvl === '1'
+ ? otherSaleStoreList.length > 0
+ ? false
+ : true
+ : otherSaleStoreList.length === 1
+ ? true
+ : false
+ }
isClearable={managementState?.tempFlg === '0' ? false : true}
- // isClearable={managementState?.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : true}
value={otherSaleStoreList.filter(function (option) {
return option.saleStoreId === otherSelOptions
})}
+ // components={{ Option: CustomOption2 }}
/>
@@ -2721,11 +2852,21 @@ export default function StuffDetail() {
{/* 진짜R 플랜끝 */}
-
+ {/*
{getMessage('stuff.detail.btn.moveList')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.detail.btn.moveList')}
+
{getMessage('stuff.detail.btn.save')}
@@ -2746,11 +2887,21 @@ export default function StuffDetail() {
{getMessage('stuff.detail.btn.save')}
)}
-
+ {/*
{getMessage('stuff.detail.btn.moveList')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.detail.btn.moveList')}
+
>
)}
diff --git a/src/components/management/StuffHeader.jsx b/src/components/management/StuffHeader.jsx
index 76fb6877..5fd12414 100644
--- a/src/components/management/StuffHeader.jsx
+++ b/src/components/management/StuffHeader.jsx
@@ -1,31 +1,26 @@
'use client'
-import { useContext } from 'react'
+import { useContext, useEffect } from 'react'
import { useMessage } from '@/hooks/useMessage'
import dayjs from 'dayjs'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
// import { ManagementContext } from '@/app/management/ManagementProvider'
+import { useSwal } from '@/hooks/useSwal'
export default function StuffHeader() {
const { getMessage } = useMessage()
+ const { swalFire } = useSwal()
const { managementState } = useContext(GlobalDataContext)
- //물건번호 복사
- // const copyObjectNo = async (objectNo) => {
- // await navigator.clipboard.writeText(objectNo)
- // alert(getMessage('stuff.detail.header.successCopy'))
- // try {
- // } catch (error) {
- // alert(getMessage('stuff.detail.header.failCopy'))
- // }
- // }
-
const copyObjectNo = async (objectNo) => {
if (navigator.clipboard && window.isSecureContext) {
await navigator.clipboard
.writeText(objectNo)
.then(() => {
- alert(getMessage('stuff.detail.header.successCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.successCopy'),
+ type: 'alert',
+ })
})
.catch(() => {
alert(getMessage('stuff.detail.header.failCopy'))
@@ -44,7 +39,10 @@ export default function StuffHeader() {
try {
document.execCommand('copy')
- alert(getMessage('stuff.detail.header.successCopy'))
+ swalFire({
+ text: getMessage('stuff.detail.header.successCopy'),
+ type: 'alert',
+ })
} catch (err) {
alert(getMessage('stuff.detail.header.failCopy'))
} finally {
@@ -69,7 +67,9 @@ export default function StuffHeader() {
{getMessage('stuff.detail.header.specificationConfirmDate')}
- {managementState?.specificationConfirmDate}
+
+ {managementState?.specificationConfirmDate ? `${dayjs(managementState.specificationConfirmDate).format('YYYY.MM.DD HH:mm:ss')}` : ''}
+
{getMessage('stuff.detail.header.lastEditDatetime')}
diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx
index ad265c55..9f840fc6 100644
--- a/src/components/management/StuffSearchCondition.jsx
+++ b/src/components/management/StuffSearchCondition.jsx
@@ -10,7 +10,7 @@ import JA from '@/locales/ja.json'
import { stuffSearchState } from '@/store/stuffAtom'
import { isEmptyArray } from '@/util/common-utils'
import dayjs from 'dayjs'
-import Link from 'next/link'
+import { useRouter } from 'next/navigation'
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
import { useMessage } from '@/hooks/useMessage'
import { isObjectNotEmpty } from '@/util/common-utils'
@@ -20,6 +20,7 @@ import { SessionContext } from '@/app/SessionProvider'
import { QcastContext } from '@/app/QcastProvider'
export default function StuffSearchCondition() {
+ const router = useRouter()
const { session } = useContext(SessionContext)
const setAppMessageState = useSetRecoilState(appMessageStore)
const globalLocaleState = useRecoilValue(globalLocaleStore)
@@ -342,7 +343,7 @@ export default function StuffSearchCondition() {
})
} else {
if (session?.storeLvl === '2') {
- if (otherSaleStoreList.length > 1) {
+ if (otherSaleStoreList.length === 1) {
setOtherSaleStoreId(session.storeId)
stuffSearch.schOtherSelSaleStoreId = session.storeId
stuffSearch.schObjectNo = ''
@@ -355,6 +356,24 @@ export default function StuffSearchCondition() {
stuffSearch.schTempFlg = ''
stuffSearch.schMyDataCheck = false
+ stuffSearch.startRow = 1
+ stuffSearch.endRow = 100
+ stuffSearch.schSortType = 'U'
+ stuffSearch.pageNo = 1
+ stuffSearch.pageSize = 100
+ } else if (otherSaleStoreList.length > 1) {
+ setOtherSaleStoreId('')
+ stuffSearch.schOtherSelSaleStoreId = session.storeId
+ stuffSearch.schObjectNo = ''
+ stuffSearch.schAddress = ''
+ stuffSearch.schObjectName = ''
+ stuffSearch.schSaleStoreName = ''
+ stuffSearch.schReceiveUser = ''
+ stuffSearch.schDispCompanyName = ''
+ stuffSearch.schDateType = 'U'
+ stuffSearch.schTempFlg = ''
+ stuffSearch.schMyDataCheck = false
+
stuffSearch.startRow = 1
stuffSearch.endRow = 100
stuffSearch.schSortType = 'U'
@@ -446,6 +465,7 @@ export default function StuffSearchCondition() {
allList = res
allList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
favList = res.filter((row) => row.saleStoreId === 'T01' || row.priority !== 'B')
+
setSchSelSaleStoreList(allList)
setFavoriteStoreList(favList)
setShowSaleStoreList(favList)
@@ -503,13 +523,23 @@ export default function StuffSearchCondition() {
})
} else {
if (stuffSearch.code === 'S') {
- setOtherSaleStoreId(session?.storeId)
- setStuffSearch({
- ...stuffSearch,
- code: 'S',
- schSelSaleStoreId: res[0].saleStoreId,
- schOtherSelSaleStoreId: otherList[0].saleStoreId,
- })
+ if (otherList.length === 1) {
+ setOtherSaleStoreId(session?.storeId)
+ setStuffSearch({
+ ...stuffSearch,
+ code: 'S',
+ schSelSaleStoreId: res[0].saleStoreId,
+ schOtherSelSaleStoreId: otherList[0].saleStoreId,
+ })
+ } else {
+ setOtherSaleStoreId('')
+ setStuffSearch({
+ ...stuffSearch,
+ code: 'S',
+ schSelSaleStoreId: res[0].saleStoreId,
+ schOtherSelSaleStoreId: '',
+ })
+ }
} else {
setOtherSaleStoreId(stuffSearch?.schOtherSelSaleStoreId)
setStuffSearch({
@@ -542,7 +572,7 @@ export default function StuffSearchCondition() {
const onInputChange = (key) => {
//내 물건보기 체크 풀어주기
setMyDataCheck(false)
-
+ stuffSearch.schMyDataCheck = false
if (key !== '') {
setShowSaleStoreList(schSelSaleStoreList)
} else {
@@ -560,7 +590,6 @@ export default function StuffSearchCondition() {
setOtherSaleStoreId('')
setSchSelSaleStoreId(key.saleStoreId)
stuffSearch.schSelSaleStoreId = key.saleStoreId
- //T01아닌 1차점은 본인으로 디폴트셋팅이고 수정할수없어서 여기안옴
//고른 1차점의 saleStoreId로 2차점 API호출하기
let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${session?.userId}`
let otherList
@@ -719,19 +748,61 @@ export default function StuffSearchCondition() {
setMyDataCheck(stuffSearch.schMyDataCheck)
}
} else {
- setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
- setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
- setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
- setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
- setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
- setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
- setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
- setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
- setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
- setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
- setMyDataCheck(stuffSearch.schMyDataCheck)
- if (session.storeLvl !== '1') {
- stuffSearch.schSelSaleStoreId = ''
+ if (stuffSearch.code === 'DELETE') {
+ //1차점인경우
+ if (session.storeLvl === '1') {
+ stuffSearch.schOtherSelSaleStoreId = ''
+ setOtherSaleStoreId('')
+ } else {
+ //2차점 본인하나인경우
+ //34있는경우
+ stuffSearch.schOtherSelSaleStoreId = ''
+ setOtherSaleStoreId('')
+ }
+
+ setObjectNo('')
+ setSaleStoreName('')
+ setAddress('')
+ setobjectName('')
+ setDispCompanyName('')
+ setReceiveUser('')
+ objectNoRef.current.value = ''
+ saleStoreNameRef.current.value = ''
+ addressRef.current.value = ''
+ objectNameRef.current.value = ''
+ dispCompanyNameRef.current.value = ''
+ receiveUserRef.current.value = ''
+ stuffSearch.schObjectNo = ''
+ stuffSearch.schAddress = ''
+ stuffSearch.schObjectName = ''
+ stuffSearch.schSaleStoreName = ''
+ stuffSearch.schReceiveUser = ''
+ stuffSearch.schDispCompanyName = ''
+ stuffSearch.schDateType = 'U'
+ stuffSearch.schTempFlg = ''
+ stuffSearch.schMyDataCheck = false
+ stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')
+ stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD')
+ stuffSearch.startRow = 1
+ stuffSearch.endRow = 100
+ stuffSearch.schSortType = 'U'
+ stuffSearch.pageNo = 1
+ stuffSearch.pageSize = 100
+ } else {
+ setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
+ setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
+ setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
+ setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
+ setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
+ setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
+ setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
+ setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
+ setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
+ setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
+ setMyDataCheck(stuffSearch.schMyDataCheck)
+ if (session.storeLvl !== '1') {
+ stuffSearch.schSelSaleStoreId = ''
+ }
}
}
@@ -801,10 +872,12 @@ export default function StuffSearchCondition() {
if (e.target.checked) {
stuffSearch.schMyDataCheck = e.target.value
setMyDataCheck(true)
-
if (otherSaleStoreList.length > 1) {
- stuffSearch.schSelSaleStoreId = otherSaleStoreId
- stuffSearch.schOtherSelSaleStoreId = ''
+ stuffSearch.schOtherSelSaleStoreId = session.storeId
+ setOtherSaleStoreId(session.storeId)
+ } else {
+ stuffSearch.schSelSaleStoreId = ''
+ stuffSearch.schOtherSelSaleStoreId = session.storeId
}
} else {
setMyDataCheck(false)
@@ -813,6 +886,30 @@ export default function StuffSearchCondition() {
}
}
+ const CustomOption = (props) => {
+ const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
+ const customClass = data.saleStoreId === 'T01' || data.priority !== 'B' ? 'special-option' : ''
+ // 기본 선택/호버 상태 적용
+ const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
+ return (
+
+ {data.label}
+
+ )
+ }
+
+ const CustomOption2 = (props) => {
+ const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
+ const customClass = data.priority !== 'B' ? 'special-option' : ''
+ // 기본 선택/호버 상태 적용
+ const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
+ return (
+
+ {data.label}
+
+ )
+ }
+
return (
<>
{/* 퍼블적용시작 */}
@@ -822,12 +919,21 @@ export default function StuffSearchCondition() {
{getMessage('stuff.search.title')}
-
- {/* */}
+ {/*
{getMessage('stuff.search.btn.register')}
-
+ */}
+ {
+ setIsGlobalLoading(true)
+ router.push(`/management/stuff/tempReg`, { scroll: false })
+ }}
+ >
+ {getMessage('stuff.search.btn.register')}
+
{getMessage('stuff.search.btn.search')}
@@ -1078,6 +1184,7 @@ export default function StuffSearchCondition() {
})}
isDisabled={session?.storeLvl !== '1' ? true : session?.storeId !== 'T01' ? true : false}
isClearable={true}
+ components={{ Option: CustomOption }}
/>
)}
{session?.storeId !== 'T01' && session?.storeLvl === '1' && (
@@ -1162,6 +1269,7 @@ export default function StuffSearchCondition() {
value={otherSaleStoreList.filter(function (option) {
return option.saleStoreId === otherSaleStoreId
})}
+ components={{ Option: CustomOption2 }}
/>
diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx
index 6dc316cb..8e61e259 100644
--- a/src/components/management/StuffSubHeader.jsx
+++ b/src/components/management/StuffSubHeader.jsx
@@ -40,8 +40,8 @@ export default function StuffSubHeader({ type }) {
if (isObjectNotEmpty(managementState)) {
if (managementState.createUser === 'T01') {
if (session.userId !== 'T01') {
- //도면 작성은 이동 할 수 있도록 변경 #457
- // setButtonStyle('none')
+ //도면 작성은 이동 할 수 있도록 변경 #457 다시 못하도록 변경#474
+ setButtonStyle('none')
}
}
}
@@ -66,87 +66,85 @@ export default function StuffSubHeader({ type }) {
}
return (
- !isGlobalLoading && (
- <>
-
-
- {type === 'list' && (
- <>
-
- {getMessage('header.menus.management')}
-
-
- -
-
-
-
-
- -
- {getMessage('header.menus.management')}
-
- -
- {getMessage('header.menus.management.stuffList')}
-
-
- >
- )}
- {type === 'temp' && (
- <>
-
- -
-
- {getMessage('stuff.temp.subTitle')}
-
-
-
-
- -
-
-
-
-
- -
- {getMessage('header.menus.management')}
-
- -
- {getMessage('header.menus.management.newStuff')}
-
-
- >
- )}
- {type === 'detail' && (
- <>
-
-
- -
-
-
-
-
- -
- {getMessage('header.menus.management')}
-
- -
- {getMessage('header.menus.management.detail')}
-
-
- >
- )}
-
+ <>
+
+
+ {type === 'list' && (
+ <>
+
+ {getMessage('header.menus.management')}
+
+
+ -
+
+
+
+
+ -
+ {getMessage('header.menus.management')}
+
+ -
+ {getMessage('header.menus.management.stuffList')}
+
+
+ >
+ )}
+ {type === 'temp' && (
+ <>
+
+ -
+
+ {getMessage('stuff.temp.subTitle')}
+
+
+
+
+ -
+
+
+
+
+ -
+ {getMessage('header.menus.management')}
+
+ -
+ {getMessage('header.menus.management.newStuff')}
+
+
+ >
+ )}
+ {type === 'detail' && (
+ <>
+
+
+ -
+
+
+
+
+ -
+ {getMessage('header.menus.management')}
+
+ -
+ {getMessage('header.menus.management.detail')}
+
+
+ >
+ )}
- >
- )
+
+ >
)
}
diff --git a/src/components/management/popup/FindAddressPop.jsx b/src/components/management/popup/FindAddressPop.jsx
index 960fd2e3..55770d12 100644
--- a/src/components/management/popup/FindAddressPop.jsx
+++ b/src/components/management/popup/FindAddressPop.jsx
@@ -56,9 +56,6 @@ export default function FindAddressPop(props) {
//우편번호 검색
const searchPostNum = () => {
- // //7830060
- // //9302226
- // //0790177 3개짜리
const params = {
zipcode: watch('zipNo'),
}
@@ -122,6 +119,28 @@ export default function FindAddressPop(props) {
}
}
+ //그리드 더블클릭
+ const getCellDoubleClicked = (event) => {
+ setAddress1(event.data.address1)
+ setAddress2(event.data.address2)
+ setAddress3(event.data.address3)
+ setPrefId(event.data.prefcode)
+ setZipNo(event.data.zipcode)
+
+ if (event.data.prefcode == null) {
+ return alert(getMessage('stuff.addressPopup.error.message2'))
+ } else {
+ props.zipInfo({
+ zipNo: event.data.zipcode,
+ address1: event.data.address1,
+ address2: event.data.address2,
+ address3: event.data.address3,
+ prefId: event.data.prefcode,
+ })
+ }
+ props.setShowAddressButtonValid(false)
+ }
+
return (
@@ -146,7 +165,7 @@ export default function FindAddressPop(props) {
-
+
diff --git a/src/components/management/popup/FindAddressPopQGrid.jsx b/src/components/management/popup/FindAddressPopQGrid.jsx
index 6447dd48..4de93e9c 100644
--- a/src/components/management/popup/FindAddressPopQGrid.jsx
+++ b/src/components/management/popup/FindAddressPopQGrid.jsx
@@ -48,6 +48,11 @@ export default function FindAddressPopGrid(props) {
props.getSelectedRowdata(selectedData)
}
+ //더블클릭
+ const onCellDoubleClicked = useCallback((event) => {
+ props.getCellDoubleClicked(event)
+ }, [])
+
return (
${getMessage('stuff.grid.noData')}`}
/>
diff --git a/src/components/management/popup/PlanRequestPop.jsx b/src/components/management/popup/PlanRequestPop.jsx
index 23a041be..033c71de 100644
--- a/src/components/management/popup/PlanRequestPop.jsx
+++ b/src/components/management/popup/PlanRequestPop.jsx
@@ -8,19 +8,12 @@ import SingleDatePicker from '@/components/common/datepicker/SingleDatePicker'
import dayjs from 'dayjs'
import PlanRequestPopQGrid from './PlanRequestPopQGrid'
import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
-import { useCommonCode } from '@/hooks/common/useCommonCode'
-import Select from 'react-select'
import QPagination from '@/components/common/pagination/QPagination'
export default function PlanRequestPop(props) {
const [pageNo, setPageNo] = useState(1) //현재 페이지 번호
const [pageSize, setPageSize] = useState(20) //페이지 당 게시물 개수
const [totalCount, setTotalCount] = useState(0) //총 갯수
- //공통코드
- const { commonCode, findCommonCode } = useCommonCode()
-
- // const [planStatCdList, setPlanStatCdList] = useState([])
-
const globalLocaleState = useRecoilValue(globalLocaleStore)
const [planReqObject, setPlanReqObject] = useState({})
@@ -71,16 +64,6 @@ export default function PlanRequestPop(props) {
}
}
- // 상태 검색조건 변경
- const onSelectionChange = (key) => {
- if (isObjectNotEmpty(key)) {
- setSchPlanStatCd(key.clCode)
- } else {
- //X누름
- setSchPlanStatCd('')
- }
- }
-
// 조회
const onSubmit = (page, type) => {
const params = {
@@ -194,7 +177,8 @@ export default function PlanRequestPop(props) {
{
field: 'title',
headerName: getMessage('stuff.planReqPopup.gridHeader.title'),
- minWidth: 150,
+ minWidth: 250,
+ cellStyle: { textAlign: 'left' },
},
{
field: 'address1',
@@ -234,13 +218,6 @@ export default function PlanRequestPop(props) {
}
}
- // useEffect(() => {
- // const code1 = findCommonCode(115800) //상태
- // if (code1 != null) {
- // setPlanStatCdList(code1)
- // }
- // }, [commonCode])
-
useEffect(() => {
onSubmit(pageNo, 'S')
}, [])
@@ -266,6 +243,13 @@ export default function PlanRequestPop(props) {
}
}
+ // 더블클릭
+ const getCellDoubleClicked = (event) => {
+ setPlanReqObject(event.data)
+ props.planReqInfo(event.data)
+ props.setShowDesignRequestButtonValid(false)
+ }
+
return (
@@ -431,9 +415,11 @@ export default function PlanRequestPop(props) {
-
-
diff --git a/src/components/management/popup/PlanRequestPopQGrid.jsx b/src/components/management/popup/PlanRequestPopQGrid.jsx
index f7dbba0f..5f78f7a3 100644
--- a/src/components/management/popup/PlanRequestPopQGrid.jsx
+++ b/src/components/management/popup/PlanRequestPopQGrid.jsx
@@ -22,8 +22,8 @@ export default function PlanRequestPopQGrid(props) {
flex: 1,
minWidth: 100,
sortable: false,
- suppressMovable: false,
- resizable: false,
+ suppressMovable: true,
+ resizable: true,
suppressSizeToFit: false,
}
}, [])
@@ -48,6 +48,11 @@ export default function PlanRequestPopQGrid(props) {
props.getSelectedRowdata(selectedData)
}
+ // 그리드 더블클릭
+ const onCellDoubleClicked = useCallback((event) => {
+ props.getCellDoubleClicked(event)
+ }, [])
+
return (
${getMessage('stuff.grid.noData')}`}
/>
diff --git a/src/components/myInfo/UserInfoModal.jsx b/src/components/myInfo/UserInfoModal.jsx
index 0d2d1898..2883bf3b 100644
--- a/src/components/myInfo/UserInfoModal.jsx
+++ b/src/components/myInfo/UserInfoModal.jsx
@@ -39,7 +39,6 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
if (resultData) {
setInfo(resultData)
- setPassword(resultData.password)
} else {
alert(getMessage('common.message.no.data'))
}
@@ -236,7 +235,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
{getMessage('myinfo.info.category')} |
-
+
|
diff --git a/src/components/simulator/Simulator.jsx b/src/components/simulator/Simulator.jsx
index ef752582..306b5365 100644
--- a/src/components/simulator/Simulator.jsx
+++ b/src/components/simulator/Simulator.jsx
@@ -16,26 +16,23 @@ import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import { convertNumberToPriceDecimal } from '@/util/common-utils'
import { usePlan } from '@/hooks/usePlan'
-import { usePopup } from '@/hooks/usePopup'
-// import { useSearchParams } from 'next/navigation'
+import { usePopup, closeAll } from '@/hooks/usePopup'
+
+import { QcastContext } from '@/app/QcastProvider'
export default function Simulator() {
+ // global 로딩바
+ const { setIsGlobalLoading } = useContext(QcastContext)
+
const { floorPlanState } = useContext(FloorPlanContext)
const { objectNo, pid } = floorPlanState
-
- // const searchParams = useSearchParams()
- // const objectNo = searchParams.get('objectNo')
- // const pid = searchParams.get('pid')
const { selectedPlan } = usePlan()
const chartRef = useRef(null)
// 캔버스 메뉴 넘버 셋팅
const { setMenuNumber } = useCanvasMenu()
-
- useEffect(() => {
- setMenuNumber(6)
- }, [])
+ const { closeAll } = usePopup()
const { get } = useAxios()
const { getMessage } = useMessage()
@@ -43,12 +40,6 @@ export default function Simulator() {
// 차트 관련
const [chartData, setChartData] = useState([])
- const { closeAll } = usePopup()
-
- useEffect(() => {
- closeAll()
- }, [])
-
const data = {
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
datasets: [
@@ -114,7 +105,6 @@ export default function Simulator() {
}
useEffect(() => {
- console.log('🚀 ~ useEffect ~ selectedPlan:', selectedPlan)
/* 초기화 작업 */
setChartData([])
setObjectDetail({})
@@ -125,11 +115,13 @@ export default function Simulator() {
setHatsudenryouPeakcutAll([])
setHatsudenryouPeakcutAllSnow([])
- if (objectNo) {
- fetchObjectDetail(objectNo)
+ if (objectNo && pid && selectedPlan) {
+ fetchObjectDetail(objectNo, selectedPlan.planNo)
fetchSimulatorNotice()
setPwrGnrSimType('D')
setPwrRecoil({ ...pwrRecoil, type: 'D' })
+ setMenuNumber(6)
+ closeAll()
}
}, [objectNo, pid, selectedPlan])
@@ -148,10 +140,13 @@ export default function Simulator() {
const [hatsudenryouPeakcutAll, setHatsudenryouPeakcutAll] = useState([])
const [hatsudenryouPeakcutAllSnow, setHatsudenryouPeakcutAllSnow] = useState([])
- const fetchObjectDetail = async (objectNo) => {
- const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${pid}`
+ const fetchObjectDetail = async (objectNo, currentPid) => {
+ setIsGlobalLoading(true)
+
+ const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${currentPid}`
const resultData = await get({ url: apiUrl })
+
if (resultData) {
setObjectDetail(resultData)
if (resultData.hatsudenryouAll) {
@@ -174,12 +169,14 @@ export default function Simulator() {
setModuleInfoList(resultData.roofModuleList)
}
}
+ setIsGlobalLoading(false)
}
// 시뮬레이션 안내사항 조회
const [content, setContent] = useState('')
const fetchSimulatorNotice = async () => {
+ setIsGlobalLoading(true)
get({ url: '/api/pwrGnrSimulation/guideInfo' }).then((res) => {
if (res.data) {
setContent(res.data.replaceAll('\n', ' '))
@@ -187,6 +184,7 @@ export default function Simulator() {
setContent(getMessage('common.message.no.data'))
}
})
+ setIsGlobalLoading(false)
}
// 차트 데이터 변경 시, list type 셋팅
@@ -234,7 +232,7 @@ export default function Simulator() {
{/* 시스템용량 */}
- {getMessage('simulator.title.sub3')}
+ {getMessage('simulator.title.sub3')}
{objectDetail.capacity ? `${convertNumberToPriceDecimal(objectDetail.capacity)} kW` : ''}
{/* 연간예측발전량 */}
@@ -257,7 +255,7 @@ export default function Simulator() {
{/* 적설조건 */}
{getMessage('simulator.title.sub7')}
- {objectDetail.snowfall} cm
+ {objectDetail.snowfall ? `${objectDetail.snowfall}cm` : ''}
{/* 풍속조건 */}
@@ -356,7 +354,10 @@ export default function Simulator() {
{/* 지붕면 */}
{moduleInfo.roofSurface} |
{/* 경사각 */}
- {convertNumberToPriceDecimal(moduleInfo.slopeAngle)}{moduleInfo.classType == 0 ? "寸":"º"} |
+
+ {convertNumberToPriceDecimal(moduleInfo.slopeAngle)}
+ {moduleInfo.classType == 0 ? '寸' : 'º'}
+ |
{/* 방위각(도) */}
{convertNumberToPriceDecimal(moduleInfo.azimuth)} |
{/* 태양전지모듈 */}
diff --git a/src/hooks/common/useCanvasPopupStatusController.js b/src/hooks/common/useCanvasPopupStatusController.js
index 88b2207a..e4b2cc46 100644
--- a/src/hooks/common/useCanvasPopupStatusController.js
+++ b/src/hooks/common/useCanvasPopupStatusController.js
@@ -1,28 +1,90 @@
'use client'
import { useEffect } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
import useSWR from 'swr'
import useSWRMutation from 'swr/mutation'
import { useAxios } from '../useAxios'
-import { useRecoilState } from 'recoil'
-import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
+import { unescapeString } from '@/util/common-utils'
+import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { compasDegAtom } from '@/store/orientationAtom'
+import { currentCanvasPlanState } from '@/store/canvasAtom'
-export function useCanvasPopupStatusController(popupType) {
- const [canvasPopupStatusState, setCanvasPopupStatusState] = useRecoilState(canvasPopupStatusStore)
+export function useCanvasPopupStatusController(param = 1) {
+ const popupType = parseInt(param)
+
+ const [compasDeg, setCompasDeg] = useRecoilState(compasDegAtom)
+ const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState)
const { getFetcher, postFetcher } = useAxios()
+
+ const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
+ // console.log('🚀 ~ Orientation ~ currentCanvasPlan:', currentCanvasPlan)
+
const {
data: popupStatus,
error,
isLoading,
- } = useSWR(popupType ? 'canvas-popup-status--data' : null, () => getFetcher(`http://localhost:8080/api/tutorial?popupType=${popupType}`))
+ } = useSWR(
+ popupType ? `/api/v1/canvas-popup-status?objectNo=${currentCanvasPlan.objectNo}&planNo=${currentCanvasPlan.planNo}&popupType=${popupType}` : null,
+ getFetcher,
+ )
useEffect(() => {
+ // console.log('🚀 ~ useEffect ~ popupStatus:', popupStatus)
if (popupStatus) {
- setCanvasPopupStatusState({ ...canvasPopupStatusState, [popupType]: popupStatus })
+ switch (parseInt(popupStatus?.popupType)) {
+ case 1:
+ setCompasDeg(popupStatus.popupStatus)
+ break
+ case 2:
+ setModuleSelectionDataStore(JSON.parse(unescapeString(popupStatus.popupStatus)))
+ break
+ case 3:
+ break
+ case 4:
+ break
+ case 5:
+ break
+ case 6:
+ break
+ default:
+ }
+ } else {
+ switch (popupType) {
+ case 1:
+ setCompasDeg(0)
+ break
+ case 2:
+ setModuleSelectionDataStore({
+ common: {},
+ roofConstructions: [],
+ })
+ break
+ case 3:
+ break
+ case 4:
+ break
+ case 5:
+ break
+ case 6:
+ break
+ default:
+ }
}
}, [popupStatus])
- const { trigger, isMutating } = useSWRMutation('canvas-popup-status-update', postFetcher)
+ const { trigger, isMutating } = useSWRMutation(
+ `/api/v1/canvas-popup-status?objectNo=${currentCanvasPlan.objectNo}&planNo=${currentCanvasPlan.planNo}&popupType=${popupType}`,
+ (url, { arg }) => {
+ const params = {
+ objectNo: currentCanvasPlan.objectNo,
+ planNo: parseInt(currentCanvasPlan.planNo),
+ popupType: popupType.toString(),
+ popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'),
+ }
+ postFetcher(`/api/v1/canvas-popup-status`, params)
+ },
+ )
return { trigger }
}
diff --git a/src/hooks/common/useCommonUtils.js b/src/hooks/common/useCommonUtils.js
index a299fd75..26cbcc8a 100644
--- a/src/hooks/common/useCommonUtils.js
+++ b/src/hooks/common/useCommonUtils.js
@@ -523,10 +523,26 @@ export function useCommonUtils() {
if (object) {
canvas?.remove(object)
- // if (object.id) {
- // const group = canvas.getObjects().filter((obj) => obj.id === object.id)
- // group.forEach((obj) => canvas?.remove(obj))
- // }
+ if (object.id) {
+ const group = canvas.getObjects().filter((obj) => obj.id === object.id)
+ group.forEach((obj) => canvas?.remove(obj))
+ }
+
+ if (object.type === 'group') {
+ object._objects.forEach((obj) => {
+ if (obj.hasOwnProperty('texts')) {
+ obj.texts.forEach((text) => {
+ canvas?.remove(text)
+ })
+ }
+ })
+ } else {
+ if (object.hasOwnProperty('texts')) {
+ object.texts.forEach((text) => {
+ canvas?.remove(text)
+ })
+ }
+ }
}
}
@@ -609,6 +625,21 @@ export function useCommonUtils() {
commonDeleteText(obj)
})
}
+
+ selectedObj.forEach((obj) => {
+ if (obj.type === 'group') {
+ obj._objects.forEach((lines) => {
+ if (lines.hasOwnProperty('arrow')) {
+ canvas
+ .getObjects()
+ .filter((obj1) => obj1.name === 'arrow' && lines.id === obj1.parentId)
+ .forEach((arrow) => {
+ canvas?.remove(arrow)
+ })
+ }
+ })
+ }
+ })
}
const moveObject = () => {
diff --git a/src/hooks/common/useMasterController.js b/src/hooks/common/useMasterController.js
index 29a17464..ef31962f 100644
--- a/src/hooks/common/useMasterController.js
+++ b/src/hooks/common/useMasterController.js
@@ -4,6 +4,8 @@ import { useSwal } from '@/hooks/useSwal'
import { getQueryString } from '@/util/common-utils'
import { trestleRequest, constructionRequest, trestleDetailRequest } from '@/models/apiModels'
import { POST } from '@/app/api/image-upload/route'
+import { canvasState } from '@/store/canvasAtom'
+import { useRecoilValue } from 'recoil'
/**
* 마스터 컨트롤러 훅
@@ -54,9 +56,9 @@ export function useMasterController() {
*/
const getTrestleList = async (params) => {
const paramString = getQueryString(params)
- console.log('🚀🚀 ~ getTrestleList ~ paramString:', paramString)
+ // console.log('🚀🚀 ~ getTrestleList ~ paramString:', paramString)
return await get({ url: '/api/v1/master/getTrestleList' + paramString }).then((res) => {
- console.log('🚀🚀 ~ getTrestleList ~ res:', res)
+ // console.log('🚀🚀 ~ getTrestleList ~ res:', res)
return res
})
}
@@ -80,9 +82,9 @@ export function useMasterController() {
*/
const getConstructionList = async (params) => {
const paramString = getQueryString(params)
- console.log('🚀🚀 ~ getConstructionList ~ paramString:', paramString)
+ // console.log('🚀🚀 ~ getConstructionList ~ paramString:', paramString)
return await get({ url: '/api/v1/master/getConstructionList' + paramString }).then((res) => {
- console.log('🚀🚀 ~ getConstructionList ~ res:', res)
+ // console.log('🚀🚀 ~ getConstructionList ~ res:', res)
return res
})
}
@@ -128,18 +130,88 @@ export function useMasterController() {
}
/**
- * PCS 메이커, 시리즈 목록 조회
- * @param {PCS 메이커코드} pcsMkrCd
- * @param {혼합모듈번호} mixMatlNo
+ * 모듈 타입별 아이템 목록 조회
+ * @param {PCS 메이커코드} pcsMkrCd
+ * @param {PCS시리즈코드 목록} pcsSerList
+ * @param {모듈아이템 ID 목록} moduleItemList
* @returns
*/
const getPcsModelList = async (params = null) => {
const test = {
pcsMkrCd: 'MKR003',
pcsSerList: [{ pcsSerCd: 'SER007' }, { pcsSerCd: 'SER009' }, { pcsSerCd: 'SER010' }],
- moduleItemList: [{ itemId: '107015', mixMatlNo: '' }, { itemId: '107077' }, { itemId: '107015' }],
+ moduleItemList: [
+ { itemId: '107015', mixMatlNo: null },
+ { itemId: '107077', mixMatlNo: null },
+ { itemId: '107015', mixMatlNo: null },
+ ],
}
- return await post({ url: '/api/v1/master/getPcsSeriesItemList', data: test }).then((res) => {
+
+ return await post({ url: '/api/v1/master/getPcsSeriesItemList', data: params }).then((res) => {
+ return res
+ })
+ }
+ /**
+ * 시리즈중 자동으로 추천 PCS 정보 조회
+ * @param {Max접속(과적)여부} maxConnYn
+ * @param {동일회로도여부} smpCirYn
+ * @param {한랭지여부} coldZoneYn
+ * @param {사용된 모듈 아이템 List} useModuleItemList
+ * @param {지붕면별 목록} roofSurfaceList
+ * @param {PCS 제품 목록} pcsItemList
+ * @returns
+ */
+ const getPcsAutoRecommendList = async (params = null) => {
+ return await post({ url: '/api/v1/master/getPcsAutoRecommendList', data: params }).then((res) => {
+ return res
+ })
+ }
+
+ const getPcsManualConfChk = async (params = null) => {
+ return await post({ url: '/api/v1/master/getPcsMenualConfChk', data: params }).then((res) => {
+ return res
+ })
+ }
+
+ /**
+ * PCS로 회로 구성 가능 여부 체크
+ * @param {Max접속(과적)여부} maxConnYn
+ * @param {동일회로도여부} smpCirYn
+ * @param {한랭지여부} coldZoneYn
+ * @param {사용된 모듈 아이템 List} useModuleItemList
+ * @param {지붕면별 목록} roofSurfaceList
+ * @param {PCS 제품 목록} pcsItemList
+ * @returns
+ */
+ const getPcsVoltageChk = async (params = null) => {
+ return await post({ url: '/api/v1/master/getPcsVoltageChk', data: params }).then((res) => {
+ return res
+ })
+ }
+
+ /**
+ * PCS 승압설정 정보 조회
+ * @param {Max접속(과적)여부} maxConnYn
+ * @param {동일회로도여부} smpCirYn
+ * @param {한랭지여부} coldZoneYn
+ * @param {사용된 모듈아이템 목록} useModuleItemList
+ * @param {지붕면 목록} roofSurfaceList
+ * @param {PCS 아이템 목록} pcsItemList
+
+ * @returns
+ */
+ const getPcsVoltageStepUpList = async (params2 = null) => {
+ const params = {
+ ...params2,
+ maxConnYn: params2.useYn.maxConnYn,
+ smpCirYn: params2.useYn.smpCirYn,
+ coldZoneYn: params2.useYn.coldZoneYn,
+ useModuleItemList: params2.useModuleItemList,
+ roofSurfaceList: params2.roofSurfaceList,
+ pcsItemList: params2.pcsItemList,
+ }
+
+ return await post({ url: '/api/v1/master/getPcsVoltageStepUpList', data: params }).then((res) => {
return res
})
}
@@ -152,5 +224,9 @@ export function useMasterController() {
getTrestleDetailList,
getPcsMakerList,
getPcsModelList,
+ getPcsAutoRecommendList,
+ getPcsVoltageChk,
+ getPcsManualConfChk,
+ getPcsVoltageStepUpList,
}
}
diff --git a/src/hooks/common/useRoofFn.js b/src/hooks/common/useRoofFn.js
index aa73dfb1..20efa87d 100644
--- a/src/hooks/common/useRoofFn.js
+++ b/src/hooks/common/useRoofFn.js
@@ -20,15 +20,24 @@ export function useRoofFn() {
const { addPitchText } = useLine()
//면형상 선택 클릭시 지붕 패턴 입히기
- function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false, roofMaterial = selectedRoofMaterial) {
+ function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false, roofMaterial = selectedRoofMaterial, isForceChange = false) {
if (!polygon) {
return
}
+ if (isForceChange) {
+ if (polygon.roofMaterial) {
+ polygon.roofMaterial = null
+ }
+ }
+
+ if (polygon.roofMaterial) {
+ return
+ }
const ratio = window.devicePixelRatio || 1
const layout = roofMaterial.layout
- let width = (roofMaterial.width ?? 226) / 10
- let height = (roofMaterial.length ?? 158) / 10
+ let width = (roofMaterial.width || 226) / 10
+ let height = (roofMaterial.length || 158) / 10
const index = roofMaterial.index ?? 0
let roofStyle = 2
const inputPatternSize = { width: width, height: height } //임시 사이즈
diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js
index 66b0974c..ebd1ad88 100644
--- a/src/hooks/floorPlan/estimate/useEstimateController.js
+++ b/src/hooks/floorPlan/estimate/useEstimateController.js
@@ -80,6 +80,7 @@ export const useEstimateController = (planNo) => {
res.data.pkgAsp = roundedNumber.toString()
}
+
setEstimateContextState(res.data)
}
}
@@ -384,7 +385,7 @@ export const useEstimateController = (planNo) => {
if (res.status === 201) {
estimateData.newFileList = []
swalFire({ text: getMessage('estimate.detail.save.alertMsg'), type: 'alert' })
- fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
+ fetchSetting(estimateData.objectNo, estimateData.planNo)
}
})
} catch (e) {
@@ -409,7 +410,7 @@ export const useEstimateController = (planNo) => {
const params = {
saleStoreId: session.storeId,
sapSalesStoreCd: session.custCd,
- objectNo: objectRecoil.floorPlanObjectNo,
+ objectNo: estimateData.objectNo,
planNo: sendPlanNo,
copySaleStoreId: otherSaleStoreId ? otherSaleStoreId : saleStoreId,
copyReceiveUser: copyReceiveUser,
diff --git a/src/hooks/module/useModule.js b/src/hooks/module/useModule.js
index a71744c6..de64c404 100644
--- a/src/hooks/module/useModule.js
+++ b/src/hooks/module/useModule.js
@@ -389,6 +389,7 @@ export function useModule() {
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0]
let isWarning = false
canvas.discardActiveObject()
+ moduleSetupSurface.set({ modules: otherModules })
canvas.remove(...columnModules)
canvas.renderAll()
@@ -503,6 +504,7 @@ export function useModule() {
let isWarning = false
canvas.discardActiveObject()
+ moduleSetupSurface.set({ modules: otherModules })
canvas.remove(...rowModules)
canvas.renderAll()
@@ -852,8 +854,12 @@ export function useModule() {
const modulesRemove = () => {
const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
- const modules = canvas.getObjects().filter((obj) => obj.surfaceId === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE)
- canvas.remove(...modules)
+ const modules = canvas
+ .getObjects()
+ .filter((obj) => obj.surfaceId === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE && activeModule.id !== obj.id)
+ const surface = canvas.getObjects().filter((obj) => obj.id === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)[0]
+ surface.set({ modules: modules })
+ canvas.remove(activeModule)
canvas.renderAll()
}
diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js
index eff37226..53966ee7 100644
--- a/src/hooks/module/useModuleBasicSetting.js
+++ b/src/hooks/module/useModuleBasicSetting.js
@@ -1,5 +1,5 @@
-import { useRecoilState, useRecoilValue } from 'recoil'
-import { canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom'
+import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
+import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom'
import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util'
import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom'
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
@@ -8,14 +8,13 @@ import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom'
import { useEvent } from '@/hooks/useEvent'
import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
import * as turf from '@turf/turf'
-import { v4 as uuidv4 } from 'uuid'
import { useSwal } from '@/hooks/useSwal'
-import { canvasSettingState } from '@/store/canvasAtom'
import { compasDegAtom } from '@/store/orientationAtom'
import { QLine } from '@/components/fabric/QLine'
import { useRoofFn } from '@/hooks/common/useRoofFn'
import { useEffect } from 'react'
import { useMessage } from '@/hooks/useMessage'
+import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
export function useModuleBasicSetting() {
const canvas = useRecoilValue(canvasState)
@@ -23,14 +22,17 @@ export function useModuleBasicSetting() {
const roofDisplay = useRecoilValue(roofDisplaySelector)
const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState)
const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState)
- const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent()
+ const { addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent()
const { swalFire } = useSwal()
- const canvasSetting = useRecoilValue(canvasSettingState)
+
const compasDeg = useRecoilValue(compasDegAtom)
const { setSurfaceShapePattern } = useRoofFn()
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const checkedModule = useRecoilValue(checkedModuleState)
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
+ const setModuleStatistics = useSetRecoilState(moduleStatisticsState)
+
+ const canvasSetting = useRecoilValue(canvasSettingState)
useEffect(() => {
// console.log('basicSetting', basicSetting)
@@ -44,7 +46,6 @@ export function useModuleBasicSetting() {
}, [])
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
- let selectedModuleInstSurfaceArray = []
//모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화
const restoreModuleInstArea = () => {
@@ -69,104 +70,6 @@ export function useModuleBasicSetting() {
})
}
- const makeModuleInstArea = () => {
- //지붕 객체 반환
- const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
- let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20
-
- if (!roofs) {
- return
- }
-
- roofs.forEach((roof) => {
- const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
- if (isExistSurface) {
- return
- }
-
- setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
- const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
- //모듈설치영역?? 생성
-
- const surfaceId = uuidv4()
-
- let setupSurface = new QPolygon(offsetPoints, {
- stroke: 'red',
- fill: 'transparent',
- strokeDashArray: [10, 4],
- strokeWidth: 1,
- lockMovementX: true,
- lockMovementY: true,
- lockRotation: true,
- lockScalingX: true,
- lockScalingY: true,
- selectable: true,
- parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌
- name: POLYGON_TYPE.MODULE_SETUP_SURFACE,
- flowDirection: roof.direction,
- direction: roof.direction,
- flipX: roof.flipX,
- flipY: roof.flipY,
- surfaceId: surfaceId,
- originX: 'center',
- originY: 'center',
- modules: [],
- roofMaterial: roof.roofMaterial,
- // angle: -compasDeg,
- })
-
- setupSurface.setViewLengthText(false)
- canvas.add(setupSurface) //모듈설치면 만들기
-
- //지붕면 선택 금지
- roof.set({
- selectable: false,
- })
-
- //모듈설치면 클릭이벤트
- addTargetMouseEventListener('mousedown', setupSurface, function () {
- toggleSelection(setupSurface)
- })
- })
- }
-
- //설치 범위 지정 클릭 이벤트
- const toggleSelection = (setupSurface) => {
- const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
- //최초 선택일때
- if (!isExist) {
- //기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
- setupSurface.set({
- ...setupSurface,
- strokeWidth: 3,
- strokeDashArray: [0],
- fill: 'transparent',
- })
- canvas.discardActiveObject() // 객체의 활성 상태 해제
- //중복으로 들어가는걸 방지하기 위한 코드
-
- canvas?.renderAll()
- selectedModuleInstSurfaceArray.push(setupSurface)
- } else {
- //선택후 재선택하면 선택안됨으로 변경
- setupSurface.set({
- ...setupSurface,
- fill: 'transparent',
- strokeDashArray: [10, 4],
- strokeWidth: 1,
- })
- canvas.discardActiveObject() // 객체의 활성 상태 해제
-
- //폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
- const removeIndex = setupSurface.parentId
- const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex)
- selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1)
- }
-
- canvas?.renderAll()
- setModuleSetupSurface([...selectedModuleInstSurfaceArray])
- }
-
/**
* trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인
* 확인 후 셀을 이동시킴
@@ -188,15 +91,7 @@ export function useModuleBasicSetting() {
}
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
- const batchObjects = canvas
- ?.getObjects()
- .filter(
- (obj) =>
- obj.name === BATCH_TYPE.OPENING ||
- obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
- obj.name === BATCH_TYPE.PENTAGON_DORMER ||
- obj.name === BATCH_TYPE.SHADOW,
- ) //도머s 객체
+ const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체
const moduleOptions = {
fill: checkedModule[0].color,
@@ -447,17 +342,7 @@ export function useModuleBasicSetting() {
//도머 객체를 가져옴
if (batchObjects) {
batchObjects.forEach((object) => {
- let dormerTurfPolygon
-
- if (object.type === 'group') {
- //도머는 그룹형태임
- dormerTurfPolygon = batchObjectGroupToTurfPolygon(object)
- } else {
- //개구, 그림자
- object.set({ points: rectToPolygon(object) })
- dormerTurfPolygon = polygonToTurfPolygon(object)
- }
-
+ let dormerTurfPolygon = polygonToTurfPolygon(object, true)
const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인
//겹치면 안됨
if (intersection) {
@@ -479,9 +364,11 @@ export function useModuleBasicSetting() {
//안겹치면 넣는다
// tempModule.setCoords()
moduleOptions.surfaceId = trestlePolygon.id
- let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
+
+ let manualModule = new QPolygon(tempModule.points, { ...moduleOptions, moduleInfo: checkedModule[0] })
canvas?.add(manualModule)
manualDrawModules.push(manualModule)
+ getModuleStatistics()
} else {
swalFire({ text: getMessage('module.place.overlab') })
}
@@ -516,15 +403,7 @@ export function useModuleBasicSetting() {
?.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && !moduleSetupSurfaces.includes(obj)) //설치면이 아닌것
- const batchObjects = canvas
- ?.getObjects()
- .filter(
- (obj) =>
- obj.name === BATCH_TYPE.OPENING ||
- obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
- obj.name === BATCH_TYPE.PENTAGON_DORMER ||
- obj.name === BATCH_TYPE.SHADOW,
- ) //도머s 객체
+ const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체
if (moduleSetupSurfaces.length === 0) {
swalFire({ text: getMessage('module.place.no.surface') })
@@ -578,18 +457,7 @@ export function useModuleBasicSetting() {
const objectsIncludeSurface = (turfModuleSetupSurface) => {
let containsBatchObjects = []
containsBatchObjects = batchObjects.filter((batchObject) => {
- let convertBatchObject
-
- if (batchObject.type === 'group') {
- //도머는 그룹형태임
- convertBatchObject = batchObjectGroupToTurfPolygon(batchObject)
- } else {
- //개구, 그림자
- batchObject.set({ points: rectToPolygon(batchObject) })
- canvas?.renderAll() // set된걸 바로 적용하기 위해
- convertBatchObject = polygonToTurfPolygon(batchObject) //rect를 폴리곤으로 변환 -> turf 폴리곤으로 변환
- }
-
+ let convertBatchObject = polygonToTurfPolygon(batchObject)
// 폴리곤 안에 도머 폴리곤이 포함되어있는지 확인해서 반환하는 로직
return turf.booleanContains(turfModuleSetupSurface, convertBatchObject) || turf.booleanWithin(convertBatchObject, turfModuleSetupSurface)
})
@@ -697,6 +565,7 @@ export function useModuleBasicSetting() {
checkedModule.forEach((module, index) => {
const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module)
+
const flowLines = getFlowLines(moduleSetupSurface, module)
//육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음
let startPoint = flowLines.bottom
@@ -746,8 +615,8 @@ export function useModuleBasicSetting() {
for (let i = 0; i <= totalWidth; i++) {
leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0
- if (isChidori) {
- chidoriLength = j % 2 === 0 ? 0 : width / 2
+ if (isChidori && !isMaxSetup) {
+ chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
}
square = [
@@ -762,7 +631,7 @@ export function useModuleBasicSetting() {
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
- moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
+ moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
@@ -847,7 +716,7 @@ export function useModuleBasicSetting() {
for (let j = 0; j < totalHeight; j++) {
leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0
- if (isChidori) {
+ if (isChidori && !isMaxSetup) {
chidoriLength = i % 2 === 0 ? 0 : height / 2
}
@@ -864,7 +733,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
- moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
+ moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects)
@@ -958,8 +827,8 @@ export function useModuleBasicSetting() {
for (let i = 0; i < diffRightEndPoint; i++) {
leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0
- if (isChidori) {
- chidoriLength = j % 2 === 0 ? 0 : width / 2
+ if (isChidori && !isMaxSetup) {
+ chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
}
square = [
@@ -975,7 +844,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
- moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
+ moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
@@ -1058,8 +927,8 @@ export function useModuleBasicSetting() {
leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0
- if (isChidori) {
- chidoriLength = i % 2 === 0 ? 0 : height / 2
+ if (isChidori && !isMaxSetup) {
+ chidoriLength = i % 2 === 0 ? 0 : height / 2 - intvHor
}
square = [
@@ -1075,7 +944,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
- moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
+ moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects)
@@ -1118,6 +987,8 @@ export function useModuleBasicSetting() {
const flowDirection = moduleSetupSurface.flowDirection
+ console.log('moduleSetupSurface', moduleSetupSurface)
+
let intvHor =
flowDirection === 'south' || flowDirection === 'north'
? moduleSetupSurface.trestleDetail.moduleIntvlHor
@@ -1204,7 +1075,7 @@ export function useModuleBasicSetting() {
})
moduleSetupSurface.set({ modules: moduleSetupArray })
-
+ getModuleStatistics()
// const moduleArray = [...moduleIsSetup]
// moduleArray.push({
// surfaceId: moduleSetupSurface.surfaceId,
@@ -1304,13 +1175,13 @@ export function useModuleBasicSetting() {
const pointX2 = coords[2].x + ((coords[2].y - top) / (coords[2].y - coords[1].y)) * (coords[1].x - coords[2].x)
const pointY2 = top
- const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
- stroke: 'red',
- strokeWidth: 1,
- selectable: true,
- })
- canvas?.add(finalLine)
- canvas?.renderAll()
+ // const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
+ // stroke: 'red',
+ // strokeWidth: 1,
+ // selectable: true,
+ // })
+ // canvas?.add(finalLine)
+ // canvas?.renderAll()
let rtnObj
//평평하면
@@ -1427,13 +1298,13 @@ export function useModuleBasicSetting() {
const pointX2 = top
const pointY2 = coords[2].y + ((coords[2].x - top) / (coords[2].x - coords[1].x)) * (coords[1].y - coords[2].y)
- const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
- stroke: 'red',
- strokeWidth: 1,
- selectable: true,
- })
- canvas?.add(finalLine)
- canvas?.renderAll()
+ // const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
+ // stroke: 'red',
+ // strokeWidth: 1,
+ // selectable: true,
+ // })
+ // canvas?.add(finalLine)
+ // canvas?.renderAll()
let rtnObj
//평평하면
@@ -1839,6 +1710,8 @@ export function useModuleBasicSetting() {
}
})
}
+
+ getModuleStatistics()
}
const autoFlatroofModuleSetup = (placementFlatRef) => {
@@ -2229,7 +2102,7 @@ export function useModuleBasicSetting() {
})
moduleSetupSurface.set({ modules: setupedModules })
-
+ getModuleStatistics()
// console.log('moduleSetupSurface', moduleSetupSurface)
// console.log('setupedModules', setupedModules)
@@ -2277,8 +2150,63 @@ export function useModuleBasicSetting() {
return isDisjoint
}
+ const getModuleStatistics = () => {
+ const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
+ console.log('🚀 ~ getModuleStatistics ~ surfaces:', surfaces)
+ let totalWpout = 0
+ let moduleInfo = {}
+ const rows = surfaces.map((surface) => {
+ let wpOut = 0
+ moduleInfo = {}
+ surface.modules.forEach((module) => {
+ if (!moduleInfo[module.moduleInfo.itemId]) {
+ moduleInfo[module.moduleInfo.itemId] = { name: module.moduleInfo.itemNm, amount: 0, id: module.moduleInfo.itemId }
+ }
+ wpOut += +module.moduleInfo.wpOut
+
+ moduleInfo[module.moduleInfo.itemId].amount++
+ })
+ totalWpout += wpOut
+ console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module)
+ const rowObject = {}
+ Object.keys(moduleInfo).forEach((key) => {
+ rowObject[key] = moduleInfo[key].amount
+ })
+ return {
+ ...rowObject, // 총 발전량 = 발전량 * 모듈 개수
+ ...surface,
+ name: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].directionText, // 지붕면
+ // powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
+ wpOut: wpOut,
+ }
+ })
+
+ console.log('🚀 ~ getModuleStatistics ~ rows:', rows)
+ console.log('🚀 ~ getModuleStatistics ~ moduleInfo:', moduleInfo)
+ const header = [
+ { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'name' },
+ ...Object.keys(moduleInfo).map((key) => {
+ return { name: moduleInfo[key].name, prop: key }
+ }),
+ { name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`, prop: 'wpOut' },
+ ]
+ let footer = ['합계']
+ let footerData = {}
+ rows.forEach((row) => {
+ Object.keys(moduleInfo).map((key) => {
+ if (!footerData[key]) footerData[key] = 0
+ footerData[key] += row[key]
+ })
+ })
+ Object.keys(footerData).forEach((key) => {
+ footer.push(footerData[key])
+ })
+ footer.push(totalWpout)
+ console.log({ header: header, rows, footer: footer })
+ setModuleStatistics({ header: header, rows, footer: footer })
+ }
+
return {
- makeModuleInstArea,
manualModuleSetup,
autoModuleSetup,
restoreModuleInstArea,
diff --git a/src/hooks/module/useModulePlace.js b/src/hooks/module/useModulePlace.js
index 856c7abb..0af46cf9 100644
--- a/src/hooks/module/useModulePlace.js
+++ b/src/hooks/module/useModulePlace.js
@@ -1,47 +1,59 @@
import { useEffect, useState } from 'react'
-import { useRecoilState, useRecoilValue } from 'recoil'
+import { useRecoilValue, useSetRecoilState } from 'recoil'
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
import { useMasterController } from '@/hooks/common/useMasterController'
-import { canvasState } from '@/store/canvasAtom'
+import { canvasSettingState, canvasState, currentCanvasPlanState, moduleSetupSurfaceState } from '@/store/canvasAtom'
+import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
+import { useRoofFn } from '@/hooks/common/useRoofFn'
+import { roofDisplaySelector } from '@/store/settingAtom'
+import offsetPolygon from '@/util/qpolygon-utils'
+import { v4 as uuidv4 } from 'uuid'
+import { QPolygon } from '@/components/fabric/QPolygon'
+import { useEvent } from '@/hooks/useEvent'
export function useModulePlace() {
const canvas = useRecoilValue(canvasState)
- const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
+ const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
const [trestleDetailParams, setTrestleDetailParams] = useState([])
const [trestleDetailList, setTrestleDetailList] = useState([])
const selectedModules = useRecoilValue(selectedModuleState)
const { getTrestleDetailList } = useMasterController()
+ const canvasSetting = useRecoilValue(canvasSettingState)
+ const { setSurfaceShapePattern } = useRoofFn()
+ const roofDisplay = useRecoilValue(roofDisplaySelector)
+ const { addTargetMouseEventListener } = useEvent()
+ const setModuleSetupSurface = useSetRecoilState(moduleSetupSurfaceState)
useEffect(() => {
- console.log('🚀 ~ useModulePlace ~ moduleSelectionData:', moduleSelectionData)
- }, [])
+ if (moduleSelectionData) {
+ const common = moduleSelectionData.common
+ const roofConstructions = moduleSelectionData.roofConstructions
- useEffect(() => {
- const common = moduleSelectionData.common
- const roofConstructions = moduleSelectionData.roofConstructions
-
- const listParams = roofConstructions.map((item) => {
- return {
- ...common,
- moduleTpCd: selectedModules.itemTp,
- roofMatlCd: item.trestle.roofMatlCd,
- trestleMkrCd: item.trestle.trestleMkrCd,
- constMthdCd: item.trestle.constMthdCd,
- roofBaseCd: item.trestle.roofBaseCd,
- constTp: item.construction.constTp,
- mixMatlNo: selectedModules.mixMatlNo,
- roofPitch: selectedModules.roofPchBase ? selectedModules.roofPchBase : null,
- inclCd: String(item.addRoof.pitch),
- roofIndex: item.addRoof.index,
- }
- })
-
- setTrestleDetailParams(listParams)
+ const listParams = roofConstructions.map((item) => {
+ return {
+ ...common,
+ moduleTpCd: selectedModules.itemTp,
+ roofMatlCd: item.trestle.roofMatlCd,
+ trestleMkrCd: item.trestle.trestleMkrCd,
+ constMthdCd: item.trestle.constMthdCd,
+ roofBaseCd: item.trestle.roofBaseCd,
+ constTp: item.construction.constTp,
+ mixMatlNo: selectedModules.mixMatlNo,
+ roofPitch: item.addRoof.roofPchBase ? item.addRoof.roofPchBase : null,
+ inclCd: String(item.addRoof.pitch),
+ roofIndex: item.addRoof.index,
+ workingWidth: item.addRoof.lenBase,
+ }
+ })
+ setTrestleDetailParams(listParams)
+ }
}, [moduleSelectionData])
const getTrestleDetailListData = async () => {
const trestleDetailList = await getTrestleDetailList(trestleDetailParams)
- setTrestleDetailList(trestleDetailList)
+ if (trestleDetailList.length > 0) {
+ setTrestleDetailList(trestleDetailList)
+ }
}
useEffect(() => {
@@ -51,33 +63,168 @@ export function useModulePlace() {
}, [trestleDetailParams])
useEffect(() => {
- console.log('🚀 ~ useModulePlace ~ trestleDetailList:', trestleDetailList)
-
- //지붕을 가져옴
- canvas
- .getObjects()
- .filter((roof) => roof.name === 'roof')
- .forEach((roof) => {
- const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
- trestleDetailList.forEach((detail) => {
- if (Number(detail.data.roofIndex) === roofIndex) {
- //roof에 상세 데이터 추가
- roof.set({ trestleDetail: detail.data })
-
- //surface에 상세 데이터 추가
- canvas
- .getObjects()
- .filter((surface) => surface.name === 'moduleSetupSurface' && surface.parentId === roof.id)
- .forEach((surface) => {
- surface.set({ trestleDetail: detail.data, roofMaterial: roof.roofMaterial })
- })
- }
+ if (trestleDetailList.length > 0) {
+ //지붕을 가져옴
+ canvas
+ .getObjects()
+ .filter((roof) => roof.name === 'roof')
+ .forEach((roof) => {
+ const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
+ trestleDetailList.forEach((detail) => {
+ if (Number(detail.data.roofIndex) === roofIndex) {
+ //roof에 상세 데이터 추가
+ roof.set({ trestleDetail: detail.data })
+ //배치면 설치 영역
+ makeModuleInstArea(roof, detail.data)
+ //surface에 상세 데이터 추가
+ }
+ })
})
-
- console.log('roof', roof)
- })
+ }
}, [trestleDetailList])
+ const makeModuleInstArea = (roof, trestleDetail) => {
+ //지붕 객체 반환
+
+ if (!roof) {
+ return
+ }
+
+ const batchObjects = canvas
+ ?.getObjects()
+ .filter(
+ (obj) =>
+ obj.name === BATCH_TYPE.OPENING ||
+ obj.name === BATCH_TYPE.SHADOW ||
+ obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
+ obj.name === BATCH_TYPE.PENTAGON_DORMER,
+ ) //도머s 객체
+
+ //도머도 외곽을 따야한다
+
+ const batchObjectOptions = {
+ stroke: 'red',
+ fill: 'transparent',
+ strokeDashArray: [10, 4],
+ strokeWidth: 1,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ selectable: true,
+ name: POLYGON_TYPE.OBJECT_SURFACE,
+ originX: 'center',
+ originY: 'center',
+ }
+
+ batchObjects.forEach((obj) => {
+ if (obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) {
+ const groupPoints = obj.groupPoints
+ const offsetObjects = offsetPolygon(groupPoints, 10)
+ const dormerOffset = new QPolygon(offsetObjects, batchObjectOptions)
+ dormerOffset.setViewLengthText(false)
+ canvas.add(dormerOffset) //모듈설치면 만들기
+ } else {
+ const points = obj.points
+ const offsetObjects = offsetPolygon(points, 10)
+ const offset = new QPolygon(offsetObjects, batchObjectOptions)
+ offset.setViewLengthText(false)
+ canvas.add(offset) //모듈설치면 만들기
+ }
+ })
+
+ const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
+ if (isExistSurface) {
+ return
+ }
+
+ let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : (trestleDetail.eaveIntvl / 10) * -1
+ setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
+ const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
+ //모듈설치영역?? 생성
+
+ const surfaceId = uuidv4()
+
+ let setupSurface = new QPolygon(offsetPoints, {
+ stroke: 'red',
+ fill: 'transparent',
+ strokeDashArray: [10, 4],
+ strokeWidth: 1,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ selectable: true,
+ parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌
+ name: POLYGON_TYPE.MODULE_SETUP_SURFACE,
+ flowDirection: roof.direction,
+ direction: roof.direction,
+ flipX: roof.flipX,
+ flipY: roof.flipY,
+ surfaceId: surfaceId,
+ originX: 'center',
+ originY: 'center',
+ modules: [],
+ roofMaterial: roof.roofMaterial,
+ trestleDetail: trestleDetail,
+ // angle: -compasDeg,
+ })
+
+ setupSurface.setViewLengthText(false)
+ canvas.add(setupSurface) //모듈설치면 만들기
+
+ //지붕면 선택 금지
+ roof.set({
+ selectable: false,
+ })
+
+ //모듈설치면 클릭이벤트
+ addTargetMouseEventListener('mousedown', setupSurface, function () {
+ toggleSelection(setupSurface)
+ })
+ }
+
+ let selectedModuleInstSurfaceArray = []
+
+ //설치 범위 지정 클릭 이벤트
+ const toggleSelection = (setupSurface) => {
+ const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
+ //최초 선택일때
+ if (!isExist) {
+ //기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
+ setupSurface.set({
+ ...setupSurface,
+ strokeWidth: 3,
+ strokeDashArray: [0],
+ fill: 'transparent',
+ })
+ canvas.discardActiveObject() // 객체의 활성 상태 해제
+ //중복으로 들어가는걸 방지하기 위한 코드
+
+ canvas?.renderAll()
+ selectedModuleInstSurfaceArray.push(setupSurface)
+ } else {
+ //선택후 재선택하면 선택안됨으로 변경
+ setupSurface.set({
+ ...setupSurface,
+ fill: 'transparent',
+ strokeDashArray: [10, 4],
+ strokeWidth: 1,
+ })
+ canvas.discardActiveObject() // 객체의 활성 상태 해제
+
+ //폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
+ const removeIndex = setupSurface.parentId
+ const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex)
+ selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1)
+ }
+
+ canvas?.renderAll()
+ setModuleSetupSurface([...selectedModuleInstSurfaceArray])
+ }
+
return {
selectedModules,
}
diff --git a/src/hooks/module/useModuleSelection.js b/src/hooks/module/useModuleSelection.js
index b28e3d97..22d1f88f 100644
--- a/src/hooks/module/useModuleSelection.js
+++ b/src/hooks/module/useModuleSelection.js
@@ -3,42 +3,50 @@ import { useContext, useEffect, useState } from 'react'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { useMasterController } from '@/hooks/common/useMasterController'
import { useCommonCode } from '@/hooks/common/useCommonCode'
-
-import { selectedModuleState, moduleSelectionInitParamsState } from '@/store/selectedModuleOptions'
-import { pitchSelector } from '@/store/canvasAtom'
+import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { isObjectNotEmpty } from '@/util/common-utils'
export function useModuleSelection(props) {
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
- const globalPitch = useRecoilValue(pitchSelector) //피치
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록
const [moduleList, setModuleList] = useState([{}]) //모듈 목록
- const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도
- const [installHeight, setInstallHeight] = useState('0') //설치 높이
+ const [installHeight, setInstallHeight] = useState() //설치 높이
const [standardWindSpeed, setStandardWindSpeed] = useState({}) //기준풍속
- const [verticalSnowCover, setVerticalSnowCover] = useState('0') //수직적설량
+ const [verticalSnowCover, setVerticalSnowCover] = useState() //수직적설량
+
+ const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
-
const { getModuleTypeItemList } = useMasterController()
-
const { findCommonCode } = useCommonCode()
- //탭별 파라메터 초기화
- useEffect(() => {
+ const bindInitData = () => {
setInstallHeight(managementState?.installHeight)
setStandardWindSpeed(managementState?.standardWindSpeedId)
setVerticalSnowCover(managementState?.verticalSnowCover)
setSelectedSurfaceType(managementState?.surfaceType)
+ }
+ const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
+
+ //탭별 파라메터 초기화
+ useEffect(() => {
+ bindInitData()
const initParams = {
illuminationTp: managementState?.surfaceTypeValue, //면조도
instHt: managementState?.installHeight, //설치높이
stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
stdSnowLd: managementState?.verticalSnowCover, //기준적설량
}
+
+ if (selectedModules) {
+ initParams.moduleTpCd = selectedModules.itemTp
+ initParams.moduleItemId = selectedModules.itemId
+ }
+
setModuleSelectionInitParams(initParams)
}, [managementState])
@@ -67,8 +75,10 @@ export function useModuleSelection(props) {
}
//새로고침시 데이터 날아가는거 방지
- if (!managementState) {
+ if (managementState === null) {
setManagementState(managementStateLoaded)
+ } else {
+ bindInitData()
}
getModuleData(roofsIds)
@@ -76,14 +86,23 @@ export function useModuleSelection(props) {
const getModuleData = async (roofsIds) => {
const list = await getModuleTypeItemList(roofsIds)
- //selectbox에 이름을 넣는다
- list.data.forEach((item) => {
- item.name = item.itemNm
- })
- //셀렉트박스 데이터 초기화
- setModuleList(list.data)
+ if (list.data.length > 0) {
+ //selectbox에 이름을 넣는다
+ list.data.forEach((item) => {
+ item.name = item.itemNm
+ })
+ //셀렉트박스 데이터 초기화
+ setModuleList(list.data)
+ }
}
+ //데이터가 있으면 모듈 자동 선택
+ useEffect(() => {
+ if (moduleList.length > 0 && isObjectNotEmpty(moduleSelectionData.module)) {
+ handleChangeModule(moduleSelectionData.module)
+ }
+ }, [moduleList])
+
const handleChangeModule = (option) => {
//선택된 모듈
setSelectedModules(option) //선택값 저장
@@ -101,31 +120,50 @@ export function useModuleSelection(props) {
...moduleSelectionInitParams,
illuminationTp: option.clCode,
})
+
+ setManagementState({
+ ...managementState,
+ surfaceType: option.clCodeNm,
+ surfaceTypeValue: option.clCode,
+ })
}
const handleChangeWindSpeed = (option) => {
setModuleSelectionInitParams({
...moduleSelectionInitParams,
- surfaceType: option.clCode,
+ stdWindSpeed: option.clCode,
+ })
+
+ setManagementState({
+ ...managementState,
+ standardWindSpeedId: option.clCode,
})
}
const handleChangeInstallHeight = (option) => {
setInstallHeight(option)
-
setModuleSelectionInitParams({
...moduleSelectionInitParams,
instHt: option,
})
+
+ setManagementState({
+ ...managementState,
+ installHeight: option,
+ })
}
const handleChangeVerticalSnowCover = (option) => {
setVerticalSnowCover(option)
-
setModuleSelectionInitParams({
...moduleSelectionInitParams,
stdSnowLd: option,
})
+
+ setManagementState({
+ ...managementState,
+ verticalSnowCover: option,
+ })
}
useEffect(() => {
diff --git a/src/hooks/module/useModuleTabContents.js b/src/hooks/module/useModuleTabContents.js
new file mode 100644
index 00000000..56365f38
--- /dev/null
+++ b/src/hooks/module/useModuleTabContents.js
@@ -0,0 +1,419 @@
+import { useEffect, useState, useRef } from 'react'
+import { useRecoilValue, useRecoilState } from 'recoil'
+import { pitchTextSelector } from '@/store/canvasAtom'
+import { useMasterController } from '@/hooks/common/useMasterController'
+import { useCommonCode } from '@/hooks/common/useCommonCode'
+import { moduleSelectionDataState, moduleSelectionInitParamsState, selectedModuleState } from '@/store/selectedModuleOptions'
+import { isObjectNotEmpty, isEqualObjects } from '@/util/common-utils'
+import { addedRoofsState } from '@/store/settingAtom'
+
+export function useModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
+ const addRoofsArray = useRecoilValue(addedRoofsState)
+ const globalPitchText = useRecoilValue(pitchTextSelector) //피치 텍스트
+
+ const { findCommonCode } = useCommonCode()
+ const [raftCodes, setRaftCodes] = useState([]) //가대 목록
+
+ const [trestleList, setTrestleList] = useState([])
+ const [constMthdList, setConstMthdList] = useState([])
+ const [roofBaseList, setRoofBaseList] = useState([])
+ const [constructionList, setConstructionList] = useState([{}]) //공법 목록
+
+ const [selectedRaftBase, setSelectedRaftBase] = useState({}) //선택된 가대
+ const [selectedTrestle, setSelectedTrestle] = useState({}) //선택된 가대
+ const [selectedConstMthd, setSelectedConstMthd] = useState({}) //선택된 공법
+ const [selectedRoofBase, setSelectedRoofBase] = useState({}) //선택된 지붕밑바탕
+ const [selectedConstruction, setSelectedConstruction] = useState({}) //선택된 공법
+ const [constructionListParams, setConstructionListParams] = useState({})
+
+ const [trestleParams, setTrestleParams] = useState({}) //서까래, 가대메이커,공법,지붕밑바탕 관련 api호출 파라메터
+ const [constructionParams, setConstructionParams] = useState({}) //공법 관련 api호출 파라메터
+ const [roofBaseParams, setRoofBaseParams] = useState({}) //지붕밑바탕 관련 api호출 파라메터
+
+ const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
+ const moduleSelectionInitOriginData = useRef(moduleSelectionInitParams)
+
+ const { getTrestleList, getConstructionList } = useMasterController()
+
+ const constructionRef = useRef([])
+ const [cvrYn, setCvrYn] = useState('N')
+ const [snowGdPossYn, setSnowGdPossYn] = useState('N')
+
+ const [cvrChecked, setCvrChecked] = useState(false)
+ const [snowGdChecked, setSnowGdChecked] = useState(false)
+
+ const [isExistData, setIsExistData] = useState(false)
+
+ const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
+ const [moduleConstructionSelectionData, setModuleConstructionSelectionData] = useState()
+
+ const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
+
+ const [hajebichi, setHajebichi] = useState(0)
+ const [lengthBase, setLengthBase] = useState(0)
+
+ const hajebichiRef = useRef()
+ const lengthRef = useRef()
+
+ //서까래간격 변경
+ const handleChangeRaftBase = (option) => {
+ setSelectedRaftBase(option)
+ setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode }) //가대메이커
+ setConstMthdList([]) //공법 초기화
+ setRoofBaseList([]) //지붕밑바탕 초기화
+ setConstructionList([]) //공법 초기화
+ }
+
+ //처마력바 체크
+ const handleCvrChecked = () => {
+ setCvrChecked(!cvrChecked)
+ setSelectedConstruction({ ...selectedConstruction, setupCover: !cvrChecked })
+ }
+
+ //눈막이금구 체크
+ const handleSnowGdChecked = () => {
+ setSnowGdChecked(!snowGdChecked)
+ setSelectedConstruction({ ...selectedConstruction, setupSnowCover: !snowGdChecked })
+ }
+
+ const getConstructionListData = async (params) => {
+ if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
+ const optionsList = await getConstructionList(params)
+ setConstructionList(optionsList.data)
+ }
+ }
+
+ useEffect(() => {
+ setHajebichi(addRoof.hajebichi)
+ setLengthBase(addRoof.lenBase)
+
+ // 202600 경사도
+ const raftCodeList = findCommonCode('203800')
+ //서까래 코드
+ raftCodeList.forEach((obj) => {
+ obj.name = obj.clCodeNm
+ obj.id = obj.clCode
+ })
+ setRaftCodes(raftCodeList)
+
+ console.log('moduleSelectionData', moduleSelectionData)
+ }, [])
+
+ //리코일에 데이터가 담기는 시점에 시작
+ useEffect(() => {
+ if (
+ isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex]) &&
+ isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex].trestle) &&
+ isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex].construction)
+ ) {
+ setModuleConstructionSelectionData(moduleSelectionData.roofConstructions[tabIndex])
+ }
+ }, [moduleSelectionData])
+
+ useEffect(() => {
+ if (isObjectNotEmpty(moduleConstructionSelectionData)) {
+ setIsExistData(true)
+ }
+ }, [moduleConstructionSelectionData])
+
+ //높이를 변경하면 addRoofs에 적용
+ // useEffect(() => {
+ // const copyAddRoof = { ...addRoof }
+ // copyAddRoof.length = Number(lengthBase)
+ // copyAddRoof.lenBase = lengthBase
+ // const index = addRoof.index
+ // const newArray = [...addRoofsArray.slice(0, index), copyAddRoof, ...addRoofsArray.slice(index + 1)]
+ // setAddedRoofs(newArray)
+ // }, [lengthBase])
+
+ // //망둥어 피치를 변경하면 addRoof 변경
+ // useEffect(() => {
+ // const copyAddRoof = { ...addRoof }
+ // copyAddRoof.hajebichi = Number(hajebichi)
+ // copyAddRoof.roofPchBase = hajebichi
+ // const index = addRoof.index
+ // const newArray = [...addRoofsArray.slice(0, index), copyAddRoof, ...addRoofsArray.slice(index + 1)]
+ // setAddedRoofs(newArray)
+ // }, [hajebichi])
+
+ useEffect(() => {
+ if (isExistData) {
+ setConstructionListParams({
+ ...moduleSelectionInitParams,
+ ...roofBaseParams,
+ roofBaseCd: selectedRoofBase.roofBaseCd,
+ inclCd: addRoof.pitch,
+ roofPitch: hajebichiRef.current ? hajebichiRef.current.value : 0,
+ raftBaseCd: addRoof.raftBaseCd,
+ })
+ }
+ }, [selectedRoofBase])
+
+ useEffect(() => {
+ if (
+ isExistData &&
+ constructionList.length > 0 &&
+ isObjectNotEmpty(moduleConstructionSelectionData?.construction) &&
+ moduleConstructionSelectionData?.construction.hasOwnProperty('constPossYn') ///키가 있으면
+ ) {
+ const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
+ const construction = constructionList[selectedIndex]
+ if (construction.constPossYn === 'Y') {
+ handleConstruction(selectedIndex)
+ }
+ }
+ }, [constructionList])
+
+ //모듈 변경
+ useEffect(() => {
+ //lengbase는 무조건 있다고 가정 하고 최초에 실행 방지
+ if (selectedModules) {
+ //가대메이커 파라메터 만들기
+ setTrestleParams({
+ moduleTpCd: selectedModules.itemTp,
+ roofMatlCd: addRoof.roofMatlCd,
+ raftBaseCd: addRoof.raftBaseCd,
+ workingWidth: lengthBase,
+ })
+ }
+ }, [selectedModules])
+
+ //가대메이커 api 호출
+ useEffect(() => {
+ if (isObjectNotEmpty(trestleParams)) {
+ getModuleOptionsListData(trestleParams, 'trestle')
+ }
+ }, [trestleParams])
+
+ //가대메이커 변경 함수
+ const handleChangeTrestle = (option) => {
+ setSelectedTrestle(option) //선택값 저장
+ setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' })
+ }
+
+ useEffect(() => {
+ if (isObjectNotEmpty(constructionParams)) {
+ getModuleOptionsListData(constructionParams, 'construction')
+ }
+ }, [constructionParams])
+
+ //공법 변경
+ const handleChangeConstMthd = (option) => {
+ setSelectedConstMthd(option) //선택된값 저장
+ setRoofBaseParams({
+ ...trestleParams,
+ trestleMkrCd: selectedTrestle.trestleMkrCd,
+ constMthdCd: option.constMthdCd,
+ roofBaseCd: '',
+ })
+ }
+
+ useEffect(() => {
+ if (isObjectNotEmpty(roofBaseParams)) {
+ getModuleOptionsListData(roofBaseParams, 'roofBase')
+ }
+ }, [roofBaseParams])
+
+ const handleChangeRoofBase = (option) => {
+ setConstructionListParams({
+ ...moduleSelectionInitParams,
+ trestleMkrCd: selectedTrestle.trestleMkrCd,
+ constMthdCd: selectedConstMthd.constMthdCd,
+ roofBaseCd: option.roofBaseCd,
+ inclCd: addRoof.pitch,
+ roofPitch: hajebichiRef.current ? hajebichiRef.current.value : 0,
+ raftBaseCd: addRoof.raftBaseCd,
+ roofMatlCd: addRoof.roofMatlCd,
+ })
+ setSelectedRoofBase(option)
+ }
+
+ //공법 리스트 변경 함수
+ useEffect(() => {
+ if (isObjectNotEmpty(constructionListParams)) {
+ getConstructionListData(constructionListParams)
+ }
+ }, [constructionListParams])
+
+ //공법 선택 함수
+ const handleConstruction = (index) => {
+ if (index > -1) {
+ const isPossibleIndex = constructionRef.current
+ .map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1))
+ .filter((index) => index !== -1)
+
+ isPossibleIndex.forEach((index) => {
+ if (constructionRef.current[index].classList.contains('blue')) {
+ constructionRef.current[index].classList.remove('blue')
+ constructionRef.current[index].classList.add('white')
+ }
+ })
+ constructionRef.current[index].classList.remove('white')
+ constructionRef.current[index].classList.add('blue')
+
+ const selectedConstruction = constructionList[index]
+ selectedConstruction.roofIndex = roofTab
+ selectedConstruction.setupCover = false //처마력바 설치 여부
+ selectedConstruction.setupSnowCover = false //눈막이금구 설치 여부
+ selectedConstruction.selectedIndex = index
+
+ setCvrYn(selectedConstruction.cvrYn)
+ setSnowGdPossYn(selectedConstruction.snowGdPossYn)
+
+ //기존에 선택된 데이터가 있으면 체크한다
+ if (moduleConstructionSelectionData && moduleConstructionSelectionData.construction) {
+ selectedConstruction.setupCover = moduleConstructionSelectionData.construction.setupCover || false
+ selectedConstruction.setupSnowCover = moduleConstructionSelectionData.construction.setupSnowCover || false
+ setCvrChecked(selectedConstruction.setupCover)
+ setSnowGdChecked(selectedConstruction.setupSnowCover)
+ }
+
+ setSelectedConstruction(selectedConstruction)
+ } else {
+ constructionRef.current.forEach((ref) => {
+ ref.classList.remove('blue')
+ })
+ }
+ }
+
+ //공법 선택시 이후 프로세스
+ useEffect(() => {
+ if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
+ if (tabIndex === roofTab) {
+ const common = { ...moduleSelectionInitParams }
+ const module = { ...selectedModules }
+ const newRoofConstructions = {
+ roofIndex: tabIndex,
+ addRoof: addRoof,
+ trestle: selectedRoofBase,
+ construction: selectedConstruction,
+ }
+
+ const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === tabIndex)
+
+ if (index > -1) {
+ const newArray = [
+ ...tempModuleSelectionData.roofConstructions.slice(0, index),
+ newRoofConstructions,
+ ...tempModuleSelectionData.roofConstructions.slice(index + 1),
+ ]
+ setTempModuleSelectionData({ common: common, module: module, roofConstructions: newArray })
+ } else {
+ setTempModuleSelectionData({
+ common: common,
+ module: module,
+ roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }],
+ })
+ }
+ }
+ }
+ }, [selectedConstruction])
+
+ const getModuleOptionsListData = async (params, type) => {
+ const optionsList = await getTrestleList(params)
+
+ if (optionsList.data.length > 0) {
+ if (type === 'trestle') {
+ setTrestleList(optionsList.data)
+ if (isExistData) {
+ handleChangeTrestle(moduleConstructionSelectionData?.trestle)
+ } else {
+ setConstMthdList([])
+ setRoofBaseList([])
+ }
+ } else if (type === 'construction') {
+ setConstMthdList(optionsList.data)
+ if (isExistData) {
+ handleChangeConstMthd(moduleConstructionSelectionData?.trestle)
+ } else {
+ setRoofBaseList([])
+ }
+ } else if (type === 'roofBase') {
+ setRoofBaseList(optionsList.data)
+ if (isExistData) {
+ handleChangeRoofBase(moduleConstructionSelectionData?.trestle)
+ }
+ }
+ }
+ }
+
+ useEffect(() => {
+ //모듈이 선택되어있을때
+ if (moduleSelectionInitOriginData.current.moduleItemId && moduleSelectionInitOriginData.current.moduleTpCd) {
+ //초기에 들어온 데이터가 수정된 데이터가 값이 다르다면`
+ if (!isEqualObjects(moduleSelectionInitOriginData.current, moduleSelectionInitParams)) {
+ //가대 선택 초기화
+ setSelectedTrestle({})
+
+ //공법 선택 초기화
+ setSelectedConstMthd({})
+
+ //지붕밑바탕 선택 초기화
+ setSelectedRoofBase({})
+
+ //공법 리스트 초기화
+ setConstructionList([])
+
+ // 기본 정보 초기화
+ setModuleSelectionData({
+ ...moduleSelectionData,
+ roofConstructions: [],
+ })
+
+ // 선택 데이터 초 기화
+ setModuleConstructionSelectionData({
+ addRoof: addRoof,
+ trestle: {},
+ construction: {},
+ })
+
+ //임시 데이터 초기화
+ setTempModuleSelectionData({
+ ...moduleSelectionData,
+ roofConstructions: [],
+ })
+
+ //처마커버 해제
+ setCvrChecked(false)
+ //눈막이금구 해제
+ setSnowGdChecked(false)
+
+ // 데이터 없음으로 변경
+ setIsExistData(false)
+
+ //변경된 데이터를 ref에 저장
+ moduleSelectionInitOriginData.current = moduleSelectionInitParams
+ }
+ }
+ }, [moduleSelectionInitParams])
+
+ return {
+ raftCodes,
+ trestleList,
+ constMthdList,
+ roofBaseList,
+ constructionList,
+ globalPitchText,
+ selectedTrestle,
+ selectedConstMthd,
+ selectedRoofBase,
+ constructionRef,
+ cvrYn,
+ cvrChecked,
+ snowGdPossYn,
+ snowGdChecked,
+ lengthBase,
+ hajebichi,
+ lengthRef,
+ hajebichiRef,
+ setLengthBase,
+ setHajebichi,
+ handleChangeRaftBase,
+ handleChangeTrestle,
+ handleChangeConstMthd,
+ handleChangeRoofBase,
+ handleConstruction,
+ handleCvrChecked,
+ handleSnowGdChecked,
+ }
+}
diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js
index 24541d22..968f782d 100644
--- a/src/hooks/module/useTrestle.js
+++ b/src/hooks/module/useTrestle.js
@@ -2,6 +2,8 @@ import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { getDegreeByChon, getTrestleLength } from '@/util/canvas-util'
+import { v4 as uuidv4 } from 'uuid'
// 회로 및 가대설정
export const useTrestle = () => {
@@ -19,17 +21,31 @@ export const useTrestle = () => {
canvas.remove(obj)
}
})
-
+ canvas.getObjects().forEach((obj) => {
+ if (obj.name === 'bracket') {
+ canvas.remove(obj)
+ }
+ })
surfaces.forEach((surface) => {
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
const roofMaterialIndex = parent.roofMaterial.index
- const construction = moduleSelectionData.roofConstructions.find((construction) => construction.roofIndex === roofMaterialIndex).construction
+ const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
+ if (!construction) {
+ alert('앞에서 셋팅 안됨')
+ return
+ }
+
+ let moduleRowsTotCnt = 0
let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover
const direction = parent.direction
-
const rack = surface.trestleDetail.rack
- let { rackQty, rackIntvlPct } = surface.trestleDetail
+ let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn } = surface.trestleDetail
+
+ if (!rack) {
+ //25/01/16 기준 랙이 없는 경우는 그냥 안그려준다.
+ return
+ }
const rackInfos = Object.keys(rack).map((key) => {
return { key, value: rack[key] }
@@ -41,12 +57,17 @@ export const useTrestle = () => {
const exposedBottomModules = [] // 아래 두면이 모두 노출 되어있는 경우
const leftExposedHalfBottomModules = [] // 왼쪽 면만 노출되어있는 경우
const rightExposedHalfBottomPoints = [] // 오른쪽 면만 노출되어 있는 경우
+ const leftExposedHalfTopModules = [] // 왼쪽 면만 노출되어 있는 경우
+ const rightExposedHalfTopPoints = [] // 오른쪽 면만 노출되어 있는 경우
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
+
modules.forEach((module) => {
const { x, y } = module.getCenterPoint()
const isExposedBottom = result.exposedBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isLeftExposedHalfBottom = result.leftExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
const isRightExposedHalfBottom = result.rightExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
+ const isRightExposedHalfTop = result.rightExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
+ const isLeftExposedHalfTop = result.leftExposedHalfTopPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
if (isExposedBottom) {
exposedBottomModules.push(module)
}
@@ -56,11 +77,26 @@ export const useTrestle = () => {
if (isRightExposedHalfBottom) {
rightExposedHalfBottomPoints.push(module)
}
+ if (isRightExposedHalfTop) {
+ leftExposedHalfTopModules.push(module)
+ }
+ if (isLeftExposedHalfTop) {
+ rightExposedHalfTopPoints.push(module)
+ }
})
+ // 4개중 한개라도 있는 경우 치조배치로 간주한다.
+ const isChidory =
+ leftExposedHalfBottomModules.length > 0 ||
+ rightExposedHalfBottomPoints.length > 0 ||
+ leftExposedHalfTopModules.length > 0 ||
+ rightExposedHalfTopPoints.length > 0
+
+ surface.set({ isChidory: isChidory })
+
canvas
.getObjects()
- .filter((obj) => obj.name === 'eaveBar')
+ .filter((obj) => ['eaveBar', 'halfEaveBar'].includes(obj.name) && obj.parent === surface)
.forEach((obj) => {
canvas.remove(obj)
})
@@ -72,19 +108,88 @@ export const useTrestle = () => {
const bottomPoints = findTopTwoPoints([...module.points], direction)
if (!bottomPoints) return
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
+ parent: surface,
name: 'eaveBar',
stroke: 'blue',
strokeWidth: 4,
selectable: false,
+ surfaceId: surface.id,
+ parentId: module.id,
})
canvas.add(eaveBar)
canvas.renderAll()
})
+
+ if (isChidory && cvrPlvrYn === 'Y') {
+ leftExposedHalfBottomModules.forEach((module) => {
+ const bottomPoints = findTopTwoPoints([...module.points], direction)
+ let barPoints = []
+ //설치해야할 반처마커버 포인트를 방향에 따라 설정
+
+ if (direction === 'south') {
+ barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x - module.width / 2, bottomPoints[1].y]
+ } else if (direction === 'north') {
+ barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
+ } else if (direction === 'east') {
+ barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[0].y - module.height / 2]
+ } else if (direction === 'west') {
+ barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y - module.height / 2]
+ }
+
+ if (!bottomPoints) return
+ const halfEaveBar = new fabric.Line(barPoints, {
+ parent: surface,
+ name: 'halfEaveBar',
+ stroke: 'blue',
+ strokeWidth: 4,
+ selectable: false,
+ surfaceId: surface.id,
+ parentId: module.id,
+ })
+ canvas.add(halfEaveBar)
+ canvas.renderAll()
+ })
+
+ rightExposedHalfBottomPoints.forEach((module) => {
+ const bottomPoints = findTopTwoPoints([...module.points], direction)
+ let barPoints = []
+ //설치해야할 반처마커버 포인트를 방향에 따라 설정
+
+ if (direction === 'south') {
+ barPoints = [bottomPoints[0].x + module.width / 2, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y]
+ } else if (direction === 'north') {
+ barPoints = [bottomPoints[0].x, bottomPoints[0].y, bottomPoints[0].x + module.width / 2, bottomPoints[1].y]
+ } else if (direction === 'east') {
+ barPoints = [bottomPoints[0].x, bottomPoints[1].y + module.height / 2, bottomPoints[1].x, bottomPoints[1].y]
+ } else if (direction === 'west') {
+ barPoints = [bottomPoints[0].x, bottomPoints[1].y - module.height / 2, bottomPoints[1].x, bottomPoints[1].y]
+ }
+
+ if (!bottomPoints) return
+ const halfEaveBar = new fabric.Line(barPoints, {
+ parent: surface,
+ name: 'halfEaveBar',
+ stroke: 'blue',
+ strokeWidth: 4,
+ selectable: false,
+ parentId: module.id,
+ })
+ canvas.add(halfEaveBar)
+ canvas.renderAll()
+ })
+ }
}
+ const horizontal = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlHor : surface.trestleDetail.moduleIntvlVer
+
+ const vertical = ['south', 'north'].includes(direction) ? surface.trestleDetail.moduleIntvlVer : surface.trestleDetail.moduleIntvlHor
+
+ let mostRowsModule = 0 // 모듈 최대 단 수
// 가대 설치를 위한 가장 아래 모듈로부터 위로 몇단인지 계산
// 오른쪽,왼쪽 둘 다 아래에 아무것도 없는, 처마 커버를 필요로 하는 모듈
exposedBottomModules.forEach((module) => {
- const { width, height } = module
+ let { width, height } = { ...module }
+ width = Math.floor(width)
+ height = Math.floor(height)
let { x: startX, y: startY } = { ...module.getCenterPoint() }
let { x, y } = { ...module.getCenterPoint() }
//TODO : 방향별로 가대 설치해야함
@@ -99,7 +204,7 @@ export const useTrestle = () => {
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
- let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
+ let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
@@ -109,10 +214,10 @@ export const useTrestle = () => {
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
- nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
- nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = true
}
@@ -134,7 +239,7 @@ export const useTrestle = () => {
// 오른쪽 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
- let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
+ let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
@@ -144,10 +249,10 @@ export const useTrestle = () => {
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
- nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
- nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
@@ -169,7 +274,7 @@ export const useTrestle = () => {
// 센터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
- let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
+ let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
@@ -196,13 +301,21 @@ export const useTrestle = () => {
return rack.value.moduleRows === centerRows
})?.value.racks
- drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L')
- drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R')
+ mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule)
- if (rackQty === 3) {
- //rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
- drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C')
+ if (rackYn === 'Y') {
+ drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
+ drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
+
+ if (rackQty === 3) {
+ //rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
+ drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C', rackYn)
+ } else if (rackQty === 4) {
+ drawRacks(leftRacks, rackQty, rackIntvlPct / 3, module, direction, 'L', rackYn)
+ drawRacks(rightRacks, rackQty, rackIntvlPct / 3, module, direction, 'R', rackYn)
+ }
}
+ module.set({ leftRows, rightRows, centerRows })
})
// 왼쪽아래에 모듈이 없는 모듈들
leftExposedHalfBottomModules.forEach((module) => {
@@ -218,7 +331,7 @@ export const useTrestle = () => {
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
- let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
+ let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
@@ -228,10 +341,10 @@ export const useTrestle = () => {
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findLeft) {
- nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = false
} else {
- nextModule = nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findLeft = true
}
@@ -250,8 +363,12 @@ export const useTrestle = () => {
const leftRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === leftRows
})?.value.racks
+ mostRowsModule = Math.max(leftRows, mostRowsModule)
+ if (rackYn === 'Y') {
+ drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
+ }
- drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L')
+ module.set({ leftRows })
})
// 오른쪽 아래에 모듈이 없는 모듈들
rightExposedHalfBottomPoints.forEach((module) => {
@@ -267,7 +384,7 @@ export const useTrestle = () => {
// 오른쪽 찾는다.
while (hasNextModule) {
//바로 위에 있는지 확인한다.
- let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
+ let nextModule = findNextModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
if (nextModule) {
// 바로 위 모듈을 찾는다.
@@ -277,10 +394,10 @@ export const useTrestle = () => {
} else {
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
if (findRight) {
- nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextRightModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = false
} else {
- nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
+ nextModule = findNextLeftModule({ x, y, width, height, horizontal, vertical }, centerPoints, direction)
findRight = true
}
@@ -299,47 +416,53 @@ export const useTrestle = () => {
const rightRacks = rackInfos.find((rack) => {
return rack.value.moduleRows === rightRows
})?.value.racks
+
+ mostRowsModule = Math.max(rightRows, mostRowsModule)
// 해당 rack으로 그려준다.
+ if (rackYn === 'Y') {
+ drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
+ }
- drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R')
+ module.set({ rightRows })
})
+
+ surface.set({ moduleRowsTotCnt: mostRowsModule })
+
+ if (rackYn === 'N') {
+ // rack이 없을경우
+ installBracketWithOutRack(surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory)
+ } else if (rackYn === 'Y') {
+ installBracket(surface)
+ }
+
+ console.log(getTrestleParams(surface))
})
-
- /*switch (rackYn) {
- case 'Y': {
- // rack이 Y일 경우 rackQty가 필요함
-
- break
- }
- case 'N': {
- break
- }
- }*/
- // 지지금구 설치
- installBracket()
}
const findNextModule = (currentPoint, centerPoints, direction) => {
- let { x, y, width, height } = currentPoint
- width = Math.floor(width)
- height = Math.floor(height)
+ let { x, y, width, height, horizontal, vertical } = { ...currentPoint }
+ width = width + horizontal
+ height = height + vertical
+
+ let maxX = 2 + horizontal * 3
+ let maxY = 2 + vertical * 3
let result
switch (direction) {
case 'south': {
- result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
+ result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
break
}
case 'north': {
- result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
+ result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
break
}
case 'east': {
- result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
+ result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
break
}
case 'west': {
- result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
+ result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
break
}
}
@@ -348,16 +471,23 @@ export const useTrestle = () => {
}
const findNextLeftModule = (currentPoint, centerPoints, direction) => {
- const { x, y, width, height } = currentPoint
+ let { x, y, width, height, horizontal, vertical } = { ...currentPoint }
+
let result
let topLeftPoint
+ let maxX = 2 + horizontal * 3
+ let maxY = 2 + vertical * 3
switch (direction) {
case 'south': {
+ width = width + horizontal
+ height = height + vertical
topLeftPoint = { x: x - width / 2, y: y - height }
break
}
case 'north': {
+ width = width + horizontal
+ height = height + vertical
topLeftPoint = { x: x + width / 2, y: y + height }
break
}
@@ -371,15 +501,20 @@ export const useTrestle = () => {
}
}
- result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2)
+ result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY)
return result
}
const findNextRightModule = (currentPoint, centerPoints, direction) => {
- const { x, y, width, height } = currentPoint
+ let { x, y, width, height, horizontal, vertical } = { ...currentPoint }
+ width = width + horizontal
+ height = height + vertical
let result
let topRightPoint
+ let maxX = 2 + horizontal * 3
+ let maxY = 2 + vertical * 3
+
switch (direction) {
case 'south': {
topRightPoint = { x: x + width / 2, y: y - height }
@@ -399,13 +534,19 @@ export const useTrestle = () => {
}
}
- result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2)
+ result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY)
return result
}
- const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l) => {
- const { width, height } = module
+ const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l, rackYn) => {
+ const { width, height, left, top, lastX, lastY, surfaceId } = module
+ const surface = canvas.getObjects().find((obj) => obj.id === surfaceId)
+ const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId)
+ const degree = getDegreeByChon(roof.roofMaterial.pitch)
+
+ const moduleLeft = lastX ?? left
+ const moduleTop = lastY ?? top
let startPointX, startPointY
@@ -484,160 +625,316 @@ export const useTrestle = () => {
switch (direction) {
case 'south': {
rackInfos.forEach((rackInfo) => {
- const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
+ const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
+ let rackLength = getTrestleLength(rackLen, degree) / 10
- const rackLength = rackLen / 10
+ if (smartRackYn === 'Y') {
+ let smartRackId = uuidv4()
+ smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
+ rackLength = getTrestleLength(setRackTpLen, degree) / 10
+ if (setRackTpCd === 'RACK') {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
+ name: 'smartRack',
+ stroke: 'blue',
+ strokeWidth: 4,
+ selectable: false,
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
- const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY - rackLength], {
- name: 'rack',
- stroke: 'red',
- strokeWidth: 4,
- selectable: false,
- fill: 'red',
- shadow: {
- color: 'black', // Outline color
- blur: 10,
- offsetX: 0,
- offsetY: 0,
- },
- supFitQty,
- supFitIntvlPct,
- rackLen,
- rackId: itemId,
- direction: 'top',
- })
+ parentId: module.id,
+ surfaceId: surface.id,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ seq,
+ smartRackId,
+ rackId: itemId,
+ direction: 'top',
+ })
+ canvas.add(rack)
+ canvas.renderAll()
+ } else if (setRackTpCd === 'INTVL') {
+ startPointY -= rackLength + 8
+ }
+ })
+ } else {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY - rackLength], {
+ name: 'rack',
+ stroke: 'red',
+ strokeWidth: 4,
+ selectable: false,
+ fill: 'red',
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ rackId: itemId,
+ direction: 'top',
+ })
- canvas.add(rack)
- canvas.renderAll()
+ canvas.add(rack)
+ canvas.renderAll()
+ }
- startPointY -= rackLength + 3
+ startPointY -= rackLength + 8
})
break
}
case 'east': {
rackInfos.forEach((rackInfo) => {
- const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
+ const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
- const rackLength = rackLen / 10
+ let rackLength = getTrestleLength(rackLen, degree) / 10
+ if (smartRackYn === 'Y') {
+ let smartRackId = uuidv4()
+ smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
+ rackLength = getTrestleLength(setRackTpLen, degree) / 10
+ if (setRackTpCd === 'RACK') {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX - rackLength, startPointY], {
+ name: 'smartRack',
+ stroke: 'blue',
+ strokeWidth: 4,
+ selectable: false,
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ seq,
+ smartRackId,
+ rackId: itemId,
+ direction: 'left',
+ })
+ canvas.add(rack)
+ canvas.renderAll()
+ } else if (setRackTpCd === 'INTVL') {
+ startPointX -= rackLength
+ }
+ })
+ } else {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX - rackLength, startPointY], {
+ name: 'rack',
+ stroke: 'red',
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ strokeWidth: 4,
+ selectable: false,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackYn,
+ rackRowsCd,
+ rackId: itemId,
+ direction: 'left',
+ })
- const rack = new fabric.Line([startPointX, startPointY, startPointX - rackLength, startPointY], {
- name: 'rack',
- stroke: 'red',
- shadow: {
- color: 'black', // Outline color
- blur: 10,
- offsetX: 0,
- offsetY: 0,
- },
- strokeWidth: 4,
- selectable: false,
- supFitQty,
- supFitIntvlPct,
- rackLen,
- rackId: itemId,
- direction: 'left',
- })
+ canvas.add(rack)
+ canvas.renderAll()
+ }
- canvas.add(rack)
- canvas.renderAll()
-
- startPointX -= rackLength + 3
+ startPointX -= rackLength + 8
})
break
}
case 'west': {
rackInfos.forEach((rackInfo) => {
- const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
+ const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
+ let rackLength = getTrestleLength(rackLen, degree) / 10
+ if (smartRackYn === 'Y') {
+ let smartRackId = uuidv4()
+ smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
+ rackLength = getTrestleLength(setRackTpLen, degree) / 10
+ if (setRackTpCd === 'RACK') {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
+ name: 'smartRack',
+ stroke: 'blue',
+ strokeWidth: 4,
+ selectable: false,
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ seq,
+ smartRackId,
+ rackId: itemId,
+ direction: 'right',
+ })
+ canvas.add(rack)
+ canvas.renderAll()
+ } else if (setRackTpCd === 'INTVL') {
+ startPointX += rackLength + 8
+ }
+ })
+ } else {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
+ name: 'rack',
+ stroke: 'red',
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ strokeWidth: 4,
+ selectable: false,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ rackId: itemId,
+ direction: 'right',
+ })
- const rackLength = rackLen / 10
+ canvas.add(rack)
+ canvas.renderAll()
+ }
- const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
- name: 'rack',
- stroke: 'red',
- shadow: {
- color: 'black', // Outline color
- blur: 10,
- offsetX: 0,
- offsetY: 0,
- },
- strokeWidth: 4,
- selectable: false,
- supFitQty,
- supFitIntvlPct,
- rackLen,
- rackId: itemId,
- direction: 'right',
- })
-
- canvas.add(rack)
- canvas.renderAll()
-
- startPointX += rackLength + 3
+ startPointX += rackLength + 8
})
break
}
case 'north': {
rackInfos.forEach((rackInfo) => {
- const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
+ const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
+ let rackLength = getTrestleLength(rackLen, degree) / 10
+ if (smartRackYn === 'Y') {
+ let smartRackId = uuidv4()
+ smartRack.forEach(({ seq, setRackTpCd, setRackTpLen, supFitQty }) => {
+ rackLength = getTrestleLength(setRackTpLen, degree) / 10
+ if (setRackTpCd === 'RACK') {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
+ name: 'smartRack',
+ stroke: 'blue',
+ strokeWidth: 4,
+ selectable: false,
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ seq,
+ smartRackId,
+ rackId: itemId,
+ direction: 'right',
+ })
+ canvas.add(rack)
+ canvas.renderAll()
+ } else if (setRackTpCd === 'INTVL') {
+ startPointY += rackLength + 8
+ }
+ })
+ } else {
+ const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY + rackLength], {
+ name: 'rack',
+ stroke: 'red',
+ shadow: {
+ color: 'black', // Outline color
+ blur: 10,
+ offsetX: 0,
+ offsetY: 0,
+ },
+ parentId: module.id,
+ surfaceId: surface.id,
+ strokeWidth: 4,
+ selectable: false,
+ supFitQty,
+ supFitIntvlPct,
+ rackLen,
+ rackRowsCd,
+ rackId: itemId,
+ direction: 'bottom',
+ })
- const rackLength = rackLen / 10
-
- const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY + rackLength], {
- name: 'rack',
- stroke: 'red',
- shadow: {
- color: 'black', // Outline color
- blur: 10,
- offsetX: 0,
- offsetY: 0,
- },
- strokeWidth: 4,
- selectable: false,
- supFitQty,
- supFitIntvlPct,
- rackLen,
- rackId: itemId,
- direction: 'bottom',
- })
-
- canvas.add(rack)
- canvas.renderAll()
-
- startPointY += rackLength + 3
+ canvas.add(rack)
+ canvas.renderAll()
+ }
+ startPointY += rackLength + 8
})
break
}
}
}
- const installBracket = () => {
- const racks = canvas.getObjects().filter((obj) => obj.name === 'rack')
- // name이 bracket인 객체를 찾아서 삭제
- canvas.getObjects().forEach((obj) => {
- if (obj.name === 'bracket') {
- canvas.remove(obj)
- }
+ const installBracket = (surface) => {
+ const modules = surface.modules
+ const racks = []
+ modules.forEach((module) => {
+ canvas
+ .getObjects()
+ .filter((obj) => obj.name === 'rack')
+ .forEach((rack) => {
+ if (rack.parentId === module.id) {
+ canvas.remove(canvas.getObjects().filter((obj) => obj.name === 'bracket' && obj.parentId === rack.id))
+ racks.push(rack)
+ }
+ })
})
+
canvas.renderAll()
racks.forEach((rack) => {
const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen } = rack
- const moduleLength = 10
+ const bracketLength = 10
if (direction === 'top') {
const result = getBracketPoints(supFitQty, supFitIntvlPct)
result.forEach((percent) => {
const bracket = new fabric.Rect({
- left: x2 - moduleLength / 3,
+ left: x2 - bracketLength / 3,
top: y2 + (rackLen / 10) * percent,
fill: 'green',
name: 'bracket',
- width: moduleLength,
- height: moduleLength,
+ parentId: rack.parentId,
+ surfaceId: surface.id,
+ width: bracketLength,
+ height: bracketLength,
selectable: false,
})
@@ -650,11 +947,13 @@ export const useTrestle = () => {
result.forEach((percent) => {
const bracket = new fabric.Rect({
left: x2 + (rackLen / 10) * percent,
- top: y2 - moduleLength / 3,
+ top: y2 - bracketLength / 3,
fill: 'green',
name: 'bracket',
- width: moduleLength,
- height: moduleLength,
+ parentId: rack.parentId,
+ surfaceId: surface.id,
+ width: bracketLength,
+ height: bracketLength,
selectable: false,
})
@@ -667,11 +966,13 @@ export const useTrestle = () => {
result.forEach((percent) => {
const bracket = new fabric.Rect({
left: x2 - (rackLen / 10) * percent,
- top: y2 - moduleLength / 3,
+ top: y2 - bracketLength / 3,
fill: 'green',
+ parentId: rack.parentId,
+ surfaceId: surface.id,
name: 'bracket',
- width: moduleLength,
- height: moduleLength,
+ width: bracketLength,
+ height: bracketLength,
selectable: false,
})
@@ -683,12 +984,14 @@ export const useTrestle = () => {
result.forEach((percent) => {
const bracket = new fabric.Rect({
- left: x2 - moduleLength / 3,
+ left: x2 - bracketLength / 3,
top: y2 - (rackLen / 10) * percent,
fill: 'green',
name: 'bracket',
- width: moduleLength,
- height: moduleLength,
+ parentId: rack.parentId,
+ surfaceId: surface.id,
+ width: bracketLength,
+ height: bracketLength,
selectable: false,
})
@@ -699,6 +1002,173 @@ export const useTrestle = () => {
})
}
+ //랙 없음 인 경우 지지금구 설치
+ const installBracketWithOutRack = (surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory) => {
+ let { rackQty, rackIntvlPct, moduleIntvlHor, moduleIntvlVer, lessSupFitQty, lessSupFitIntvlPct } = surface.trestleDetail
+ const direction = surface.direction
+ rackQty = 3
+ rackIntvlPct = 10
+
+ canvas.renderAll()
+ exposedBottomModules.forEach((module) => {
+ canvas.renderAll()
+ drawBracketWithOutRack(module, rackIntvlPct, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ drawBracketWithOutRack(module, rackIntvlPct, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ if (!isChidory && rackQty === 3) {
+ // 치도리가 아니면서 갯수가 3개인 경우 센터도 설치 필요함
+ drawBracketWithOutRack(module, rackIntvlPct, module.centerRows + 1, 'C', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+
+ if (isChidory && rackQty === 3) {
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+ if (rackQty === 4) {
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+
+ if (!isChidory && rackQty === 5) {
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'C', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+ })
+
+ leftExposedHalfBottomModules.forEach((module) => {
+ drawBracketWithOutRack(module, rackIntvlPct, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ if (rackQty === 3 && findSamePointInBottom(exposedBottomModules, module)) {
+ // 해당 모듈과 같은 위치 맨 아래에 모듈이 있는 경우 하나 더 설치 필요
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+ if (rackQty === 4) {
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.leftRows + 1, 'L', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+ })
+
+ rightExposedHalfBottomPoints.forEach((module) => {
+ drawBracketWithOutRack(module, rackIntvlPct, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ if (rackQty === 3 && !findSamePointInBottom(exposedBottomModules, module)) {
+ // 해당 모듈과 같은 위치 맨 아래에 모듈이 없는 경우 하나 더 설치 필요
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+ if (rackQty === 4) {
+ drawBracketWithOutRack(module, rackIntvlPct / 3, module.rightRows + 1, 'R', surface.direction, moduleIntvlHor, moduleIntvlVer)
+ }
+ })
+ }
+
+ // 방향에 따라 가장 아래모듈중 같은 좌표가 있는지 확인
+ const findSamePointInBottom = (exposedBottomModules, module) => {
+ const { x, y } = module.getCenterPoint()
+ return exposedBottomModules.find((exposedBottomModule) => {
+ const { x: exposedX, y: exposedY } = exposedBottomModule.getCenterPoint()
+ return Math.abs(x - exposedX) < 2 || Math.abs(y - exposedY) < 2
+ })
+ }
+
+ const drawBracketWithOutRack = (module, rackIntvlPct, count, l, direction, moduleIntvlHor, moduleIntvlVer) => {
+ let { width, height, left, top } = module
+ let startPointX
+ let startPointY
+
+ switch (l) {
+ case 'L': {
+ // 왼쪽부분 시작 점
+ if (direction === 'south') {
+ startPointX = left + width / rackIntvlPct
+ startPointY = top + height
+ break
+ } else if (direction === 'east') {
+ startPointX = left + width
+ startPointY = top + height - height / rackIntvlPct
+ break
+ } else if (direction === 'west') {
+ startPointX = left
+ startPointY = top + height / rackIntvlPct
+ break
+ } else if (direction === 'north') {
+ startPointX = left + width - width / rackIntvlPct
+ startPointY = top
+ break
+ }
+ }
+
+ case 'R': {
+ // 오른쪽부분 시작 점
+ if (direction === 'south') {
+ startPointX = left + width - width / rackIntvlPct
+ startPointY = top + height / 2 + height / 2
+ break
+ } else if (direction === 'east') {
+ startPointX = left + width
+ startPointY = top + height / rackIntvlPct
+ break
+ } else if (direction === 'west') {
+ startPointX = left
+ startPointY = top + height - height / rackIntvlPct
+ break
+ } else if (direction === 'north') {
+ startPointX = left + width / rackIntvlPct
+ startPointY = top
+ break
+ }
+ }
+ case 'C': {
+ // 중간부분 시작점
+ if (direction === 'south') {
+ const x = left + width / 2
+ const y = top + height / 2
+ startPointX = x
+ startPointY = y + height / 2
+ break
+ } else if (direction === 'east') {
+ const x = left + width
+ const y = top + height / 2
+ startPointX = x
+ startPointY = y
+ break
+ } else if (direction === 'west') {
+ const x = left
+ const y = top + height / 2
+ startPointX = x
+ startPointY = y
+ break
+ } else if (direction === 'north') {
+ const x = left + width / 2
+ const y = top
+ startPointX = x
+ startPointY = y
+ break
+ }
+ }
+ }
+
+ for (let i = 0; i < count; i++) {
+ const bracket = new fabric.Rect({
+ left: startPointX - 5,
+ top: startPointY - 5,
+ fill: 'green',
+ name: 'bracket',
+ parentId: module.id,
+ surfaceId: module.surfaceId,
+ width: 10,
+ height: 10,
+ selectable: false,
+ })
+ canvas.add(bracket)
+ canvas.renderAll()
+ if (direction === 'south') {
+ startPointY -= height + moduleIntvlVer
+ } else if (direction === 'north') {
+ startPointY += height + moduleIntvlVer
+ } else if (direction === 'east') {
+ startPointX -= width + moduleIntvlHor
+ } else if (direction === 'west') {
+ startPointX += width + moduleIntvlHor
+ }
+ }
+ }
+
const getBracketPoints = (n, percent) => {
if (n < 2) {
throw new Error('Number of points must be at least 2')
@@ -747,10 +1217,18 @@ export const useTrestle = () => {
const direction = moduleSurface.direction
const modules = moduleSurface.modules
+ const horizontal = ['south', 'north'].includes(direction)
+ ? moduleSurface.trestleDetail.moduleIntvlHor
+ : moduleSurface.trestleDetail.moduleIntvlVer
+
+ const vertical = ['south', 'north'].includes(direction) ? moduleSurface.trestleDetail.moduleIntvlVer : moduleSurface.trestleDetail.moduleIntvlHor
+
+ const maxX = 2 + horizontal * 3
+ const maxY = 2 + vertical * 3
modules.forEach((module, index) => {
module.tempIndex = index
const { x, y } = module.getCenterPoint()
- const { width, height } = module
+ const { width, height } = { ...module }
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
})
@@ -775,9 +1253,11 @@ export const useTrestle = () => {
// 반노출 bottom면의 points
let leftExposedHalfBottomPoints = []
let rightExposedHalfBottomPoints = []
+ let leftExposedHalfTopPoints = []
+ let rightExposedHalfTopPoints = []
centerPoints.forEach((centerPoint, index) => {
- const { x, y, width, height } = centerPoint
+ let { x, y, width, height } = { ...centerPoint }
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
let bottomCell
let bottomLeftPoint
@@ -787,22 +1267,28 @@ export const useTrestle = () => {
switch (direction) {
case 'south':
- bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
+ width = width + horizontal
+ height = height + vertical
+ bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
bottomLeftPoint = { x: x - width / 2, y: y + height }
bottomRightPoint = { x: x + width / 2, y: y + height }
break
case 'north':
- bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
+ width = width + horizontal
+ height = height + vertical
+ bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
bottomLeftPoint = { x: x + width / 2, y: y - height }
bottomRightPoint = { x: x - width / 2, y: y - height }
break
case 'east':
- bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
+ bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
+ width = width + horizontal
bottomLeftPoint = { x: x + width, y: y + height / 2 }
bottomRightPoint = { x: x + width, y: y - height / 2 }
break
case 'west':
- bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
+ bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
+ width = width + horizontal
bottomLeftPoint = { x: x - width, y: y - height / 2 }
bottomRightPoint = { x: x - width, y: y + height / 2 }
break
@@ -814,10 +1300,10 @@ export const useTrestle = () => {
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
leftBottomCnt = centerPoints.filter(
- (centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
+ (centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - bottomLeftPoint.y) < maxY,
).length
rightBottomCnt = centerPoints.filter(
- (centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
+ (centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < maxX && Math.abs(centerPoint.y - bottomRightPoint.y) < maxY,
).length
if (leftBottomCnt + rightBottomCnt === 1) {
@@ -835,7 +1321,7 @@ export const useTrestle = () => {
// 노출상면 및 접면 체크
centerPoints.forEach((centerPoint, index) => {
- const { x, y, width, height } = centerPoint
+ let { x, y, width, height } = { ...centerPoint }
let topCell
let topLeftPoint
@@ -845,22 +1331,27 @@ export const useTrestle = () => {
switch (direction) {
case 'south':
- topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
+ width = width + horizontal
+ height = height + vertical
+ topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
topLeftPoint = { x: x - width / 2, y: y - height }
topRightPoint = { x: x + width / 2, y: y - height }
break
case 'north':
- topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
+ height = height + vertical
+ topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
topLeftPoint = { x: x + width / 2, y: y + height }
topRightPoint = { x: x - width / 2, y: y + height }
break
case 'east':
- topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
+ width = width + horizontal
+ topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
topLeftPoint = { x: x - width, y: y + height / 2 }
topRightPoint = { x: x - width, y: y - height / 2 }
break
case 'west':
- topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
+ width = width + horizontal
+ topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
topLeftPoint = { x: x + width, y: y - height / 2 }
topRightPoint = { x: x + width, y: y + height / 2 }
break
@@ -872,10 +1363,10 @@ export const useTrestle = () => {
}
leftTopCnt = centerPoints.filter(
- (centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2,
+ (centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < maxX && Math.abs(centerPoint.y - topLeftPoint.y) < maxY,
).length
rightTopCnt = centerPoints.filter(
- (centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
+ (centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < maxX && Math.abs(centerPoint.y - topRightPoint.y) < maxY,
).length
if (leftTopCnt + rightTopCnt === 2) {
@@ -886,6 +1377,12 @@ export const useTrestle = () => {
if (leftTopCnt + rightTopCnt === 1) {
exposedHalfTop++
halfTouchDimension++
+ if (leftTopCnt === 1) {
+ rightExposedHalfTopPoints.push(centerPoint)
+ }
+ if (rightTopCnt === 1) {
+ leftExposedHalfTopPoints.push(centerPoint)
+ }
return
}
if (leftTopCnt + rightTopCnt === 0) {
@@ -894,10 +1391,6 @@ export const useTrestle = () => {
})
// 완전 노출 하면 계산
- /*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
- const points = cells.map((cell) => {
- return cell.getCenterPoint()
- })*/
const groupPoints = groupCoordinates(centerPoints, modules[0], direction)
groupPoints.forEach((group) => {
@@ -937,6 +1430,8 @@ export const useTrestle = () => {
exposedBottomPoints,
leftExposedHalfBottomPoints,
rightExposedHalfBottomPoints,
+ leftExposedHalfTopPoints,
+ rightExposedHalfTopPoints,
centerPoints,
}
}
@@ -984,5 +1479,329 @@ export const useTrestle = () => {
return groups
}
- return { apply }
+ const getTrestleParams = (surface) => {
+ const result = calculateForApi(surface)
+
+ const eaveBar = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'eaveBar')
+ const halfEaveBar = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'halfEaveBar')
+
+ const rackList = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'rack')
+ const smartRackList = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'smartRack')
+ // smartRackList을 smartRackId 기준으로 그룹화 한 배열
+ const smartRackGroup = smartRackList.reduce((acc, cur) => {
+ if (!acc[cur.smartRackId]) {
+ acc[cur.smartRackId] = []
+ }
+ acc[cur.smartRackId].push(cur)
+ return acc
+ }, {})
+
+ const bracketList = canvas.getObjects().filter((obj) => obj.surfaceId === surface.id && obj.name === 'bracket')
+ let rackParams = rackList.map((rack, index) => {
+ return {
+ seq: index,
+ rackId: rack.rackId,
+ rackFittingCnt: rack.supFitQty,
+ rackRows: rack.rackRowsCd,
+ }
+ })
+
+ return {
+ exposedLowerBottomTotCnt: result.exposedBottom, // 노출 최하면 갯수
+ exposedHalfBottomTotCnt: result.exposedHalfBottom, // 노출 반하면 갯수
+ exposedTopTotCnt: result.exposedTop, // 노출 상면 총 수
+ exposedHalfTopTotCnt: result.exposedHalfTop, // 노출 반상면 총 수
+ exposedBottomTotCnt: result.exposedBottomPoints.length, // 노출 하면 수
+ touchedSurfaceTotCnt: result.touchDimension, // 접면 총 수
+ touchedHalfSurfaceTotCnt: result.halfTouchDimension, // 반접면 총 수
+ moduleRowsTotCnt: surface.moduleRowsTotCnt, // 모듈 총 단 수
+ eavesTotCnt: eaveBar.length,
+ eavesHalfTotCnt: halfEaveBar.length,
+ racks: rackParams,
+ rackTotCnt: rackList.length ?? 0 + smartRackGroup.length ?? 0,
+ rackFittingCnt: bracketList.length,
+ moduleRows: getMostLeftModules(surface),
+ }
+ }
+
+ // 가장 왼쪽에 있는 모듈을 기준으로 같은 단에 있는 모듈들 파라미터 생성
+ const getMostLeftModules = (surface) => {
+ const { direction, modules } = surface
+ const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
+ const roofMaterialIndex = parent.roofMaterial.index
+ const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
+ let isEaveBar = construction.setupCover
+ let isSnowGuard = construction.setupSnowCover
+ let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
+
+ if (rackYn === 'N') {
+ rackQty = lessSupFitQty
+ }
+
+ // 같은 단에 있는 모듈들의 리스트
+ let sameLineModuleList = []
+ let result = []
+
+ if (direction === 'south') {
+ // 모듈의 top으로 groupBy
+ const groupedByTop = modules.reduce((acc, module) => {
+ const key = module.top
+ if (!acc[key]) {
+ acc[key] = []
+ }
+ acc[key].push(module)
+ return acc
+ }, {})
+ // groupedByTop의 키값을 기준으로 정렬한 데이터를 배열로 변환
+ sameLineModuleList = Object.values(groupedByTop).sort((a, b) => b[0].top - a[0].top)
+ } else if (direction === 'north') {
+ const groupedByTop = modules.reduce((acc, module) => {
+ const key = module.top
+ if (!acc[key]) {
+ acc[key] = []
+ }
+ acc[key].push(module)
+ return acc
+ }, {})
+ sameLineModuleList = Object.values(groupedByTop).sort((a, b) => a[0].top - b[0].top)
+ } else if (direction === 'east') {
+ const groupedByLeft = modules.reduce((acc, module) => {
+ const key = module.left
+ if (!acc[key]) {
+ acc[key] = []
+ }
+ acc[key].push(module)
+ return acc
+ }, {})
+ sameLineModuleList = Object.values(groupedByLeft).sort((a, b) => a[0].left - b[0].left)
+ } else if (direction === 'west') {
+ const groupedByLeft = modules.reduce((acc, module) => {
+ const key = module.left
+ if (!acc[key]) {
+ acc[key] = []
+ }
+ acc[key].push(module)
+ return acc
+ }, {})
+ sameLineModuleList = Object.values(groupedByLeft).sort((a, b) => b[0].left - a[0].left)
+ }
+ sameLineModuleList.forEach((modules, index) => {
+ const moduleRowResultData = {
+ seq: index,
+ moduleItemId: modules[0].moduleInfo.itemId,
+ moduleTpCd: modules[0].moduleInfo.itemTp,
+ moduleCnt: modules.length,
+ exposedBottomCnt: 0,
+ exposedHalfBottomCnt: 0,
+ exposedTopCnt: 0,
+ exposedHalfTopCnt: 0,
+ touchedSurfaceCnt: 0,
+ touchedHalfSurfaceCnt: 0,
+ exposedBottomBracketCnt: 0,
+ exposedHalfBottomBracketCnt: 0,
+ exposedTopBracketCnt: 0,
+ exposedHalfTopBracketCnt: 0,
+ touchedSurfaceBracketCnt: 0,
+ touchedHalfSurfaceBracketCnt: 0,
+ eavesCnt: 0,
+ eavesHalfCnt: 0,
+ exposedSideEavesCnt: 0,
+ }
+
+ if (direction === 'south') {
+ modules.sort((a, b) => a.left - b.left)
+ } else if (direction === 'north') {
+ modules.sort((a, b) => b.left - a.left)
+ } else if (direction === 'east') {
+ modules.sort((a, b) => a.top - b.top)
+ } else if (direction === 'west') {
+ modules.sort((a, b) => b.top - a.top)
+ }
+ // 모듈 하면,최하면 등 구해야함
+ modules.forEach((module, index) => {
+ // 해당 모듈 주변에 다른 모듈이 있는지 확인
+ let {
+ bottomModule,
+ topModule,
+ halfBottomLeftModule,
+ halfBottomRightModule,
+ halfTopLeftModule,
+ halfTopRightModule,
+ leftModule,
+ rightModule,
+ bottomLeftModule,
+ bottomRightModule,
+ } = findSideModule(module, surface)
+ if (bottomModule) {
+ moduleRowResultData.touchedSurfaceCnt++
+ }
+ if (!bottomModule) {
+ if (halfBottomLeftModule && halfBottomRightModule) {
+ moduleRowResultData.touchedSurfaceCnt++
+ } else if ((halfBottomLeftModule && !halfBottomRightModule) || (!halfBottomLeftModule && halfBottomRightModule)) {
+ moduleRowResultData.touchedHalfSurfaceCnt++
+ moduleRowResultData.exposedHalfBottomCnt++
+ if (cvrPlvrYn === 'Y') {
+ moduleRowResultData.eavesHalfCnt++
+ if (bottomLeftModule || bottomRightModule || halfBottomLeftModule || halfBottomRightModule) {
+ //처마커버 한개 노출 추가
+ moduleRowResultData.exposedSideEavesCnt++
+ }
+ }
+ } else {
+ moduleRowResultData.exposedBottomCnt++
+ if (isEaveBar) {
+ moduleRowResultData.eavesCnt++
+ if ((rightModule && !leftModule) || (!rightModule && leftModule)) {
+ // 둘중 하나가 없는경우는 처마커버 노출 추가
+ moduleRowResultData.exposedSideEavesCnt++
+ }
+ }
+ }
+ }
+ if (!topModule) {
+ if ((halfTopLeftModule && !halfTopRightModule) || (!halfTopLeftModule && halfTopRightModule)) {
+ moduleRowResultData.exposedHalfTopCnt++
+ } else if (!halfTopLeftModule && !halfTopRightModule) {
+ moduleRowResultData.exposedTopCnt++
+ }
+ }
+ })
+
+ result.push(moduleRowResultData)
+ })
+
+ return result
+ }
+
+ // 해당 모듈이 해당 설치면에서 상하좌우, 대각선에 있는지 확인
+ const findSideModule = (module, surface) => {
+ const { direction, modules } = surface
+ let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail
+
+ const centerPoints = modules.map((module) => {
+ return module.getCenterPoint()
+ })
+
+ const horizontal = ['south', 'north'].includes(direction) ? moduleIntvlHor : moduleIntvlVer
+
+ const vertical = ['south', 'north'].includes(direction) ? moduleIntvlVer : moduleIntvlHor
+ const maxX = 2 + horizontal * 3
+ const maxY = 2 + vertical * 3
+ let { width, height } = { ...module }
+ let { x, y } = { ...module.getCenterPoint() }
+
+ let halfBottomLeftPoint
+ let halfBottomRightPoint
+ let halfTopLeftPoint
+ let halfTopRightPoint
+ let leftPoint
+ let rightPoint
+ let bottomLeftPoint
+ let bottomRightPoint
+
+ let bottomModule
+ let topModule
+ let halfBottomLeftModule
+ let halfBottomRightModule
+ let halfTopLeftModule
+ let halfTopRightModule
+ let leftModule
+ let rightModule
+ let bottomLeftModule
+ let bottomRightModule
+
+ switch (direction) {
+ case 'south':
+ width = width + horizontal
+ height = height + vertical
+ bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
+ halfBottomLeftPoint = { x: x - width / 2, y: y + height }
+ halfBottomRightPoint = { x: x + width / 2, y: y + height }
+ topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
+ halfTopLeftPoint = { x: x - width / 2, y: y - height }
+ halfTopRightPoint = { x: x + width / 2, y: y - height }
+ leftPoint = { x: x - width, y: y }
+ rightPoint = { x: x + width, y: y }
+ bottomLeftModule = { x: x - width, y: y + height }
+ bottomRightModule = { x: x + width, y: y + height }
+ break
+ case 'north':
+ width = width + horizontal
+ height = height + vertical
+ bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY)
+ halfBottomLeftPoint = { x: x + width / 2, y: y - height }
+ halfBottomRightPoint = { x: x - width / 2, y: y - height }
+ topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY)
+ halfTopLeftPoint = { x: x + width / 2, y: y + height }
+ halfTopRightPoint = { x: x - width / 2, y: y + height }
+ leftPoint = { x: x + width, y: y }
+ rightPoint = { x: x - width, y: y }
+ bottomLeftModule = { x: x + width, y: y - height }
+ bottomRightModule = { x: x - width, y: y - height }
+ break
+ case 'east':
+ bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
+ width = width + horizontal
+ halfBottomLeftPoint = { x: x + width, y: y + height / 2 }
+ halfBottomRightPoint = { x: x + width, y: y - height / 2 }
+ topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
+ halfTopLeftPoint = { x: x - width, y: y + height / 2 }
+ halfTopRightPoint = { x: x - width, y: y - height / 2 }
+ leftPoint = { x: x, y: y + height }
+ rightPoint = { x: x, y: y - height }
+ bottomLeftModule = { x: x + width, y: y + height }
+ bottomRightModule = { x: x + width, y: y - height }
+ break
+ case 'west':
+ bottomModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
+ width = width + horizontal
+ halfBottomLeftPoint = { x: x - width, y: y - height / 2 }
+ halfBottomRightPoint = { x: x - width, y: y + height / 2 }
+ topModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY)
+ halfTopLeftPoint = { x: x + width, y: y - height / 2 }
+ halfTopRightPoint = { x: x + width, y: y + height / 2 }
+ leftPoint = { x: x, y: y - height }
+ rightPoint = { x: x, y: y + height }
+ bottomLeftModule = { x: x - width, y: y - height }
+ bottomRightModule = { x: x - width, y: y + height }
+ break
+ }
+
+ halfTopLeftModule = centerPoints.find(
+ (centerPoint) => Math.abs(centerPoint.x - halfTopLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfTopLeftPoint.y) < maxY,
+ )
+ halfTopRightModule = centerPoints.find(
+ (centerPoint) => Math.abs(centerPoint.x - halfTopRightPoint.x) < maxX && Math.abs(centerPoint.y - halfTopRightPoint.y) < maxY,
+ )
+ halfBottomLeftModule = centerPoints.find(
+ (centerPoint) => Math.abs(centerPoint.x - halfBottomLeftPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomLeftPoint.y) < maxY,
+ )
+ halfBottomRightModule = centerPoints.find(
+ (centerPoint) => Math.abs(centerPoint.x - halfBottomRightPoint.x) < maxX && Math.abs(centerPoint.y - halfBottomRightPoint.y) < maxY,
+ )
+ leftModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - leftPoint.x) < maxX && Math.abs(centerPoint.y - leftPoint.y) < maxY)
+ rightModule = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - rightPoint.x) < maxX && Math.abs(centerPoint.y - rightPoint.y) < maxY)
+ bottomLeftModule = centerPoints.find(
+ (centerPoint) => Math.abs(centerPoint.x - bottomLeftModule.x) < maxX && Math.abs(centerPoint.y - bottomLeftModule.y) < maxY,
+ )
+ bottomRightModule = centerPoints.find(
+ (centerPoint) => Math.abs(centerPoint.x - bottomRightModule.x) < maxX && Math.abs(centerPoint.y - bottomRightModule.y) < maxY,
+ )
+
+ return {
+ bottomModule,
+ topModule,
+ halfBottomLeftModule,
+ halfBottomRightModule,
+ halfTopLeftModule,
+ halfTopRightModule,
+ leftModule,
+ rightModule,
+ bottomLeftModule,
+ bottomRightModule,
+ }
+ }
+
+ return { apply, getTrestleParams }
}
diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js
index 27676eab..b7c5d248 100644
--- a/src/hooks/object/useObjectBatch.js
+++ b/src/hooks/object/useObjectBatch.js
@@ -93,7 +93,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
})
if (!selectedSurface) {
- swalFire({ text: '지붕안에 그려야해요', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
initEvent() //이벤트 초기화
if (setIsHidden) setIsHidden(false)
return
@@ -150,7 +150,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
//지붕 밖으로 그렸을때
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
- swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
//일단 지워
deleteTempObjects()
return
@@ -162,14 +162,14 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
if (isCross) {
- swalFire({ text: '겹치기 불가요...', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.notinstall.cross'), icon: 'error' })
deleteTempObjects()
return
}
}
isDown = false
- rect.set({ name: objName, parentId: selectedSurface.id })
+ rect.set({ name: objName, parentId: selectedSurface.id, points: rectToPolygon(rect) })
rect.setCoords()
initEvent()
@@ -232,7 +232,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
//지붕 밖으로 그렸을때
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
- swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
//일단 지워
deleteTempObjects()
return
@@ -244,14 +244,14 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
if (isCross) {
- swalFire({ text: '겹치기 불가요...', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.notinstall.cross'), icon: 'error' })
deleteTempObjects()
return
}
}
isDown = false
- rect.set({ name: objName, parentId: selectedSurface.id })
+ rect.set({ name: objName, parentId: selectedSurface.id, points: rectToPolygon(rect) })
rect.setCoords()
initEvent()
if (setIsHidden) setIsHidden(false)
@@ -377,12 +377,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer))
const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
- console.log('trianglePolygon', trianglePolygon)
- console.log('selectedSurfacePolygon', selectedSurfacePolygon)
-
//지붕 밖으로 그렸을때
if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) {
- swalFire({ text: '도머를 배치할 수 없습니다.', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
//일단 지워
deleteTempObjects()
return
@@ -406,6 +403,8 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
direction = 'north'
}
+ const groupPoints = offsetRef > 0 ? triangleToPolygon(dormerOffset) : triangleToPolygon(dormer)
+
let splitedTriangle = offsetRef > 0 ? splitDormerTriangle(dormerOffset, directionRef) : splitDormerTriangle(dormer, directionRef)
canvas?.remove(offsetRef > 0 ? dormerOffset : dormer)
@@ -499,6 +498,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
parentId: selectedSurface.id,
originX: 'center',
originY: 'center',
+ groupPoints: groupPoints,
})
canvas?.add(objectGroup)
@@ -604,7 +604,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
//지붕 밖으로 그렸을때
if (!turf.booleanWithin(pentagonPolygon, selectedSurfacePolygon)) {
- swalFire({ text: '도머를 배치할 수 없습니다.', icon: 'error' })
+ swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
//일단 지워
deleteTempObjects()
return
@@ -708,6 +708,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
}
const groupPolygon = offsetPolygon ? [leftPentagon, rightPentagon, offsetPolygon] : [leftPentagon, rightPentagon]
+ const groupPoints = offsetRef > 0 ? pentagonOffsetPoints : pentagonPoints
const objectGroup = new fabric.Group(groupPolygon, {
subTargetCheck: true,
@@ -717,6 +718,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
groupYn: true,
originX: 'center',
originY: 'center',
+ groupPoints: groupPoints,
})
canvas?.add(objectGroup)
diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js
index 951d9801..29287689 100644
--- a/src/hooks/option/useCanvasSetting.js
+++ b/src/hooks/option/useCanvasSetting.js
@@ -1,4 +1,4 @@
-import { useEffect, useState, useRef } from 'react'
+import { useEffect, useState, useRef, useContext } from 'react'
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
import {
adsorptionPointModeState,
@@ -35,6 +35,7 @@ import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementSha
import { useCanvasMenu } from '../common/useCanvasMenu'
import { menuTypeState } from '@/store/menuAtom'
import { usePopup } from '../usePopup'
+import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
const defaultDotLineGridSetting = {
INTERVAL: {
@@ -58,17 +59,22 @@ export function useCanvasSetting() {
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
+ const resetSettingModalFirstOptions = useResetRecoilState(settingModalFirstOptionsState)
+ const resetSettingModalSecondOptions = useResetRecoilState(settingModalSecondOptionsState)
const [selectedFont, setSelectedFont] = useState()
const [selectedFontWeight, setSelectedFontWeight] = useState()
const [selectedFontSize, setSelectedFontSize] = useState()
const [selectedFontColor, setSelectedFontColor] = useState()
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
+ const resetGlobalFont = useResetRecoilState(globalFontAtom)
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState)
const [planSizeSettingMode, setPlanSizeSettingMode] = useRecoilState(planSizeSettingState)
+ const resetPlanSizeSettingMode = useResetRecoilState(planSizeSettingState)
const [dimensionLineSettings, setDimensionLineSettings] = useRecoilState(dimensionLineSettingsState)
+ const resetDimensionLineSettings = useResetRecoilState(dimensionLineSettingsState)
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
@@ -117,9 +123,13 @@ export function useCanvasSetting() {
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
+ const { floorPlanState } = useContext(FloorPlanContext)
+
const { closeAll } = usePopup()
useEffect(() => {
+ console.log('correntObjectNo', correntObjectNo)
+
setFetchRoofMaterials(!fetchRoofMaterials)
if (fetchRoofMaterials) {
addRoofMaterials()
@@ -159,21 +169,28 @@ export function useCanvasSetting() {
setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial })
}
+ const previousObjectNoRef = useRef(null)
const previousRoofMaterialsRef = useRef(null)
useEffect(() => {
// 지붕재 select 정보가 존재해야 배치면초기설정 DB 정보 비교 후 지붕재 정보를 가져올 수 있음
- if (roofMaterials.length !== 0 && JSON.stringify(previousRoofMaterialsRef.current) !== JSON.stringify(roofMaterials)) {
- // 지붕재 select 정보 비교 후 변경된 것이 없으면 1회만 실행
+ if (
+ (!previousObjectNoRef.current && !correntObjectNo && previousObjectNoRef.current !== correntObjectNo) ||
+ (roofMaterials.length !== 0 && JSON.stringify(previousRoofMaterialsRef.current) !== JSON.stringify(roofMaterials))
+ ) {
+ // 1회만 실행
if (roofMaterials && previousRoofMaterialsYn === 'N') {
- fetchBasicSettings()
- previousRoofMaterialsYn = 'Y'
+ if (correntObjectNo) {
+ fetchBasicSettings()
+ previousRoofMaterialsYn = 'Y'
+ }
}
// 이전 값을 업데이트
+ previousObjectNoRef.current = correntObjectNo
previousRoofMaterialsRef.current = roofMaterials
}
- }, [roofMaterials])
+ }, [roofMaterials, correntObjectNo])
useEffect(() => {
if (!canvas) {
@@ -181,6 +198,9 @@ export function useCanvasSetting() {
}
const { column } = corridorDimension
const lengthTexts = canvas.getObjects().filter((obj) => obj.name === 'lengthText')
+ lengthTexts.forEach((obj) => {
+ obj.set({ text: '' })
+ })
switch (column) {
case 'corridorDimension':
lengthTexts.forEach((obj) => {
@@ -206,7 +226,6 @@ export function useCanvasSetting() {
}, [corridorDimension])
useEffect(() => {
- console.log('🚀 ~ useEffect ~ settingsDataSave:', settingsDataSave)
if (settingsDataSave !== undefined) onClickOption2()
}, [settingsData])
@@ -297,8 +316,8 @@ export function useCanvasSetting() {
})
roofsArray = res.map((item) => {
return {
- roofApply: true,
- roofSeq: 0,
+ roofApply: item.roofApply,
+ roofSeq: item.roofSeq,
roofMatlCd: item.roofMatlCd,
roofWidth: item.roofWidth,
roofHeight: item.roofHeight,
@@ -328,6 +347,7 @@ export function useCanvasSetting() {
roofGap: 'HEI_455',
roofLayout: 'P',
roofPitch: 4,
+ roofAngle: 21.8,
},
]
}
@@ -354,7 +374,6 @@ export function useCanvasSetting() {
}
})
}
- console.log('🚀 ~ fetchBasicSettings ~ addRoofs:', addRoofs)
setAddedRoofs(addRoofs)
setBasicSettings({
...basicSetting,
@@ -362,16 +381,16 @@ export function useCanvasSetting() {
roofSizeSet: roofsRow[0].roofSizeSet,
roofAngleSet: roofsRow[0].roofAngleSet,
roofsData: roofsArray,
- selectedRoofMaterial: addRoofs[0],
+ selectedRoofMaterial: addRoofs.find((roof) => roof.selected),
})
})
} catch (error) {
console.error('Data fetching error:', error)
}
- if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
- setBasicSettings({ ...canvasSetting })
- }
+ // if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
+ // setBasicSettings({ ...canvasSetting })
+ // }
setCanvasSetting({ ...basicSetting })
}
@@ -438,7 +457,7 @@ export function useCanvasSetting() {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${correntObjectNo}` })
console.log('res', res)
- if (res) {
+ if (Object.keys(res).length > 0) {
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
@@ -527,26 +546,27 @@ export function useCanvasSetting() {
//그리드 색 설정
setGridColor(res.gridColor)
} else {
- //조회된 글꼴 데이터가 없는 경우
+ //조회된 글꼴 데이터가 없는 경우 (데이터 초기화)
//흡착점 ON/OFF
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false })
//치수선 설정
- setDimensionLineSettings({ ...dimensionLineSettings })
+ // setDimensionLineSettings({ ...dimensionLineSettings, ...dimensionLineSettingsState.default })
+ resetDimensionLineSettings()
//도면크기 설정
- setPlanSizeSettingMode({ ...planSizeSettingMode })
+ // setPlanSizeSettingMode({ ...planSizeSettingMode, ...planSizeSettingState.default })
+ resetPlanSizeSettingMode()
// 데이터 설정
- setSettingModalFirstOptions({
- ...settingModalFirstOptions,
- })
- setSettingModalSecondOptions({
- ...settingModalSecondOptions,
- })
+ // setSettingModalFirstOptions({ ...settingModalFirstOptions, ...settingModalFirstOptionsState.default })
+ resetSettingModalFirstOptions()
+ //setSettingModalSecondOptions({ ...settingModalSecondOptions, ...settingModalSecondOptionsState.default })
+ resetSettingModalSecondOptions()
- setGlobalFont({ ...globalFont })
+ // setGlobalFont({ ...globalFont, ...globalFontAtom.default })
+ resetGlobalFont()
//점/선 그리드
setDotLineGridSettingState({ ...defaultDotLineGridSetting })
@@ -671,7 +691,7 @@ export function useCanvasSetting() {
// HTTP POST 요청 보내기
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
.then((res) => {
- // swalFire({ text: getMessage(res.returnMessage) })
+ //swalFire({ text: getMessage(res.returnMessage) })
// Canvas 디스플레이 설정 시 해당 옵션 적용
frontSettings()
@@ -679,7 +699,8 @@ export function useCanvasSetting() {
fetchSettings()
})
.catch((error) => {
- swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
+ //swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
+ swalFire({ text: error.message, icon: 'error' })
})
//setAdsorptionRange(item.range)
@@ -770,6 +791,7 @@ export function useCanvasSetting() {
adsorptionRange,
setAdsorptionRange,
fetchSettings,
+ fetchBasicSettings,
frontSettings,
globalFont,
setGlobalFont,
diff --git a/src/hooks/roofcover/usePropertiesSetting.js b/src/hooks/roofcover/usePropertiesSetting.js
index 73a72e5a..425f0642 100644
--- a/src/hooks/roofcover/usePropertiesSetting.js
+++ b/src/hooks/roofcover/usePropertiesSetting.js
@@ -120,37 +120,49 @@ export function usePropertiesSetting(id) {
}
const handleFix = () => {
- if (!confirm('외벽선 속성 설정을 완료하시겠습니까?')) {
- return
- }
- const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
+ const isClose = confirm('외벽선 속성 설정을 완료하시겠습니까?')
+ if (isClose) {
+ const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
- const notSetAttributes = lines.filter((line) => !line.attributes?.type)
- if (notSetAttributes.length > 0) {
- alert('설정되지 않은 외벽선이 있습니다.')
- return
- }
+ const notSetAttributes = lines.filter((line) => !line.attributes?.type)
+ if (notSetAttributes.length > 0) {
+ // 세팅이 하나라도 안되어있으면 초기화
+ lines.forEach((line) => {
+ line.set({
+ stroke: '#000000',
+ strokeWidth: 4,
+ })
+ })
+ canvas.discardActiveObject()
+ closePopup(id)
+ return
+ }
- lines.forEach((line) => {
- line.set({
- attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
- stroke: '#000000',
- strokeWidth: 4,
+ lines.forEach((line) => {
+ line.set({
+ attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
+ stroke: '#000000',
+ strokeWidth: 4,
+ })
+
+ hideLine(line)
})
- hideLine(line)
- })
+ const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
- const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
+ wall.lines = [...lines]
- wall.lines = [...lines]
+ const roof = drawRoofPolygon(wall)
- const roof = drawRoofPolygon(wall)
+ setPoints([])
+ canvas.renderAll()
+ roof.drawHelpLine()
- setPoints([])
- canvas.renderAll()
- roof.drawHelpLine()
- closePopup(id)
+ closePopup(id)
+ return
+ } else {
+ return
+ }
}
const closeModal = (fn) => {
diff --git a/src/hooks/roofcover/useRoofAllocationSetting.js b/src/hooks/roofcover/useRoofAllocationSetting.js
index 546ebe0b..ee865d65 100644
--- a/src/hooks/roofcover/useRoofAllocationSetting.js
+++ b/src/hooks/roofcover/useRoofAllocationSetting.js
@@ -24,6 +24,8 @@ import { useRoofFn } from '@/hooks/common/useRoofFn'
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
import { globalLocaleStore } from '@/store/localeAtom'
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
+import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
+import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
// 지붕면 할당
export function useRoofAllocationSetting(id) {
@@ -42,7 +44,7 @@ export function useRoofAllocationSetting(id) {
const [currentRoofMaterial, setCurrentRoofMaterial] = useState(roofMaterials[0]) // 팝업 내 기준 지붕재
const [roofList, setRoofList] = useRecoilState(addedRoofsState) // 배치면 초기설정에서 선택한 지붕재 배열
const [editingLines, setEditingLines] = useState([])
- const [currentRoofList, setCurrentRoofList] = useState(null)
+ const [currentRoofList, setCurrentRoofList] = useState([])
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const globalLocaleState = useRecoilValue(globalLocaleStore)
const [basicInfo, setBasicInfo] = useState(null)
@@ -52,6 +54,8 @@ export function useRoofAllocationSetting(id) {
const { setSurfaceShapePattern } = useRoofFn()
+ const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
+
useEffect(() => {
setCurrentRoofList(roofList)
}, [])
@@ -169,6 +173,7 @@ export function useRoofAllocationSetting(id) {
roofSizeSet: res[0].roofSizeSet,
roofAngleSet: res[0].roofAngleSet,
roofsData: roofsArray,
+ selectedRoofMaterial: selectRoofs.find((roof) => roof.selected),
})
setBasicInfo({
roofSizeSet: '' + res[0].roofSizeSet,
@@ -188,7 +193,7 @@ export function useRoofAllocationSetting(id) {
roofSizeSet: Number(basicSetting.roofSizeSet),
roofAngleSet: basicSetting.roofAngleSet,
roofAllocationList: currentRoofList.map((item, index) => ({
- roofApply: item.selected === null || item.selected === undefined ? 'true' : item.selected,
+ roofApply: item.selected,
roofSeq: index,
roofMatlCd: item.roofMatlCd === null || item.roofMatlCd === undefined ? 'ROOF_ID_WA_53A' : item.roofMatlCd,
roofWidth: item.width === null || item.width === undefined ? 0 : Number(item.width),
@@ -269,6 +274,7 @@ export function useRoofAllocationSetting(id) {
setRoofList(newRoofList)
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial)
+ modifyModuleSelectionData()
closeAll()
}
@@ -368,6 +374,8 @@ export function useRoofAllocationSetting(id) {
closeAll()
setMenuNumber(3)
setMenuType('surface')
+
+ modifyModuleSelectionData()
}
const setLineSize = (id, size) => {
@@ -499,6 +507,16 @@ export function useRoofAllocationSetting(id) {
setCurrentRoofList(newRoofList)
}
+ // 모듈 선택에서 선택한 데이터 초기화
+ const modifyModuleSelectionData = () => {
+ if (moduleSelectionData.roofConstructions.length > 0) {
+ setModuleSelectionData({ ...moduleSelectionData, roofConstructions: [] })
+ moduleSelectedDataTrigger({ ...moduleSelectionData, roofConstructions: [] })
+ }
+ }
+
+ const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
+
return {
handleSave,
onAddRoofMaterial,
diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js
index 99eed453..4cb3586f 100644
--- a/src/hooks/surface/useSurfaceShapeBatch.js
+++ b/src/hooks/surface/useSurfaceShapeBatch.js
@@ -1,6 +1,6 @@
'use client'
-import { useRecoilValue } from 'recoil'
+import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState, globalPitchState } from '@/store/canvasAtom'
import { MENU, POLYGON_TYPE } from '@/common/common'
import { getIntersectionPoint } from '@/util/canvas-util'
@@ -16,11 +16,13 @@ import { fontSelector } from '@/store/fontAtom'
import { slopeSelector } from '@/store/commonAtom'
import { QLine } from '@/components/fabric/QLine'
import { useRoofFn } from '@/hooks/common/useRoofFn'
+import { outerLinePointsState } from '@/store/outerLineAtom'
export function useSurfaceShapeBatch() {
const { getMessage } = useMessage()
const { drawDirectionArrow } = usePolygon()
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
+ const [points, setPoints] = useRecoilState(outerLinePointsState)
const canvas = useRecoilValue(canvasState)
const globalPitch = useRecoilValue(globalPitchState)
@@ -649,11 +651,12 @@ export function useSurfaceShapeBatch() {
const deleteAllSurfacesAndObjects = () => {
swalFire({
- text: '배치면 내용을 전부 삭제하시겠습니까?',
+ text: getMessage('batch.canvas.delete.all'),
type: 'confirm',
confirmFn: () => {
canvas.clear()
- swalFire({ text: '삭제 완료 되었습니다.' })
+ setPoints([])
+ swalFire({ text: getMessage('plan.message.delete') })
},
// denyFn: () => {
// swalFire({ text: '취소되었습니다.', icon: 'error' })
diff --git a/src/hooks/useAxios.js b/src/hooks/useAxios.js
index 35c90a87..b4b9652d 100644
--- a/src/hooks/useAxios.js
+++ b/src/hooks/useAxios.js
@@ -97,13 +97,11 @@ export function useAxios(lang = '') {
const getFetcher = async (url) => {
const res = await get({ url })
- console.log('🚀 ~ getFetcher ~ res:', res)
return res
}
- const postFetcher = async (url, { arg }) => {
+ const postFetcher = async (url, arg) => {
const res = await post({ url, data: arg })
- console.log('🚀 ~ postFetcher ~ res:', res)
return res
}
diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js
index 7ea3e03c..9076bbc8 100644
--- a/src/hooks/useCanvasEvent.js
+++ b/src/hooks/useCanvasEvent.js
@@ -198,7 +198,7 @@ export function useCanvasEvent() {
if (selected?.length > 0) {
selected.forEach((obj) => {
- if (obj.type === 'QPolygon') {
+ if (obj.type === 'QPolygon' && obj.name !== 'module') {
obj.set({ stroke: 'red' })
}
})
@@ -235,7 +235,7 @@ export function useCanvasEvent() {
if (selected?.length > 0) {
selected.forEach((obj) => {
- if (obj.type === 'QPolygon') {
+ if (obj.type === 'QPolygon' && obj.name !== 'module') {
obj.set({ stroke: 'red' })
}
})
diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js
index 82817f62..a815b800 100644
--- a/src/hooks/useContextMenu.js
+++ b/src/hooks/useContextMenu.js
@@ -1,4 +1,4 @@
-import { useRecoilState, useRecoilValue } from 'recoil'
+import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom'
import { useEffect, useState } from 'react'
import { MENU, POLYGON_TYPE } from '@/common/common'
@@ -45,7 +45,7 @@ import { MODULE_ALIGN_TYPE, useModule } from './module/useModule'
export function useContextMenu() {
const canvas = useRecoilValue(canvasState)
const currentMenu = useRecoilValue(currentMenuState) // 현재 메뉴
- const [contextPopupPosition, setContextPopupPosition] = useRecoilState(contextPopupPositionState) // 현재 메뉴
+ const setContextPopupPosition = useSetRecoilState(contextPopupPositionState) // 현재 메뉴
const [contextMenu, setContextMenu] = useRecoilState(contextMenuListState) // 메뉴.object 별 context menu
const [currentContextMenu, setCurrentContextMenu] = useRecoilState(contextPopupState) // 선택한 contextMenu
const currentObject = useRecoilValue(currentObjectState)
@@ -67,7 +67,7 @@ export function useContextMenu() {
const commonTextFont = useRecoilValue(fontSelector('commonText'))
const { settingsData, setSettingsDataSave } = useCanvasSetting()
const { swalFire } = useSwal()
- const { alignModule } = useModule()
+ const { alignModule, modulesRemove } = useModule()
const { removeRoofMaterial, removeAllRoofMaterial, moveRoofMaterial } = useRoofFn()
const currentMenuSetting = () => {
@@ -297,7 +297,6 @@ export function useContextMenu() {
}
const handleClick = (e, menu) => {
- // console.log('handleClick', e.clientX, e.clientY, menu)
if (menu?.fn) {
menu.fn(qContextMenu.currentMousePos)
}
@@ -660,7 +659,7 @@ export function useContextMenu() {
{
id: 'remove',
name: getMessage('contextmenu.remove'),
- fn: () => deleteObject(),
+ fn: () => modulesRemove(),
},
{
id: 'move',
diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js
index db170dc7..6b468405 100644
--- a/src/hooks/usePlan.js
+++ b/src/hooks/usePlan.js
@@ -4,7 +4,6 @@ import { useContext, useEffect, useState } from 'react'
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
import { useRecoilState } from 'recoil'
-import { v4 as uuidv4 } from 'uuid'
import { canvasState, currentCanvasPlanState, plansState } from '@/store/canvasAtom'
import { useAxios } from '@/hooks/useAxios'
@@ -15,10 +14,10 @@ import { SAVE_KEY } from '@/common/common'
import { readImage, removeImage } from '@/lib/fileAction'
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
+
export function usePlan(params = {}) {
const { floorPlanState } = useContext(FloorPlanContext)
- const [planNum, setPlanNum] = useState(0)
const [selectedPlan, setSelectedPlan] = useState(null)
const [canvas, setCanvas] = useRecoilState(canvasState)
@@ -129,37 +128,61 @@ export function usePlan(params = {}) {
/**
* objectNo에 해당하는 canvas 목록을 조회
*/
- const getCanvasByObjectNo = async (userId, objectNo) => {
+ const getCanvasByObjectNo = async (userId, objectNo, planNo) => {
return await get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) =>
- res.map((item, index) => ({
+ res.map((item) => ({
id: item.id,
+ objectNo: item.objectNo,
+ planNo: item.planNo,
userId: item.userId,
canvasStatus: dbToCanvasFormat(item.canvasStatus),
- isCurrent: false,
+ isCurrent: planNo === item.planNo,
bgImageName: item.bgImageName,
mapPositionAddress: item.mapPositionAddress,
- ordering: index + 1,
})),
)
}
+ /**
+ * 물건번호(object) plan 추가 (canvas 생성 전 planNo 할당)
+ */
+ const postObjectPlan = async (userId, objectNo) => {
+ return await promisePost({ url: '/api/object/add-plan', data: { userId: userId, objectNo: objectNo } })
+ .then((res) => {
+ return res.data.planNo
+ })
+ .catch((error) => {
+ swalFire({ text: error.response.data.message, icon: 'error' })
+ return null
+ })
+ }
+
/**
* 신규 canvas 데이터를 저장
*/
- const postCanvasStatus = async (userId, objectNo, canvasStatus) => {
+ const postCanvasStatus = async (userId, objectNo, canvasStatus, isInitPlan = false) => {
+ const planNo = await postObjectPlan(userId, objectNo)
+ if (!planNo) return
+
const planData = {
userId: userId,
- imageName: 'image_name', // api 필수항목이여서 임시로 넣음, 이후 삭제 필요
objectNo: objectNo,
+ planNo: planNo,
bgImageName: currentCanvasPlan?.bgImageName ?? null,
mapPositionAddress: currentCanvasPlan?.mapPositionAddress ?? null,
canvasStatus: canvasToDbFormat(canvasStatus),
}
await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
- setPlans((plans) => [...plans, { id: res.data, objectNo: objectNo, userId: userId, canvasStatus: canvasStatus, ordering: planNum + 1 }])
- updateCurrentPlan(res.data)
- setPlanNum(planNum + 1)
+ const newPlan = { id: res.data, objectNo: objectNo, planNo: planNo, userId: userId, canvasStatus: canvasStatus, isCurrent: true }
+ setCurrentCanvasPlan(newPlan)
+ if (isInitPlan) {
+ // 초기 플랜 생성인 경우 플랜 목록 초기화
+ setPlans([newPlan])
+ } else {
+ setPlans((plans) => [...plans.map((plan) => ({ ...plan, isCurrent: false })), newPlan])
+ swalFire({ text: getMessage('plan.message.save') })
+ }
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
@@ -179,6 +202,7 @@ export function usePlan(params = {}) {
await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
+ swalFire({ text: getMessage('plan.message.save') })
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
@@ -204,64 +228,75 @@ export function usePlan(params = {}) {
* 현재 plan의 작업상태를 저장 후 이동
*/
const handleCurrentPlan = async (newCurrentId) => {
- const orderingNo = plans?.find((obj) => obj.id === newCurrentId).ordering
+ const planNo = plans?.find((obj) => obj.id === newCurrentId).planNo
const objectNo = floorPlanState.objectNo
- await promiseGet({ url: `/api/estimate/${objectNo}/${orderingNo}/detail` })
- .then((res) => {
- if (res.status === 200) {
- const estimateDetail = res.data
- if (estimateDetail.docNo) {
- res.data.resetFlag = 'N'
+ //견적서 or 발전시뮬
- if (res.data.itemList.length > 0) {
- res.data.itemList.map((item) => {
- item.delFlg = '0'
- })
- }
- if (res.data.pkgAsp === null || res.data.pkgAsp == undefined) {
- res.data.pkgAsp = '0.00'
+ if (pathname !== '/floor-plan') {
+ await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` })
+ .then((res) => {
+ if (res.status === 200) {
+ const estimateDetail = res.data
+ if (pathname === '/floor-plan/estimate/5') {
+ if (estimateDetail.tempFlg === '0' && estimateDetail.estimateDate !== null) {
+ res.data.resetFlag = 'N'
+
+ if (res.data.itemList.length > 0) {
+ res.data.itemList.map((item) => {
+ item.delFlg = '0'
+ })
+ }
+ if (res.data.pkgAsp === null || res.data.pkgAsp == undefined) {
+ res.data.pkgAsp = '0.00'
+ } else {
+ const number = parseFloat(res.data.pkgAsp)
+ const roundedNumber = isNaN(number) ? '0.00' : number.toFixed(2)
+
+ res.data.pkgAsp = roundedNumber.toString()
+ }
+ setEstimateContextState(res.data)
+ // 클릭한 플랜 탭으로 이동
+ setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
+ setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
+ } else {
+ swalFire({ text: getMessage('estimate.menu.move.valid1') })
+ }
} else {
- const number = parseFloat(res.data.pkgAsp)
- const roundedNumber = isNaN(number) ? '0.00' : number.toFixed(2)
-
- res.data.pkgAsp = roundedNumber.toString()
- }
- setEstimateContextState(res.data)
-
- if (pathname === '/floor-plan') {
- if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
- saveCanvas()
+ // 발전시뮬레이션
+ if (estimateDetail.tempFlg === '0') {
+ setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
+ setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
+ } else {
+ swalFire({ text: getMessage('simulator.menu.move.valid1') })
}
}
- updateCurrentPlan(newCurrentId)
- } else {
- swalFire({ text: getMessage('estimate.menu.move.valid1') })
}
- }
- })
- .catch((error) => {
- swalFire({ text: getMessage('estimate.menu.move.valid1') })
- })
- }
-
- const updateCurrentPlan = (newCurrentId) => {
- setPlans((plans) =>
- plans.map((plan) => {
- return { ...plan, isCurrent: plan.id === newCurrentId }
- }),
- )
+ })
+ .catch((error) => {
+ if (pathname === '/floor-plan/estimate/5') {
+ swalFire({ text: getMessage('estimate.menu.move.valid1') })
+ } else {
+ swalFire({ text: getMessage('simulator.menu.move.valid1') })
+ }
+ })
+ } else {
+ if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
+ await saveCanvas()
+ }
+ setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
+ setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
+ }
}
useEffect(() => {
- setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null)
- setSelectedPlan(plans.find((plan) => plan.isCurrent))
+ setSelectedPlan(currentCanvasPlan)
handleCurrentPlanUrl()
// setBgImage()
- }, [plans])
+ }, [currentCanvasPlan])
const handleCurrentPlanUrl = () => {
const currentPlan = plans.find((plan) => plan.isCurrent)
- if (currentPlan) router.push(`${pathname}?pid=${currentPlan?.ordering}&objectNo=${floorPlanState?.objectNo}`)
+ if (currentPlan) router.push(`${pathname}?pid=${currentPlan?.planNo}&objectNo=${floorPlanState?.objectNo}`)
}
const setBgImage = () => {
@@ -278,44 +313,44 @@ export function usePlan(params = {}) {
}
JSON.parse(currentCanvasData()).objects.length > 0
? swalFire({
- text: `Plan ${currentCanvasPlan.ordering} ` + getMessage('plan.message.confirm.copy'),
+ text: `Plan ${currentCanvasPlan.planNo} ` + getMessage('plan.message.confirm.copy'),
type: 'confirm',
confirmFn: async () => {
- await postCanvasStatus(userId, objectNo, currentCanvasData())
+ await postCanvasStatus(userId, objectNo, currentCanvasData(), false)
},
denyFn: async () => {
- await postCanvasStatus(userId, objectNo, '')
+ await postCanvasStatus(userId, objectNo, '', false)
},
})
- : await postCanvasStatus(userId, objectNo, '')
+ : await postCanvasStatus(userId, objectNo, '', false)
}
/**
- * DB에 추가하지 않고 화면 상에서 plan을 추가하는 함수
+ * 물건번호(object) plan 삭제 (canvas 삭제 전 planNo 삭제)
*/
- const addPlan = (userId, objectNo, canvasStatus) => {
- const id = uuidv4()
- const newPlan = {
- id: id,
- objectNo: objectNo,
- userId: userId,
- canvasStatus: canvasStatus,
- ordering: planNum + 1,
- }
- setPlans([...plans, newPlan])
- handleCurrentPlan(id)
- setPlanNum(planNum + 1)
+ const deleteObjectPlan = async (userId, objectNo, planNo) => {
+ return await promiseDel({ url: `/api/object/plan/${objectNo}/${planNo}?userId=${userId}` })
+ .then((res) => {
+ return true
+ })
+ .catch((error) => {
+ swalFire({ text: error.response.data.message, icon: 'error' })
+ return false
+ })
}
/**
* plan 삭제
*/
- const handleDeletePlan = async (e, id) => {
+ const handleDeletePlan = async (e, targetPlan) => {
e.stopPropagation() // 이벤트 버블링 방지
- await delCanvasById(id)
+ const isSuccess = await deleteObjectPlan(targetPlan.id, targetPlan.objectNo, targetPlan.planNo)
+ if (!isSuccess) return
+
+ await delCanvasById(targetPlan.id)
.then((res) => {
- setPlans((plans) => plans.filter((plan) => plan.id !== id))
+ setPlans((plans) => plans.filter((plan) => plan.id !== targetPlan.id))
removeImage(currentCanvasPlan.id)
swalFire({ text: getMessage('plan.message.delete') })
})
@@ -324,27 +359,26 @@ export function usePlan(params = {}) {
})
// 삭제 후 last 데이터에 포커싱
- const lastPlan = plans.filter((plan) => plan.id !== id).at(-1)
+ const lastPlan = plans.filter((plan) => plan.id !== targetPlan.id).at(-1)
if (!lastPlan) {
- setPlanNum(0)
setCurrentCanvasPlan(null)
- } else if (id !== lastPlan.id) {
- updateCurrentPlan(lastPlan.id)
+ } else if (targetPlan.id !== lastPlan.id) {
+ setCurrentCanvasPlan(lastPlan)
+ setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === lastPlan.id })))
}
}
/**
* plan 조회
*/
- const loadCanvasPlanData = async (userId, objectNo, pid) => {
- await getCanvasByObjectNo(userId, objectNo).then((res) => {
- // console.log('canvas 목록 ', res)
+ const loadCanvasPlanData = async (userId, objectNo, planNo) => {
+ console.log('🚀 ~ loadCanvasPlanData ~ userId, objectNo, planNo:', userId, objectNo, planNo)
+ await getCanvasByObjectNo(userId, objectNo, planNo).then((res) => {
if (res.length > 0) {
+ setCurrentCanvasPlan(res.find((plan) => plan.planNo === planNo))
setPlans(res)
- updateCurrentPlan(res[pid - 1].id)
- setPlanNum(res.length)
} else {
- postCanvasStatus(userId, objectNo, '')
+ postCanvasStatus(userId, objectNo, '', true)
}
})
}
@@ -353,12 +387,13 @@ export function usePlan(params = {}) {
* 현재 plan 이동 -> 새로운 링크로 이동
*/
const handlePlanMove = () => {
- router.push(`${pathname}?objectNo=${floorPlanState.objectNo}&pid=${currentCanvasPlan?.ordering}`)
+ router.push(`${pathname}?objectNo=${floorPlanState.objectNo}&pid=${currentCanvasPlan?.planNo}`)
}
return {
canvas,
plans,
+ currentCanvasPlan,
selectedPlan,
saveCanvas,
handleCurrentPlan,
diff --git a/src/hooks/usePolygon.js b/src/hooks/usePolygon.js
index 4a8ecfdc..e1f127a5 100644
--- a/src/hooks/usePolygon.js
+++ b/src/hooks/usePolygon.js
@@ -427,6 +427,13 @@ export const usePolygon = () => {
text = '西西南'
}
+ const sameDirectionCnt = canvas.getObjects().filter((obj) => {
+ const onlyStrDirection = obj.directionText?.replace(/[0-9]/g, '')
+ return obj.name === POLYGON_TYPE.ROOF && obj !== polygon && onlyStrDirection === text
+ })
+
+ text = text + (sameDirectionCnt.length + 1)
+ polygon.set('directionText', text)
const textObj = new fabric.Text(`${text} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`, {
fontFamily: flowFontOptions.fontFamily.value,
fontWeight: flowFontOptions.fontWeight.value.toLowerCase().includes('bold') ? 'bold' : 'normal',
@@ -852,10 +859,11 @@ export const usePolygon = () => {
line.endPoint = endPoint
})
+ // polygon line에서 각각 출발한다.
polygonLines.forEach((line) => {
- line.set({ strokeWidth: 5, stroke: 'green' })
+ /*line.set({ strokeWidth: 5, stroke: 'green' })
canvas.add(line)
- canvas.renderAll()
+ canvas.renderAll()*/
const startPoint = line.startPoint // 시작점
let arrivalPoint = line.endPoint // 도착점
@@ -865,9 +873,11 @@ export const usePolygon = () => {
const startLine = line
const visitPoints = [startPoint]
const visitLines = [startLine]
+ let notVisitedLines = []
let cnt = 0
while (!isSamePoint(currentPoint, arrivalPoint)) {
+ //현재 점으로 부터 갈 수 있는 다른 라인을 찾는다.
let nextLines = allLines.filter(
(line2) =>
(isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) &&
@@ -885,8 +895,13 @@ export const usePolygon = () => {
)
}
- if (!nextLines) {
- break
+ if (nextLines.length === 0) {
+ //아직 안갔던 line중 0번째를 선택한다.
+ if (notVisitedLines.length === 0) {
+ break
+ } else {
+ // nextLines = [...notVisitedLines.shift().line]
+ }
}
let comparisonPoints = []
@@ -912,6 +927,14 @@ export const usePolygon = () => {
nextLines.forEach((nextLine) => {
if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) {
visitLines.push(nextLine)
+ } else {
+ notVisitedLines.push({
+ line: nextLine,
+ endPoint: nextLine.endPoint,
+ startPoint: nextLine.startPoint,
+ currentPoint: { ...currentPoint },
+ roofPoints: [...roofPoints],
+ })
}
})
diff --git a/src/hooks/useSwal.js b/src/hooks/useSwal.js
index 018d8f32..f904091d 100644
--- a/src/hooks/useSwal.js
+++ b/src/hooks/useSwal.js
@@ -1,5 +1,6 @@
import Swal from 'sweetalert2'
import withReactContent from 'sweetalert2-react-content'
+import { useMessage } from '@/hooks/useMessage'
/**
* title: 제목
@@ -13,14 +14,25 @@ import withReactContent from 'sweetalert2-react-content'
*/
export const useSwal = () => {
const MySwal = withReactContent(Swal)
+ const { getMessage } = useMessage()
- const swalFire = ({ title = '', text = '', html = '', type = 'alert', icon = '', confirmFn = () => {}, denyFn = () => {} }) => {
+ const swalFire = ({
+ title = '',
+ text = '',
+ html = '',
+ type = 'alert',
+ icon = '',
+ confirmButtonText = '',
+ cancelButtonText = '',
+ confirmFn = () => {},
+ denyFn = () => {},
+ }) => {
if (type === 'alert') {
MySwal.fire({
title,
text,
icon: icon === '' ? 'success' : icon,
- confirmButtonText: '확인',
+ confirmButtonText: getMessage('common.ok'),
}).then(() => {
confirmFn()
})
@@ -32,8 +44,8 @@ export const useSwal = () => {
icon: icon === '' ? 'question' : icon,
showCloseButton: true,
showCancelButton: true,
- confirmButtonText: '확인',
- cancelButtonText: '취소',
+ confirmButtonText: confirmButtonText === '' ? getMessage('common.ok') : confirmButtonText,
+ cancelButtonText: cancelButtonText === '' ? getMessage('common.cancel') : cancelButtonText,
}).then((result) => {
if (result.isConfirmed) {
confirmFn()
diff --git a/src/locales/ja.json b/src/locales/ja.json
index a96ff061..42509426 100644
--- a/src/locales/ja.json
+++ b/src/locales/ja.json
@@ -141,9 +141,11 @@
"modal.circuit.trestle.setting.circuit.allocation": "回路割り当て",
"modal.circuit.trestle.setting.circuit.allocation.auto": "自動回路割り当て",
"modal.circuit.trestle.setting.circuit.allocation.passivity": "手動回路割当",
+ "modal.circuit.trestle.setting.circuit.allocation.passivity.circuit": "回路",
"modal.circuit.trestle.setting.circuit.allocation.passivity.info": "同じ回路のモジュールを選択状態にした後、 [番号確認]ボタンを押すと番号が割り当てられます。",
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional": "選択したパワーコンディショナー",
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num": "設定する回路番号 (1~)",
+ "modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info": "標準回路{0}枚~{1}枚",
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset": "選択されたパワーコンディショナーの回路番号の初期化",
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset": "すべての回路番号の初期化",
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix": "番号確定",
@@ -279,6 +281,12 @@
"modal.object.setting.direction.select": "方向の選択",
"modal.placement.surface.setting.info": "ⓘ ①の長さ入力後に対角線の長さを入力すると、②の長さを自動計算します。",
"modal.placement.surface.setting.diagonal.length": "斜めの長さ",
+ "modal.placement.surface.drawing.straight.line": "직선(JA)",
+ "modal.placement.surface.drawing.right.angle": "직각(JA)",
+ "modal.placement.surface.drawing.double.pitch": "이구배(JA)",
+ "modal.placement.surface.drawing.angle": "각도(JA)",
+ "modal.placement.surface.drawing.diagonal": "대각선(JA)",
+ "modal.placement.surface.drawing.fix": "배치면 확정(JA)",
"modal.color.picker.title": "色の設定",
"modal.color.picker.default.color": "基本色",
"modal.size.setting": "サイズ変更",
@@ -303,6 +311,9 @@
"plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?",
"plan.message.save": "저장되었습니다.",
"plan.message.delete": "삭제되었습니다.",
+ "plan.message.leave": "物件状況(リスト)に移動しますか? [はい]を選択した場合は、保存して移動します。",
+ "plan.message.confirm.yes": "はい",
+ "plan.message.confirm.no": "いいえ",
"setting": "設定",
"delete": "삭제(JA)",
"delete.all": "전체 삭제(JA)",
@@ -498,6 +509,7 @@
"common.require": "必須",
"common.finish": "完了",
"common.ok": "確認",
+ "common.cancel": "キャンセル",
"commons.west": "立つ",
"commons.east": "ドン",
"commons.south": "南",
@@ -672,6 +684,7 @@
"stuff.detail.tooltip.surfaceType": "塩害地域の定義は各メーカーの設置マニュアルをご確認ください",
"stuff.detail.tempSave.message1": "一時保存されました。商品番号を取得するには、必須項目をすべて入力してください。",
"stuff.detail.tempSave.message2": "担当者は10桁以下で入力してください.",
+ "stuff.detail.tempSave.message3": "二次販売店を選択してください.",
"stuff.detail.confirm.message1": "販売店情報を変更すると、設計依頼文書番号が削除されます。変更しますか?",
"stuff.detail.delete.message1": "仕様が確定したものは削除できません。",
"stuff.detail.planList.title": "プランリスト",
@@ -935,7 +948,8 @@
"estimate.detail.reset.alertMsg": "初期化されました.",
"estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?",
"estimate.detail.lock.alertMsg": "見積書を[ロック]すると、変更できません。見積もりを編集するには、ロックを解除してください.",
- "estimate.detail.unlock.alertMsg": "見積書を修正して保存",
+ "estimate.detail.unlock.alertMsg": "[ロック解除]すると、見積書を編集できます.\n 解除しますか?",
+ "estimate.detail.unlock.confirmBtnName": "解放",
"estimate.detail.alert.delFile": "添付ファイルを完全に削除するには[保存]ボタンをクリックしてください",
"estimate.detail.alert.selectDelItem": "削除する商品を選択してください.",
"estimate.menu.move.valid1": "回路を分割していないため、見積もりを呼び出すことはできません.",
@@ -965,5 +979,6 @@
"can.not.copy.module": "모듈을 복사할 수 없습니다.(JA)",
"can.not.remove.module": "모듈을 삭제할 수 없습니다.(JA)",
"can.not.insert.module": "모듈을 삽입할 수 없습니다.(JA)",
- "can.not.align.module": "모듈을 정렬할 수 없습니다.(JA)"
+ "can.not.align.module": "모듈을 정렬할 수 없습니다.(JA)",
+ "menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다."
}
diff --git a/src/locales/ko.json b/src/locales/ko.json
index 2d049d61..d02746ea 100644
--- a/src/locales/ko.json
+++ b/src/locales/ko.json
@@ -80,6 +80,7 @@
"modal.placement.surface.drawing.double.pitch": "이구배",
"modal.placement.surface.drawing.angle": "각도",
"modal.placement.surface.drawing.diagonal": "대각선",
+ "modal.placement.surface.drawing.fix": "배치면 확정",
"plan.menu.placement.surface.arrangement": "면형상 배치",
"plan.menu.placement.surface.object": "오브젝트 배치",
"plan.menu.placement.surface.all.remove": "배치면 전체 삭제",
@@ -94,6 +95,7 @@
"modal.module.basic.setting.module.construction.method": "공법",
"modal.module.basic.setting.module.under.roof": "지붕밑바탕",
"modal.module.basic.setting.module.setting": "모듈 선택",
+ "modal.module.basic.setting.module.hajebichi": "망둥어 피치",
"modal.module.basic.setting.module.setting.info1": "※ 구배의 범위에는 제한이 있습니다. 지붕경사가 2.5치 미만, 10치를 초과하는 경우에는 시공이 가능한지 시공 매뉴얼을 확인해주십시오.",
"modal.module.basic.setting.module.setting.info2": "※ 모듈 배치 시에는 시공 매뉴얼에 기재된 <모듈 배치 조건>을 반드시 확인해주십시오.",
"modal.module.basic.setting.module.stuff.info": "물건정보",
@@ -145,9 +147,11 @@
"modal.circuit.trestle.setting.circuit.allocation": "회로 할당",
"modal.circuit.trestle.setting.circuit.allocation.auto": "자동 회로 할당",
"modal.circuit.trestle.setting.circuit.allocation.passivity": "수동 회로 할당",
+ "modal.circuit.trestle.setting.circuit.allocation.passivity.circuit": "회로",
"modal.circuit.trestle.setting.circuit.allocation.passivity.info": "동일한 회로의 모듈을 선택 상태로 만든 후 [번호 확정] 버튼을 누르면 번호가 할당됩니다.",
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional": "선택된 파워컨디셔너",
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num": "설정할 회로번호(1~)",
+ "modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info": "표준회로{0}장~{1}장",
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset": "선택된 파워컨디셔너의 회로번호 초기화",
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset": "모든 회로번호 초기화",
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix": "번호 확정",
@@ -308,6 +312,9 @@
"plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?",
"plan.message.save": "저장되었습니다.",
"plan.message.delete": "삭제되었습니다.",
+ "plan.message.leave": "물건현황(목록)으로 이동하시겠습니까? [예]를 선택한 경우, 저장하고 이동합니다.",
+ "plan.message.corfirm.yes": "예",
+ "plan.message.confirm.no": "아니오",
"setting": "설정",
"delete": "삭제",
"delete.all": "전체 삭제",
@@ -507,6 +514,7 @@
"common.require": "필수",
"common.finish": "완료",
"common.ok": "확인",
+ "common.cancel": "취소",
"commons.west": "서",
"commons.east": "동",
"commons.south": "남",
@@ -681,6 +689,7 @@
"stuff.detail.tooltip.surfaceType": "염해지역 정의는 각 메이커의 설치 메뉴얼을 확인해주십시오",
"stuff.detail.tempSave.message1": "임시저장 되었습니다. 물건번호를 획득하려면 필수 항목을 모두 입력해 주십시오.",
"stuff.detail.tempSave.message2": "담당자는 10자리 이하로 입력해 주십시오.",
+ "stuff.detail.tempSave.message3": "2차 판매점을 선택해주세요.",
"stuff.detail.confirm.message1": "판매점 정보를 변경하면, 설계의뢰 문서번호가 삭제됩니다. 변경하시겠습니까?",
"stuff.detail.delete.message1": "사양이 확정된 물건은 삭제할 수 없습니다.",
"stuff.detail.planList.title": "플랜리스트",
@@ -943,8 +952,9 @@
"estimate.detail.save.requiredSalePrice": "단가는 0보다 큰값을 입력해주세요.",
"estimate.detail.reset.alertMsg": "초기화 되었습니다.",
"estimate.detail.reset.confirmMsg": "수기 변경(저장)한 견적 정보가 초기화되고, 최근 저장된 도면정보가 반영됩니다. 정말로 초기화하시겠습니까?",
- "estimate.detail.lock.alertMsg": "견적서를 [잠금]하면, 수정할 수 없습니다. 견적서를 수정하려면 잠금해제를 하십시오",
- "estimate.detail.unlock.alertMsg": "견적서를 수정하고, 저장하십시오",
+ "estimate.detail.lock.alertMsg": "견적서를 [잠금]하면, 수정할 수 없습니다. 견적서를 수정하려면 잠금해제를 하십시오.",
+ "estimate.detail.unlock.alertMsg": "[잠금해제]하면 견적서를 수정할 수 있습니다. 해제하시겠습니까?",
+ "estimate.detail.unlock.confirmBtnName": "해제",
"estimate.detail.alert.delFile": "첨부파일을 완전히 삭제하려면 [저장]버튼을 클릭하십시오.",
"estimate.detail.alert.selectDelItem": "삭제할 제품을 선택하세요.",
"estimate.menu.move.valid1": "회로를 나누지 않았기 때문에 견적서를 호출할 수 없습니다.",
@@ -981,5 +991,11 @@
"module.place.out": "설치면 밖으로 모듈을 설치 할 수 없습니다.",
"module.place.no.surface": "선택된 모듈 설치면이 없습니다.",
"module.place.select.module": "모듈을 선택해주세요.",
- "module.place.select.one.module": "모듈은 하나만 선택해주세요."
+ "module.place.select.one.module": "모듈은 하나만 선택해주세요.",
+ "batch.canvas.delete.all": "배치면 내용을 전부 삭제하시겠습니까?",
+ "module.not.found": "설치 모듈을 선택하세요.",
+ "construction.length.difference": "지붕면 공법을 전부 선택해주세요.",
+ "menu.validation.canvas.roof": "패널을 배치하려면 지붕면을 입력해야 합니다.",
+ "batch.object.outside.roof": "오브젝트는 지붕내에 설치해야 합니다.",
+ "batch.object.notinstall.cross": "오브젝트는 겹쳐서 설치 할 수 없습니다."
}
diff --git a/src/store/circuitTrestleAtom.js b/src/store/circuitTrestleAtom.js
index bac7ee7a..ea54835a 100644
--- a/src/store/circuitTrestleAtom.js
+++ b/src/store/circuitTrestleAtom.js
@@ -1,17 +1,51 @@
+import { useMessage } from '@/hooks/useMessage'
import { atom } from 'recoil'
-export const makerState = atom({
- key: 'makerState',
- default: { makers: [], selectedMaker: null },
+export const makersState = atom({
+ key: 'makersState',
+ default: [],
dangerouslyAllowMutability: true,
})
+export const selectedMakerState = atom({
+ key: 'selectedMakerState',
+ default: null,
+})
+
export const seriesState = atom({
key: 'seriesState',
- default: { series: [], selectedSeries: [] },
+ default: [],
})
-export const modelState = atom({
+export const modelsState = atom({
key: 'modelState',
- default: { models: [], selectedModels: [] },
+ default: [],
+})
+
+export const selectedModelsState = atom({
+ key: 'selectedModelsState',
+ default: [],
+})
+
+export const pcsCheckState = atom({
+ key: 'divisionCircuitState',
+ default: { division: true, max: false },
+})
+
+export const moduleStatisticsState = atom({
+ key: 'moduleStatisticsState',
+ default: {
+ header: [
+ { name: '지붕면', prop: 'name' },
+ { name: `발전량(kW)`, prop: 'amount' },
+ ],
+ rows: [],
+ footer: ['합계', '0'],
+ },
+ dangerouslyAllowMutability: true,
+})
+
+export const stepUpListDataState = atom({
+ key: 'stepUpListDataState',
+ default: [],
})
diff --git a/src/store/selectedModuleOptions.js b/src/store/selectedModuleOptions.js
index faa979fd..c312c694 100644
--- a/src/store/selectedModuleOptions.js
+++ b/src/store/selectedModuleOptions.js
@@ -81,6 +81,7 @@ export const moduleSelectionDataState = atom({
key: 'moduleSelectionDataState',
default: {
common: {},
+ module: {},
roofConstructions: [],
},
dangerouslyAllowMutability: true,
diff --git a/src/styles/_canvasside.scss b/src/styles/_canvasside.scss
index efb79f02..b49087ed 100644
--- a/src/styles/_canvasside.scss
+++ b/src/styles/_canvasside.scss
@@ -3,7 +3,7 @@
position: fixed;
top: 200px;
left: 50px;
- z-index: 999999;
+ z-index: 100000;
display: flex;
width: 237px;
height: 40px;
@@ -37,7 +37,7 @@
border: 1px solid #3D3D3D;
padding: 20px;
.penal-table{
- table-layout: fixed;
+ table-layout: auto;
border-collapse: collapse;
thead{
th{
@@ -45,8 +45,11 @@
background-color:rgba(255, 255, 255, 0.05);
font-size: 12px;
font-weight: 500;
+ min-width: 140px;
+ padding: 0 15px;
color: #fff;
border: 1px solid #505050;
+ white-space: nowrap;
}
}
tbody{
diff --git a/src/styles/_main.scss b/src/styles/_main.scss
index 5da1350d..4322b535 100644
--- a/src/styles/_main.scss
+++ b/src/styles/_main.scss
@@ -167,13 +167,20 @@
display: flex;
align-items: center;
span{
+ width: 0;
+ flex: 1;
position: relative;
display: block;
font-size: 13px;
color: #101010;
font-weight: 400;
padding: 0 10px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
&.time{
+ flex: none;
+ width: 160px;
padding-left: 22px;
&::before{
content: '';
@@ -187,6 +194,10 @@
background-size: cover;
}
}
+ &.product{
+ flex: none;
+ width: 160px;
+ }
&:after{
content: '';
position: absolute;
diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss
index 0e767ee7..61f631cd 100644
--- a/src/styles/_modal.scss
+++ b/src/styles/_modal.scss
@@ -127,6 +127,7 @@ $alert-color: #101010;
padding: 10px 24px;
background-color: #000;
// overflow: hidden;
+ cursor: pointer;
h1.title{
font-size: 13px;
color: $pop-color;
@@ -211,6 +212,13 @@ $alert-color: #101010;
font-weight: $pop-normal-weight;
}
}
+.modal-foot{
+ display: block;
+ width: 100%;
+ padding: 5px 0;
+ background-color: #000;
+ cursor: pointer;
+}
.adsorption-point{
display: flex;
diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss
index ceb5aff3..2f5c7f79 100644
--- a/src/styles/_reset.scss
+++ b/src/styles/_reset.scss
@@ -414,6 +414,15 @@ button{
transform: translateY(-50%) rotate(-180deg);
}
}
+ &.disabled{
+ cursor: default;
+ p{
+ color: #aaa;
+ }
+ &::after{
+ opacity: 0.7;
+ }
+ }
}
.select-light{
@@ -903,9 +912,22 @@ input[type=text]{
font-size: 13px;
padding: 7px 10px;
color: #45576F;
+
}
.custom__option--is-selected{
- color: #fff;
+ background-color: #2684FF;
+ color: #fff !important;
+ &.custom__option--is-focused{
+ background-color: #2684FF;
+ color: #fff;
+ }
+ }
+ .custom__option--is-focused{
+ background-color: #DEEBFF;
+ color: #45576F;
+ }
+ .special-option{
+ color: #2684FF;
}
// disable
&.custom--is-disabled{
@@ -916,6 +938,7 @@ input[type=text]{
color: #999999;
}
}
+
}
// toggle
@@ -973,4 +996,9 @@ input:checked + .slider {
&:before {
transform: translateX(35px);
}
+}
+
+// alert z-index
+.swal2-container{
+ z-index: 100000;
}
\ No newline at end of file
diff --git a/src/styles/spinner.scss b/src/styles/spinner.scss
index b6398e94..45e124ae 100644
--- a/src/styles/spinner.scss
+++ b/src/styles/spinner.scss
@@ -1,10 +1,14 @@
.spinner-wrap{
+ position: fixed;
+ top: 0;
+ left: 0;
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
- background-color: #fff;
+ background-color: rgba($color: #101010, $alpha: 0.2);
+ z-index: 2000000;
.loader {
font-size: 10px;
width: 1.2em;
diff --git a/src/util/board-utils.js b/src/util/board-utils.js
index c41ba22a..9a6b622c 100644
--- a/src/util/board-utils.js
+++ b/src/util/board-utils.js
@@ -1,12 +1,13 @@
import { useAxios } from '@/hooks/useAxios'
// 파일 다운로드
-export const handleFileDown = async (file) => {
+export const handleFileDown = async (keyNo, zipYn) => {
const { promiseGet } = useAxios()
const url = `/api/board/file/download`
const params = new URLSearchParams({
- encodeFileNo: file.encodeFileNo,
+ keyNo: keyNo,
+ zipYn: zipYn,
})
const options = { responseType: 'blob' }
const apiUrl = `${url}?${params.toString()}`
@@ -18,8 +19,17 @@ export const handleFileDown = async (file) => {
const fileUrl = window.URL.createObjectURL(blob)
const link = document.createElement('a')
+ const contentDisposition = resultData.headers.get('content-disposition')
+ let filename = 'filename'
+ if (contentDisposition) {
+ const matches = contentDisposition.match(/filename="?([^"]+)"?/)
+ if (matches && matches[1]) {
+ filename = matches[1]
+ }
+ }
+
+ link.download = decodeURIComponent(filename)
link.href = fileUrl
- link.download = file.srcFileNm
document.body.appendChild(link)
link.click()
link.remove()
diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js
index b4d5e42f..5df32879 100644
--- a/src/util/canvas-util.js
+++ b/src/util/canvas-util.js
@@ -1031,3 +1031,8 @@ export function calculateVisibleModuleHeight(sourceWidth, sourceHeight, angle, d
height: Number(visibleHeight.toFixed(1)), // 소수점 두 자리로 고정
}
}
+
+export function getTrestleLength(length, degree) {
+ const radians = (degree * Math.PI) / 180
+ return length * Math.cos(radians)
+}
diff --git a/src/util/common-utils.js b/src/util/common-utils.js
index 47498464..ee003ec3 100644
--- a/src/util/common-utils.js
+++ b/src/util/common-utils.js
@@ -134,3 +134,44 @@ export const getQueryString = (o) => {
.join('&')
return `?${queryString}`
}
+
+export const unescapeString = (str) => {
+ const regex = /&(amp|lt|gt|quot|#39);/g
+ const chars = {
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ ''': "'",
+ }
+
+ if (regex.test(str)) {
+ return str.replace(regex, (matched) => chars[matched] || matched)
+ }
+}
+
+export const isNullOrUndefined = (value) => {
+ return value === null || value === undefined
+}
+
+export const isEqualObjects = (obj1, obj2) => {
+ const keys1 = Object.keys(obj1)
+ const keys2 = Object.keys(obj2)
+
+ if (keys1.length !== keys2.length) return false
+
+ for (let key of keys1) {
+ const val1 = obj1[key]
+ const val2 = obj2[key]
+ const areObjects = isObject(val1) && isObject(val2)
+
+ if (areObjects && !deepEqual(val1, val2)) return false
+ if (!areObjects && val1 !== val2) return false
+ }
+
+ return true
+}
+
+function isObject(value) {
+ return value !== null && typeof value === 'object'
+}
|