Merge branch 'dev' of ssh://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev

# Conflicts:
#	src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx
This commit is contained in:
김민식 2025-02-03 09:40:30 +09:00
commit 41ab4af9ed
23 changed files with 2038 additions and 755 deletions

View File

@ -174,6 +174,9 @@ export const SAVE_KEY = [
'turfPoints',
'tempIndex',
'surfaceId',
'moduleRowsTotCnt',
'seq',
'smartRackId',
]
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]

View File

@ -15,6 +15,7 @@ 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()

View File

@ -1,4 +1,4 @@
import { useEffect, useState, useReducer } from 'react'
import { useEffect, useState, useReducer, useRef } from 'react'
import { useRecoilValue, useRecoilState } from 'recoil'
import { addedRoofsState } from '@/store/settingAtom'
import { currentCanvasPlanState } from '@/store/canvasAtom'
@ -41,6 +41,7 @@ export default function Module({ setTabNum }) {
const [debouncedVerticalSnowCover] = useDebounceValue(inputVerticalSnowCover, 500)
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //
const [tempModuleSelectionData, setTempModuleSelectionData] = useReducer((prevState, nextState) => {
return { ...prevState, ...nextState }
}, moduleSelectionData)
@ -55,15 +56,13 @@ export default function Module({ setTabNum }) {
}, [installHeight, verticalSnowCover])
useEffect(() => {
if (tempModuleSelectionData) {
setModuleSelectionData(tempModuleSelectionData)
if (
tempModuleSelectionData.common.moduleItemId &&
isObjectNotEmpty(tempModuleSelectionData.module) &&
tempModuleSelectionData.roofConstructions.length > 0
) {
moduleSelectedDataTrigger(tempModuleSelectionData)
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])
@ -134,7 +133,8 @@ export default function Module({ setTabNum }) {
</tr>
</thead>
<tbody>
{selectedModules.itemList &&
{selectedModules &&
selectedModules.itemList &&
selectedModules.itemList.map((row, index) => (
<tr key={index}>
<td>
@ -250,10 +250,10 @@ export default function Module({ setTabNum }) {
<div style={{ display: roofTab === index ? 'block' : 'none' }} key={index}>
<ModuleTabContents
key={index}
index={index}
tabIndex={index}
addRoof={roof}
setAddedRoofs={setAddedRoofs}
roofTab={index}
roofTab={roofTab}
tempModuleSelectionData={tempModuleSelectionData}
setTempModuleSelectionData={setTempModuleSelectionData}
/>

View File

@ -1,361 +1,42 @@
import { useEffect, useState, useRef, useReducer } from 'react'
import { useRecoilValue, useRecoilState } from 'recoil'
import { currentCanvasPlanState, 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 { moduleSelectionDataState, moduleSelectionInitParamsState, selectedModuleState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils'
import QSelectBox from '@/components/common/select/QSelectBox'
import { addedRoofsState } from '@/store/settingAtom'
import { useModuleTabContents } from '@/hooks/module/useModuleTabContents'
export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
const { getMessage } = useMessage()
const [roofMaterial, setRoofMaterial] = useState(addRoof) //`
const addRoofsArray = useRecoilValue(addedRoofsState)
const globalPitchText = useRecoilValue(pitchTextSelector) //
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
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 [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()
useEffect(() => {
setHajebichi(addRoof.hajebichi)
setLengthBase(addRoof.lenBase)
}, [])
// addRoofs
useEffect(() => {
// api
setTrestleParams({ ...trestleParams, workingWidth: lengthBase })
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 (moduleSelectionData.roofConstructions.length > 0) {
setModuleConstructionSelectionData(moduleSelectionData.roofConstructions[roofTab])
}
}, [moduleSelectionData])
//
const handleChangeRaftBase = (option) => {
setSelectedRaftBase(option)
setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode }) //
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: '',
roofPitch: hajebichiRef.current ? hajebichiRef.current.value : '',
})
setRoofBaseList([]) //
setConstructionList([]) //
}
//
const handleChangeRoofBase = (option) => {
// if (option) {
setConstructionListParams({
...moduleSelectionInitParams,
...roofBaseParams,
roofBaseCd: option.roofBaseCd,
inclCd: addRoof.pitch,
})
setSelectedRoofBase(option)
}
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
//
if (moduleConstructionSelectionData && moduleConstructionSelectionData.construction) {
selectedConstruction.setupCover = moduleConstructionSelectionData.construction.setupCover
selectedConstruction.setupSnowCover = moduleConstructionSelectionData.construction.setupSnowCover
setCvrChecked(selectedConstruction.setupCover)
setSnowGdChecked(selectedConstruction.setupSnowCover)
}
setCvrYn(selectedConstruction.cvrYn)
setSnowGdPossYn(selectedConstruction.snowGdPossYn)
setSelectedConstruction(selectedConstruction)
} else {
constructionRef.current.forEach((ref) => {
ref.classList.remove('blue')
})
}
}
const handleCvrChecked = () => {
setCvrChecked(!cvrChecked)
setSelectedConstruction({ ...selectedConstruction, setupCover: !cvrChecked })
}
const handleSnowGdChecked = () => {
setSnowGdChecked(!snowGdChecked)
setSelectedConstruction({ ...selectedConstruction, setupSnowCover: !snowGdChecked })
}
const getModuleOptionsListData = async (params) => {
const optionsList = await getTrestleList(params)
if (optionsList.data.length > 0) {
if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd === null) {
setTrestleList(optionsList.data)
if (isExistData) {
setSelectedTrestle({ ...moduleConstructionSelectionData?.trestle })
} else {
setConstMthdList([])
setRoofBaseList([])
}
}
if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd === null) {
setConstMthdList(optionsList.data)
if (isExistData) {
setSelectedConstMthd({ ...moduleConstructionSelectionData?.trestle })
} else {
setRoofBaseList([])
}
}
if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd) {
setRoofBaseList(optionsList.data)
if (isExistData) {
setSelectedRoofBase({ ...moduleConstructionSelectionData?.trestle })
}
}
}
}
const getConstructionListData = async (params) => {
if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
const optionsList = await getConstructionList(params)
setConstructionList(optionsList.data)
}
}
useEffect(() => {
if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
const newRoofConstructions = {
roofIndex: roofTab,
addRoof: addRoof,
trestle: selectedRoofBase,
construction: selectedConstruction,
}
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])
useEffect(() => {
if (isExistData) {
setConstructionListParams({
...moduleSelectionInitParams,
...roofBaseParams,
roofBaseCd: selectedRoofBase.roofBaseCd,
inclCd: addRoof.pitch,
})
}
}, [selectedRoofBase])
useEffect(() => {
console.log('moduleConstructionSelectionData', moduleConstructionSelectionData)
if (
isExistData &&
constructionList.length > 0 &&
isObjectNotEmpty(moduleConstructionSelectionData?.construction) &&
moduleConstructionSelectionData?.construction.hasOwnProperty('constPossYn') ///
) {
const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
const construction = constructionList[selectedIndex]
if (construction.constPossYn === 'Y') {
handleConstruction(selectedIndex)
}
}
}, [constructionList])
useEffect(() => {
if (isObjectNotEmpty(moduleSelectionData) && isObjectNotEmpty(moduleSelectionData.module)) {
setSelectedModules(moduleSelectionData.module)
}
}, [moduleSelectionData])
useEffect(() => {
// 202600
const raftCodeList = findCommonCode('203800')
//
raftCodeList.forEach((obj) => {
obj.name = obj.clCodeNm
obj.id = obj.clCode
})
setRaftCodes(raftCodeList)
}, [])
useEffect(() => {
//
if (
moduleSelectionInitParams.illuminationTp &&
moduleSelectionInitParams.instHt &&
moduleSelectionInitParams.stdSnowLd &&
moduleSelectionInitParams.stdWindSpeed
) {
const isModuleLoaded = moduleSelectionInitParams.hasOwnProperty('moduleTpCd') //
if (isModuleLoaded) {
setTrestleParams({
moduleTpCd: moduleSelectionInitParams.moduleTpCd,
roofMatlCd: addRoof.roofMatlCd,
raftBaseCd: addRoof.raftBaseCd,
workingWidth: lengthBase,
})
setConstructionList([])
if (isObjectNotEmpty(moduleConstructionSelectionData)) {
//
setConstructionParams({ ...moduleConstructionSelectionData.trestle, constMthdCd: '', roofBaseCd: '' })
setRoofBaseParams({ ...moduleConstructionSelectionData.trestle, roofBaseCd: '' })
setIsExistData(true)
}
}
}
setTempModuleSelectionData({ common: moduleSelectionInitParams, module: selectedModules })
}, [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 (
<>
@ -526,22 +207,22 @@ export default function ModuleTabContents({ addRoof, setAddedRoofs, roofTab, tem
<div className="d-check-box pop">
<input
type="checkbox"
id={`ch01_${roofTab}`}
id={`ch01_${tabIndex}`}
disabled={cvrYn === 'N' ? true : false}
checked={cvrChecked}
checked={cvrChecked || false}
onChange={handleCvrChecked}
/>
<label htmlFor={`ch01_${roofTab}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
<label htmlFor={`ch01_${tabIndex}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
</div>
<div className="d-check-box pop">
<input
type="checkbox"
id={`ch02_${roofTab}`}
id={`ch02_${tabIndex}`}
disabled={snowGdPossYn === 'N' ? true : false}
checked={snowGdChecked}
checked={snowGdChecked || false}
onChange={handleSnowGdChecked}
/>
<label htmlFor={`ch02_${roofTab}`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
<label htmlFor={`ch02_${tabIndex}`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
</div>
</div>
</div>

View File

@ -8,7 +8,7 @@ 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)

View File

@ -18,6 +18,9 @@ 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',
@ -42,7 +45,13 @@ export default function CircuitTrestleSetting({ id }) {
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
const selectedModules = useRecoilValue(selectedModuleState)
const { getPcsAutoRecommendList } = useMasterController()
const { getPcsAutoRecommendList, getPcsVoltageChk } = useMasterController()
// ()
const [selectedStepUpValues, setSelectedStepUpValues] = useState({})
const [getStepUpSelections, setGetStepUpSelections] = useState(null)
const [stepUpListData, setStepUpListData] = useRecoilState(stepUpListDataState)
useEffect(() => {
if (!managementState) {
@ -50,6 +59,18 @@ export default function CircuitTrestleSetting({ id }) {
}
}, [])
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({
@ -66,17 +87,48 @@ export default function CircuitTrestleSetting({ id }) {
pcsItemList: getPcsItemList(),
}
getPcsAutoRecommendList(params).then((res) => {
if (res.data?.pcsItemList) {
setModels(res.data.pcsItemList)
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)
} else {
swalFire({
title: '파워컨디셔너를 추가해 주세요.',
type: 'alert',
})
}
})
})
}
}
const getOptYn = () => {
@ -97,45 +149,11 @@ export default function CircuitTrestleSetting({ id }) {
})
}
const getSelectModelList = () => {
return 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: [
{
roofSurfaceId: '',
roofSurface: '',
roofSurfaceIncl: '',
moduleList: [
{
itemId: '',
circuit: '',
pcsItemId: '',
},
],
},
],
},
],
}
})
}
const getUseModuleItemList = () => {
return selectedModules.itemList.map((m) => {
return {
itemId: m.itemId,
//mixMatlNo: m.mixMatlNo,
mixMatlNo: m.mixMatlNo,
}
})
}
@ -145,6 +163,7 @@ export default function CircuitTrestleSetting({ id }) {
.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
.map((obj) => {
getModuleList(obj)
return {
roofSurfaceId: obj.id,
roofSurface: canvas
@ -152,15 +171,90 @@ export default function CircuitTrestleSetting({ id }) {
.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: obj.modules.map((module) => {
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
@ -176,28 +270,56 @@ export default function CircuitTrestleSetting({ id }) {
return acc + parseInt(model.moduleMaxQty)
}, 0)
}
const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
// 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
}
// if (placementModules.length > target) {
// swalFire({
// title: ' . .',
// type: 'alert',
// })
// return
// }
// setAllocationType(ALLOCATION_TYPE.AUTO)
setTabNum(2)
// setTabNum(2)
}
const onPassivityAllocation = () => {
if (selectedModels.length === 0) {
swalFire({
title: '파워 컨디셔너를 추가해 주세요.',
type: 'alert',
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',
})
}
})
return
} else if (pcsCheck.max) {
const moduleStdQty = selectedModels.reduce((acc, model) => {
return acc + parseInt(model.moduleStdQty)
@ -221,6 +343,96 @@ export default function CircuitTrestleSetting({ id }) {
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,
@ -243,11 +455,9 @@ export default function CircuitTrestleSetting({ id }) {
pcsCheck,
selectedModels,
setSelectedModels,
getApiProps,
getSelectedModuleList,
getSelectModelList,
getOptYn,
getUseModuleItemList,
getRoofSurfaceList,
getModelList,
}
const stepUpProps = {
@ -261,6 +471,7 @@ export default function CircuitTrestleSetting({ id }) {
getUseModuleItemList, // List
getRoofSurfaceList, //
getPcsItemList, // PCS
onValuesSelected: handleStepUpValuesSelected, //
}
return (
@ -282,7 +493,7 @@ export default function CircuitTrestleSetting({ id }) {
</div>
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && <PowerConditionalSelect {...powerConditionalSelectProps} />}
{tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && <PassivityCircuitAllocation {...passivityProps} />}
{tabNum === 2 && <StepUp {...stepUpProps} />}
{tabNum === 2 && <StepUp {...stepUpProps} onInitialize={handleStepUpInitialize} />}
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && (
<div className="grid-btn-wrap">
<button className="btn-frame modal mr5" onClick={() => onAutoAllocation()}>
@ -308,7 +519,8 @@ export default function CircuitTrestleSetting({ id }) {
<button className="btn-frame modal mr5" onClick={() => setTabNum(1)}>
{getMessage('modal.common.prev')}
</button>
<button className="btn-frame modal act" onClick={() => apply()}>
{/* <button className="btn-frame modal act" onClick={() => apply()}> */}
<button className="btn-frame modal act" onClick={onApply}>
{getMessage('modal.common.save')}({getMessage('modal.circuit.trestle.setting.circuit.allocation')})
</button>
</div>

View File

@ -64,6 +64,7 @@ export default function PowerConditionalSelect(props) {
useEffect(() => {
if (makers.length === 0) {
getPcsMakerList().then((res) => {
console.log('getPcsMakerList', res.data)
setMakers(res.data)
})
}
@ -90,6 +91,7 @@ export default function PowerConditionalSelect(props) {
}
const onCheckSeries = (data) => {
console.log('data', data)
const copySeries = series.map((s) => {
return {
...s,
@ -97,12 +99,19 @@ export default function PowerConditionalSelect(props) {
}
})
setSeries(copySeries)
console.log('copySeries', copySeries)
handleSetmodels(copySeries.filter((s) => s.selected))
}
const handleSetmodels = (series) => {
const pcsMkrCd = series[0]?.pcsMkrCd
const pcsSerList = series.map((series) => {
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) => {
@ -123,11 +132,10 @@ export default function PowerConditionalSelect(props) {
}
}),
)
return
} else {
setModels([])
setSelectedModels([])
}
setModels([])
setSelectedModels([])
})
}
@ -146,15 +154,16 @@ export default function PowerConditionalSelect(props) {
}
const onRemoveSelectedModel = (model) => {
setModels(models.map((m) => ({ ...m, selected: m.code !== model.code ? m.selected : false })))
setSelectedModels(selectedModels.filter((m) => m.id !== model.id))
}
const onChangeMaker = (option) => {
if (option) {
setModels(null)
setModels([])
setSelectedMaker(option)
getPcsMakerList(option).then((res) => {
console.log('getPcsMakerList(series)', res.data)
setSeries(
res.data.map((series) => {
return { ...series, selected: false }

View File

@ -24,19 +24,24 @@ export default function StepUp(props) {
const [stepUpListData, setStepUpListData] = useState([])
const [optCodes, setOptCodes] = useState([])
useCanvasPopupStatusController(6)
const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore)
if (Object.keys(canvasPopupStatusState[6]).length !== 0) {
console.log('🚀 ~ useEffect ~ canvasPopupStatusState :', canvasPopupStatusState)
}
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(() => {
console.log('🚀 ~ useEffect ~ >>>>>>>>>>>> props:', props)
// PCS
fetchStepUpData()
}, [])
// PCS
const fetchStepUpData = async () => {
try {
const params = {
@ -46,14 +51,14 @@ export default function StepUp(props) {
pcsItemList: props.getPcsItemList(), // PCS
}
console.log('🚀 ~ fetchStepUpData ~ params:', params)
// PCS
const res = await getPcsVoltageStepUpList(params)
console.log('🚀 ~ fetchStepUpData ~ res:', res)
if (res?.result.code === 200 && res?.data) {
const dataArray = Array.isArray(res.data) ? res.data : [res.data]
const stepUpListData = formatStepUpListData(dataArray)
console.log('🚀 ~ useEffect ~ getPcsVoltageStepUpList ~ stepUpListData:', stepUpListData)
// PCS SET
setStepUpListData(stepUpListData)
// PCS
@ -74,13 +79,59 @@ export default function StepUp(props) {
}))
}
// PCS
// // 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 = []) => {
return dataArray?.map((stepUps) => ({
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
@ -107,6 +158,8 @@ export default function StepUp(props) {
// PCS
const formatConnList = (connList = []) => {
if (!connList) return [] // null
return connList?.map((conn) => ({
connAllowCur: conn.connAllowCur ? conn.connAllowCur : 0,
connMaxParalCnt: conn.connMaxParalCnt ? conn.connMaxParalCnt : 0,
@ -122,17 +175,114 @@ export default function StepUp(props) {
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 = (stepUpId, idx, tabNumber) => {
const handleTabChange = (goodsNo, idx, tabNumber) => {
setModuleTabs((prev) => ({
...prev,
[`${stepUpId}_${idx}`]: tabNumber,
[`${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 (
<>
<div className="properties-setting-wrap outer">
@ -143,9 +293,7 @@ export default function StepUp(props) {
{stepUp?.pcsItemList.map((_, idx) => (
<div key={idx} className="module-table-inner">
<div className="mb-box">
<div key={idx} className="circuit-table-tit">
{stepUp.pcsItemList[idx].goodsNo}
</div>
<div className="circuit-table-tit">{stepUp.pcsItemList[idx].goodsNo}</div>
<div className="roof-module-table overflow-y min">
<table>
<thead>
@ -155,9 +303,21 @@ export default function StepUp(props) {
</tr>
</thead>
<tbody>
{stepUp.pcsItemList[idx].serQtyList.map((item) => {
{stepUp.pcsItemList[idx].serQtyList.map((item, serQtyIdx) => {
const rowKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}_${serQtyIdx}`
const pcsKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}`
return (
<tr className="on">
<tr
key={rowKey}
className={`${
(!isManualSelection[stepUp.pcsItemList[idx].goodsNo]?.[pcsKey] && item.rmdYn === 'Y') ||
(selectedRows[stepUp.pcsItemList[idx].goodsNo] && selectedRows[stepUp.pcsItemList[idx].goodsNo][pcsKey] === rowKey)
? 'on'
: ''
}`}
onClick={() => handleRowClick(stepUp.pcsItemList[idx].goodsNo, idx, serQtyIdx, item.serQty, item.paralQty)}
style={{ cursor: 'pointer' }}
>
<td className="al-r">{item.serQty}</td>
<td className="al-r">{item.paralQty}</td>
</tr>
@ -169,20 +329,20 @@ export default function StepUp(props) {
</div>
<div className="module-box-tab mb10">
<button
className={`module-btn ${(moduleTabs[`${stepUp.id}_${idx}`] || 1) === 1 ? 'act' : ''}`}
onClick={() => handleTabChange(stepUp.id, idx, 1)}
className={`module-btn ${(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 1 ? 'act' : ''}`}
onClick={() => handleTabChange(stepUp.pcsItemList[idx].goodsNo, idx, 1)}
>
{getMessage('modal.circuit.trestle.setting.step.up.allocation.connected')}
</button>
<button
className={`module-btn ${(moduleTabs[`${stepUp.id}_${idx}`] || 1) === 2 ? 'act' : ''}`}
onClick={() => handleTabChange(stepUp.id, idx, 2)}
className={`module-btn ${(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 2 ? 'act' : ''}`}
onClick={() => handleTabChange(stepUp.pcsItemList[idx].goodsNo, idx, 2)}
>
{getMessage('modal.circuit.trestle.setting.step.up.allocation.option')}
</button>
</div>
<div className="circuit-table-flx-wrap">
{(moduleTabs[`${stepUp.id}_${idx}`] || 1) === 1 && (
{(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 1 && (
<div className="circuit-table-flx-box">
<div className="roof-module-table min mb10">
<table>
@ -195,16 +355,24 @@ export default function StepUp(props) {
</thead>
<tbody>
<tr>
<td className="al-c">{stepUp.pcsItemList[idx].connList?.goodsNo}</td>
<td className="al-r">{stepUp.pcsItemList[idx].connList?.connMaxParalCnt}</td>
<td className="al-r">{stepUp.pcsItemList[idx].connList?.vstuParalCnt}</td>
<td className="al-c">
{stepUp.pcsItemList[idx].connList?.[0]?.goodsNo ? stepUp.pcsItemList[idx].connList?.[0]?.goodsNo : '-'}
</td>
<td className="al-c">
{stepUp.pcsItemList[idx].connList?.[0]?.connMaxParalCnt
? (stepUp.pcsItemList[idx].connList?.[0]?.connMaxParalCnt ?? '-')
: '-'}
</td>
<td className="al-c">
{stepUp.pcsItemList[idx].connList?.[0]?.vstuParalCnt ? stepUp.pcsItemList[idx].connList?.[0]?.vstuParalCnt : '-'}
</td>
</tr>
</tbody>
</table>
</div>
</div>
)}
{(moduleTabs[`${stepUp.id}_${idx}`] || 1) === 2 && (
{(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 2 && (
<div className="circuit-table-flx-box">
<div className="roof-module-table min mb10">
<table>

View File

@ -10,7 +10,16 @@ import { useContext, useEffect, useState } from 'react'
import { useRecoilValue } from 'recoil'
export default function PassivityCircuitAllocation(props) {
const { tabNum, setTabNum, selectedModels, getApiProps, getSelectedModuleList, getSelectModelList, getRoofSurfaceList, getModelList } = props
const {
tabNum,
setTabNum,
selectedModels,
getOptYn: getApiProps,
getUseModuleItemList: getSelectedModuleList,
getSelectModelList: getSelectModelList,
getRoofSurfaceList,
getModelList,
} = props
const { swalFire } = useSwal()
const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState)
@ -19,21 +28,40 @@ export default function PassivityCircuitAllocation(props) {
const moduleStatistics = useRecoilValue(moduleStatisticsState)
// const [totalWpout, setTotalWpout] = useState(0)
const [selectedPcs, setSelectedPcs] = useState(selectedModels[0])
const { header, rows: row } = moduleStatistics
const [headers, setHeaders] = useState(header)
const [rows, setRows] = useState(row)
// 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('🚀 ~ PassivityCircuitAllocation ~ selectedModels:', selectedModels)
}, [])
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))
})
useEffect(() => {
console.log('🚀 ~ PassivityCircuitAllocation ~ selectedPcs:', selectedPcs)
}, [selectedPcs])
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)) {
@ -54,32 +82,9 @@ export default function PassivityCircuitAllocation(props) {
canvas.renderAll()
}
useEffect(() => {
setSurfaceInfo()
if (!managementState) {
setManagementState(managementStateLoaded)
}
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
modules.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 setSurfaceInfo = () => {
const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
setHeaders([header[0], { name: '회로', prop: 'circuit' }, ...header.slice(1)])
// setHeaders([header[0], { name: '', prop: 'circuit' }, ...header.slice(1)])
setRows(
rows.map((row) => {
return {
@ -155,62 +160,145 @@ export default function PassivityCircuitAllocation(props) {
if (!circuitNumber || circuitNumber === 0) {
swalFire({
text: '회로번호를 1 이상입력해주세요.',
type: 'warning',
type: 'alert',
icon: 'warning',
})
return
} else if (targetModules.length === 0) {
swalFire({
text: '모듈을 선택해주세요.',
type: 'warning',
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: getSelectModelList(),
pcsItemList: pcsItemList,
}
console.log(params)
// getPcsManualConfChk(params).then((res) => {
// console.log(res)
//
// })
// 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
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()
},
})
// obj.circuit = moduleCircuitText
// canvas.add(moduleCircuitText)
// canvas.renderAll()
// console.log(obj)
// })
// setTargetModules([])
// setCircuitNumber(+circuitNumber + 1)
// canvas.renderAll()
return
}
setTargetModules([])
setCircuitNumber(+circuitNumber + 1)
setTableData()
})
}
const getCircuitNumber = () => {
@ -221,12 +309,100 @@ export default function PassivityCircuitAllocation(props) {
}
}
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 = () => {
console.log(
'module',
canvas.getObjects().filter((obj) => obj.name === 'module'),
)
console.log('selectedPcs', selectedPcs)
swalFire({
title: '선택된 파워 컨디셔너의 회로할당을 초기화합니다.',
type: 'confirm',
@ -281,7 +457,7 @@ export default function PassivityCircuitAllocation(props) {
<table>
<thead>
<tr>
{headers.map((header, index) => (
{header.map((header, index) => (
<th key={'header' + index}>{header.name}</th>
))}
</tr>
@ -289,7 +465,7 @@ export default function PassivityCircuitAllocation(props) {
<tbody>
{rows.map((row, index) => (
<tr key={'row' + index}>
{headers.map((header, i) => (
{header.map((header, i) => (
<td className="al-c" key={'rowcell' + i}>
{row[header.prop]}
</td>
@ -297,9 +473,9 @@ export default function PassivityCircuitAllocation(props) {
</tr>
))}
<tr>
{footer.map((footer, index) => (
<td className="al-c" key={'footer' + index}>
{footer}
{header.map((header, i) => (
<td className="al-c" key={'footer' + i}>
{footer[header.prop]}
</td>
))}
</tr>
@ -323,7 +499,7 @@ export default function PassivityCircuitAllocation(props) {
name="radio01"
id={`ra0${index + 1}`}
value={model}
checked={selectedPcs.id === model.id}
checked={selectedPcs?.id === model.id}
onChange={() => setSelectedPcs(model)}
/>
<label htmlFor={`ra0${index + 1}`}>
@ -361,7 +537,7 @@ export default function PassivityCircuitAllocation(props) {
<div className="input-grid mr5" style={{ width: '70px' }}>
<input
type="text"
className="input-origin block"
className="block input-origin"
value={circuitNumber}
min={1}
max={99}

View File

@ -350,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
@ -358,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({
@ -450,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)
@ -527,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')
@ -649,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) {
@ -985,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)
@ -1413,8 +1421,6 @@ export default function StuffDetail() {
type: 'alert',
confirmFn: () => {
callDetailApi(objectNo)
// setManagementState({ ...managementState, params })
// router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
},
})
}
@ -1426,48 +1432,22 @@ export default function StuffDetail() {
}
}
const callDetailApi = (objectNo) => {
promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => {
if (res.status === 200) {
if (res?.data?.createUser === 'T01' && session?.userId !== 'T01') {
//createUser T01 T01
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')
}
if (isObjectNotEmpty(res.data)) {
let surfaceTypeValue
if (res.data.surfaceType === 'Ⅲ・Ⅳ') {
surfaceTypeValue = '3'
} else if (res.data.surfaceType === 'Ⅱ') {
surfaceTypeValue = '2'
}
setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
} else {
setManagementState({})
swalFire({
text: getMessage('stuff.detail.header.notExistObjectNo'),
type: 'alert',
confirmFn: () => {
router.push('/management/stuff', { scroll: false })
},
})
}
if (isNotEmptyArray(res.data.planList)) {
setPlanGridProps({ ...planGridProps, planGridData: res.data.planList })
} else {
setPlanGridProps({ ...planGridProps, planGridData: [] })
}
} else {
setManagementState({})
setPlanGridProps({ ...planGridProps, planGridData: [] })
swalFire({
text: getMessage('stuff.detail.header.notExistObjectNo'),
type: 'alert',
confirmFn: () => {
router.push('/management/stuff', { scroll: false })
},
})
}
let surfaceTypeValue
if (res.data.surfaceType === 'Ⅲ・Ⅳ') {
surfaceTypeValue = '3'
} else {
surfaceTypeValue = '2'
}
setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
})
}
@ -1680,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 (
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
{data.label}
</div>
)
}
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 (
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
{data.label}
</div>
)
}
return (
<>
{(editMode === 'NEW' && (
@ -1847,6 +1852,7 @@ export default function StuffDetail() {
value={saleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
components={{ Option: CustomOption }}
></Select>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -1879,6 +1885,7 @@ export default function StuffDetail() {
value={showSaleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
// components={{ Option: CustomOption }}
></Select>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -1910,6 +1917,7 @@ export default function StuffDetail() {
value={showSaleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
// components={{ Option: CustomOption }}
></Select>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -1962,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 }}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -2413,7 +2421,7 @@ export default function StuffDetail() {
<>
<div className="select-wrap mr5" style={{ width: '567px' }}>
<Select
menuPlacement={'auto'}
// menuPlacement={'auto'}
id="long-value-select1"
instanceId="long-value-select1"
className="react-select-custom"
@ -2429,6 +2437,7 @@ export default function StuffDetail() {
value={saleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
components={{ Option: CustomOption }}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -2469,6 +2478,7 @@ export default function StuffDetail() {
value={showSaleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
// components={{ Option: CustomOption }}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -2503,6 +2513,7 @@ export default function StuffDetail() {
return option.saleStoreId
}
})}
// components={{ Option: CustomOption }}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -2557,6 +2568,7 @@ export default function StuffDetail() {
value={otherSaleStoreList.filter(function (option) {
return option.saleStoreId === otherSelOptions
})}
// components={{ Option: CustomOption2 }}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>

View File

@ -67,7 +67,9 @@ export default function StuffHeader() {
</div>
<div className="sub-table-box">
<div className="info-title">{getMessage('stuff.detail.header.specificationConfirmDate')}</div>
<div className="info-inner">{managementState?.specificationConfirmDate}</div>
<div className="info-inner">
{managementState?.specificationConfirmDate ? `${dayjs(managementState.specificationConfirmDate).format('YYYY.MM.DD HH:mm:ss')}` : ''}
</div>
</div>
<div className="sub-table-box">
<div className="info-title">{getMessage('stuff.detail.header.lastEditDatetime')}</div>

View File

@ -891,7 +891,6 @@ export default function StuffSearchCondition() {
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' : ''}`
console.log(optionClass)
return (
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
{data.label}

View File

@ -18,7 +18,12 @@ import { convertNumberToPriceDecimal } from '@/util/common-utils'
import { usePlan } from '@/hooks/usePlan'
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 { selectedPlan } = usePlan()
@ -136,9 +141,12 @@ export default function Simulator() {
const [hatsudenryouPeakcutAllSnow, setHatsudenryouPeakcutAllSnow] = useState([])
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) {
@ -161,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', '<br/>'))
@ -174,6 +184,7 @@ export default function Simulator() {
setContent(getMessage('common.message.no.data'))
}
})
setIsGlobalLoading(false)
}
// , list type

View File

@ -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 = () => {

View File

@ -147,7 +147,7 @@ export function useMasterController() {
],
}
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
})
}
@ -173,6 +173,22 @@ export function useMasterController() {
})
}
/**
* 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
@ -195,10 +211,7 @@ export function useMasterController() {
pcsItemList: params2.pcsItemList,
}
console.log('🚀 ~ getPcsVoltageStepUpList ~ params >>>>> :', params)
return await post({ url: '/api/v1/master/getPcsVoltageStepUpList', data: params }).then((res) => {
console.log('🚀🚀 ~ getPcsVoltageStepUpList ~ res:', res)
return res
})
}
@ -212,6 +225,7 @@ export function useMasterController() {
getPcsMakerList,
getPcsModelList,
getPcsAutoRecommendList,
getPcsVoltageChk,
getPcsManualConfChk,
getPcsVoltageStepUpList,
}

View File

@ -615,7 +615,7 @@ export function useModuleBasicSetting() {
for (let i = 0; i <= totalWidth; i++) {
leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0
if (isChidori) {
if (isChidori && !isMaxSetup) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
}
@ -716,7 +716,7 @@ export function useModuleBasicSetting() {
for (let j = 0; j < totalHeight; j++) {
leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0
if (isChidori) {
if (isChidori && !isMaxSetup) {
chidoriLength = i % 2 === 0 ? 0 : height / 2
}
@ -827,7 +827,7 @@ export function useModuleBasicSetting() {
for (let i = 0; i < diffRightEndPoint; i++) {
leftMargin = i === 0 ? 0 : intvHor * i
chidoriLength = 0
if (isChidori) {
if (isChidori && !isMaxSetup) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
}
@ -927,7 +927,7 @@ export function useModuleBasicSetting() {
leftMargin = j === 0 ? 0 : intvVer * j
chidoriLength = 0
if (isChidori) {
if (isChidori && !isMaxSetup) {
chidoriLength = i % 2 === 0 ? 0 : height / 2 - intvHor
}

View File

@ -3,8 +3,8 @@ import { useContext, useEffect, useState } from 'react'
import { GlobalDataContext } from '@/app/GlobalDataProvider'
import { useMasterController } from '@/hooks/common/useMasterController'
import { useCommonCode } from '@/hooks/common/useCommonCode'
import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
import { isObjectNotEmpty } from '@/util/common-utils'
export function useModuleSelection(props) {
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
@ -30,6 +30,8 @@ export function useModuleSelection(props) {
setSelectedSurfaceType(managementState?.surfaceType)
}
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
//탭별 파라메터 초기화
useEffect(() => {
bindInitData()
@ -94,6 +96,13 @@ export function useModuleSelection(props) {
}
}
//데이터가 있으면 모듈 자동 선택
useEffect(() => {
if (moduleList.length > 0 && isObjectNotEmpty(moduleSelectionData.module)) {
handleChangeModule(moduleSelectionData.module)
}
}, [moduleList])
const handleChangeModule = (option) => {
//선택된 모듈
setSelectedModules(option) //선택값 저장

View File

@ -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,
}
}

View File

@ -3,6 +3,7 @@ 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 = () => {
@ -33,15 +34,13 @@ export const useTrestle = () => {
alert('앞에서 셋팅 안됨')
return
}
let isEaveBar = construction.setupCover
let moduleRowsTotCnt = 0
let isEaveBar = construction.setupCover
let isSnowGuard = construction.setupSnowCover
const direction = parent.direction
const rack = surface.trestleDetail.rack
let { rackQty, rackIntvlPct, rackYn, cvrPlvrYn } = surface.trestleDetail
rackYn = 'N'
rackQty = 5
cvrPlvrYn = 'Y'
if (!rack) {
//25/01/16 기준 랙이 없는 경우는 그냥 안그려준다.
@ -93,6 +92,8 @@ export const useTrestle = () => {
leftExposedHalfTopModules.length > 0 ||
rightExposedHalfTopPoints.length > 0
surface.set({ isChidory: isChidory })
canvas
.getObjects()
.filter((obj) => ['eaveBar', 'halfEaveBar'].includes(obj.name) && obj.parent === surface)
@ -112,6 +113,7 @@ export const useTrestle = () => {
stroke: 'blue',
strokeWidth: 4,
selectable: false,
surfaceId: surface.id,
parentId: module.id,
})
canvas.add(eaveBar)
@ -141,6 +143,7 @@ export const useTrestle = () => {
stroke: 'blue',
strokeWidth: 4,
selectable: false,
surfaceId: surface.id,
parentId: module.id,
})
canvas.add(halfEaveBar)
@ -179,6 +182,8 @@ export const useTrestle = () => {
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) => {
@ -296,6 +301,8 @@ export const useTrestle = () => {
return rack.value.moduleRows === centerRows
})?.value.racks
mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule)
if (rackYn === 'Y') {
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn)
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R', rackYn)
@ -356,7 +363,7 @@ 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)
}
@ -409,6 +416,8 @@ 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)
@ -417,12 +426,16 @@ export const useTrestle = () => {
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))
})
}
@ -612,32 +625,69 @@ 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 = 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,
},
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,
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 + 8
})
@ -646,32 +696,68 @@ export const useTrestle = () => {
}
case 'east': {
rackInfos.forEach((rackInfo) => {
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
const { rackLen, itemId, supFitQty, supFitIntvlPct, rackRowsCd, smartRack, smartRackYn } = rackInfo
const rackLength = getTrestleLength(rackLen, degree) / 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,
},
parentId: module.id,
strokeWidth: 4,
selectable: false,
supFitQty,
supFitIntvlPct,
rackLen,
rackYn,
rackId: itemId,
direction: 'left',
})
canvas.add(rack)
canvas.renderAll()
canvas.add(rack)
canvas.renderAll()
}
startPointX -= rackLength + 8
})
@ -680,31 +766,66 @@ export const useTrestle = () => {
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 = getTrestleLength(rackLen, degree) / 10
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,
strokeWidth: 4,
selectable: false,
supFitQty,
supFitIntvlPct,
rackLen,
rackId: itemId,
direction: 'right',
})
canvas.add(rack)
canvas.renderAll()
canvas.add(rack)
canvas.renderAll()
}
startPointX += rackLength + 8
})
@ -712,32 +833,66 @@ export const useTrestle = () => {
}
case 'north': {
rackInfos.forEach((rackInfo) => {
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
const rackLength = getTrestleLength(rackLen, degree) / 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,
},
parentId: module.id,
strokeWidth: 4,
selectable: false,
supFitQty,
supFitIntvlPct,
rackLen,
rackId: itemId,
direction: 'bottom',
})
canvas.add(rack)
canvas.renderAll()
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',
})
canvas.add(rack)
canvas.renderAll()
}
startPointY += rackLength + 8
})
break
@ -777,6 +932,7 @@ export const useTrestle = () => {
fill: 'green',
name: 'bracket',
parentId: rack.parentId,
surfaceId: surface.id,
width: bracketLength,
height: bracketLength,
selectable: false,
@ -795,6 +951,7 @@ export const useTrestle = () => {
fill: 'green',
name: 'bracket',
parentId: rack.parentId,
surfaceId: surface.id,
width: bracketLength,
height: bracketLength,
selectable: false,
@ -812,6 +969,7 @@ export const useTrestle = () => {
top: y2 - bracketLength / 3,
fill: 'green',
parentId: rack.parentId,
surfaceId: surface.id,
name: 'bracket',
width: bracketLength,
height: bracketLength,
@ -831,6 +989,7 @@ export const useTrestle = () => {
fill: 'green',
name: 'bracket',
parentId: rack.parentId,
surfaceId: surface.id,
width: bracketLength,
height: bracketLength,
selectable: false,
@ -845,9 +1004,10 @@ export const useTrestle = () => {
//랙 없음 인 경우 지지금구 설치
const installBracketWithOutRack = (surface, exposedBottomModules, leftExposedHalfBottomModules, rightExposedHalfBottomPoints, isChidory) => {
let { rackQty, rackIntvlPct, moduleIntvlHor, moduleIntvlVer } = surface.trestleDetail
let { rackQty, rackIntvlPct, moduleIntvlHor, moduleIntvlVer, lessSupFitQty, lessSupFitIntvlPct } = surface.trestleDetail
const direction = surface.direction
rackQty = 3
rackIntvlPct = 10
canvas.renderAll()
exposedBottomModules.forEach((module) => {
@ -990,6 +1150,7 @@ export const useTrestle = () => {
fill: 'green',
name: 'bracket',
parentId: module.id,
surfaceId: module.surfaceId,
width: 10,
height: 10,
selectable: false,
@ -1318,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 }
}

View File

@ -122,40 +122,47 @@ export function usePropertiesSetting(id) {
const handleFix = () => {
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) {
// 세팅이 하나라도 안되어있으면 초기화
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,
})
hideLine(line)
})
const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
wall.lines = [...lines]
const roof = drawRoofPolygon(wall)
setPoints([])
canvas.renderAll()
roof.drawHelpLine()
closePopup(id)
return
} else {
return
}
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
const notSetAttributes = lines.filter((line) => !line.attributes?.type)
if (notSetAttributes.length > 0) {
alert('설정되지 않은 외벽선이 있습니다.')
return
}
lines.forEach((line) => {
line.set({
attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
stroke: '#000000',
strokeWidth: 4,
})
hideLine(line)
})
const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
wall.lines = [...lines]
const roof = drawRoofPolygon(wall)
setPoints([])
canvas.renderAll()
roof.drawHelpLine()
closePopup(id)
}
const closeModal = (fn) => {

View File

@ -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) {
@ -52,6 +54,8 @@ export function useRoofAllocationSetting(id) {
const { setSurfaceShapePattern } = useRoofFn()
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
useEffect(() => {
setCurrentRoofList(roofList)
}, [])
@ -270,6 +274,7 @@ export function useRoofAllocationSetting(id) {
setRoofList(newRoofList)
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial)
modifyModuleSelectionData()
closeAll()
}
@ -369,6 +374,8 @@ export function useRoofAllocationSetting(id) {
closeAll()
setMenuNumber(3)
setMenuType('surface')
modifyModuleSelectionData()
}
const setLineSize = (id, size) => {
@ -500,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,

View File

@ -44,3 +44,8 @@ export const moduleStatisticsState = atom({
},
dangerouslyAllowMutability: true,
})
export const stepUpListDataState = atom({
key: 'stepUpListDataState',
default: [],
})

View File

@ -153,3 +153,25 @@ export const unescapeString = (str) => {
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'
}