diff --git a/.env.development b/.env.development index f59d542c..cfc50e71 100644 --- a/.env.development +++ b/.env.development @@ -1,8 +1,11 @@ NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" +NEXT_PUBLIC_HOST_URL="http://1.248.227.176:4000" + SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" -NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" +# NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" +NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_yAS4QDalL9jgQ7vS" NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-stg.q-cells.jp:8120/eos/login/autoLogin" NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-stg.q-cells.jp:8120/qm/login/autoLogin" \ No newline at end of file diff --git a/.env.production b/.env.production index c4c7918d..381c7264 100644 --- a/.env.production +++ b/.env.production @@ -1,8 +1,11 @@ NEXT_PUBLIC_API_SERVER_PATH="http://1.248.227.176:38080" +NEXT_PUBLIC_HOST_URL="http://1.248.227.176:4000" + SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y=" -NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" +# NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3" +NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_yAS4QDalL9jgQ7vS" NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="https://q-order.q-cells.jp/eos/login/autoLogin" NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="https://q-musubi.q-cells.jp/qm/login/autoLogin" \ No newline at end of file diff --git a/src/common/common.js b/src/common/common.js index a35dc8c4..f53210ab 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -177,8 +177,15 @@ export const SAVE_KEY = [ 'moduleRowsTotCnt', 'seq', 'smartRackId', + 'directionText', 'quotationParam', 'pcses', + 'roofMaterial', + 'isComplete', + 'moduleInfo', + 'circuitNumber', + 'circuit', + 'onlyOffset', ] export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype] diff --git a/src/components/Main.jsx b/src/components/Main.jsx index cbdea01d..520014b1 100644 --- a/src/components/Main.jsx +++ b/src/components/Main.jsx @@ -13,6 +13,8 @@ import { QcastContext } from '@/app/QcastProvider' import { sessionStore } from '@/store/commonAtom' import { isObjectNotEmpty } from '@/util/common-utils' +import BoardDetailModal from './community/modal/BoardDetailModal' + export default function MainPage() { const [sessionState, setSessionState] = useRecoilState(sessionStore) const [chagePasswordPopOpen, setChagePasswordPopOpen] = useState(false) @@ -79,8 +81,13 @@ export default function MainPage() { } }, [sessionState]) + // FAQ 팝업 관련 + const [open, setOpen] = useState(false) + const [modalNoticeNo, setModalNoticeNo] = useState('') + return ( <> + {open && } {(!chagePasswordPopOpen && ( <>
@@ -120,7 +127,7 @@ export default function MainPage() { - + )) || ( diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index b2e64edc..8a365646 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -28,6 +28,8 @@ import useSWRMutation from 'swr/mutation' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom' import { moduleSelectionDataPlanListState } from '@/store/selectedModuleOptions' +import { useRouter } from 'next/navigation' +import { QcastContext } from '@/app/QcastProvider' export default function Playground() { const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) @@ -56,6 +58,13 @@ export default function Playground() { const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) + const router = useRouter() + const { setIsGlobalLoading } = useContext(QcastContext) + + useEffect(() => { + setIsGlobalLoading(false) + }, []) + useEffect(() => { console.log('textInput:', textInput) }, [textInput]) @@ -891,6 +900,19 @@ export default function Playground() { Test Data insert +
+ +
) diff --git a/src/components/auth/AutoLogin.jsx b/src/components/auth/AutoLogin.jsx index 0d539cbb..d400f2c4 100644 --- a/src/components/auth/AutoLogin.jsx +++ b/src/components/auth/AutoLogin.jsx @@ -1,21 +1,27 @@ 'use client' +import { useState } from 'react' import { useMessage } from '@/hooks/useMessage' +import GlobalSpinner from '@/components/common/spinner/GlobalSpinner' export default function AutoLoginPage() { + const [isLoading, setIsLoading] = useState(true) const { getMessage } = useMessage() return ( -
-
- {getMessage('site.name')} - {getMessage('site.sub_name')} -
-
-
- {getMessage('login.auto.page.text')} + <> + {isLoading && } +
+
+ {getMessage('site.name')} + {getMessage('site.sub_name')} +
+
+
+ {getMessage('login.auto.page.text')} +
-
+ ) } diff --git a/src/components/auth/Login.jsx b/src/components/auth/Login.jsx index eca80361..b23f9c53 100644 --- a/src/components/auth/Login.jsx +++ b/src/components/auth/Login.jsx @@ -10,14 +10,15 @@ import { useMessage } from '@/hooks/useMessage' import { globalLocaleStore } from '@/store/localeAtom' import { sessionStore } from '@/store/commonAtom' import { useRouter } from 'next/navigation' - -import Cookies from 'js-cookie' - import { useSearchParams } from 'next/navigation' +import GlobalSpinner from '@/components/common/spinner/GlobalSpinner' +import Cookies from 'js-cookie' import AutoLogin from './AutoLogin' export default function Login() { + const [isLoading, setIsLoading] = useState(false) + // 자동 로그인 const initParams = useSearchParams() const autoLoginParam = initParams.get('autoLoginParam1') @@ -35,11 +36,13 @@ export default function Login() { }, []) const autoLoginProcess = async (autoLoginParam) => { + setIsLoading(true) await promisePost({ url: '/api/login/v1.0/user/login/autoLoginDecryptData', data: { loginId: autoLoginParam } }) .then((res) => { if (res) { if (res.data) { post({ url: '/api/login/v1.0/user', data: { loginId: res.data } }).then((response) => { + setIsLoading(false) if (response) { const result = { ...response, storeLvl: response.groupId === '60000' ? '1' : '2', pwdInitYn: 'Y' } setSession(result) @@ -53,6 +56,7 @@ export default function Login() { } }) .catch((error) => { + setIsLoading(false) router.push('/login') }) } @@ -93,9 +97,11 @@ export default function Login() { loginId: formData.get('id'), pwd: formData.get('password'), } + setIsLoading(true) await promisePost({ url: '/api/login/v1.0/login', data: param }) .then((res) => { if (res) { + setIsLoading(false) if (res.data.result.resultCode === 'S') { setSession(res.data.data) setSessionState(res.data.data) @@ -105,7 +111,6 @@ export default function Login() { } else { Cookies.remove('chkLoginId') } - // router.push('/') login() } else { alert(res.data.result.resultMsg) @@ -113,6 +118,7 @@ export default function Login() { } }) .catch((error) => { + setIsLoading(false) alert(error.response.data.message) }) } @@ -123,12 +129,14 @@ export default function Login() { loginId: checkId, email: checkEmail, } + setIsLoading(true) await promisePatch({ url: '/api/login/v1.0/user/init-password', data: param, }) .then((res) => { if (res) { + setIsLoading(false) if (res.data.result.resultCode == 'S') { alert(getMessage('login.init_password.complete_message')) setCheckId('') @@ -140,36 +148,135 @@ export default function Login() { } }) .catch((error) => { + setIsLoading(false) alert(error.response.data.message) }) } return ( -
-
- - react - - {!autoLoginParam && passwordReset === 1 && ( - <> -
-
-
- {getMessage('site.name')} - {getMessage('site.sub_name')} + <> + {isLoading && } +
+
+ + react + + {!autoLoginParam && passwordReset === 1 && ( + <> +
+ +
+ {getMessage('site.name')} + {getMessage('site.sub_name')} +
+
+
+ { + setUserId(e.target.value) + }} + onFocus={() => setIdFocus(true)} + onBlur={() => setIdFocus(false)} + /> + +
+
+ { + setPasswordVisible(passwordVisible) + }} + onFocus={() => setSecFocus(true)} + onBlur={() => setSecFocus(false)} + /> + +
+
+ { + setChkLoginId(e.target.checked) + }} + /> + +
+
+ +
+
+ +
+
+ +
+
+ + {getMessage('login.guide.text')} +
+ {getMessage('login.guide.sub1')} {getMessage('login.guide.join.btn')} + {getMessage('login.guide.sub2')} +
+ + )} + {!autoLoginParam && passwordReset === 2 && ( + <> +
+
+ {getMessage('login.init_password.title')} + {getMessage('login.init_password.sub_title')}
{ - setUserId(e.target.value) + setCheckId(e.target.value) }} onFocus={() => setIdFocus(true)} onBlur={() => setIdFocus(false)} @@ -177,146 +284,58 @@ export default function Login() {
-
+
{ - setPasswordVisible(passwordVisible) + setCheckEmail(e.target.value) }} + placeholder={getMessage('login.init_password.email.placeholder')} onFocus={() => setSecFocus(true)} onBlur={() => setSecFocus(false)} />
-
- { - setChkLoginId(e.target.checked) +
+
-
- -
-
-
- -
-
- - {getMessage('login.guide.text')} -
- {getMessage('login.guide.sub1')} {getMessage('login.guide.join.btn')} - {getMessage('login.guide.sub2')} -
- - )} - {!autoLoginParam && passwordReset === 2 && ( - <> -
-
- {getMessage('login.init_password.title')} - {getMessage('login.init_password.sub_title')}
-
-
- { - setCheckId(e.target.value) - }} - onFocus={() => setIdFocus(true)} - onBlur={() => setIdFocus(false)} - /> - -
-
- { - setCheckEmail(e.target.value) - }} - placeholder={getMessage('login.init_password.email.placeholder')} - onFocus={() => setSecFocus(true)} - onBlur={() => setSecFocus(false)} - /> - -
-
- - -
-
-
- - )} - {autoLoginParam && } + + )} + {autoLoginParam && } +
+
COPYRIGHT©2024 Hanwha Japan All Rights Reserved.
-
COPYRIGHT©2024 Hanwha Japan All Rights Reserved.
-
+ ) } diff --git a/src/components/common/font/FontSetting.jsx b/src/components/common/font/FontSetting.jsx index 26d07ea7..ddddefca 100644 --- a/src/components/common/font/FontSetting.jsx +++ b/src/components/common/font/FontSetting.jsx @@ -87,25 +87,60 @@ export default function FontSetting(props) {
{getMessage('modal.font')}(F)
- setSelectedFont(e)} /> + { + setSelectedFont(e) + }} + showKey={'name'} + sourceKey={'value'} + targetKey={'value'} + />
{getMessage('modal.font.style')}(Y)
- setSelectedFontWeight(e)} /> + { + setSelectedFontWeight(e) + }} + showKey={'name'} + targetKey={'id'} + sourceKey={'id'} + />
{getMessage('modal.font.size')}(S)
- setSelectedFontSize(e)} /> + setSelectedFontSize(e)} + showKey={'name'} + sourceKey={'value'} + targetKey={'value'} + />
{getMessage('modal.font.color')}
- setSelectedFontColor(e)} /> + { + setSelectedFontColor(e) + }} + />
diff --git a/src/components/common/select/QSelectBox.jsx b/src/components/common/select/QSelectBox.jsx index 12c72b5e..f1041da3 100644 --- a/src/components/common/select/QSelectBox.jsx +++ b/src/components/common/select/QSelectBox.jsx @@ -1,6 +1,7 @@ 'use client' import { useEffect, useRef, useState } from 'react' import { useOnClickOutside } from 'usehooks-ts' +import { useMessage } from '@/hooks/useMessage' /** * @@ -26,13 +27,15 @@ export default function QSelectBox({ showKey = '', params = {}, }) { + const { getMessage } = useMessage() + /** * 초기 상태 처리 * useState 초기 값으로 사용해야 해서 useState 보다 위에 작성 * @returns {string} 초기 상태 */ const handleInitState = () => { - if (options.length === 0) return title !== '' ? title : '선택하세요.' + if (options.length === 0) return title !== '' ? title : getMessage('selectbox.title') if (showKey !== '' && !value) { //value가 없으면 showKey가 있으면 우선 보여준다 // return options[0][showKey] @@ -44,13 +47,13 @@ export default function QSelectBox({ return option[sourceKey] === value[targetKey] }) if (!option) { - return title !== '' ? title : '선택하세요.' + return title !== '' ? title : getMessage('selectbox.title') } else { return option[showKey] } } else { //일치하는 조건이 없으면 기본값을 보여준다. - return title !== '' ? title : '선택하세요.' + return title !== '' ? title : getMessage('selectbox.title') } } diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index a97cb4cb..609ba73e 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -19,10 +19,11 @@ import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from import ProductFeaturesPop from './popup/ProductFeaturesPop' import { v4 as uuidv4 } from 'uuid' import { correntObjectNoState } from '@/store/settingAtom' -import { useRouter, useSearchParams } from 'next/navigation' -import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' +import { useSearchParams } from 'next/navigation' import { usePlan } from '@/hooks/usePlan' import { usePopup } from '@/hooks/usePopup' +import { useSwal } from '@/hooks/useSwal' +import { QcastContext } from '@/app/QcastProvider' export default function Estimate({}) { const [uniqueData, setUniqueData] = useState([]) @@ -33,6 +34,8 @@ export default function Estimate({}) { const [objectNo, setObjectNo] = useState('') //물건번호 const [planNo, setPlanNo] = useState('') //플랜번호 + const { swalFire } = useSwal() + const [files, setFiles] = useState([]) // 보내는 첨부파일 const [originFiles, setOriginFiles] = useState([]) //기존 첨부파일 @@ -79,6 +82,7 @@ export default function Estimate({}) { const [specialNoteList, setSpecialNoteList] = useState([]) const [popShowSpecialNoteList, setPopShowSpecialNoteList] = useState([]) + const { setIsGlobalLoading } = useContext(QcastContext) const globalLocaleState = useRecoilValue(globalLocaleStore) const { get, post, promisePost } = useAxios(globalLocaleState) @@ -347,7 +351,11 @@ export default function Estimate({}) { setEstimateContextState({ originFiles: originFiles, }) - alert(getMessage('estimate.detail.alert.delFile')) + + swalFire({ + text: getMessage('estimate.detail.alert.delFile'), + type: 'alert', + }) } //가격표시 option 목록 최초세팅 && 주문분류 변경시 @@ -476,10 +484,15 @@ export default function Estimate({}) { if (!pass) { //Pricing이 누락된 아이템이 있습니다. Pricing을 진행해주세요. - return alert(getMessage('estimate.detail.showPrice.pricingBtn.noItemId')) + return swalFire({ + text: getMessage('estimate.detail.showPrice.pricingBtn.noItemId'), + type: 'alert', + icon: 'warning', + }) } } + setIsGlobalLoading(true) await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => { let updateList = [] if (res) { @@ -527,6 +540,7 @@ export default function Estimate({}) { } } } + setIsGlobalLoading(false) }) } @@ -787,7 +801,11 @@ export default function Estimate({}) { const removeItem = () => { const array = [...selection] if (isEmptyArray(array)) { - return alert(getMessage('estimate.detail.alert.selectDelItem')) + return swalFire({ + text: getMessage('estimate.detail.alert.selectDelItem'), + type: 'alert', + icon: 'warning', + }) } let delList = [] estimateContextState.itemList.filter((row) => { @@ -817,7 +835,11 @@ export default function Estimate({}) { }) if (delCnt === updateList.length) { - return alert(getMessage('estimate.detail.save.requiredItem')) + return swalFire({ + text: getMessage('estimate.detail.save.requiredItem'), + type: 'alert', + icon: 'warning', + }) } setEstimateContextState({ @@ -1188,7 +1210,7 @@ export default function Estimate({}) { @@ -1206,7 +1228,7 @@ export default function Estimate({}) { @@ -1297,13 +1319,13 @@ export default function Estimate({}) { //사양시공 let constructSpecificationMulti = estimateContextState?.constructSpecificationMulti?.split('、') return ( -
+
- +
{constructSpecificationMulti ? (
- +
) : null}
@@ -1316,7 +1338,6 @@ export default function Estimate({}) { {getMessage('estimate.detail.remarks')}
- {/* */}
+ {estimateContextState?.northArrangement === '1' && ( +
{getMessage('estimate.detail.dragFileGuide')}
+ )}
diff --git a/src/components/estimate/popup/DocDownOptionPop.jsx b/src/components/estimate/popup/DocDownOptionPop.jsx index 50dfd018..13477b63 100644 --- a/src/components/estimate/popup/DocDownOptionPop.jsx +++ b/src/components/estimate/popup/DocDownOptionPop.jsx @@ -4,20 +4,21 @@ import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useRecoilValue } from 'recoil' import { floorPlanObjectState, estimateState } from '@/store/floorPlanObjectAtom' -import { usePathname } from 'next/navigation' +import { usePathname, useSearchParams } from 'next/navigation' export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDownPopLockFlg }) { const { getMessage } = useMessage() const { promisePost } = useAxios() const pathName = usePathname() + const searchParams = useSearchParams() //EXCEL, PDF 구분 const [schDownload, setSchDownload] = useState('EXCEL') //다운로드 파일 EXCEL const [schUnitPriceFlg, setSchUnitPriceFlg] = useState('0') //견적제출서 표시명 - const [schDisplayFlg, setSchSchDisplayFlg] = useState('0') + const [schDisplayFlg, setSchDisplayFlg] = useState('0') //가대 중량표 포함(포함:1 미포함 : 0) const [schWeightFlg, setSchWeightFlg] = useState('1') //도면/시뮬레이션 파일 포함 @@ -53,8 +54,9 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown defaultSchDrawingFlg = defaultSchDrawingFlg.concat('|', '2', '|', '3') } + //objectRecoil.floorPlanObjectNo가 비워지는 경우가 있어서 없으면 url에서 뺴오도록 추가 const params = { - objectNo: objectRecoil.floorPlanObjectNo, + objectNo: objectRecoil?.floorPlanObjectNo ? objectRecoil.floorPlanObjectNo : searchParams.get('objectNo'), planNo: planNo, schDownload: schDownload, schUnitPriceFlg: sendUnitPriceFlg, @@ -206,7 +208,7 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown value={'0'} checked={schDisplayFlg === '0'} onChange={(e) => { - setSchSchDisplayFlg(e.target.value) + setSchDisplayFlg(e.target.value) }} /> @@ -219,7 +221,7 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown value={'1'} checked={schDisplayFlg === '1'} onChange={(e) => { - setSchSchDisplayFlg(e.target.value) + setSchDisplayFlg(e.target.value) }} /> diff --git a/src/components/estimate/popup/EstimateCopyPop.jsx b/src/components/estimate/popup/EstimateCopyPop.jsx index 001de6e9..35d8d54b 100644 --- a/src/components/estimate/popup/EstimateCopyPop.jsx +++ b/src/components/estimate/popup/EstimateCopyPop.jsx @@ -69,7 +69,7 @@ export default function EstimateCopyPop({ planNo, setEstimateCopyPopupOpen }) { get({ url: url }).then((res) => { if (!isEmptyArray(res)) { res.map((row) => { - row.value == row.saleStoreId + row.value = row.saleStoreId row.label = row.saleStoreName }) otherList = res diff --git a/src/components/estimate/popup/ProductFeaturesPop.jsx b/src/components/estimate/popup/ProductFeaturesPop.jsx index f2d98800..b6b02c64 100644 --- a/src/components/estimate/popup/ProductFeaturesPop.jsx +++ b/src/components/estimate/popup/ProductFeaturesPop.jsx @@ -7,16 +7,16 @@ export default function ProductFeaturesPop({ popShowSpecialNoteList, showProduct useEffect(() => { let pushData = [] - popShowSpecialNoteList.map((row) => { + popShowSpecialNoteList.forEach((row) => { let option = showProductFeatureData.split('、') - option.map((row2) => { + option.forEach((row2) => { if (row.code === row2) { pushData.push(row) } }) }) setShowSpecialNoteList(pushData) - }, [popShowSpecialNoteList]) + }, [popShowSpecialNoteList, showProductFeatureData]) return (
diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 26563ad3..22ef408b 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -249,6 +249,9 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { }, addLengthText() { + if ([POLYGON_TYPE.MODULE, 'arrow', POLYGON_TYPE.MODULE_SETUP_SURFACE, POLYGON_TYPE.OBJECT_SURFACE].includes(this.name)) { + return + } this.canvas ?.getObjects() .filter((obj) => obj.name === 'lengthText' && obj.parentId === this.id) diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index 31698b1a..f5ecb10d 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -16,7 +16,16 @@ import { totalDisplaySelector } from '@/store/settingAtom' import { MENU } from '@/common/common' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { QcastContext } from '@/app/QcastProvider' -import { moduleStatisticsState } from '@/store/circuitTrestleAtom' +import { + makersState, + modelsState, + moduleStatisticsState, + pcsCheckState, + selectedMakerState, + selectedModelsState, + seriesState, +} from '@/store/circuitTrestleAtom' +import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' export default function CanvasFrame() { const canvasRef = useRef(null) @@ -25,33 +34,59 @@ export default function CanvasFrame() { const currentMenu = useRecoilValue(currentMenuState) const { floorPlanState } = useContext(FloorPlanContext) const { contextMenu, handleClick } = useContextMenu() - const { currentCanvasPlan } = usePlan() + const { plans, currentCanvasPlan, resetCanvasStatus } = usePlan() const totalDisplay = useRecoilValue(totalDisplaySelector) // 집계표 표시 여부 const { setIsGlobalLoading } = useContext(QcastContext) - const [moduleStatistics, setModuleStatistics] = useRecoilState(moduleStatisticsState) - const reset = useResetRecoilState(moduleStatisticsState) + const resetModuleStatisticsState = useResetRecoilState(moduleStatisticsState) + const resetMakersState = useResetRecoilState(makersState) + const resetSelectedMakerState = useResetRecoilState(selectedMakerState) + const resetSeriesState = useResetRecoilState(seriesState) + const resetModelsState = useResetRecoilState(modelsState) + const resetSelectedModelsState = useResetRecoilState(selectedModelsState) + const resetPcsCheckState = useResetRecoilState(pcsCheckState) + const { handleModuleSelectionTotal } = useCanvasPopupStatusController() + const loadCanvas = () => { - if (canvas) { - canvas?.clear() // 캔버스를 초기화합니다. - if (currentCanvasPlan?.canvasStatus && floorPlanState.objectNo === currentCanvasPlan.objectNo) { - canvas?.loadFromJSON(JSON.parse(currentCanvasPlan.canvasStatus), function () { + if (!canvas) return + + canvas?.clear() // 캔버스를 초기화합니다. + if (currentCanvasPlan) { + const plan = plans.find((plan) => plan.id === currentCanvasPlan.id) + if (plan?.canvasStatus && floorPlanState.objectNo === currentCanvasPlan.objectNo) { + canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () { canvasLoadInit() //config된 상태로 캔버스 객체를 그린다 canvas?.renderAll() // 캔버스를 다시 그립니다. }) } - gridInit() } + gridInit() } useEffect(() => { loadCanvas() - reset() + resetRecoilData() + Object.keys(currentCanvasPlan).length > 0 && handleModuleSelectionTotal() }, [currentCanvasPlan, canvas]) useEffect(() => { setIsGlobalLoading(false) + + return () => { + canvas?.clear() + resetCanvasStatus() + } }, []) + const resetRecoilData = () => { + resetModuleStatisticsState() + resetMakersState() + resetSelectedMakerState() + resetSeriesState() + resetModelsState() + resetSelectedModelsState() + resetPcsCheckState() + } + return (
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index bc1a4007..6a7d5ef0 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -1,6 +1,7 @@ 'use client' import { useContext, useEffect } from 'react' +import { usePathname } from 'next/navigation' import { useRecoilValue } from 'recoil' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { SessionContext } from '@/app/SessionProvider' @@ -12,6 +13,7 @@ import { globalLocaleStore } from '@/store/localeAtom' export default function CanvasLayout({ children }) { // const { menuNumber } = props + const pathname = usePathname() const { menuNumber } = useCanvasMenu() const { session } = useContext(SessionContext) const { floorPlanState } = useContext(FloorPlanContext) @@ -37,10 +39,12 @@ export default function CanvasLayout({ children }) { onClick={() => handleCurrentPlan(plan.id)} > {`Plan ${plan.planNo}`} - {index !== 0 && ( + {index !== 0 && !pathname.includes('/estimate') && !pathname.includes('/simulator') && ( + onClick={(e) => { + //삭제 아이콘 눌렀는데 handleCurrentPlan실행되서 추가 + e.stopPropagation() swalFire({ text: `Plan ${plan.planNo} ` + getMessage('plan.message.confirm.delete'), type: 'confirm', @@ -48,13 +52,13 @@ export default function CanvasLayout({ children }) { handleDeletePlan(e, plan) }, }) - } + }} > )} ))}
- {plans.length < 10 && ( + {plans.length < 10 && !pathname.includes('/estimate') && !pathname.includes('/simulator') && ( */}
diff --git a/src/components/floor-plan/modal/basic/BasicSetting.jsx b/src/components/floor-plan/modal/basic/BasicSetting.jsx index f4fc830d..68c1e617 100644 --- a/src/components/floor-plan/modal/basic/BasicSetting.jsx +++ b/src/components/floor-plan/modal/basic/BasicSetting.jsx @@ -6,19 +6,20 @@ import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchMod import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement' import Placement from '@/components/floor-plan/modal/basic/step/Placement' import { useRecoilValue, useRecoilState } from 'recoil' -import { canvasSettingState, isManualModuleSetupState } from '@/store/canvasAtom' +import { canvasSettingState, canvasState, isManualModuleSetupState } from '@/store/canvasAtom' import { usePopup } from '@/hooks/usePopup' import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useEvent } from '@/hooks/useEvent' import { moduleSelectionDataState } from '@/store/selectedModuleOptions' -import { addedRoofsState } from '@/store/settingAtom' +import { addedRoofsState, corridorDimensionSelector } from '@/store/settingAtom' import { isObjectNotEmpty } from '@/util/common-utils' import Swal from 'sweetalert2' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' import { useMasterController } from '@/hooks/common/useMasterController' import { loginUserStore } from '@/store/commonAtom' import { currentCanvasPlanState } from '@/store/canvasAtom' +import { POLYGON_TYPE } from '@/common/common' export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const { getMessage } = useMessage() @@ -32,39 +33,51 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const addedRoofs = useRecoilValue(addedRoofsState) const loginUserState = useRecoilValue(loginUserStore) const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) + const canvas = useRecoilValue(canvasState) + + const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 }) // const { initEvent } = useContext(EventContext) - const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting() + const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(tabNum) const { updateObjectDate } = useMasterController() const handleBtnNextStep = () => { if (tabNum === 1) { orientationRef.current.handleNextStep() } else if (tabNum === 2) { - if (!isObjectNotEmpty(moduleSelectionData.module)) { - Swal.fire({ - title: getMessage('module.not.found'), - icon: 'warning', - }) - return - } + if (canvasSetting.roofSizeSet !== '3') { + if (!isObjectNotEmpty(moduleSelectionData.module)) { + Swal.fire({ + title: getMessage('module.not.found'), + icon: 'warning', + }) + return + } - if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) { - Swal.fire({ - title: getMessage('construction.length.difference'), - icon: 'warning', + if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) { + Swal.fire({ + title: getMessage('construction.length.difference'), + icon: 'warning', + }) + return + } + //물건정보 갱신일 수정 + updateObjectDataApi({ + objectNo: currentCanvasPlan.objectNo, //오브젝트_no + standardWindSpeedId: moduleSelectionData.common.stdWindSpeed, //기준풍속코드 + verticalSnowCover: moduleSelectionData.common.stdSnowLd, //적설량 + surfaceType: moduleSelectionData.common.illuminationTpNm, //면조도구분 + installHeight: moduleSelectionData.common.instHt, //설치높이 + userId: loginUserState.userId, //작성자아아디 }) - return + } else { + if (!isObjectNotEmpty(moduleSelectionData.flatModule)) { + Swal.fire({ + title: getMessage('module.not.found'), + icon: 'warning', + }) + return + } } - - //물건정보 갱신일 수정 - updateObjectDataApi({ - objectNo: currentCanvasPlan.objectNo, //오브젝트_no - standardWindSpeedId: moduleSelectionData.common.stdWindSpeed, //기준풍속코드 - verticalSnowCover: moduleSelectionData.common.stdSnowLd, //적설량 - surfaceType: moduleSelectionData.common.illuminationTpNm, //면조도구분 - installHeight: moduleSelectionData.common.instHt, //설치높이 - userId: loginUserState.userId, //작성자아아디 - }) } setTabNum(tabNum + 1) @@ -72,7 +85,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { const placementRef = { isChidori: useRef('false'), - setupLocation: useRef('center'), + setupLocation: useRef('eaves'), isMaxSetup: useRef('false'), } @@ -84,20 +97,49 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { setIsManualModuleSetup(!isManualModuleSetup) } - useEffect(() => { - manualModuleSetup() - }, [isManualModuleSetup]) - const updateObjectDataApi = async (params) => { const res = await updateObjectDate(params) } + useEffect(() => { + let hasModules = canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + .some((obj) => obj.modules?.length > 0) + + if (hasModules) { + orientationRef.current.handleNextStep() + setTabNum(3) + } + }, []) + + //팝업 닫기 버튼 이벤트 + const handleClosePopup = (id) => { + if (tabNum == 3) { + if (isManualModuleSetup) { + setIsManualModuleSetup(false) + } + } + setIsClosePopup({ close: true, id: id }) + } + + useEffect(() => { + if (canvasSetting.roofSizeSet !== '3') { + manualModuleSetup(placementRef) + } else { + manualFlatroofModuleSetup(placementFlatRef) + } + if (isClosePopup.close) { + closePopup(isClosePopup.id) + } + }, [isManualModuleSetup, isClosePopup]) + return (

{getMessage('plan.menu.module.circuit.setting.default')}

-
@@ -111,12 +153,12 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
{tabNum === 1 && } {/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/} - {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != 3 && tabNum === 2 && } - {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != 3 && tabNum === 3 && } + {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != '3' && tabNum === 2 && } + {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != '3' && tabNum === 3 && } {/*배치면 초기설정 - 입력방법: 육지붕*/} - {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && tabNum === 2 && } - {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && tabNum === 3 && ( + {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == '3' && tabNum === 2 && } + {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == '3' && tabNum === 3 && ( )} @@ -145,9 +187,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) { )} - {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet === 3 && ( + {canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && ( <> -
- mm + cm
@@ -271,7 +272,6 @@ export default function Module({ setTabNum }) {
{/* 설정 오류시 노출 */} -
※ 施工方法が選択できません。 基準風速または基準積雪量を確認してください。
diff --git a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx index 706fad9f..75c8dcd9 100644 --- a/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx +++ b/src/components/floor-plan/modal/basic/step/ModuleTabContents.jsx @@ -120,7 +120,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro value={selectedTrestle} sourceKey={'trestleMkrCd'} targetKey={'trestleMkrCd'} - showKey={'trestleMkrCdNm'} + showKey={'trestleMkrCdJp'} onChange={handleChangeTrestle} /> )} @@ -138,7 +138,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro value={selectedConstMthd} sourceKey={'constMthdCd'} targetKey={'constMthdCd'} - showKey={'constMthdCdNm'} + showKey={'constMthdCdJp'} onChange={handleChangeConstMthd} /> )} @@ -156,7 +156,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro value={selectedRoofBase} sourceKey={'roofBaseCd'} targetKey={'roofBaseCd'} - showKey={'roofBaseCdNm'} + showKey={'roofBaseCdJp'} onChange={handleChangeRoofBase} /> )} @@ -203,7 +203,7 @@ export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, ro 強化施工 -
+
{ }, [compasDeg]) const checkDegree = (e) => { - if (numberCheck(Number(e)) && Number(e) >= -180 && Number(e) <= 180) { - setCompasDeg(Number(e)) + if (e === '-0' || e === '-') { + setCompasDeg('-') + return + } + if (e === '0-') { + setCompasDeg('-0') + return + } + if (Number(e) >= -180 && Number(e) <= 180) { + if (numberCheck(Number(e))) { + setCompasDeg(Number(e)) + } } else { setCompasDeg(compasDeg) } @@ -46,8 +56,14 @@ export const Orientation = forwardRef(({ tabNum }, ref) => { {Array.from({ length: 180 / 15 }).map((dot, index) => (
setCompasDeg(15 * (12 + index))} + className={`circle ${getDegreeInOrientation(compasDeg) === -1 * (-15 * index + 180) || (index === 0 && compasDeg >= 172 && index === 0 && compasDeg <= 180) || (compasDeg === -180 && index === 0) ? 'act' : ''}`} + onClick={() => { + if (index === 0) { + setCompasDeg(180) + return + } + setCompasDeg(-1 * (-15 * index + 180)) + }} > {index === 0 && 180°} {index === 6 && -90°} @@ -56,7 +72,7 @@ export const Orientation = forwardRef(({ tabNum }, ref) => { {Array.from({ length: 180 / 15 }).map((dot, index) => (
setCompasDeg(15 * index)} > {index === 0 && } diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index eff568cd..4eeeab0a 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -2,25 +2,24 @@ import { forwardRef, useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { checkedModuleState, currentCanvasPlanState } from '@/store/canvasAtom' -import { useRecoilValue, useSetRecoilState } from 'recoil' -import { moduleSelectionDataState } from '@/store/selectedModuleOptions' -import { useModulePlace } from '@/hooks/module/useModulePlace' +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' +import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' +import { isObjectNotEmpty } from '@/util/common-utils' const Placement = forwardRef((props, refs) => { const { getMessage } = useMessage() const [isChidori, setIsChidori] = useState(false) const [isChidoriNotAble, setIsChidoriNotAble] = useState(false) - const currentCanvasPlan = useRecoilValue(currentCanvasPlanState) - const [setupLocation, setSetupLocation] = useState('center') + const [setupLocation, setSetupLocation] = useState('eaves') const [isMaxSetup, setIsMaxSetup] = useState('false') const [selectedItems, setSelectedItems] = useState({}) - const { makeModuleInstArea } = useModuleBasicSetting() - const { selectedModules } = useModulePlace() + const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) const setCheckedModules = useSetRecoilState(checkedModuleState) const moduleSelectionData = useRecoilValue(moduleSelectionDataState) + const { makeModuleInitArea } = useModuleBasicSetting(3) //모듈 배치면 생성 useEffect(() => { @@ -30,17 +29,39 @@ const Placement = forwardRef((props, refs) => { if (isChidroriValue) { setIsChidoriNotAble(true) } + makeModuleInitArea(moduleSelectionData) } }, []) + //최초 지입시 체크 + useEffect(() => { + if (isObjectNotEmpty(moduleSelectionData)) { + //두번째 선택한 데이터가를 기반으로 세번째 선택을 체크한다 + if (moduleSelectionData.roofConstructions.length > 0 && moduleSelectionData.module.itemList.length > 0) { + let initCheckedModule = {} + moduleSelectionData.module.itemList.forEach((obj, index) => { + if (index === 0) { + initCheckedModule = { [obj.itemId]: true } + } else { + initCheckedModule = { ...initCheckedModule, [obj.itemId]: true } + } + }) + setSelectedItems(initCheckedModule) + setSelectedModules(moduleSelectionData.module) + } + } + }, [moduleSelectionData]) + //체크된 모듈 데이터 useEffect(() => { - const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key]) - const moduleArray = selectedModules.itemList.filter((item) => { - return checkedModuleIds.includes(item.itemId) - }) - setCheckedModules(moduleArray) - }, [selectedItems]) + if (isObjectNotEmpty(selectedItems) && isObjectNotEmpty(selectedModules)) { + const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key]) + const moduleArray = selectedModules.itemList.filter((item) => { + return checkedModuleIds.includes(item.itemId) + }) + setCheckedModules(moduleArray) + } + }, [selectedItems, selectedModules]) const moduleData = { header: [ @@ -77,20 +98,6 @@ const Placement = forwardRef((props, refs) => { setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked }) } - useEffect(() => { - if (moduleSelectionData && moduleSelectionData.module.itemList.length > 0) { - let initCheckedModule = {} - moduleSelectionData.module.itemList.forEach((obj, index) => { - if (index === 0) { - initCheckedModule = { [obj.itemId]: true } - } else { - initCheckedModule = { ...initCheckedModule, [obj.itemId]: true } - } - }) - setSelectedItems(initCheckedModule) - } - }, []) - return ( <>
@@ -117,29 +124,27 @@ const Placement = forwardRef((props, refs) => { {selectedModules.itemList && selectedModules.itemList.map((item, index) => ( - <> - - -
- - -
- - -
- - {item.itemNm} -
- - {item.wpOut} - - + + +
+ + +
+ + +
+ + {item.itemNm} +
+ + {item.wpOut} + ))} @@ -215,10 +220,10 @@ const Placement = forwardRef((props, refs) => {
-
+ {/*
-
+
*/}
diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx index 255833a8..39d0ee19 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchModule.jsx @@ -1,12 +1,22 @@ +import { useState, useEffect } from 'react' +import { useRecoilState } from 'recoil' import { useMessage } from '@/hooks/useMessage' import QSelectBox from '@/components/common/select/QSelectBox' +import { useMasterController } from '@/hooks/common/useMasterController' +import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' +import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' +import { isObjectNotEmpty } from '@/util/common-utils' export default function PitchModule({}) { const { getMessage } = useMessage() - const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }] + const { getModuleTypeItemList } = useMasterController() + const [moduleList, setModuleList] = useState([]) + const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈 + const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터 + const moduleData = { header: [ - { name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' }, + { name: getMessage('module'), width: 250, prop: 'module', type: 'color-box' }, { name: `${getMessage('높이')} (mm)`, prop: 'height', @@ -14,24 +24,45 @@ export default function PitchModule({}) { { name: `${getMessage('width')} (mm)`, prop: 'width' }, { name: `${getMessage('output')} (W)`, prop: 'output' }, ], - rows: [ - { - module: { name: 'Re.RISE-G3 440', color: '#AA6768' }, - height: { name: '1134' }, - width: { name: '1722' }, - output: { name: '440' }, - }, - { - module: { - name: 'Re.RISE MS-G3 290', - color: '#67A2AA', - }, - height: { name: '1134' }, - width: { name: '1722' }, - output: { name: '240' }, - }, - ], } + + const getModuleData = async (roofsIds) => { + const list = await getModuleTypeItemList(roofsIds) + if (list.data.length > 0) { + //selectbox에 이름을 넣는다 + list.data.forEach((item) => { + item.name = item.itemNm + }) + //셀렉트박스 데이터 초기화 + setModuleList(list.data) + } + } + + useEffect(() => { + getModuleData(['FLAT_ROOF']) + }, []) + + const handleChangeModule = (option) => { + //선택된 모듈 + setSelectedModules(option) //선택값 저장 + setModuleSelectionData({ + ...moduleSelectionData, + flatModule: option, + }) + moduleSelectedDataTrigger({ + ...moduleSelectionData, + flatModule: option, + }) + } + + useEffect(() => { + if (isObjectNotEmpty(moduleSelectionData.flatModule) && moduleList.length > 0) { + handleChangeModule(moduleSelectionData.flatModule) + } + }, [moduleList]) + + const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2) + return ( <>
@@ -39,7 +70,17 @@ export default function PitchModule({}) {
{getMessage('modal.module.basic.setting.module.setting')}
- + {moduleList && ( + + )}
@@ -54,33 +95,21 @@ export default function PitchModule({}) { - {moduleData.rows.map((row) => ( - <> - - {moduleData.header.map((header) => ( - <> - {header.type === 'color-box' && ( - -
- - {row[header.prop].name} -
- - )} - {!header.type && header.type !== 'color-box' && {row[header.prop].name}} - - ))} + {selectedModules && + selectedModules.itemList && + selectedModules.itemList.map((row, index) => ( + + +
+ + {row.itemNm} +
+ + {Number(row.shortAxis).toFixed(0)} + {Number(row.longAxis).toFixed(0)} + {Number(row.wpOut).toFixed(0)} - - ))} - {Array.from({ length: 3 - moduleData.rows.length }).map((_, i) => ( - - - - - - - ))} + ))}
diff --git a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx index a292ed2d..660d3717 100644 --- a/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx +++ b/src/components/floor-plan/modal/basic/step/pitch/PitchPlacement.jsx @@ -1,49 +1,48 @@ import { forwardRef, useState, useEffect } from 'react' import { useMessage } from '@/hooks/useMessage' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' -import { canvasState } from '@/store/canvasAtom' -import { useRecoilValue } from 'recoil' +import { canvasState, checkedModuleState } from '@/store/canvasAtom' +import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { POLYGON_TYPE } from '@/common/common' import { useEvent } from '@/hooks/useEvent' +import { moduleSelectionDataState } from '@/store/selectedModuleOptions' const PitchPlacement = forwardRef((props, refs) => { const { getMessage } = useMessage() const [setupLocation, setSetupLocation] = useState('south') - const { makeModuleInstArea } = useModuleBasicSetting() const canvas = useRecoilValue(canvasState) const { initEvent } = useEvent() - useEffect(() => { - makeModuleInstArea() - }, []) + const { selectedModules } = useModuleBasicSetting(3) + const setCheckedModules = useSetRecoilState(checkedModuleState) + const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터 + const [selectedItems, setSelectedItems] = useState({}) useEffect(() => { handleChangeSetupLocation() }, [setupLocation]) + const handleSelectedItem = (e) => { + setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked }) + } + const moduleData = { header: [ { type: 'check', name: '', prop: 'check', width: 70 }, { type: 'color-box', name: getMessage('module'), prop: 'module' }, { type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 }, ], - rows: [ - { - check: false, - module: { name: 'Re.RISE-G3 440', color: '#AA6768' }, - output: { name: '440' }, - }, - { - check: false, - module: { - name: 'Re.RISE MS-G3 290', - color: '#67A2AA', - }, - output: { name: '240' }, - }, - ], } + //체크된 모듈 데이터 + useEffect(() => { + const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key]) + const moduleArray = selectedModules.itemList.filter((item) => { + return checkedModuleIds.includes(item.itemId) + }) + setCheckedModules(moduleArray) + }, [selectedItems]) + const handleSetupLocation = (e) => { initEvent() refs.setupLocation.current = e.target @@ -81,6 +80,20 @@ const PitchPlacement = forwardRef((props, refs) => { } } + useEffect(() => { + if (moduleSelectionData && moduleSelectionData.flatModule.itemList.length > 0) { + let initCheckedModule = {} + moduleSelectionData.flatModule.itemList.forEach((obj, index) => { + if (index === 0) { + initCheckedModule = { [obj.itemId]: true } + } else { + initCheckedModule = { ...initCheckedModule, [obj.itemId]: true } + } + }) + setSelectedItems(initCheckedModule) + } + }, []) + return ( <>
@@ -104,33 +117,30 @@ const PitchPlacement = forwardRef((props, refs) => { - {moduleData.rows.map((row) => ( - <> - - {moduleData.header.map((header) => ( - <> - {header.type === 'color-box' && ( - -
- - {row[header.prop].name} -
- - )} - {header.type === 'check' && ( - -
- - -
- - )} - {header.type && header.type !== 'color-box' && header.type !== 'check' && {row[header.prop].name}} - - ))} + {selectedModules.itemList && + selectedModules.itemList.map((item, index) => ( + + +
+ + +
+ + +
+ + {item.itemNm} +
+ + {item.wpOut} - - ))} + ))}
@@ -150,8 +160,7 @@ const PitchPlacement = forwardRef((props, refs) => { name="radio01" id="ra01" value={'south'} - checked={setupLocation === 'south'} - defaultChecked + defaultChecked={setupLocation === 'south'} onClick={handleSetupLocation} /> @@ -162,7 +171,7 @@ const PitchPlacement = forwardRef((props, refs) => { name="radio01" id="ra02" value={'excreta'} - checked={setupLocation === 'excreta'} + defaultChecked={setupLocation === 'excreta'} onClick={handleSetupLocation} /> diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index 3783e033..1e989963 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -1,7 +1,6 @@ import WithDraggable from '@/components/common/draggable/WithDraggable' import { useState, useEffect, useContext } from 'react' import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect' -import CircuitAllocation from '@/components/floor-plan/modal/circuitTrestle/step/CircuitAllocation' import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp' import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' @@ -20,7 +19,11 @@ import { useTrestle } from '@/hooks/module/useTrestle' import { selectedModuleState } from '@/store/selectedModuleOptions' import { v4 as uuidv4 } from 'uuid' -import { stepUpListDataState } from '@/store/circuitTrestleAtom' +import { useEstimate } from '@/hooks/useEstimate' +import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' +import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' +import { useImgLoader } from '@/hooks/floorPlan/useImgLoader' +import { usePlan } from '@/hooks/usePlan' const ALLOCATION_TYPE = { AUTO: 'auto', @@ -29,52 +32,73 @@ const ALLOCATION_TYPE = { export default function CircuitTrestleSetting({ id }) { const { getMessage } = useMessage() const { closePopup } = usePopup() - const { apply } = useTrestle() + const { apply, setViewCircuitNumberTexts } = useTrestle() const { swalFire } = useSwal() + const { saveEstimate } = useEstimate() const canvas = useRecoilValue(canvasState) - const [makers, setMakers] = useRecoilState(makersState) - const [selectedMaker, setSelectedMaker] = useRecoilState(selectedMakerState) - const [series, setSeries] = useRecoilState(seriesState) - const [models, setModels] = useRecoilState(modelsState) - const [selectedModels, setSelectedModels] = useRecoilState(selectedModelsState) - const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState) - const [tabNum, setTabNum] = useState(1) const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO) const [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({}) const [getStepUpSelections, setGetStepUpSelections] = useState(null) + // const { trigger: setCircuitData } = useCanvasPopupStatusController(4) + // const [stepUpListData, setStepUpListData] = useRecoilState(stepUpListDataState) + const [stepUpListData, setStepUpListData] = useState([]) + const [seletedOption, setSeletedOption] = useState(null) + const { setModuleStatisticsData } = useCircuitTrestle() - const [stepUpListData, setStepUpListData] = useRecoilState(stepUpListDataState) + const { handleCanvasToPng } = useImgLoader() + const { saveCanvas } = usePlan() + const { + makers, + setMakers, + selectedMaker, + setSelectedMaker, + series, + setSeries, + models, + setModels, + selectedModels, + setSelectedModels, + pcsCheck, + setPcsCheck, + getOptYn, + getPcsItemList, + getSelectedPcsItemList, + getUseModuleItemList, + getRoofSurfaceList, + getModuleList, + removeNotAllocationModules, + } = useCircuitTrestle() + // const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2) useEffect(() => { if (!managementState) { setManagementState(managementStateLoaded) } + // setCircuitData({ + // makers, + // selectedMaker, + // series, + // models, + // selectedModels, + // pcsCheck, + // }) }, []) - 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]) + // 수동할당 시 모듈 삭제 + // 시리즈중 자동으로 추천 PCS 정보 조회 const onAutoRecommend = () => { if (series.filter((s) => s.selected).length === 0) { swalFire({ - title: '시리즈를 선택해 주세요.', + title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.validation.error02'), type: 'alert', }) return @@ -87,27 +111,45 @@ 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) => { - return res.data?.pcsItemList.map((item) => item.itemId).includes(model.itemId) + let pcsItemList = [] + let pcsObj = {} + + models.forEach((model) => { + pcsObj[model.itemId] = model }) - const selectedModels = itemList.map((model) => { - return { - ...model, - id: uuidv4(), + res.data?.pcsItemList.forEach((item) => { + if (pcsObj[item.itemId]) { + pcsItemList.push({ + ...pcsObj[item.itemId], + isUsed: false, + id: uuidv4(), + }) } }) + // 회로 구성 가능 여부 체크 요청 파라미터 const pcsVoltageChkParams = { ...getOptYn(), useModuleItemList: getUseModuleItemList(), roofSurfaceList: getRoofSurfaceList(), - pcsItemList: getPcsItemList(), + pcsItemList: pcsItemList, } - setSelectedModels(selectedModels) + // 추천 목록 선택 + setSelectedModels(pcsItemList) + // 회로 구성 가능 여부 체크 getPcsVoltageChk(pcsVoltageChkParams).then((res) => { - setTabNum(2) + if (res.resultCode === 'S') { + setTabNum(2) + } else { + swalFire({ + title: res.resultMsg, + type: 'alert', + }) + } }) } else { // 데이터가 없는 경우 오류 메시지 확인 필요 @@ -125,144 +167,37 @@ export default function CircuitTrestleSetting({ id }) { } }) } else { - getPcsVoltageChk(params).then((res) => { - setTabNum(2) - }) - } - } - - const getOptYn = () => { - return { - maxConnYn: pcsCheck.max ? 'Y' : 'N', - smpCirYn: pcsCheck.division ? 'Y' : 'N', - coldZoneYn: managementState?.coldRegionFlg === '1' ? 'Y' : 'N', - } - } - - const getPcsItemList = () => { - return models.map((model) => { - return { - itemId: model.itemId, - pcsMkrCd: model.pcsMkrCd, - pcsSerCd: model.pcsSerCd, - } - }) - } - - const getUseModuleItemList = () => { - return selectedModules.itemList.map((m) => { - return { - itemId: m.itemId, - mixMatlNo: m.mixMatlNo, - } - }) - } - - const getRoofSurfaceList = () => { - return canvas - .getObjects() - .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) - .map((obj) => { - return { - roofSurfaceId: obj.id, - roofSurface: canvas - .getObjects() - .filter((o) => o.id === obj.parentId)[0] - .directionText.replace(/[0-9]/g, ''), - roofSurfaceIncl: canvas.getObjects().filter((o) => o.id === obj.parentId)[0].roofMaterial.pitch, - moduleList: getModuleList(obj).map((module) => { - return { - itemId: module.moduleInfo.itemId, - circuit: module.circuitNumber ? module.circuitNumber : null, - pcsItemId: module.circuit ? module.circuit?.pcsItemId : null, - uniqueId: module.id ? module.id : null, - } - }), + // 회로 구성 가능 여부 체크 + 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', + }) } }) - } - - const getModuleList = (surface) => { - let moduleList = [] - let [xObj, yObj] = [{}, {}] - let [xPoints, yPoints] = [[], []] - surface.modules.forEach((module) => { - if (!xObj[module.left]) { - xObj[module.left] = module.left - xPoints.push(module.left) - } - if (!yObj[module.top]) { - yObj[module.top] = module.top - yPoints.push(module.top) - } - }) - switch (surface.direction) { - case 'south': - xPoints.sort((a, b) => a - b) - yPoints.sort((a, b) => b - a) - yPoints.forEach((y, index) => { - let temp = surface.modules.filter((m) => m.top === y) - if (index % 2 === 0) { - temp.sort((a, b) => a.left - b.left) - } else { - temp.sort((a, b) => b.left - a.left) - } - moduleList = [...moduleList, ...temp] - }) - break - case 'north': - xPoints.sort((a, b) => b - a) - yPoints.sort((a, b) => a - b) - yPoints.forEach((y, index) => { - let temp = surface.modules.filter((m) => m.top === y) - if (index % 2 === 0) { - temp.sort((a, b) => b.left - a.left) - } else { - temp.sort((a, b) => a.left - b.left) - } - moduleList = [...moduleList, ...temp] - }) - break - case 'west': - xPoints.sort((a, b) => a - b) - yPoints.sort((a, b) => a - b) - xPoints.forEach((x, index) => { - let temp = surface.modules.filter((m) => m.left === x) - if (index % 2 === 0) { - temp.sort((a, b) => a.top - b.top) - } else { - temp.sort((a, b) => b.top - a.top) - } - moduleList = [...moduleList, ...temp] - }) - break - case 'east': - xPoints.sort((a, b) => b - a) - yPoints.sort((a, b) => b - a) - xPoints.forEach((x, index) => { - let temp = surface.modules.filter((m) => m.left === x) - if (index % 2 === 0) { - temp.sort((a, b) => b.top - a.top) - } else { - temp.sort((a, b) => a.top - b.top) - } - moduleList = [...moduleList, ...temp] - }) - break - default: - return [] } - return moduleList } + // 자동할당 버튼 클릭 시 const onAutoAllocation = () => { let moduleStdQty = 0 let moduleMaxQty = 0 const selectedModels = models.filter((m) => m.selected) + // 시리즈중 자동으로 추천 PCS 정보 조회 if (selectedModels.length === 0) { onAutoRecommend() } else { + // 모듈 최소 매수 moduleStdQty = selectedModels.reduce((acc, model) => { return acc + parseInt(model.moduleStdQty) }, 0) @@ -285,42 +220,71 @@ export default function CircuitTrestleSetting({ id }) { // setTabNum(2) } + // 수동할당 버튼 클릭 시 const onPassivityAllocation = () => { if (selectedModels.length === 0) { const params = { ...getOptYn(), useModuleItemList: getUseModuleItemList(), - roofSurfaceList: getRoofSurfaceList(), + roofSurfaceList: getRoofSurfaceList().map((surface) => { + return { + ...surface, + moduleList: surface.moduleList.map((module) => { + return { + itemId: module.itemId, + uniqueId: module.uniqueId, + } + }), + } + }), 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) + let pcsItemList = [] + let pcsObj = {} + models.forEach((model) => { + pcsObj[model.itemId] = model }) - const selectedModels = itemList.map((model) => { - return { - ...model, - id: uuidv4(), + res.data?.pcsItemList.forEach((item) => { + if (pcsObj[item.itemId]) { + pcsItemList.push({ + ...pcsObj[item.itemId], + isUsed: false, + id: uuidv4(), + }) } }) - const PcsVoltageChkParams = { + const pcsVoltageChkParams = { ...getOptYn(), useModuleItemList: getUseModuleItemList(), roofSurfaceList: getRoofSurfaceList(), - pcsItemList: getPcsItemList(), + pcsItemList: pcsItemList.map((item) => { + return { + itemId: item.itemId, + pcsMkrCd: item.pcsMkrCd, + pcsSerCd: item.pcsSerCd, + } + }), } - setSelectedModels(selectedModels) - getPcsVoltageChk(PcsVoltageChkParams).then((res) => {}) + setSelectedModels(pcsItemList) + 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) @@ -333,14 +297,14 @@ export default function CircuitTrestleSetting({ id }) { if (placementModules.length > target) { swalFire({ - title: '배치가능 매수를 초과합니다. 파워컨디셔너를 다시 선택해 주세요.', + title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.validation.error01'), type: 'alert', }) return } - } - setAllocationType(ALLOCATION_TYPE.PASSIVITY) + setAllocationType(ALLOCATION_TYPE.PASSIVITY) + } } // StepUp에서 선택된 값들을 처리하는 함수 수정 @@ -358,83 +322,59 @@ export default function CircuitTrestleSetting({ id }) { 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 onApply = async () => { + canvas + .getObjects() + .filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) + .map((obj) => { + obj.pcses = getStepUpListData() }) + + setViewCircuitNumberTexts(false) + + handleCanvasToPng(1) + + const result = await apply() + if (result) { + handleCanvasToPng(2) + setViewCircuitNumberTexts(true) + // 캔버스 저장 + await saveCanvas(false) + // 견적서 저장 + await saveEstimate(result) } + // removeNotAllocationModules() } + // 이전 버튼 클릭 시 const onClickPrev = () => { - setAllocationType(ALLOCATION_TYPE.AUTO) + // setAllocationType(ALLOCATION_TYPE.AUTO) swalFire({ - text: '할당한 회로 번호가 초기화됩니다.', + text: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset.info'), type: 'alert', icon: 'warning', confirmFn: () => { - const circuitModules = canvas - .getObjects() - .filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id)) + const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module') canvas.remove(...circuitModules.map((module) => module.circuit)) circuitModules.forEach((obj) => { obj.circuit = null obj.pcsItemId = null }) - setAllocationType(ALLOCATION_TYPE.AUTO) + + if (allocationType === ALLOCATION_TYPE.PASSIVITY) { + setAllocationType(ALLOCATION_TYPE.AUTO) + } else { + setTabNum(1) + } + canvas.renderAll() + setModuleStatisticsData() }, }) } + // 파워컨디셔너 컴포넌트 속성 const powerConditionalSelectProps = { tabNum, setTabNum, @@ -449,8 +389,10 @@ export default function CircuitTrestleSetting({ id }) { selectedModels, setSelectedModels, managementState, + getUseModuleItemList, } + // 수동할당 컴포넌트 속성 const passivityProps = { tabNum, setTabNum, @@ -462,18 +404,86 @@ export default function CircuitTrestleSetting({ id }) { getRoofSurfaceList, } + // 승압설정 컴포넌트 속성 const stepUpProps = { tabNum, setTabNum, models, setModels, + allocationType, circuitAllocationType, setCircuitAllocationType, + selectedModels, + setSelectedModels, + getSelectedPcsItemList, getOptYn, // 옵션 Y/N getUseModuleItemList, // 사용된 모듈아이템 List getRoofSurfaceList, // 지붕면 목록 getPcsItemList, // PCS 아이템 목록 onValuesSelected: handleStepUpValuesSelected, // 선택된 값들을 처리하는 함수 + stepUpListData, + setStepUpListData, + seletedOption, + setSeletedOption, + getModuleList, + } + + // 승압설정 목록 조회 + const getStepUpListData = () => { + return stepUpListData[0].pcsItemList.map((item) => { + return item.serQtyList + .filter((serQty) => serQty.selected) + .map((serQty) => { + return { + pcsMkrCd: item.pcsMkrCd, + pcsSerCd: item.pcsSerCd, + pcsItemId: item.itemId, + pscOptCd: seletedOption.code, + paralQty: serQty.paralQty, + connections: item.connList?.length + ? [ + { + connItemId: item.connList[0].itemId, + }, + ] + : [], + } + })[0] + }) + } + + const handleStepUp = () => { + const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit) + if (notAllocationModules.length > 0) { + swalFire({ + title: getMessage('not.allocation.exist.module'), + type: 'alert', + confirmFn: () => {}, + }) + return + // canvas.remove(...notAllocationModules) + // canvas.renderAll() + } + setTabNum(2) + } + + // 닫기 버튼 클릭 시 처리하는 함수 추가 + 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) } return ( @@ -481,7 +491,8 @@ export default function CircuitTrestleSetting({ id }) {

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

-
@@ -498,7 +509,7 @@ export default function CircuitTrestleSetting({ id }) { {tabNum === 2 && } {tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && (
- -
)} {tabNum === 2 && (
- {/* - -
-
-
{getMessage('modal.circuit.trestle.setting.circuit.allocation')}
- {circuitAllocationType === 1 && } - {circuitAllocationType === 2 && } -
- - ) -} diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx index 407c5e34..5ab5b70c 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx @@ -1,11 +1,12 @@ import { GlobalDataContext } from '@/app/GlobalDataProvider' import QSelectBox from '@/components/common/select/QSelectBox' +import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' import { useMasterController } from '@/hooks/common/useMasterController' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' import { pcsCheckState } from '@/store/circuitTrestleAtom' import { globalLocaleStore } from '@/store/localeAtom' -import { selectedModuleState } from '@/store/selectedModuleOptions' +import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { isNullOrUndefined } from '@/util/common-utils' import { useContext, useEffect, useState } from 'react' import { useRecoilState } from 'recoil' @@ -27,6 +28,7 @@ export default function PowerConditionalSelect(props) { selectedModels, setSelectedModels, managementState, + getUseModuleItemList, } = props const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState) @@ -36,9 +38,11 @@ export default function PowerConditionalSelect(props) { const { getPcsMakerList, getPcsModelList } = useMasterController() const selectedModules = useRecoilValue(selectedModuleState) const { swalFire } = useSwal() + const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2) + const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) const modelHeader = [ - { name: getMessage('시리즈'), width: '15%', prop: 'pcsSerNm', type: 'color-box' }, - { name: getMessage('명칭'), width: '15%', prop: 'itemNm', type: 'color-box' }, + { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.series'), width: '15%', prop: 'pcsSerNm', type: 'color-box' }, + { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.name'), width: '15%', prop: 'goodsNo', type: 'color-box' }, { name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.rated.output')} (kW)`, width: '10%', @@ -64,60 +68,54 @@ export default function PowerConditionalSelect(props) { useEffect(() => { if (makers.length === 0) { getPcsMakerList().then((res) => { - console.log('getPcsMakerList', res.data) setMakers(res.data) }) } }, []) - const checkValidation = () => { - const checkedSeries = series.filter((s) => s.selected) - if (checkedSeries.length === 0) { - swalFire({ - title: 'PCS 시리즈를 선택해 주세요.', - icon: 'warning', - }) - return false - } else if (checkedSeries.length === 1) { - if (checkedSeries[0].pcsMkrMultiType === 'SINGLE-P' && checkedSeries[0].pcsSerParallelYn === 'Y') { - swalFire({ - title: '병설은 단독으로 안 됨', - icon: 'warning', - }) - } - return false - } - return true - } - const onCheckSeries = (data) => { - console.log('data', data) - const copySeries = series.map((s) => { - return { - ...s, - selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.selected, - } - }) + let copySeries = [] + if (data.pcsMkrMultiType === 'MULTI') { + copySeries = series.map((s) => { + return { + ...s, + selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.selected, + } + }) + } else if (data.pcsMkrMultiType === 'SINGLE-P') { + copySeries = series.map((s) => { + return { + ...s, + selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.pcsMkrMultiType === 'MULTI' ? s.selected : false, + } + }) + } else { + copySeries = series.map((s) => { + return { + ...s, + selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : false, + } + }) + } setSeries(copySeries) - console.log('copySeries', copySeries) handleSetmodels(copySeries.filter((s) => s.selected)) } const handleSetmodels = (selectedSeries) => { - console.log('series', selectedSeries) if (selectedSeries.length === 0) { setModels([]) setSelectedModels([]) return } + console.log('moduleSelectionData', moduleSelectionData) const pcsMkrCd = selectedSeries[0]?.pcsMkrCd const pcsSerList = selectedSeries.map((series) => { return { pcsSerCd: series.pcsSerCd } }) - const moduleItemList = selectedModules.itemList?.map((module) => { + const moduleItemList = moduleSelectionData.module.itemList.map((item) => { return { - itemId: module.itemId, - mixMatlNo: module.mixMatlNo, + itemId: item.itemId, + mixMatlNo: item.mixMatlNo, } }) getPcsModelList({ pcsMkrCd, pcsSerList, moduleItemList }).then((res) => { @@ -143,13 +141,17 @@ export default function PowerConditionalSelect(props) { if (selectedRow === null) return if (selectedModels.length === 3) { swalFire({ - title: '최대 3개까지 선택할 수 있습니다.', + title: getMessage('max.select', [3]), icon: 'warning', }) return } - setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4() }]) + if (selectedMaker.pcsMkrMultiType === 'MULTI') { + setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4(), isUsed: false }]) + } else if (!selectedModels.find((m) => m.itemId === selectedRow.itemId)) { + setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4(), isUsed: false }]) + } setSelectedRow(null) } @@ -160,10 +162,14 @@ export default function PowerConditionalSelect(props) { const onChangeMaker = (option) => { if (option) { setModels([]) + setSelectedModels([]) setSelectedMaker(option) + const param = { + pcsMkrCd: option.pcsMkrCd, + mixMatlNo: moduleSelectionData.module.mixMatlNo, + } - getPcsMakerList(option).then((res) => { - console.log('getPcsMakerList(series)', res.data) + getPcsMakerList(param).then((res) => { setSeries( res.data.map((series) => { return { ...series, selected: false } @@ -198,7 +204,7 @@ export default function PowerConditionalSelect(props) {
{series?.map((series, index) => ( -
+
onCheckSeries(series)} checked={series.selected} />
@@ -238,9 +244,9 @@ export default function PowerConditionalSelect(props) {
- {selectedModels?.map((model) => ( - - {model.itemNm} + {selectedModels?.map((model, index) => ( + + {model.goodsNo} ))}
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx index 71dd3e30..e0bd7592 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/StepUp.jsx @@ -9,19 +9,36 @@ import { useRecoilState, useRecoilValue } from 'recoil' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' 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' +import { useSwal } from '@/hooks/useSwal' +import { circuitNumDisplaySelector } from '@/store/settingAtom' export default function StepUp(props) { + const { + models, + allocationType, + stepUpListData, + setStepUpListData, + seletedOption, + setSeletedOption, + selectedModels, + setSelectedModels, + getSelectedPcsItemList, + getModuleList, + } = props const { getMessage } = useMessage() + const { swalFire } = useSwal() + 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, getPcsConnOptionItemList } = useMasterController() const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext) const canvas = useRecoilValue(canvasState) const selectedModules = useRecoilValue(selectedModuleState) - const [stepUpListData, setStepUpListData] = useState([]) const [optCodes, setOptCodes] = useState([]) const [selectedRows, setSelectedRows] = useState({}) @@ -29,7 +46,7 @@ export default function StepUp(props) { // 선택된 값들을 저장할 상태 추가 const [selectedValues, setSelectedValues] = useState({}) - + const isDisplayCircuitNumber = useRecoilValue(circuitNumDisplaySelector) // useCanvasPopupStatusController(6) // const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore) // if (Object.keys(canvasPopupStatusState[6]).length !== 0) { @@ -37,34 +54,176 @@ export default function StepUp(props) { // } useEffect(() => { - // PCS 승압설정 정보 조회 - fetchStepUpData() + console.log(allocationType) + + if (allocationType === 'auto') { + // PCS 자동 승압설정 정보 조회 + fetchAutoStepUpData() + } else { + // PCS 수동 승압설정 정보 조회 + fetchPassiStepUpData() + } }, []) - // PCS 승압설정 정보 조회 - const fetchStepUpData = async () => { + // PCS 자동 승압설정 정보 조회 + const fetchAutoStepUpData = 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: props.getSelectedPcsItemList(), // PCS 아이템 목록 } - // PCS 승압설정 정보 조회 - const res = await getPcsVoltageStepUpList(params) + // 회로 구성 가능 여부 체크 통과 시 승압설정 정보 조회 + getPcsVoltageStepUpList(params).then((res) => { + if (res.result.resultCode === 'S') { + if (res?.result.code === 200 && res?.data) { + 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) + // 캔버스에 회로 정보 적용 + //stepUpListData[0].pcsItemList.forEach((pcsItem) => { + stepUpListData[0].pcsItemList.forEach((pcsItem) => { + const selectedSerQty = pcsItem.serQtyList.find((serQty) => serQty.selected) + if (selectedSerQty) { + selectedSerQty.roofSurfaceList.forEach((roofSurface) => { + const targetSurface = canvas.getObjects().filter((obj) => obj.id === roofSurface.roofSurfaceId)[0] + const moduleIds = targetSurface.modules.map((module) => module.id) + + // 기존 모듈 텍스트 삭제 + canvas + .getObjects() + .filter((obj) => moduleIds.includes(obj.parentId)) + .forEach((text) => canvas.remove(text)) + + // 새로운 모듈 회로 정보 추가 + roofSurface.moduleList.forEach((module) => { + const targetModule = canvas.getObjects().filter((obj) => obj.id === module.uniqueId)[0] + const moduleCircuitText = new fabric.Text(module.circuit, { + left: targetModule.left + targetModule.width / 2, + top: targetModule.top + targetModule.height / 2, + fill: 'black', + fontSize: 20, + width: targetModule.width, + height: targetModule.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + parentId: targetModule.id, + circuitInfo: module.pcsItemId, + selectable: false, + visible: isDisplayCircuitNumber, + }) + targetModule.circuit = moduleCircuitText + targetModule.pcsItemId = module.pcsItemId + targetModule.circuitNumber = module.circuit + canvas.add(moduleCircuitText) + }) + }) + } + }) + + canvas.renderAll() + } else { + swalFire({ + title: res.result.resultMsg, + type: 'alert', + }) + } + } + }) + } catch (error) { + console.error('Error fetching step up data:', error) + } + } + + // PCS 수동 승압설정 정보 조회 + const fetchPassiStepUpData = async () => { + try { + // 1-1 2-2 + // canvas + // .getObjects() + // .filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuit) + // .map((module) => module.circuitNumber) + + // 모듈 데이터 가져오기 + const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) + + // PCS별 회로 정보를 저장할 객체 + const pcsSummary = {} + + // 각 모듈을 순회하며 PCS별 회로 정보 수집 + modules.forEach((module) => { + if (!module.circuit || !module.pcsItemId) return + + if (!pcsSummary[module.pcsItemId]) { + pcsSummary[module.pcsItemId] = { + circuits: {}, + totalModules: 0, + } + } + + const circuitNumber = module.circuitNumber + if (!pcsSummary[module.pcsItemId].circuits[circuitNumber]) { + pcsSummary[module.pcsItemId].circuits[circuitNumber] = 0 + } + pcsSummary[module.pcsItemId].circuits[circuitNumber]++ + pcsSummary[module.pcsItemId].totalModules++ + }) + + const params = { + useModuleItemList: props.getUseModuleItemList(), + pcsItemList: getSelectedPcsItemList(), } + + // PCS 접속함 및 옵션 목록 조회 + getPcsConnOptionItemList(params).then((res) => { + if (res?.result.code === 200 && res?.data) { + // PCS 아이템 리스트에 serQtyList 추가 + const pcsItemListWithSerQty = res.data.pcsItemList.map((pcsItem) => { + const pcsData = pcsSummary[pcsItem.itemId] || { circuits: {}, totalModules: 0 } + const circuitCounts = Object.values(pcsData.circuits) + return { + ...pcsItem, + serQtyList: [ + { + // 한 회로당 최대 모듈 수 + serQty: circuitCounts.length > 0 ? Math.max(...circuitCounts) : 0, + // 회로 개수 + paralQty: Object.keys(pcsData.circuits).length || 0, + rmdYn: 'Y', + usePossYn: 'Y', + roofSurfaceList: props.getRoofSurfaceList(), + }, + ], + } + }) + + // Update res.data with modified pcsItemList + res.data.pcsItemList = pcsItemListWithSerQty + + 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]) + } + }) } catch (error) { console.error('Error fetching step up data:', error) } @@ -79,16 +238,6 @@ export default function StepUp(props) { })) } - // // PCS 승압설정 정보 포맷 - // const formatStepUpListData = (dataArray = []) => { - // return dataArray?.map((stepUps) => ({ - // ...stepUps, - // optionList: formatOptionList(stepUps.optionList), - // pcsItemList: formatPcsItemList(stepUps.pcsItemList), - // selectedPcsItem: formatPcsItemList(stepUps.pcsItemList), - // })) - // } - // PCS 승압설정 정보 포맷 후 추천 값 저장 const formatStepUpListData = (dataArray = []) => { const formattedData = dataArray?.map((stepUps) => ({ @@ -98,39 +247,6 @@ export default function StepUp(props) { 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 } @@ -145,12 +261,13 @@ export default function StepUp(props) { // PCS 아이템 포맷 const formatPcsItemList = (pcsItemList = []) => { - return pcsItemList?.map((item) => ({ + return pcsItemList?.map((item, index) => ({ goodsNo: item.goodsNo ? item.goodsNo : '', itemId: item.itemId ? item.itemId : '', itemNm: item.itemNm ? item.itemNm : '', pcsMkrCd: item.pcsMkrCd ? item.pcsMkrCd : '', pcsSerCd: item.pcsSerCd ? item.pcsSerCd : '', + uniqueIndex: `${item.itemId}_${index}`, // 고유 식별자 추가(동일한 PCS를 구분) connList: formatConnList(item.connList), serQtyList: formatSerQtyList(item.serQtyList), })) @@ -173,11 +290,13 @@ export default function StepUp(props) { // PCS 시리즈 포맷 const formatSerQtyList = (serQtyList = []) => { return serQtyList?.map((qty) => ({ + code: uuidv4(), serQty: qty.serQty ? qty.serQty : 0, paralQty: qty.paralQty ? qty.paralQty : 0, rmdYn: qty.rmdYn ? qty.rmdYn : 'N', usePossYn: qty.usePossYn ? qty.usePossYn : 'Y', roofSurfaceList: formatRoofSurfaceList(qty.roofSurfaceList), + selected: qty.rmdYn === 'Y', })) } @@ -209,79 +328,139 @@ export default function StepUp(props) { } // 행 선택 핸들러 함수 추가 - const handleRowClick = (goodsNo, pcsIdx, serQtyIdx, serQty, paralQty) => { - const rowKey = `${goodsNo}_${pcsIdx}_${serQtyIdx}` - const pcsKey = `${goodsNo}_${pcsIdx}` + const handleRowClick = (mainIdx, subIdx) => { + // 자동 승압 설정인 경우만 실행 + if (allocationType !== 'auto') return - console.log('goodsNo >> ', goodsNo, serQty, paralQty) + let tempStepUpListData = [...stepUpListData] + let selectedData = {} - // 현재 선택된 PCS 아이템 정보 가져오기 - const pcsItem = stepUpListData.find((stepUp) => stepUp.pcsItemList.find((item) => item.goodsNo === goodsNo))?.pcsItemList[pcsIdx] + tempStepUpListData[0].pcsItemList[mainIdx].serQtyList.forEach((item, index) => { + if (index === subIdx) { + selectedData = item + } + item.selected = index === subIdx + }) + // 선택된 행 정보 저장 + setStepUpListData(tempStepUpListData) - if (!pcsItem) { - console.error('PCS item not found:', { goodsNo, pcsIdx }) - return - } + // console.log('🚀 ~ handleRowClick ~ tempStepUpListData:', tempStepUpListData) + // console.log('🚀 ~ handleRowClick ~ selectedData:', selectedData) - // 선택된 값들 업데이트 - 더 자세한 정보 포함 - const selectionData = { - goodsNo: goodsNo, - pcsInfo: { - itemId: pcsItem?.itemId, - goodsNo: pcsItem?.goodsNo, - pcsMkrCd: pcsItem?.pcsMkrCd, - pcsSerCd: pcsItem?.pcsSerCd, - }, - allocation: { - serQty: serQty, - paralQty: paralQty, - }, - } + // PCS 2개 이상 또는 첫번째 PCS 선택 시에만 실행 + if (stepUpListData[0].pcsItemList.length > 1 && mainIdx === 0) { + // 파워컨디셔너 옵션 조회 요청 파라미터 + const params = { + ...props.getOptYn(), // 옵션 Y/N + useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List + roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록 + pcsItemList: props.getSelectedPcsItemList().map((pcsItem, index) => { + // PCS 아이템 목록 + // tempStepUpListData에서 해당 PCS 아이템 찾기 + // uniqueIndex를 사용하여 매칭 + const matchingPcsItem = tempStepUpListData[0].pcsItemList.find((item) => item.uniqueIndex === `${pcsItem.itemId}_${index}`) - // 선택된 값들 업데이트 - setSelectedValues((prev) => ({ - ...prev, - [goodsNo]: { - ...prev[goodsNo], - [pcsKey]: selectionData, - }, - })) + // 선택된 serQty 찾기 + const selectedSerQty = matchingPcsItem?.serQtyList.find((serQty) => serQty.selected)?.serQty || 0 - // 부모 컴포넌트에 선택된 값들 전달 - if (props.onValuesSelected) { - props.onValuesSelected(selectionData) - } - - setSelectedRows((prev) => { - // 현재 stepUpId에 대한 선택 상태가 없으면 빈 객체로 초기화 - const currentStepUpSelections = prev[goodsNo] || {} - - // 이미 선택된 행을 다시 클릭하는 경우, 선택을 해제하지 않음 - if (currentStepUpSelections[pcsKey] === rowKey) { - return prev + return { + ...pcsItem, + applySerQty: selectedSerQty, + } + }), } - return { - ...prev, - [goodsNo]: { - ...currentStepUpSelections, - [pcsKey]: rowKey, - }, + // PCS가 1개 이고 2번째 또는 3번째 PCS serQty가 0인 경우는 추천 API 실행하지 않음 + if (params.pcsItemList.length !== 1 && (params.pcsItemList[1]?.applySerQty !== 0 || params.pcsItemList[2]?.applySerQty) !== 0) { + // 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 + }) + + targetSurface.modules.map((module) => { + module.circuit = null + module.circuitNumber = null + module.pcsItemId = null + }) + + // 모듈 목록 삭제 + canvas + .getObjects() + .filter((obj) => moduleIds.includes(obj.parentId)) + .map((text) => { + canvas.remove(text) + }) + + // 모듈 목록 추가 + canvas.renderAll() + + roofSurface.moduleList.forEach((module) => { + const targetModule = canvas.getObjects().filter((obj) => obj.id === module.uniqueId)[0] + if (module.circuit === '') return + const moduleCircuitText = new fabric.Text(module.circuit, { + left: targetModule.left + targetModule.width / 2, + top: targetModule.top + targetModule.height / 2, + fill: 'black', + fontSize: 20, + width: targetModule.width, + height: targetModule.height, + textAlign: 'center', + originX: 'center', + originY: 'center', + name: 'circuitNumber', + parentId: targetModule.id, + circuitInfo: module.pcsItemId, + visible: isDisplayCircuitNumber, + }) + targetModule.circuit = moduleCircuitText + targetModule.pcsItemId = module.pcsItemId + targetModule.circuitNumber = module.circuit + canvas.add(moduleCircuitText) + }) }) - // 수동 선택 상태를 업데이트하되, 기존 추천 선택은 유지 - setIsManualSelection((prev) => ({ - ...prev, - [goodsNo]: { - ...prev[goodsNo], - [pcsKey]: true, - }, - })) + canvas.renderAll() } // 현재 선택된 값들을 가져오는 함수 추가 const getCurrentSelections = () => { + const selectedValues = stepUpListData[0].pcsItemList.forEach((item) => { + item.serQtyList.filter((serQty) => serQty.selected) + return item.serQtyList.map((serQty) => { + return { + pcsMkrCd: serQty.pcsMkrCd, + pcsSerCd: serQty.pcsSerCd, + pcsItemId: serQty.itemId, + pcsOptCd: seletedOption, + paralQty: serQty.paralQty, + connections: { + connItemId: item.connList[0].itemId, + }, + } + }) + }) + return selectedValues } @@ -310,7 +489,7 @@ export default function StepUp(props) { {/* 3개일때 className = by-max */} {stepUpListData.map((stepUp, index) => (
- {stepUp?.pcsItemList.map((_, idx) => ( + {stepUp?.pcsItemList.map((pcsItem, idx) => (
{stepUp.pcsItemList[idx].goodsNo}
@@ -323,20 +502,13 @@ export default function StepUp(props) { - {stepUp.pcsItemList[idx].serQtyList.map((item, serQtyIdx) => { - const rowKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}_${serQtyIdx}` - const pcsKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}` + {pcsItem.serQtyList.map((item, serQtyIdx) => { return ( handleRowClick(stepUp.pcsItemList[idx].goodsNo, idx, serQtyIdx, item.serQty, item.paralQty)} - style={{ cursor: 'pointer' }} + key={`row-${serQtyIdx}`} + className={`${item.selected ? 'on' : ''}`} + onClick={() => handleRowClick(idx, serQtyIdx)} + style={{ cursor: allocationType === 'auto' ? 'pointer' : 'default' }} > {item.serQty} {item.paralQty} @@ -428,7 +600,18 @@ export default function StepUp(props) { {optCodes.length > 0 && (
{/* */} - + { + return { ...roof, name: globalLocale === 'ko' ? roof.name : roof.nameJp } + })} + title={globalLocale === 'ko' ? optCodes[0].name : optCodes[0].nameJp} + value={seletedOption} + sourceKey="code" + targetKey="code" + showKey="name" + onChange={(e) => setSeletedOption(e)} + />
)}
diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/AutoCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/AutoCircuitAllocation.jsx deleted file mode 100644 index 026bbaee..00000000 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/AutoCircuitAllocation.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import { useMessage } from '@/hooks/useMessage' - -export default function AutoCircuitAllocation() { - const { getMessage } = useMessage() - return ( -
-
-
-
- - -
-
-
-
- ) -} 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 32b15236..e77c2b66 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -1,46 +1,40 @@ import { GlobalDataContext } from '@/app/GlobalDataProvider' import { POLYGON_TYPE } from '@/common/common' import { useMasterController } from '@/hooks/common/useMasterController' +import { useModule } from '@/hooks/module/useModule' +import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' import { useMessage } from '@/hooks/useMessage' import { useSwal } from '@/hooks/useSwal' import { canvasState } from '@/store/canvasAtom' import { moduleStatisticsState } from '@/store/circuitTrestleAtom' import { selectedModuleState } from '@/store/selectedModuleOptions' +import { circuitNumDisplaySelector } from '@/store/settingAtom' import { useContext, useEffect, useState } from 'react' 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 { getPcsManualConfChk } = useMasterController() + const isDisplayCircuitNumber = useRecoilValue(circuitNumDisplaySelector) + const { setModuleStatisticsData } = useCircuitTrestle() useEffect(() => { - console.log('header, rows', header, rows) - console.log('selectedModels', selectedModels) - // setSurfaceInfo() - setTableData() + setModuleStatisticsData() if (!managementState) { setManagementState(managementStateLoaded) } @@ -82,82 +76,15 @@ export default function PassivityCircuitAllocation(props) { canvas.renderAll() } - const setSurfaceInfo = () => { - const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name) - // setHeaders([header[0], { name: '회로', prop: 'circuit' }, ...header.slice(1)]) - setRows( - rows.map((row) => { - return { - ...row, - circuit: '', - } - }), - ) - let totals = {} - - rows.forEach((row) => { - if (header.length === 4) { - if (!totals[header[2].prop]) totals[header[2].prop] = 0 - totals[header[2].prop] += +row[header[2].prop] - } else if (header.length === 5) { - if (!totals[header[2].prop]) totals[header[2].prop] = 0 - totals[header[2].prop] += +row[header[2].prop] - if (!totals[header[3].prop]) totals[header[3].prop] = 0 - totals[header[3]] += +row[header[3]] - } - }) - setFooter([ - ...['합계', ''], - ...Object.keys(totals).map((key) => { - return totals[key] - }), - Object.keys(totals).reduce((acc, key) => { - return acc + totals[key] - }, 0), - ]) - // let totalWpout = 0 - // const rows = surfaces.map((surface) => { - // let wpOut = 0 - // let moduleInfo = {} - // surface.modules.forEach((module) => { - // wpOut += +module.moduleInfo.wpOut - // if (!moduleInfo[module.moduleInfo.itemId]) moduleInfo[module.moduleInfo.itemId] = 0 - // moduleInfo[module.moduleInfo.itemId]++ - // }) - // totalWpout += wpOut - // console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module) - // return { - // roofShape: DIRECTION[surface.direction], - // powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }), - // ...moduleInfo, - // } - // }) - - // setTotalWpout(totalWpout) - // 지붕면 리스트 -> 지붕면에 있는 모듈 리스트 -> 발전량 총합 계산 - // wpOut - - // setModuleData({ - // header: [ - // { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' }, - // { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' }, - // ...selectedModules.itemList.map((module) => { - // return { - // name: module.itemNm, - // prop: module.itemId, - // } - // }), - // { - // name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`, - // prop: 'powerGeneration', - // }, - // ], - // rows: rows, - // }) - } - const handleCircuitNumberFix = () => { - 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 이상입력해주세요.', @@ -173,16 +100,8 @@ 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 ( number.split('-')[1] === circuitNumber + ')' && @@ -201,11 +120,15 @@ export default function PassivityCircuitAllocation(props) { } } + let tempSelectedPcs = { ...selectedPcs } canvas.discardActiveObject() canvas .getObjects() .filter((obj) => targetModules.includes(obj.id)) .forEach((obj) => { + if (obj.circuit) { + canvas.remove(obj.circuit) + } const moduleCircuitText = new fabric.Text(getCircuitNumber(), { left: obj.left + obj.width / 2, top: obj.top + obj.height / 2, @@ -217,21 +140,33 @@ export default function PassivityCircuitAllocation(props) { originX: 'center', originY: 'center', name: 'circuitNumber', + selectable: false, parentId: obj.id, circuitInfo: selectedPcs, + visible: isDisplayCircuitNumber, }) obj.set({ strokeWidth: 0.3, }) obj.pcsItemId = selectedPcs.itemId + obj.pcsItemCode = selectedPcs.id obj.circuit = moduleCircuitText obj.circuitNumber = getCircuitNumber() + tempSelectedPcs.used = true + setSelectedPcs(tempSelectedPcs) canvas.add(moduleCircuitText) }) + let pcsList = JSON.parse(JSON.stringify(selectedModels)).map((model) => { + if (model.id === selectedPcs.id) { + model.isUsed = true + } + return model + }) + const roofSurfaceList = canvas .getObjects() - .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name) + .filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name && obj?.modules.length > 0) .map((surface) => { return { roofSurfaceId: surface.id, @@ -247,7 +182,8 @@ export default function PassivityCircuitAllocation(props) { } }) - const pcsItemList = selectedModels.map((model) => { + const usedPcses = pcsList.filter((model) => model.isUsed) + const pcsItemList = usedPcses.map((model, index) => { return { pcsMkrCd: model.pcsMkrCd, pcsSerCd: model.pcsSerCd, @@ -257,7 +193,7 @@ export default function PassivityCircuitAllocation(props) { serQtyList: [ { serQty: targetModules.length, - paralQty: 0, + paralQty: uniqueCircuitNumbers.length, rmdYn: 'Y', usePossYn: 'Y', roofSurfaceList: roofSurfaceList, @@ -273,7 +209,7 @@ export default function PassivityCircuitAllocation(props) { } getPcsManualConfChk(params).then((res) => { - if (res.resultCode === 'E') { + if (res?.resultCode === 'E') { swalFire({ text: res.resultMsg, type: 'alert', @@ -292,13 +228,16 @@ export default function PassivityCircuitAllocation(props) { canvas.renderAll() }, }) - + setSelectedPcs({ ...selectedPcs, used: false }) + setTargetModules([]) return } + setSelectedModels(pcsList) + setTargetModules([]) setCircuitNumber(+circuitNumber + 1) - setTableData() + setModuleStatisticsData() }) } @@ -310,116 +249,29 @@ 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'), + title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info'), type: 'confirm', icon: 'warning', confirmFn: () => { const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module' && obj.circuit?.circuitInfo?.id === selectedPcs.id) + const circuitNumbers = circuitModules.map((obj) => { + const circuitNumber = obj.circuitNumber.replace(/[()]/g, '').split('-') + return parseInt(circuitNumber[circuitNumber.length - 1]) + }) + const minCircuitNumber = Math.min(...circuitNumbers) canvas.remove(...circuitModules.map((module) => module.circuit)) circuitModules.forEach((obj) => { obj.circuit = null obj.pcsItemId = null }) + setCircuitNumber(minCircuitNumber) setTargetModules([]) canvas.renderAll() canvas.discardActiveObject() + setModuleStatisticsData() }, }) } @@ -427,7 +279,7 @@ export default function PassivityCircuitAllocation(props) { const initAllPcsCircuitNumber = () => { canvas.discardActiveObject() swalFire({ - title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.init.setting.info'), + title: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset.info'), type: 'confirm', icon: 'warning', confirmFn: () => { @@ -439,9 +291,9 @@ export default function PassivityCircuitAllocation(props) { obj.circuit = null obj.pcsItemId = null }) - setTargetModules([]) - canvas.renderAll() + setTargetModules([]) + setModuleStatisticsData() }, }) } @@ -479,9 +331,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]} ))} @@ -509,7 +359,7 @@ export default function PassivityCircuitAllocation(props) { onChange={() => setSelectedPcs(model)} />
))} - {/*
- - -
-
- - -
-
- - -
*/}
diff --git a/src/components/floor-plan/modal/module/PanelEdit.jsx b/src/components/floor-plan/modal/module/PanelEdit.jsx index 8e1f9fac..bfff66a2 100644 --- a/src/components/floor-plan/modal/module/PanelEdit.jsx +++ b/src/components/floor-plan/modal/module/PanelEdit.jsx @@ -36,7 +36,7 @@ export default function PanelEdit(props) { const { moduleMove, moduleCopy, moduleMultiMove, moduleMultiCopy, moduleMoveAll, moduleCopyAll } = useModule() useEffect(() => { - if (canvas) { + if (!canvas) { const isSetupModules = canvas.getObjects().filter((obj) => obj.name === 'module') // selectedObj에 없는 객체만 필터링 isSetupModules.forEach((obj) => obj.set({ lockMovementX: false, lockMovementY: false })) } @@ -52,18 +52,30 @@ export default function PanelEdit(props) { }) return } + debugger + const completeSurfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.isComplete) + + if (completeSurfaces.length > 0) { + swalFire({ + title: getMessage('modal.module.can.not.edit'), + type: 'alert', + icon: 'error', + }) + return + } + switch (type) { case PANEL_EDIT_TYPE.MOVE: moduleMove(length, direction) break case PANEL_EDIT_TYPE.MOVE_ALL: - moduleMoveAll(length, direction) + moduleMoveAll(length, direction, props.arrayData) break case PANEL_EDIT_TYPE.COPY: moduleCopy(length, direction) break case PANEL_EDIT_TYPE.COPY_ALL: - moduleCopyAll(length, direction) + moduleCopyAll(length, direction, props.arrayData) break case PANEL_EDIT_TYPE.COLUMN_MOVE: moduleMultiMove('column', length, direction) diff --git a/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx b/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx index 4b41b72e..8cd0de0e 100644 --- a/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx +++ b/src/components/floor-plan/modal/panelBatch/PanelBatchStatistics.jsx @@ -1,10 +1,16 @@ 'use client' -import { useState } from 'react' +import { useEffect, useState } from 'react' import { useMessage } from '@/hooks/useMessage' import WithDraggable from '@/components/common/draggable/WithDraggable' import { moduleStatisticsState } from '@/store/circuitTrestleAtom' -import { useRecoilValue, useResetRecoilState } from 'recoil' +import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' +import { useModule } from '@/hooks/module/useModule' +import { useEavesGableEdit } from '@/hooks/roofcover/useEavesGableEdit' +import { canvasState } from '@/store/canvasAtom' +import { POLYGON_TYPE } from '@/common/common' +import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle' +import { moduleSelectionDataState } from '@/store/selectedModuleOptions' export default function PanelBatchStatistics() { const { getMessage } = useMessage() @@ -13,7 +19,14 @@ export default function PanelBatchStatistics() { x: 0, y: 30, }) + const canvas = useRecoilValue(canvasState) const { header, rows, footer } = useRecoilValue(moduleStatisticsState) + const { setModuleStatisticsData } = useCircuitTrestle() + const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState) + + useEffect(() => { + if (moduleSelectionDataStore && moduleSelectionDataStore.module) setModuleStatisticsData() + }, []) return ( @@ -33,9 +46,7 @@ export default function PanelBatchStatistics() { {rows.map((row, index) => ( {header.map((item, i) => ( - - {typeof row[item.prop] === 'number' ? row[item.prop].toLocaleString('ko-KR', { maximumFractionDigits: 4 }) : row[item.prop]} - + {row[item.prop] ?? 0} ))} ))} diff --git a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx index 1a5ea92a..5439b303 100644 --- a/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx +++ b/src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx @@ -258,7 +258,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
{ diff --git a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx index 5bfad3e4..2374c582 100644 --- a/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting.jsx @@ -31,6 +31,7 @@ export default function ContextRoofAllocationSetting(props) { handleSaveContext, currentRoofList, handleChangeInput, + handleChangePitch, } = useRoofAllocationSetting(id) const { findCommonCode } = useCommonCode() @@ -45,114 +46,82 @@ 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 -
- -
-
- )} -
- )} - {(roof.raftAuth || roof.roofPchAuth) && ( -
+
{roof.raftAuth && (
{getMessage('modal.placement.initial.setting.rafter')} {raftCodes.length > 0 && ( -
+
)} + + {(roof.widAuth || roof.lenAuth) && ( + <> + {roof.widAuth && ( +
+
+ W +
+ { + handleChangeInput(e, 'width', index) + }} + /> +
+
+
+ )} + {roof.lenAuth && ( +
+
+ L +
+ { + handleChangeInput(e, 'length', index) + }} + /> +
+
+
+ )} + + )} {roof.roofPchAuth && (
{getMessage('hajebichi')} -
+
handleChangeInput(e, 'hajebichi', index)} />
)} -
- )} -
-
- - +
+
+ {getMessage('slope')} +
+ { + // handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index) + handleChangePitch(e, index) + }} + value={currentAngleType === 'slope' ? roof.pitch : roof.angle} + defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + /> +
+ {pitchText} +
+
+
+
+ + +
+
-
-
- ) - })} -
-
- -
-
+ ) + })} +
+
+
+ +
+
+ + )}
diff --git a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx index 0142a329..acd2291c 100644 --- a/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx +++ b/src/components/floor-plan/modal/roofAllocation/RoofAllocationSetting.jsx @@ -33,6 +33,7 @@ export default function RoofAllocationSetting(props) { handleChangeLayout, currentRoofList, handleChangeInput, + handleChangePitch, } = useRoofAllocationSetting(id) const pitchText = useRecoilValue(pitchTextSelector) const { findCommonCode } = useCommonCode() @@ -99,7 +100,7 @@ export default function RoofAllocationSetting(props) {
-
+
handleChangeRoofMaterial(e, index)} />
- {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} - {index !== 0 && } + {index === 0 && {getMessage('modal.roof.alloc.default.roof.material')}} + {index !== 0 && ( + + + + )}
-
-
- {getMessage('slope')} -
- { - handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index) - }} - defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} - /> -
- {pitchText} -
-
- {(roof.widAuth || roof.lenAuth) && ( + + {roof.raftAuth && (
- {roof.widAuth && ( -
- W -
- handleChangeInput(e, 'width', index)} - readOnly={roof.widAuth === 'R'} +
+ {getMessage('modal.placement.initial.setting.rafter')} + {raftCodes.length > 0 && ( +
+ handleChangeRaft(e, index)} />
-
- )} - {roof.lenAuth && ( -
- L -
- handleChangeInput(e, 'length', index)} - readOnly={roof.lenAuth === 'R'} - /> -
-
- )} + )} +
)} - {(roof.raftAuth || roof.roofPchAuth) && ( -
- {roof.raftAuth && ( + + {(roof.widAuth || roof.lenAuth) && ( + <> + {roof.widAuth && (
- {getMessage('modal.placement.initial.setting.rafter')} - {raftCodes.length > 0 && ( -
- handleChangeRaft(e, index)} - /> -
- )} -
-
- )} - {roof.roofPchAuth && ( -
-
- {getMessage('hajebichi')} -
+ W +
handleChangeInput(e, 'hajebichi', index)} - value={parseInt(roof.hajebichi)} - readOnly={roof.roofPchAuth === 'R'} + defaultValue={roof.width} + onChange={(e) => handleChangeInput(e, 'width', index)} + readOnly={roof.widAuth === 'R'} />
)} + {roof.lenAuth && ( +
+
+ L +
+ handleChangeInput(e, 'length', index)} + readOnly={roof.lenAuth === 'R'} + /> +
+
+
+ )} + + )} + {roof.roofPchAuth && ( +
+
+ {getMessage('hajebichi')} +
+ handleChangeInput(e, 'hajebichi', index)} + value={parseInt(roof.hajebichi)} + readOnly={roof.roofPchAuth === 'R'} + /> +
+
)} +
+
+ {getMessage('slope')} +
+ { + handleChangePitch(e, index) + }} + value={currentAngleType === 'slope' ? roof.pitch : roof.angle} + defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle} + /> +
+ {pitchText} +
+
diff --git a/src/components/main/MainContents.jsx b/src/components/main/MainContents.jsx index 3c1e184b..2985484e 100644 --- a/src/components/main/MainContents.jsx +++ b/src/components/main/MainContents.jsx @@ -14,10 +14,9 @@ import { useMainContentsController } from '@/hooks/main/useMainContentsControlle import { QcastContext } from '@/app/QcastProvider' import { useSwal } from '@/hooks/useSwal' -import BoardDetailModal from '../community/modal/BoardDetailModal' import { handleFileDown } from '@/util/board-utils' -export default function MainContents() { +export default function MainContents({ setFaqOpen, setFaqModalNoticeNo }) { const { swalFire } = useSwal() const { getMessage } = useMessage() @@ -116,10 +115,6 @@ export default function MainContents() { } } - // FAQ 팝업 관련 - const [open, setOpen] = useState(false) - const [modalNoticeNo, setModalNoticeNo] = useState('') - return (
@@ -178,7 +173,6 @@ export default function MainContents() {
- {open && }
{recentFaqList.length > 0 ? ( @@ -192,8 +186,8 @@ export default function MainContents() { className="faq-title pre" style={{ cursor: 'pointer' }} onClick={() => { - setOpen(true) - setModalNoticeNo(row.noticeNo) + setFaqOpen(true) + setFaqModalNoticeNo(row.noticeNo) }} > {row.title} diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index 2155331c..51154e92 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -149,7 +149,22 @@ export default function Stuff() { cellStyle: { textAlign: 'left' }, }, { field: 'saleStoreName', minWidth: 300, headerName: getMessage('stuff.gridHeader.saleStoreName'), cellStyle: { textAlign: 'left' } }, - { field: 'address', headerName: getMessage('stuff.gridHeader.address'), cellStyle: { textAlign: 'left' } }, + { + field: 'address', + headerName: getMessage('stuff.gridHeader.address'), + cellStyle: { textAlign: 'left' }, + cellRenderer: (params) => { + let prefName = params?.data?.prefName + let address = params?.data?.address + let showAddress + if (params?.data?.prefName && params?.data?.address) { + showAddress = prefName + ' ' + address + } else { + showAddress = null + } + return showAddress + }, + }, { field: 'dispCompanyName', headerName: getMessage('stuff.gridHeader.dispCompanyName'), cellStyle: { textAlign: 'left' } }, { field: 'receiveUser', headerName: getMessage('stuff.gridHeader.receiveUser'), cellStyle: { textAlign: 'left' } }, { @@ -215,8 +230,6 @@ export default function Stuff() { startRow: (stuffSearch.pageNo - 1) * stuffSearchParams.pageSize + 1, endRow: stuffSearchParams?.endRow, schSaleStoreId: stuffSearchParams?.schMyDataCheck ? stuffSearchParams.schSaleStoreId : '', - // schSelSaleStoreId: stuffSearchParams?.schSelSaleStoreId ? stuffSearchParams.schSelSaleStoreId : '', - // schOtherSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : '', schSelSaleStoreId: stuffSearchParams?.schMyDataCheck ? '' : stuffSearchParams.schSelSaleStoreId, schOtherSelSaleStoreId: stuffSearchParams?.schMyDataCheck ? '' : stuffSearchParams.schOtherSelSaleStoreId, schSortType: stuffSearchParams.schSortType, @@ -288,11 +301,6 @@ export default function Stuff() { stuffSearchParams.schSaleStoreId = session.storeId stuffSearchParams.schOtherSelSaleStoreId = '' stuffSearchParams.schSelSaleStoreId = '' - // if (session.storeLvl === '1') { - // stuffSearchParams.schSaleStoreId = session.storeId - // stuffSearchParams.schOtherSelSaleStoreId = '' - // stuffSearchParams.schSelSaleStoreId = '' - // } } async function fetchData() { diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index e4ef732c..e200da48 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -282,23 +282,26 @@ export default function StuffDetail() { autoHeight: true, cellStyle: { justifyContent: 'center' }, cellRenderer: (params) => { - let buttonStyle + let buttonStyle = '' + let buttonStyle2 = '' if (params.value == null) { - buttonStyle = { - display: 'none', + buttonStyle = 'none' + buttonStyle2 = 'none' + } else { + if (params?.data?.createSaleStoreId === 'T01') { + if (session?.storeId !== 'T01') { + buttonStyle = 'none' + } } - } - if (managementState?.createUser === 'T01') { - if (session.userId !== 'T01') { - // #474 - buttonStyle = { display: 'none' } + if (params?.data?.tempFlg === '1') { + buttonStyle2 = 'none' } } return ( <>