diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index a97cb4cb..b5d8bce0 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -1366,6 +1366,9 @@ export default function Estimate({}) { {getMessage('estimate.detail.fileFlg')} + {estimateContextState?.northArrangement === '1' && ( +
{getMessage('estimate.detail.dragFileGuide')}
+ )}
diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index 31698b1a..85315a23 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -28,7 +28,6 @@ export default function CanvasFrame() { const { currentCanvasPlan } = usePlan() const totalDisplay = useRecoilValue(totalDisplaySelector) // 집계표 표시 여부 const { setIsGlobalLoading } = useContext(QcastContext) - const [moduleStatistics, setModuleStatistics] = useRecoilState(moduleStatisticsState) const reset = useResetRecoilState(moduleStatisticsState) const loadCanvas = () => { if (canvas) { diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index 67e2faa1..58cf29b5 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -84,10 +84,6 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { setIsManualModuleSetup(!isManualModuleSetup) } - useEffect(() => { - manualModuleSetup() - }, [isManualModuleSetup]) - const updateObjectDataApi = async (params) => { const res = await updateObjectDate(params) } diff --git a/src/components/floor-plan/modal/basic/step/Module.jsx b/src/components/floor-plan/modal/basic/step/Module.jsx index 4823ab6e..347e4c69 100644 --- a/src/components/floor-plan/modal/basic/step/Module.jsx +++ b/src/components/floor-plan/modal/basic/step/Module.jsx @@ -189,7 +189,7 @@ export default function Module({ setTabNum }) { onChange={(e) => setInputInstallHeight(e.target.value)} />
- mm + m @@ -226,7 +226,7 @@ export default function Module({ setTabNum }) { onChange={(e) => setInputVerticalSnowCover(e.target.value)} /> - mm + cm diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index d7d31ffa..a11ae0f8 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -10,7 +10,7 @@ const Placement = forwardRef((props, refs) => { const [isChidori, setIsChidori] = useState(false) const [isChidoriNotAble, setIsChidoriNotAble] = useState(false) - const [setupLocation, setSetupLocation] = useState('center') + const [setupLocation, setSetupLocation] = useState('eaves') const [isMaxSetup, setIsMaxSetup] = useState('false') const [selectedItems, setSelectedItems] = useState({}) diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index adeb0300..240bc554 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -21,6 +21,7 @@ import { selectedModuleState } from '@/store/selectedModuleOptions' import { v4 as uuidv4 } from 'uuid' import { stepUpListDataState } from '@/store/circuitTrestleAtom' +import { useEstimate } from '@/hooks/useEstimate' const ALLOCATION_TYPE = { AUTO: 'auto', @@ -31,6 +32,7 @@ export default function CircuitTrestleSetting({ id }) { const { closePopup } = usePopup() const { apply } = useTrestle() const { swalFire } = useSwal() + const { saveEstimate } = useEstimate() const canvas = useRecoilValue(canvasState) const [makers, setMakers] = useRecoilState(makersState) @@ -45,7 +47,7 @@ export default function CircuitTrestleSetting({ id }) { const [circuitAllocationType, setCircuitAllocationType] = useState(1) const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const selectedModules = useRecoilValue(selectedModuleState) - const { getPcsAutoRecommendList, getPcsVoltageChk } = useMasterController() + const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList } = useMasterController() // 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가 const [selectedStepUpValues, setSelectedStepUpValues] = useState({}) @@ -61,6 +63,7 @@ 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) @@ -69,6 +72,7 @@ export default function CircuitTrestleSetting({ id }) { } }, [tabNum]) + // 시리즈중 자동으로 추천 PCS 정보 조회 const onAutoRecommend = () => { if (series.filter((s) => s.selected).length === 0) { swalFire({ @@ -85,7 +89,9 @@ export default function CircuitTrestleSetting({ id }) { pcsItemList: getPcsItemList(), } + // 파워컨디셔너 추천 목록 조회 if (selectedModels.length === 0) { + // 시리즈중 자동으로 추천 PCS 정보 조회 getPcsAutoRecommendList(params).then((res) => { if (res.data?.pcsItemList) { const itemList = models.filter((model) => { @@ -98,15 +104,25 @@ export default function CircuitTrestleSetting({ id }) { isUsed: false, } }) + // 회로 구성 가능 여부 체크 요청 파라미터 const pcsVoltageChkParams = { ...getOptYn(), useModuleItemList: getUseModuleItemList(), roofSurfaceList: getRoofSurfaceList(), pcsItemList: getPcsItemList(), } + // 추천 목록 선택 setSelectedModels(selectedModels) + // 회로 구성 가능 여부 체크 getPcsVoltageChk(pcsVoltageChkParams).then((res) => { - setTabNum(2) + if (res.resultCode === 'S') { + setTabNum(2) + } else { + swalFire({ + title: res.resultMsg, + type: 'alert', + }) + } }) } else { // 데이터가 없는 경우 오류 메시지 확인 필요 @@ -124,12 +140,27 @@ export default function CircuitTrestleSetting({ id }) { } }) } else { - getPcsVoltageChk(params).then((res) => { - setTabNum(2) + // 회로 구성 가능 여부 체크 + getPcsVoltageChk({ ...params, pcsItemList: getSelectedPcsItemList() }).then((res) => { + if (res.resultCode === 'S') { + // 회로 구성 가능 여부 체크 통과 시 승압설정 정보 조회 + getPcsVoltageStepUpList({ + ...params, + pcsItemList: getSelectedPcsItemList(), + }).then((res) => { + setTabNum(2) + }) + } else { + swalFire({ + title: res.resultMsg, + type: 'alert', + }) + } }) } } + // 옵션 Y/N const getOptYn = () => { return { maxConnYn: pcsCheck.max ? 'Y' : 'N', @@ -138,6 +169,7 @@ export default function CircuitTrestleSetting({ id }) { } } + // PCS 아이템 목록 const getPcsItemList = () => { return models.map((model) => { return { @@ -148,6 +180,18 @@ export default function CircuitTrestleSetting({ id }) { }) } + // 선택된 PCS 아이템 목록 + const getSelectedPcsItemList = () => { + return selectedModels.map((model) => { + return { + itemId: model.itemId, + pcsMkrCd: model.pcsMkrCd, + pcsSerCd: model.pcsSerCd, + } + }) + } + + // 사용된 모듈아이템 목록 const getUseModuleItemList = () => { return selectedModules.itemList.map((m) => { return { @@ -157,6 +201,7 @@ export default function CircuitTrestleSetting({ id }) { }) } + // 지붕면 목록 const getRoofSurfaceList = () => { const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) roofSurfaceList.sort((a, b) => a.left - b.left || b.top - a.top) @@ -180,6 +225,7 @@ export default function CircuitTrestleSetting({ id }) { }) } + // 모듈 목록 const getModuleList = (surface) => { let moduleList = [] let [xObj, yObj] = [{}, {}] @@ -253,6 +299,40 @@ export default function CircuitTrestleSetting({ id }) { return moduleList } + // 자동할당 버튼 클릭 시 + const onAutoAllocation = () => { + let moduleStdQty = 0 + let moduleMaxQty = 0 + const selectedModels = models.filter((m) => m.selected) + + // 시리즈중 자동으로 추천 PCS 정보 조회 + if (selectedModels.length === 0) { + onAutoRecommend() + } else { + // 모듈 최소 매수 + moduleStdQty = selectedModels.reduce((acc, model) => { + return acc + parseInt(model.moduleStdQty) + }, 0) + moduleMaxQty = selectedModels.reduce((acc, model) => { + return acc + parseInt(model.moduleMaxQty) + }, 0) + } + // const target = pcsCheck.max ? moduleMaxQty : moduleStdQty + // const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) + + // if (placementModules.length > target) { + // swalFire({ + // title: '배치가능 매수를 초과합니다. 파워컨디셔너를 다시 선택해 주세요.', + // type: 'alert', + // }) + // return + // } + + // setAllocationType(ALLOCATION_TYPE.AUTO) + // setTabNum(2) + } + + // 수동할당 버튼 클릭 시 const onPassivityAllocation = () => { if (selectedModels.length === 0) { const params = { @@ -262,6 +342,7 @@ export default function CircuitTrestleSetting({ id }) { pcsItemList: getPcsItemList(), } + // 파워컨디셔너 추천 목록 조회 getPcsAutoRecommendList(params).then((res) => { if (res.data?.pcsItemList) { const itemList = models.filter((model) => { @@ -273,22 +354,28 @@ export default function CircuitTrestleSetting({ id }) { id: uuidv4(), } }) - const PcsVoltageChkParams = { + const pcsVoltageChkParams = { ...getOptYn(), useModuleItemList: getUseModuleItemList(), roofSurfaceList: getRoofSurfaceList(), pcsItemList: getPcsItemList(), } setSelectedModels(selectedModels) - getPcsVoltageChk(PcsVoltageChkParams).then((res) => {}) + getPcsVoltageChk(pcsVoltageChkParams).then((res) => { + setAllocationType(ALLOCATION_TYPE.PASSIVITY) + }) } else { swalFire({ - title: '파워컨디셔너를 추가해 주세요.', + title: res.result.resultMsg, type: 'alert', + confirmFn: () => { + return + }, }) + return } }) - } else if (pcsCheck.max) { + } else { const moduleStdQty = selectedModels.reduce((acc, model) => { return acc + parseInt(model.moduleStdQty) }, 0) @@ -306,9 +393,9 @@ export default function CircuitTrestleSetting({ id }) { }) return } - } - setAllocationType(ALLOCATION_TYPE.PASSIVITY) + setAllocationType(ALLOCATION_TYPE.PASSIVITY) + } } // StepUp에서 선택된 값들을 처리하는 함수 수정 @@ -336,8 +423,10 @@ export default function CircuitTrestleSetting({ id }) { }) const result = await apply() + if (result) { + await saveEstimate(result) + } removeNotAllocationModules() - apply() } const removeNotAllocationModules = () => { @@ -346,6 +435,7 @@ export default function CircuitTrestleSetting({ id }) { canvas.renderAll() } + // 이전 버튼 클릭 시 const onClickPrev = () => { setAllocationType(ALLOCATION_TYPE.AUTO) swalFire({ @@ -367,6 +457,7 @@ export default function CircuitTrestleSetting({ id }) { }) } + // 파워컨디셔너 컴포넌트 속성 const powerConditionalSelectProps = { tabNum, setTabNum, @@ -383,6 +474,7 @@ export default function CircuitTrestleSetting({ id }) { managementState, } + // 수동할당 컴포넌트 속성 const passivityProps = { tabNum, setTabNum, @@ -394,13 +486,18 @@ export default function CircuitTrestleSetting({ id }) { getRoofSurfaceList, } + // 승압설정 컴포넌트 속성 const stepUpProps = { tabNum, setTabNum, models, setModels, + allocationType, circuitAllocationType, setCircuitAllocationType, + selectedModels, + setSelectedModels, + getSelectedPcsItemList, getOptYn, // 옵션 Y/N getUseModuleItemList, // 사용된 모듈아이템 List getRoofSurfaceList, // 지붕면 목록 @@ -410,8 +507,10 @@ export default function CircuitTrestleSetting({ id }) { setStepUpListData, seletedOption, setSeletedOption, + getModuleList, } + // 승압설정 목록 조회 const getStepUpListData = () => { return stepUpListData[0].pcsItemList.map((item) => { return item.serQtyList @@ -422,7 +521,6 @@ export default function CircuitTrestleSetting({ id }) { pcsSerCd: item.pcsSerCd, pcsItemId: item.itemId, pscOptCd: seletedOption.code, - // pcsOptCd: 'CLC_RMC', paralQty: serQty.paralQty, connections: [ { @@ -434,12 +532,65 @@ export default function CircuitTrestleSetting({ id }) { }) } + // 닫기 버튼 클릭 시 처리하는 함수 추가 + const handleClose = () => { + // // 회로 번호 텍스트 제거 + // const circuitTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber') + // canvas.remove(...circuitTexts) + + // // 모듈의 회로 정보 초기화 + // canvas + // .getObjects() + // .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + // .forEach((obj) => { + // obj.circuit = null + // obj.pcsItemId = null + // obj.circuitNumber = null + // }) + + // canvas.renderAll() + // closePopup(id) + + swalFire({ + title: '변경사항을 저장하시겠습니까?', + //text: '저장하지 않은 변경사항은 모두 사라집니다.', + type: 'confirm', + confirmButtonText: '저장', + cancelButtonText: '취소', + icon: 'warning', + confirmFn: async () => { + // 저장 로직 실행 + await onApply() + closePopup(id) + }, + denyFn: () => { + // 회로 번호 텍스트 제거 + const circuitTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber') + canvas.remove(...circuitTexts) + + // 모듈의 회로 정보 초기화 + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE) + .forEach((obj) => { + obj.circuit = null + obj.pcsItemId = null + obj.circuitNumber = null + }) + + canvas.renderAll() + closePopup(id) + }, + }) + } + return (

{getMessage('modal.circuit.trestle.setting')}

-
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx index 7d2da472..65e35583 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx @@ -10,16 +10,29 @@ import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupSta import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom' import { useMasterController } from '@/hooks/common/useMasterController' import { v4 as uuidv4 } from 'uuid' +import { globalLocaleStore } from '@/store/localeAtom' +import { POLYGON_TYPE } from '@/common/common' export default function StepUp(props) { - const { stepUpListData, setStepUpListData, seletedOption, setSeletedOption } = props + const { + models, + allocationType, + stepUpListData, + setStepUpListData, + seletedOption, + setSeletedOption, + selectedModels, + setSelectedModels, + getSelectedPcsItemList, + getModuleList, + } = props const { getMessage } = useMessage() + const globalLocale = useRecoilValue(globalLocaleStore) const [moduleTab, setModuleTab] = useState(1) const [moduleTabs, setModuleTabs] = useState({}) const [arrayLength, setArrayLength] = useState(3) //module-table-inner의 반복 개수 const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState) - const { models } = props - const { getPcsVoltageStepUpList, getPcsAutoRecommendList } = useMasterController() + const { getPcsVoltageStepUpList, getPcsAutoRecommendList, getPcsVoltageChk } = useMasterController() const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const canvas = useRecoilValue(canvasState) const selectedModules = useRecoilValue(selectedModuleState) @@ -39,34 +52,55 @@ export default function StepUp(props) { useEffect(() => { // PCS 승압설정 정보 조회 - fetchStepUpData() + if (allocationType === 'auto') { + fetchStepUpData() + } else { + // 1-1 2-2 + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuit) + .map((module) => module.circuitNumber) + } }, []) // PCS 승압설정 정보 조회 const fetchStepUpData = async () => { try { const params = { - useYn: props.getOptYn(), // 옵션 Y/N + ...props.getOptYn(), // 옵션 Y/N useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록 - pcsItemList: props.getPcsItemList(), // PCS 아이템 목록 + pcsItemList: selectedModels.length === 0 ? props.getPcsItemList() : getSelectedPcsItemList(), // PCS 아이템 목록 } - // PCS 승압설정 정보 조회 - const res = await getPcsVoltageStepUpList(params) + // 회로 구성 가능 여부 체크 + getPcsVoltageChk({ ...params, pcsItemList: getSelectedPcsItemList() }).then((res) => { + if (res.resultCode === 'S') { + // 회로 구성 가능 여부 체크 통과 시 승압설정 정보 조회 + getPcsVoltageStepUpList(params).then((res) => { + if (res?.result.code === 200 && res?.data) { + if (selectedModels.length === 0) { + setSelectedModels(res.data.pcsItemList) + } + const dataArray = Array.isArray(res.data) ? res.data : [res.data] + const stepUpListData = formatStepUpListData(dataArray) - if (res?.result.code === 200 && res?.data) { - const dataArray = Array.isArray(res.data) ? res.data : [res.data] - const stepUpListData = formatStepUpListData(dataArray) + // PCS 승압설정 정보 SET + setStepUpListData(stepUpListData) - // PCS 승압설정 정보 SET - setStepUpListData(stepUpListData) - - // PCS 옵션 조회 - const formattedOptCodes = formatOptionCodes(res.data.optionList) - setOptCodes(formattedOptCodes) - setSeletedOption(formattedOptCodes[0]) - } + // PCS 옵션 조회 + const formattedOptCodes = formatOptionCodes(res.data.optionList) + setOptCodes(formattedOptCodes) + setSeletedOption(formattedOptCodes[0]) + } + }) + } else { + swalFire({ + title: res.resultMsg, + type: 'alert', + }) + } + }) } catch (error) { console.error('Error fetching step up data:', error) } @@ -121,6 +155,7 @@ export default function StepUp(props) { }) }) + // 초기 추천 값들을 selectedValues에 저장 setSelectedValues(initialSelectedValues) return formattedData @@ -212,17 +247,57 @@ export default function StepUp(props) { } item.selected = index === subIdx }) + // 선택된 행 정보 저장 setStepUpListData(tempStepUpListData) console.log('🚀 ~ handleRowClick ~ tempStepUpListData:', tempStepUpListData) console.log('🚀 ~ handleRowClick ~ selectedData:', selectedData) + // 파워컨디셔너 옵션 조회 요청 파라미터 + const params = { + ...props.getOptYn(), // 옵션 Y/N + useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List + roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록 + pcsItemList: props.getSelectedPcsItemList().map((pcsItem) => { + // PCS 아이템 목록 + // tempStepUpListData에서 해당 PCS 아이템 찾기 + const matchingPcsItem = tempStepUpListData[0].pcsItemList.find((item) => item.pcsId === pcsItem.pcsId && item.itemId === pcsItem.itemId) + + // 선택된 serQty 찾기 + const selectedSerQty = matchingPcsItem?.serQtyList.find((serQty) => serQty.selected)?.serQty || 0 + + return { + ...pcsItem, + applySerQty: selectedSerQty, + } + }), + } + + // PCS 승압설정 정보 조회 + //const res = await getPcsVoltageStepUpList(params) + //getPcsManualConfChk(params).then((res) => { + getPcsVoltageStepUpList(params).then((res) => { + if (res?.result.code === 200 && res?.data) { + const dataArray = Array.isArray(res.data) ? res.data : [res.data] + const stepUpListData = formatStepUpListData(dataArray) + + // PCS 승압설정 정보 SET + setStepUpListData(stepUpListData) + + // PCS 옵션 조회 + const formattedOptCodes = formatOptionCodes(res.data.optionList) + setOptCodes(formattedOptCodes) + setSeletedOption(formattedOptCodes[0]) + } + }) + selectedData.roofSurfaceList.forEach((roofSurface) => { const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] const moduleIds = targetSurface.modules.map((module) => { return module.id }) + // 모듈 목록 삭제 canvas .getObjects() .filter((obj) => moduleIds.includes(obj.parentId)) @@ -230,7 +305,9 @@ export default function StepUp(props) { canvas.remove(text) }) + // 모듈 목록 추가 canvas.renderAll() + roofSurface.moduleList.forEach((module) => { const targetModule = canvas.getObjects().filter((obj) => obj.id === module.uniqueId)[0] const moduleCircuitText = new fabric.Text(module.circuit, { @@ -415,8 +492,11 @@ export default function StepUp(props) {
{/* */} { + return { ...roof, name: globalLocale === 'ko' ? roof.name : roof.nameJp } + })} + title={globalLocale === 'ko' ? optCodes[0].name : optCodes[0].nameJp} value={seletedOption} sourceKey="code" targetKey="code" diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 7cbca2da..aa151d9c 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -1,6 +1,7 @@ import { GlobalDataContext } from '@/app/GlobalDataProvider' import { POLYGON_TYPE } from '@/common/common' import { useMasterController } from '@/hooks/common/useMasterController' +import { useModule } from '@/hooks/module/useModule' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' import { canvasState } from '@/store/canvasAtom' @@ -11,37 +12,29 @@ import { useRecoilState, useRecoilValue } from 'recoil' export default function PassivityCircuitAllocation(props) { const { - tabNum, - setTabNum, selectedModels, setSelectedModels, getOptYn: getApiProps, getUseModuleItemList: getSelectedModuleList, getSelectModelList: getSelectModelList, - getRoofSurfaceList, - getModelList, } = props const { swalFire } = useSwal() const { getMessage } = useMessage() const canvas = useRecoilValue(canvasState) const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const selectedModules = useRecoilValue(selectedModuleState) - const [moduleStatistics, setModuleStatistics] = useRecoilState(moduleStatisticsState) - // const [totalWpout, setTotalWpout] = useState(0) const [selectedPcs, setSelectedPcs] = useState(selectedModels[0]) - // const { header, rows: row } = moduleStatistics - const [header, setHeader] = useState(moduleStatistics.header) - const [rows, setRows] = useState(moduleStatistics.rows) - const [footer, setFooter] = useState(['합계']) + const { header, rows, footer } = useRecoilValue(moduleStatisticsState) const [circuitNumber, setCircuitNumber] = useState(1) const [targetModules, setTargetModules] = useState([]) + const { setModuleStatisticsData } = useModule() const { getPcsManualConfChk } = useMasterController() useEffect(() => { console.log('header, rows', header, rows) console.log('selectedModels', selectedModels) // setSurfaceInfo() - setTableData() + setModuleStatisticsData() if (!managementState) { setManagementState(managementStateLoaded) } @@ -158,7 +151,14 @@ export default function PassivityCircuitAllocation(props) { } const handleCircuitNumberFix = () => { - let uniqueCircuitNumbers = null + let uniqueCircuitNumbers = [ + ...new Set( + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuitNumber) + .map((obj) => obj.circuitNumber), + ), + ] if (!circuitNumber || circuitNumber === 0) { swalFire({ text: '회로번호를 1 이상입력해주세요.', @@ -174,15 +174,6 @@ export default function PassivityCircuitAllocation(props) { }) return } else if (selectedModels.length > 1) { - 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 ( @@ -335,7 +326,7 @@ export default function PassivityCircuitAllocation(props) { setTargetModules([]) setCircuitNumber(+circuitNumber + 1) - setTableData() + setModuleStatisticsData() }) } @@ -347,100 +338,6 @@ export default function PassivityCircuitAllocation(props) { } } - const setTableData = () => { - const tempHeader = [ - { name: getMessage('simulator.table.sub1'), prop: 'name' }, - { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' }, - ...selectedModules.itemList.map((module) => { - return { - name: module.itemNm, - prop: module.itemId, - } - }), - { name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`, prop: '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) - }) - - setHeader(tempHeader) - setRows(tempRows.filter((row) => row.wpOut !== 0)) - setFooter(tempFooter) - setModuleStatistics({ header: tempHeader, rows: tempRows.filter((row) => row.wpOut !== 0), footer: tempFooter }) - } - const initSelectedPcsCircuitNumber = () => { swalFire({ title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.init.info'), @@ -516,9 +413,7 @@ export default function PassivityCircuitAllocation(props) { {header.map((header, i) => ( - {typeof footer[header.prop] === 'number' - ? footer[header.prop].toLocaleString('ko-KR', { maximumFractionDigits: 4 }) - : footer[header.prop]} + {footer[header.prop]} ))} diff --git a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx index 5bfad3e4..88188887 100644 --- a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx @@ -45,175 +45,188 @@ export default function ContextRoofAllocationSetting(props) { return (
-
-

{getMessage('plan.menu.estimate.roof.alloc')}

- -
-
-
{getMessage('modal.roof.alloc.info')}
-
- {getMessage('modal.roof.alloc.select.roof.material')} -
- { - // const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id) - setCurrentRoofMaterial(e) - }} - showKey={'roofMatlNm'} - sourceKey={'roofMatlCd'} - targetKey={'roofMatlCd'} - /> + {currentRoofList && ( + <> +
+

{getMessage('plan.menu.estimate.roof.alloc')}

+
- -
-
- {currentRoofList.length > 0 && - currentRoofList.map((roof, index) => { - return ( -
-
- - -
-
-
-
-
- handleChangeRoofMaterial(e, index)} - /> -
- {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} - {index !== 0 && } +
+
{getMessage('modal.roof.alloc.info')}
+
+ {getMessage('modal.roof.alloc.select.roof.material')} +
+ { + // const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id) + setCurrentRoofMaterial(e) + }} + showKey={'roofMatlNm'} + sourceKey={'roofMatlCd'} + targetKey={'roofMatlCd'} + /> +
+ +
+
+
+ {currentRoofList.map((roof, index) => { + return ( +
+
+ +
-
-
-
- {getMessage('slope')} -
- { - handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index) - }} - defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} - /> -
- {pitchText} -
-
- {(roof.widAuth || roof.lenAuth) && ( -
- {roof.widAuth && ( +
+
- W -
- +
+ handleChangeRoofMaterial(e, index)} + />
+ {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} + {index !== 0 && ( + + + + )}
- )} - {roof.lenAuth && ( +
+
- L -
- + {getMessage('slope')} +
+ { + handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index) + }} + defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + />
+ {pitchText}
- )} -
- )} - {(roof.raftAuth || roof.roofPchAuth) && ( -
- {roof.raftAuth && ( -
-
- {getMessage('modal.placement.initial.setting.rafter')} - {raftCodes.length > 0 && ( -
- +
+ {(roof.widAuth || roof.lenAuth) && ( + <> + {roof.widAuth && ( +
+
+ W +
+ +
- )} -
-
- )} - {roof.roofPchAuth && ( -
-
- {getMessage('hajebichi')} -
-
-
-
+ )} + {roof.lenAuth && ( +
+
+ L +
+ +
+
+
+ )} + )} -
- )} -
-
- - + {(roof.raftAuth || roof.roofPchAuth) && ( + <> + {roof.raftAuth && ( +
+
+ {getMessage('modal.placement.initial.setting.rafter')} + {raftCodes.length > 0 && ( +
+ +
+ )} +
+
+ )} + {roof.roofPchAuth && ( +
+
+ {getMessage('hajebichi')} +
+ +
+
+
+ )} + + )} +
+
+ + +
+
-
-
- ) - })} -
-
- -
-
+ ) + })} +
+
+
+ +
+
+ + )}
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 191b3156..fe8fea47 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -411,11 +411,12 @@ export default function StuffDetail() { if (session?.storeId === 'T01') { url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}` } else { - if (session.storeLvl === '1') { - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` - } else { - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` - } + // if (session.storeLvl === '1') { + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` + // } else { + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` + // } + url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } get({ url: url }).then((res) => { @@ -523,11 +524,12 @@ export default function StuffDetail() { if (session?.storeId === 'T01') { url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}` } else { - if (session.storeLvl === '1') { - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` - } else { - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` - } + // if (session.storeLvl === '1') { + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` + // } else { + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` + // } + url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } get({ url: url }).then((res) => { if (!isEmptyArray(res)) { diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 62b75483..5021548d 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -474,12 +474,13 @@ export default function StuffSearchCondition() { //T01일떄 url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}` } else { - if (session.storeLvl === '1') { - //T01아닌 1차점일때 - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` - } else { - url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` - } + // if (session.storeLvl === '1') { + // //T01아닌 1차점일때 + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` + // } else { + // url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` + // } + url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}` } get({ url: url }).then((res) => { diff --git a/src/hooks/common/useMasterController.js b/src/hooks/common/useMasterController.js index f2ca3adf..85236e9c 100644 --- a/src/hooks/common/useMasterController.js +++ b/src/hooks/common/useMasterController.js @@ -201,13 +201,22 @@ export function useMasterController() { * @returns */ const getPcsVoltageStepUpList = async (params2 = null) => { + // roofSurfaceList의 moduleList에서 circuit 속성을 제외 + const modifiedRoofSurfaceList = params2.roofSurfaceList.map((surface) => ({ + ...surface, + moduleList: surface.moduleList.map((module) => ({ + itemId: module.itemId, + uniqueId: module.uniqueId, + })), + })) + const params = { ...params2, - maxConnYn: params2.useYn.maxConnYn, - smpCirYn: params2.useYn.smpCirYn, - coldZoneYn: params2.useYn.coldZoneYn, + maxConnYn: params2.maxConnYn, + smpCirYn: params2.smpCirYn, + coldZoneYn: params2.coldZoneYn, useModuleItemList: params2.useModuleItemList, - roofSurfaceList: params2.roofSurfaceList, + roofSurfaceList: modifiedRoofSurfaceList, pcsItemList: params2.pcsItemList, } diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index ebd1ad88..7654f3ba 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -80,7 +80,6 @@ export const useEstimateController = (planNo) => { res.data.pkgAsp = roundedNumber.toString() } - setEstimateContextState(res.data) } } @@ -155,7 +154,7 @@ export const useEstimateController = (planNo) => { }) .catch((error) => { console.log('::FileDownLoad Error::', error) - alert('File does not exist.') + return swalFire({ text: getMessage('File does not exist'), type: 'alert' }) }) } @@ -169,19 +168,19 @@ export const useEstimateController = (planNo) => { if (estimateData?.charger === null || estimateData?.charger?.trim().length === 0) { flag = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredCharger')) + return swalFire({ text: getMessage('estimate.detail.save.requiredCharger'), type: 'alert' }) } if (estimateData?.objectName === null || estimateData?.objectName?.trim().length === 0) { flag = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredObjectName')) + return swalFire({ text: getMessage('estimate.detail.save.requiredObjectName'), type: 'alert' }) } if (isNaN(Date.parse(estimateData.estimateDate))) { flag = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredEstimateDate')) + return swalFire({ text: getMessage('estimate.detail.save.requiredEstimateDate'), type: 'alert' }) } if (estimateData.estimateType === 'YJSS') { @@ -189,7 +188,7 @@ export const useEstimateController = (planNo) => { if (pkgAsp === '0') { flag = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredPkgAsp')) + return swalFire({ text: getMessage('estimate.detail.save.requiredPkgAsp'), type: 'alert' }) } } @@ -209,6 +208,14 @@ export const useEstimateController = (planNo) => { //기존에 첨부된 파일이 없으면 if (isEmptyArray(estimateData.newFileList)) { //새로 첨부한 파일이 없으면 + + //북면 먼저 체크 + if (estimateData?.northArrangement === '1') { + fileFlg = false + setIsGlobalLoading(false) + return swalFire({ text: getMessage('estimate.detail.save.requiredNorthArrangementFileUpload'), type: 'alert' }) + } + if (estimateData.itemList.length > 1) { estimateData.itemList.map((row) => { if (row.delFlg === '0') { @@ -217,7 +224,7 @@ export const useEstimateController = (planNo) => { if (estimateData.fileFlg === '0') { fileFlg = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredFileUpload')) + return swalFire({ text: getMessage('estimate.detail.save.requiredFileUpload'), type: 'alert' }) } } } @@ -235,7 +242,7 @@ export const useEstimateController = (planNo) => { if (item.itemId === '') { itemFlg = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredItemId')) + return swalFire({ text: getMessage('estimate.detail.save.requiredItemId'), type: 'alert' }) } } @@ -251,7 +258,7 @@ export const useEstimateController = (planNo) => { if (item.amount < 1) { itemFlg = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredAmount')) + return swalFire({ text: getMessage('estimate.detail.save.requiredAmount'), type: 'alert' }) } if (estimateData.estimateType !== 'YJSS') { @@ -263,7 +270,7 @@ export const useEstimateController = (planNo) => { if (item.salePrice < 1) { itemFlg = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredSalePrice')) + return swalFire({ text: getMessage('estimate.detail.save.requiredSalePrice'), type: 'alert' }) } } @@ -274,7 +281,7 @@ export const useEstimateController = (planNo) => { if (isNaN(item.salePrice)) { itemFlg = false setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredSalePrice')) + return swalFire({ text: getMessage('estimate.detail.save.requiredSalePrice'), type: 'alert' }) } } } @@ -292,7 +299,7 @@ export const useEstimateController = (planNo) => { }) if (delCnt === estimateData.itemList.length) { setIsGlobalLoading(false) - return alert(getMessage('estimate.detail.save.requiredItem')) + return swalFire({ text: getMessage('estimate.detail.save.requiredItem'), type: 'alert' }) } } diff --git a/src/hooks/module/useModule.js b/src/hooks/module/useModule.js index de64c404..80aa17d7 100644 --- a/src/hooks/module/useModule.js +++ b/src/hooks/module/useModule.js @@ -1,12 +1,14 @@ import { BATCH_TYPE, POLYGON_TYPE } from '@/common/common' import { canvasState } from '@/store/canvasAtom' import { isOverlap, polygonToTurfPolygon, rectToPolygon } from '@/util/canvas-util' -import { useRecoilValue } from 'recoil' +import { useRecoilValue, useSetRecoilState } from 'recoil' import { v4 as uuidv4 } from 'uuid' import * as turf from '@turf/turf' import { useSwal } from '../useSwal' import { useModuleBasicSetting } from './useModuleBasicSetting' import { useMessage } from '../useMessage' +import { selectedModuleState } from '@/store/selectedModuleOptions' +import { moduleStatisticsState } from '@/store/circuitTrestleAtom' export const MODULE_REMOVE_TYPE = { LEFT: 'left', @@ -35,6 +37,8 @@ export function useModule() { const { swalFire } = useSwal() const { getMessage } = useMessage() const { checkModuleDisjointObjects } = useModuleBasicSetting() + const selectedModules = useRecoilValue(selectedModuleState) + const setModuleStatistics = useSetRecoilState(moduleStatisticsState) const moduleMove = (length, direction) => { const selectedObj = canvas.getActiveObjects() //선택된 객체들을 가져옴 @@ -929,6 +933,92 @@ export function useModule() { .filter((obj) => [BATCH_TYPE.OPENING, BATCH_TYPE.TRIANGLE_DORMER, BATCH_TYPE.PENTAGON_DORMER, BATCH_TYPE.SHADOW].includes(obj.name)) } + const setModuleStatisticsData = () => { + const tempHeader = [ + { name: getMessage('simulator.table.sub1'), prop: 'name' }, + { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' }, + ...selectedModules.itemList.map((module) => { + return { + name: module.itemNm, + prop: module.itemId, + } + }), + { name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`, prop: 'wpOut' }, + ] + const surfaceObjects = {} + const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + const rows = surfaces.map((surface) => { + 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]-- + } + }) + }) + let tempRows = [] + Object.keys(surfaceObjects).forEach((key) => { + let tempRow = { + name: surfaceObjects[key].roofSurface, + circuit: surfaceObjects[key].circuit, + wpOut: parseInt((surfaceObjects[key].wpOut / 1000).toFixed(3)), + } + 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: parseInt((surfaceObjects[key].circuits[circuit].circuits.wpOut / 1000).toFixed(3)), + } + selectedModules.itemList.forEach((module) => { + row[module.itemId] = surfaceObjects[key].circuits[circuit].circuits[module.itemId] + }) + tempRows.push(row) + }) + }) + + const tempFooter = { + name: getMessage('modal.panel.batch.statistic.total'), + 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) + }) + setModuleStatistics({ header: tempHeader, rows: tempRows.filter((row) => row.wpOut !== 0), footer: tempFooter }) + } + return { moduleMove, moduleMultiMove, @@ -942,5 +1032,6 @@ export function useModule() { muduleRowInsert, modulesRemove, alignModule, + setModuleStatisticsData, } } diff --git a/src/hooks/module/useModuleBasicSetting.js b/src/hooks/module/useModuleBasicSetting.js index 67a5e467..1462fef5 100644 --- a/src/hooks/module/useModuleBasicSetting.js +++ b/src/hooks/module/useModuleBasicSetting.js @@ -324,6 +324,18 @@ export function useModuleBasicSetting(tabNum) { }) } + useEffect(() => { + console.log('리코일 바뀌냐??') + console.log('isManualModuleSetup', isManualModuleSetup) + console.log('saleStoreNorthFlg', saleStoreNorthFlg) + + if (moduleSelectionData.common.saleStoreNorthFlg === '1') { + setSaleStoreNorthFlg(true) + } + + manualModuleSetup() + }, [isManualModuleSetup]) + /** * trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인 * 확인 후 셀을 이동시킴 @@ -364,7 +376,7 @@ export function useModuleBasicSetting(tabNum) { lockRotation: true, // 회전 잠금 lockScalingX: true, // X 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금 - name: 'module', + name: POLYGON_TYPE.MODULE, } if (moduleSetupSurfaces.length !== 0) { @@ -429,6 +441,10 @@ export function useModuleBasicSetting(tabNum) { parentId: moduleSetupSurfaces[i].parentId, }) + console.log('trestlePolygon', trestlePolygon) + console.log('saleStoreNorthFlg', saleStoreNorthFlg) + console.log('trestlePolygon.isNorth', trestlePolygon.isNorth) + //북면이고 북면설치상점이 아니면 그냥 return if (trestlePolygon.isNorth && !saleStoreNorthFlg) { return @@ -646,13 +662,15 @@ export function useModuleBasicSetting(tabNum) { }) } } else { - //수동모드 해제시 모듈 설치면 선택 잠금 - moduleSetupSurfaces.forEach((obj) => { - obj.set({ - selectable: true, - evented: true, + if (moduleSetupSurfaces) { + //수동모드 해제시 모듈 설치면 선택 잠금 + moduleSetupSurfaces.forEach((obj) => { + obj.set({ + selectable: true, + evented: true, + }) }) - }) + } removeMouseEvent('mouse:up') removeMouseEvent('mouse:move') @@ -1693,7 +1711,7 @@ export function useModuleBasicSetting(tabNum) { lockScalingY: true, // Y 축 크기 조정 잠금 parentId: moduleSetupSurface.parentId, surfaceId: moduleSetupSurface.id, - name: 'module', + name: POLYGON_TYPE.MODULE, } if (moduleSetupSurfaces.length !== 0) { @@ -2102,7 +2120,7 @@ export function useModuleBasicSetting(tabNum) { lockScalingY: true, // Y 축 크기 조정 잠금 parentId: moduleSetupSurface.parentId, surfaceId: moduleSetupSurface.id, - name: 'module', + name: POLYGON_TYPE.MODULE, } let leftMargin, bottomMargin, square @@ -2450,7 +2468,7 @@ export function useModuleBasicSetting(tabNum) { ...surface, name: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].directionText, // 지붕면 // powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }), - wpOut: wpOut, + wpOut: (wpOut / 1000).toFixed(3), } }) @@ -2463,7 +2481,7 @@ export function useModuleBasicSetting(tabNum) { }), { name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`, prop: 'wpOut' }, ] - let footer = ['합계'] + let footer = [getMessage('modal.panel.batch.statistic.total')] let footerData = {} rows.forEach((row) => { Object.keys(moduleInfo).map((key) => { @@ -2474,7 +2492,7 @@ export function useModuleBasicSetting(tabNum) { Object.keys(footerData).forEach((key) => { footer.push(footerData[key]) }) - footer.push(totalWpout) + footer.push((totalWpout / 1000).toFixed(3)) console.log({ header: header, rows, footer: footer }) setModuleStatistics({ header: header, rows, footer: footer }) } diff --git a/src/hooks/module/useModuleSelection.js b/src/hooks/module/useModuleSelection.js index d0b812e5..3208a71a 100644 --- a/src/hooks/module/useModuleSelection.js +++ b/src/hooks/module/useModuleSelection.js @@ -89,11 +89,12 @@ export function useModuleSelection(props) { getModuleData(roofsIds) - //메뉴 이동시 배치면 삭제 - const moduleSurfacesArray = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + //해당 메뉴 이동시 배치면 삭제 + const moduleSurfacesArray = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE || obj.name === POLYGON_TYPE.MODULE) if (moduleSurfacesArray.length > 0) { moduleSurfacesArray.forEach((moduleSurface) => { - moduleSurface.module = [] canvas.remove(moduleSurface) }) canvas.renderAll() diff --git a/src/hooks/module/useTrestle.js b/src/hooks/module/useTrestle.js index 083c24c3..9c580971 100644 --- a/src/hooks/module/useTrestle.js +++ b/src/hooks/module/useTrestle.js @@ -1,18 +1,16 @@ -import { useRecoilState, useRecoilValue } from 'recoil' +import { useRecoilValue } from 'recoil' import { canvasState, currentAngleTypeSelector } 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' import { useMasterController } from '@/hooks/common/useMasterController' -import { estimateParamAtom } from '@/store/estimateAtom' // 회로 및 가대설정 export const useTrestle = () => { const canvas = useRecoilValue(canvasState) const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터 const { getQuotationItem } = useMasterController() - const [estimateParam, setEstimateParam] = useRecoilState(estimateParamAtom) const currentAngleType = useRecoilValue(currentAngleTypeSelector) const apply = () => { @@ -41,6 +39,7 @@ export const useTrestle = () => { return } + const plvrYn = construction.plvrYn let moduleRowsTotCnt = 0 let isEaveBar = construction.setupCover let isSnowGuard = construction.setupSnowCover @@ -102,6 +101,14 @@ export const useTrestle = () => { leftExposedHalfTopModules.length > 0 || rightExposedHalfTopPoints.length > 0 + console.log('isChidory', isChidory) + + if (plvrYn === 'N' && isChidory) { + alert('치조불가공법입니다.') + clear() + throw new Error('치조불가공법입니다.') + } + surface.set({ isChidory: isChidory }) canvas @@ -210,6 +217,10 @@ export const useTrestle = () => { let findLeft = true let findRight = true + let leftFindModuleList = [module] + let rightFindModuleList = [module] + let centerFindModuleList = [module] + //우선 절반을 나눈 뒤 왼쪽부터 찾는다. while (hasNextModule) { //바로 위에 있는지 확인한다. @@ -218,6 +229,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. leftRows++ + leftFindModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -233,6 +245,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. leftRows++ + leftFindModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -253,6 +266,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. rightRows++ + rightFindModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -268,6 +282,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. rightRows++ + rightFindModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -287,6 +302,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. + centerFindModuleList.push(nextModule) centerRows++ x = nextModule.x y = nextModule.y @@ -295,19 +311,77 @@ export const useTrestle = () => { } } + const leftModuleInfos = leftFindModuleList.map((module) => { + return { + moduleTpCd: module.moduleInfo.moduleTpCd, + } + }) + + const rightModuleInfos = rightFindModuleList.map((module) => { + return { + moduleTpCd: module.moduleInfo.moduleTpCd, + } + }) + + const centerModuleInfos = centerFindModuleList.map((module) => { + return { + moduleTpCd: module.moduleInfo.moduleTpCd, + } + }) + + const leftRowsInfo = moduleTransformData(leftModuleInfos) + const rightRowsInfo = moduleTransformData(rightModuleInfos) + const centerRowsInfo = moduleTransformData(centerModuleInfos) + // 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다. const leftRacks = rackInfos.find((rack) => { - return rack.value.moduleRows === leftRows + if (leftRowsInfo.rowsInfo.length === 1) { + return ( + rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && + rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) + ) + } else { + return ( + rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && + rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + rack.value.moduleTpRows1 === leftRowsInfo.rowsInfo[0].count && + rack.value.moduleTpRows2 === leftRowsInfo.rowsInfo[1].count + ) + } })?.value.racks // 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다. const rightRacks = rackInfos.find((rack) => { - return rack.value.moduleRows === rightRows + if (rightRowsInfo.rowsInfo.length === 1) { + return ( + rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && + rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) + ) + } else { + return ( + rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && + rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + rack.value.moduleTpRows1 === rightRowsInfo.rowsInfo[0].count && + rack.value.moduleTpRows2 === rightRowsInfo.rowsInfo[1].count + ) + } })?.value.racks // 해당 rack으로 그려준다. const centerRacks = rackInfos.find((rack) => { - return rack.value.moduleRows === centerRows + if (centerRowsInfo.rowsInfo.length === 1) { + return ( + rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp && + rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) + ) + } else { + return ( + rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp && + rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + rack.value.moduleTpRows1 === centerRowsInfo.rowsInfo[0].count && + rack.value.moduleTpRows2 === centerRowsInfo.rowsInfo[1].count + ) + } })?.value.racks mostRowsModule = Math.max(leftRows, rightRows, centerRows, mostRowsModule) @@ -336,6 +410,7 @@ export const useTrestle = () => { let leftRows = 1 let hasNextModule = true let findLeft = true + let findModuleList = [module] //우선 절반을 나눈 뒤 왼쪽부터 찾는다. while (hasNextModule) { @@ -345,6 +420,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. leftRows++ + findModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -371,6 +447,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. leftRows++ + findModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -379,10 +456,30 @@ export const useTrestle = () => { } } + const leftModuleInfos = findModuleList.map((module) => { + return { + moduleTpCd: module.moduleInfo.moduleTpCd, + } + }) + const leftRowsInfo = moduleTransformData(leftModuleInfos) + // 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다. const leftRacks = rackInfos.find((rack) => { - return rack.value.moduleRows === leftRows + if (leftRowsInfo.rowsInfo.length === 1) { + return ( + rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && + rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) + ) + } else { + return ( + rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp && + rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + rack.value.moduleTpRows1 === leftRowsInfo.rowsInfo[0].count && + rack.value.moduleTpRows2 === leftRowsInfo.rowsInfo[1].count + ) + } })?.value.racks + mostRowsModule = Math.max(leftRows, mostRowsModule) if (rackYn === 'Y') { drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L', rackYn) @@ -400,6 +497,7 @@ export const useTrestle = () => { let rightRows = 1 let hasNextModule = true let findRight = true + let findModuleList = [module] // 오른쪽 찾는다. while (hasNextModule) { @@ -409,6 +507,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. rightRows++ + findModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -424,6 +523,7 @@ export const useTrestle = () => { if (nextModule) { // 바로 위 모듈을 찾는다. rightRows++ + findModuleList.push(nextModule) x = nextModule.x y = nextModule.y } else { @@ -432,11 +532,30 @@ export const useTrestle = () => { } } + const rightRowsInfos = findModuleList.map((module) => { + return { + moduleTpCd: module.moduleInfo.moduleTpCd, + } + }) + + const rightRowsInfo = moduleTransformData(rightRowsInfos) + // 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다. const rightRacks = rackInfos.find((rack) => { - return rack.value.moduleRows === rightRows + if (rightRowsInfo.rowsInfo.length === 1) { + return ( + rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && + rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) + ) + } else { + return ( + rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp && + rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) && + rack.value.moduleTpRows1 === rightRowsInfo.rowsInfo[0].count && + rack.value.moduleTpRows2 === rightRowsInfo.rowsInfo[1].count + ) + } })?.value.racks - mostRowsModule = Math.max(rightRows, mostRowsModule) // 해당 rack으로 그려준다. if (rackYn === 'Y') { @@ -462,10 +581,24 @@ export const useTrestle = () => { return setEstimateData() } catch (e) { - return false + return null } } + //module Rack 정보를 얻기위한 데이터 가공 + function moduleTransformData(arr) { + let counts = {} + + arr.forEach((item) => { + counts[item.moduleTpCd] = (counts[item.moduleTpCd] || 0) + 1 + }) + + let moduleTotalTp = Object.keys(counts).join('') + let rowsInfo = Object.entries(counts).map(([moduleTpCd, count]) => ({ moduleTpCd, count })) + + return { moduleTotalTp, rowsInfo } + } + // itemList 조회 후 estimateParam에 저장 const setEstimateData = async () => { const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) @@ -480,7 +613,7 @@ export const useTrestle = () => { //견적서 itemList 조회 const res = await getQuotationItem(params) if (!res.data) { - return false + return null } const itemList = res.data //northArrangement 북면 설치 여부 @@ -540,10 +673,10 @@ export const useTrestle = () => { } }) - setEstimateParam({ ...estimateParam, itemList, northArrangement, roofSurfaceList, circuitItemList }) + const estimateParam = { itemList, northArrangement, roofSurfaceList, circuitItemList } // 정상적으로 완료 되면 true 반환 - return true + return estimateParam } const getNorthArrangement = () => { @@ -565,9 +698,11 @@ export const useTrestle = () => { } const findNextModule = (currentPoint, centerPoints, direction) => { - let { x, y, width, height, horizontal, vertical } = { ...currentPoint } - width = width + horizontal - height = height + vertical + let { x, y, horizontal, vertical } = { ...currentPoint } + let { widthArr, heightArr } = centerPoints[0] + + let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal + let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical let maxX = 2 + horizontal * 3 let maxY = 2 + vertical * 3 @@ -596,7 +731,11 @@ export const useTrestle = () => { } const findNextLeftModule = (currentPoint, centerPoints, direction) => { - let { x, y, width, height, horizontal, vertical } = { ...currentPoint } + let { x, y, horizontal, vertical } = { ...currentPoint } + let { widthArr, heightArr } = centerPoints[0] + + let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal + let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical let result let topLeftPoint @@ -631,9 +770,11 @@ export const useTrestle = () => { return result } const findNextRightModule = (currentPoint, centerPoints, direction) => { - let { x, y, width, height, horizontal, vertical } = { ...currentPoint } - width = width + horizontal - height = height + vertical + let { x, y, horizontal, vertical } = { ...currentPoint } + let { widthArr, heightArr } = centerPoints[0] + + let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal + let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical let result let topRightPoint @@ -665,6 +806,9 @@ export const useTrestle = () => { } const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l, rackYn) => { + if (!rackInfos) { + return + } const { width, height, left, top, lastX, lastY, surfaceId } = module const surface = canvas.getObjects().find((obj) => obj.id === surfaceId) const roof = canvas.getObjects().find((obj) => obj.id === surface.parentId) @@ -762,7 +906,7 @@ export const useTrestle = () => { name: 'smartRack', stroke: 'red', strokeWidth: 4, - selectable: false, + selectable: true, shadow: { color: 'black', // Outline color blur: 10, @@ -774,17 +918,18 @@ export const useTrestle = () => { surfaceId: surface.id, supFitQty, supFitIntvlPct, - rackLen, + rackLen: rackLength, rackRowsCd, seq, smartRackId, rackId: itemId, direction: 'top', }) + startPointY -= rackLength + 8 canvas.add(rack) canvas.renderAll() } else if (setRackTpCd === 'INTVL') { - startPointY -= rackLength + 8 + startPointY -= rackLength } }) } else { @@ -844,13 +989,14 @@ export const useTrestle = () => { surfaceId: surface.id, supFitQty, supFitIntvlPct, - rackLen, + rackLen: rackLength, rackRowsCd, seq, smartRackId, rackId: itemId, direction: 'left', }) + startPointX -= rackLength + 8 canvas.add(rack) canvas.renderAll() } else if (setRackTpCd === 'INTVL') { @@ -873,7 +1019,7 @@ export const useTrestle = () => { selectable: false, supFitQty, supFitIntvlPct, - rackLen, + rackLen: rackLength, rackYn, rackRowsCd, rackId: itemId, @@ -913,17 +1059,18 @@ export const useTrestle = () => { surfaceId: surface.id, supFitQty, supFitIntvlPct, - rackLen, + rackLen: rackLength, rackRowsCd, seq, smartRackId, rackId: itemId, direction: 'right', }) + startPointX += rackLength + 8 canvas.add(rack) canvas.renderAll() } else if (setRackTpCd === 'INTVL') { - startPointX += rackLength + 8 + startPointX += rackLength } }) } else { @@ -989,8 +1136,9 @@ export const useTrestle = () => { }) canvas.add(rack) canvas.renderAll() - } else if (setRackTpCd === 'INTVL') { startPointY += rackLength + 8 + } else if (setRackTpCd === 'INTVL') { + startPointY += rackLength } }) } else { @@ -1043,17 +1191,16 @@ export const useTrestle = () => { canvas.renderAll() racks.forEach((rack) => { - const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen } = rack + const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen, name } = rack const bracketLength = 10 if (direction === 'top') { const result = getBracketPoints(supFitQty, supFitIntvlPct) - result.forEach((percent) => { const bracket = new fabric.Rect({ left: x2 - bracketLength / 3, - top: y2 + (rackLen / 10) * percent, + top: name === 'smartRack' ? y2 + rackLen * percent : y2 + (rackLen / 10) * percent, fill: 'green', name: 'bracket', parentId: rack.parentId, @@ -1071,7 +1218,7 @@ export const useTrestle = () => { result.forEach((percent) => { const bracket = new fabric.Rect({ - left: x2 + (rackLen / 10) * percent, + left: name === 'smartRack' ? x2 + rackLen * percent : x2 + (rackLen / 10) * percent, top: y2 - bracketLength / 3, fill: 'green', name: 'bracket', @@ -1090,7 +1237,7 @@ export const useTrestle = () => { result.forEach((percent) => { const bracket = new fabric.Rect({ - left: x2 - (rackLen / 10) * percent, + left: name === 'smartRack' ? x2 - rackLen * percent : x2 - (rackLen / 10) * percent, top: y2 - bracketLength / 3, fill: 'green', parentId: rack.parentId, @@ -1110,7 +1257,7 @@ export const useTrestle = () => { result.forEach((percent) => { const bracket = new fabric.Rect({ left: x2 - bracketLength / 3, - top: y2 - (rackLen / 10) * percent, + top: name === 'smartRack' ? y2 - rackLen * percent : y2 - (rackLen / 10) * percent, fill: 'green', name: 'bracket', parentId: rack.parentId, @@ -1337,8 +1484,49 @@ export const useTrestle = () => { return points.slice(0, 2) } - const calculateForApi = (moduleSurface) => { + const getCenterPoints = (moduleSurface) => { const centerPoints = [] + let widthArr = [] + let heightArr = [] + const modules = moduleSurface.modules + modules.forEach((module, index) => { + module.tempIndex = index + const { x, y } = module.getCenterPoint() + const { width, height } = { ...module } + widthArr.push(width) + heightArr.push(height) + centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index, moduleInfo: module.moduleInfo }) + }) + + //widthArr 중복 제거 1이상 차이가 나지 않으면 같은 너비로 간주 + widthArr = removeCloseValues(Array.from(new Set(widthArr))) + heightArr = removeCloseValues(Array.from(new Set(heightArr))) + + centerPoints.forEach((centerPoint, index) => { + centerPoint.widthArr = [...widthArr] + + centerPoint.heightArr = [...heightArr] + }) + + function removeCloseValues(arr, threshold = 1) { + arr.sort((a, b) => a - b) // 배열을 정렬 + + let result = [] + + for (let i = 0; i < arr.length; i++) { + if (i === 0 || Math.abs(arr[i] - arr[i - 1]) >= threshold) { + result.push(arr[i]) + } + } + + return result + } + + return centerPoints + } + + const calculateForApi = (moduleSurface) => { + const centerPoints = getCenterPoints(moduleSurface) const direction = moduleSurface.direction const modules = moduleSurface.modules @@ -1350,12 +1538,6 @@ export const useTrestle = () => { const maxX = 2 + horizontal * 3 const maxY = 2 + vertical * 3 - modules.forEach((module, index) => { - module.tempIndex = index - const { x, y } = module.getCenterPoint() - const { width, height } = { ...module } - centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index }) - }) if (centerPoints.length === 0) return @@ -1382,7 +1564,7 @@ export const useTrestle = () => { let rightExposedHalfTopPoints = [] centerPoints.forEach((centerPoint, index) => { - let { x, y, width, height } = { ...centerPoint } + let { x, y, width, height, widthArr, heightArr } = { ...centerPoint } // centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인 let bottomCell let bottomLeftPoint @@ -1392,28 +1574,29 @@ export const useTrestle = () => { switch (direction) { case 'south': - width = width + horizontal - height = height + vertical + //widthArr의 값을 전부 더한 후 widthArr의 길이로 나누어 평균값을 구한다. + width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal + height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y + height)) < maxY) bottomLeftPoint = { x: x - width / 2, y: y + height } bottomRightPoint = { x: x + width / 2, y: y + height } break case 'north': - width = width + horizontal - height = height + vertical + width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal + height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length + vertical bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < maxX && Math.abs(centerPoint.y - (y - height)) < maxY) bottomLeftPoint = { x: x + width / 2, y: y - height } bottomRightPoint = { x: x - width / 2, y: y - height } break case 'east': bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < maxX && Math.abs(centerPoint.y - y) < maxY) - width = width + horizontal + width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal bottomLeftPoint = { x: x + width, y: y + height / 2 } bottomRightPoint = { x: x + width, y: y - height / 2 } break case 'west': bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < maxX && Math.abs(centerPoint.y - y) < maxY) - width = width + horizontal + width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + horizontal bottomLeftPoint = { x: x - width, y: y - height / 2 } bottomRightPoint = { x: x - width, y: y + height / 2 } break @@ -1870,16 +2053,16 @@ export const useTrestle = () => { const { direction, modules } = surface let { rackYn, cvrPlvrYn, moduleIntvlHor, moduleIntvlVer, rackQty, lessSupFitQty } = surface.trestleDetail - const centerPoints = modules.map((module) => { - return module.getCenterPoint() - }) + const centerPoints = getCenterPoints(surface) 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 { widthArr, heightArr } = centerPoints[0] + let width = widthArr.reduce((acc, num) => acc + num, 0) / widthArr.length + let height = heightArr.reduce((acc, num) => acc + num, 0) / heightArr.length let { x, y } = { ...module.getCenterPoint() } let halfBottomLeftPoint diff --git a/src/hooks/useEstimate.js b/src/hooks/useEstimate.js new file mode 100644 index 00000000..7fa4ff60 --- /dev/null +++ b/src/hooks/useEstimate.js @@ -0,0 +1,59 @@ +import { useContext } from 'react' + +import { useRecoilValue } from 'recoil' + +import { useAxios } from '@/hooks/useAxios' +import { useSwal } from '@/hooks/useSwal' +import { GlobalDataContext } from '@/app/GlobalDataProvider' +import { currentCanvasPlanState } from '@/store/canvasAtom' +import { loginUserStore } from '@/store/commonAtom' + +export function useEstimate() { + const { managementStateLoaded } = useContext(GlobalDataContext) + + const loginUserState = useRecoilValue(loginUserStore) + const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) + + const { swalFire } = useSwal() + const { promisePost } = useAxios() + + /** + * 도면 견적서 저장 + */ + const saveEstimate = async (estimateParam) => { + const userId = loginUserState.userId + const saleStoreId = managementStateLoaded.saleStoreId + const objectNo = currentCanvasPlan.objectNo + const planNo = currentCanvasPlan.planNo + const slope = estimateParam.roofSurfaceList[0].slope + const angle = estimateParam.roofSurfaceList[0].angle + const surfaceType = managementStateLoaded.surfaceType + const setupHeight = managementStateLoaded.installHeight + const standardWindSpeedId = managementStateLoaded.standardWindSpeedId + const snowfall = managementStateLoaded.verticalSnowCover + const drawingFlg = '1' + + const saveEstimateData = { + ...estimateParam, + userId: userId, + saleStoreId: saleStoreId, + objectNo: objectNo, + planNo: planNo, + slope: slope, + angle: angle, + surfaceType: surfaceType, + setupHeight: setupHeight, + standardWindSpeedId: standardWindSpeedId, + snowfall: snowfall, + drawingFlg: drawingFlg, + } + + await promisePost({ url: '/api/estimate/save-estimate', data: saveEstimateData }).catch((error) => { + swalFire({ text: error.message, icon: 'error' }) + }) + } + + return { + saveEstimate, + } +} diff --git a/src/locales/ja.json b/src/locales/ja.json index 38723da7..47257675 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -999,5 +999,6 @@ "construction.length.difference": "屋根面工法をすべて選択してください。", "menu.validation.canvas.roof": "パネルを配置するには、屋根面を入力する必要があります。", "batch.object.outside.roof": "オブジェクトは屋根に設置する必要があります。", - "batch.object.notinstall.cross": "オブジェクトは重複してインストールできません。" + "batch.object.notinstall.cross": "オブジェクトは重複してインストールできません。", + "module.not.batch.north": "북쪽에는 모듈을 배치할 수 없습니다." } diff --git a/src/locales/ko.json b/src/locales/ko.json index 5c7c17d6..7249b0f5 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -90,7 +90,7 @@ "modal.module.basic.setting.orientation.setting.info": "※시뮬레이션 계산용 방위를 지정합니다. 남쪽의 방위를 설정해주세요.", "modal.module.basic.setting.orientation.setting.angle.passivity": "각도를 직접 입력", "modal.module.basic.setting.module.roof.material": "지붕재", - "modal.module.basic.setting.module.trestle.maker": "가대메이거", + "modal.module.basic.setting.module.trestle.maker": "가대메이커", "modal.module.basic.setting.module.rafter.margin": "서까래 간격", "modal.module.basic.setting.module.construction.method": "공법", "modal.module.basic.setting.module.under.roof": "지붕밑바탕", diff --git a/src/store/circuitTrestleAtom.js b/src/store/circuitTrestleAtom.js index ea54835a..d1477e13 100644 --- a/src/store/circuitTrestleAtom.js +++ b/src/store/circuitTrestleAtom.js @@ -40,7 +40,10 @@ export const moduleStatisticsState = atom({ { name: `발전량(kW)`, prop: 'amount' }, ], rows: [], - footer: ['합계', '0'], + footer: [ + { name: '-', prop: 'name' }, + { name: 0, prop: 'amount' }, + ], }, dangerouslyAllowMutability: true, })