diff --git a/src/components/Main.jsx b/src/components/Main.jsx index a6c00444..cbdea01d 100644 --- a/src/components/Main.jsx +++ b/src/components/Main.jsx @@ -28,11 +28,12 @@ export default function MainPage() { const [searchForm, setSearchForm] = useRecoilState(searchState) - const { qcastState } = useContext(QcastContext) + const { qcastState, setIsGlobalLoading } = useContext(QcastContext) // 엔터 이벤트 const handleByOnKeyUp = (e) => { if (e.key === 'Enter') { + setIsGlobalLoading(true) //물건번호 일떄 if (searchRadioType === 'object') { setStuffSearch({ @@ -55,6 +56,7 @@ export default function MainPage() { // 돋보기 클릭 const handleOnSubmit = () => { + setIsGlobalLoading(true) if (searchRadioType === 'object') { setStuffSearch({ ...stuffSearch, diff --git a/src/components/community/Faq.jsx b/src/components/community/Faq.jsx index 17254f5c..d1304106 100644 --- a/src/components/community/Faq.jsx +++ b/src/components/community/Faq.jsx @@ -7,12 +7,16 @@ import Search from '@/components/community/Search' import Pagination from '@/components/community/Pagination' import Table from '@/components/community/Table' +import { useContext } from 'react' + import { useEffect, useState } from 'react' import { useResetRecoilState, useRecoilValue, useRecoilState } from 'recoil' import { useMessage } from '@/hooks/useMessage' import { searchState } from '@/store/boardAtom' +import { QcastContext } from '@/app/QcastProvider' + export default function Faq() { const { getMessage } = useMessage() const resetSearch = useResetRecoilState(searchState) @@ -21,10 +25,14 @@ export default function Faq() { const search = useRecoilValue(searchState) const [searchForm, setSearchForm] = useRecoilState(searchState) + const { setIsGlobalLoading } = useContext(QcastContext) + useEffect(() => { if (search.mainFlag === 'N') { resetSearch() } else { + //메인에서 FAQ 조회 왔을때 로딩바 해제 + setIsGlobalLoading(false) setSearchForm({ ...searchForm, mainFlag: 'N' }) } setIsInitialized(true) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 71affac4..44e706ec 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -294,6 +294,7 @@ export default function Estimate({}) { const originReset = () => { setOriginFiles([]) + estimateContextState.resetFlag = 'N' } // 삭제누른 첨부파일 복원 const returnOriginFile = (no) => { @@ -894,6 +895,7 @@ export default function Estimate({}) { } } }) + // console.log('itemList::', itemList) let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 totals.pkgTotPrice = pkgAsp * totals.totVolKw * 1000 diff --git a/src/components/estimate/popup/DocDownOptionPop.jsx b/src/components/estimate/popup/DocDownOptionPop.jsx index 6fe73c53..01a979cf 100644 --- a/src/components/estimate/popup/DocDownOptionPop.jsx +++ b/src/components/estimate/popup/DocDownOptionPop.jsx @@ -3,9 +3,9 @@ import { useState } from 'react' import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useRecoilValue } from 'recoil' -import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' +import { floorPlanObjectState, estimateState } from '@/store/floorPlanObjectAtom' -export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) { +export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDownPopLockFlg }) { const { getMessage } = useMessage() const { promisePost } = useAxios() @@ -22,6 +22,7 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) { // recoil 물건번호 const objectRecoil = useRecoilValue(floorPlanObjectState) + const estimateRecoilState = useRecoilValue(estimateState) //문서 다운로드 const handleFileDown = async () => { @@ -82,6 +83,9 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen }) { link.click() link.remove() window.URL.revokeObjectURL(fileUrl) + //문서 다운받으면 lockFlg = 1 잠금상태로! + estimateRecoilState.lockFlg = '1' + docDownPopLockFlg() } }) .catch((error) => { diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index b06f5e6e..8a244650 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -85,7 +85,11 @@ export default function CanvasMenu(props) { const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) //견적서버튼 노출용 - const [buttonStyle, setButtonStyle] = useState('') + const [buttonStyle1, setButtonStyle1] = useState('') //문서 다운로드 버튼 + const [buttonStyle2, setButtonStyle2] = useState('') //저장 버튼 + const [buttonStyle3, setButtonStyle3] = useState('') //초기화 버튼 + const [buttonStyle4, setButtonStyle4] = useState('') //견적서 복사 버튼 + const [buttonStyle5, setButtonStyle5] = useState('') //잠금 버튼 // 발전시뮬레이션 메뉴 이동 const { objectNo, pid } = floorPlanState @@ -256,22 +260,19 @@ export default function CanvasMenu(props) { // 견적서 초기화 버튼 const handleEstimateReset = () => { swalFire({ - //저장된 견적서 정보가 초기화되고, 도면정보가 반영됩니다. 정말로 초기화 하시겠습니까? - //물건정보 text: getMessage('estimate.detail.reset.confirmMsg'), type: 'confirm', confirmFn: async () => { + setIsGlobalLoading(true) const params = { objectNo: objectNo, planNo: pid, userId: sessionState.userId, } - //디테일 호출 try { await promisePost({ url: '/api/estimate/reset-estimate', data: params }).then((res) => { - setIsGlobalLoading(true) if (res.status === 201) { - swalFire({ text: getMessage('estimate.detail.copy.alertMsg'), type: 'alert' }) + swalFire({ text: getMessage('estimate.detail.reset.alertMsg'), type: 'alert' }) fetchSetting(objectNo, pid, 'R') } }) @@ -281,7 +282,7 @@ export default function CanvasMenu(props) { } }, denyFn: () => { - console.log('초기화하지 않음. 변경일시 갱신안함') + setIsGlobalLoading(false) }, }) } @@ -314,12 +315,112 @@ export default function CanvasMenu(props) { if (isObjectNotEmpty(estimateRecoilState)) { if (estimateRecoilState?.createUser === 'T01') { if (sessionState.userId !== 'T01') { - setButtonStyle('none') + setButtonStyle1('none') + setButtonStyle2('none') + setButtonStyle3('none') + setButtonStyle4('none') + setButtonStyle5('none') + } + } else { + if (estimateRecoilState?.tempFlg === '1') { + setButtonStyle1('none') + setButtonStyle2('') + setButtonStyle3('none') + setButtonStyle4('none') + setButtonStyle5('none') + } else { + if (estimateRecoilState?.tempFlg === '0' && estimateRecoilState?.lockFlg === '0') { + setButtonStyle1('') + setButtonStyle2('') + setButtonStyle3('') + setButtonStyle4('') + setButtonStyle5('') + } else { + setButtonStyle1('') + setButtonStyle2('none') + setButtonStyle3('none') + setButtonStyle4('') + setButtonStyle5('') + } } } } }, [estimateRecoilState]) + /** + * 견적서 잠금 / 해제 + * lockFlg : 0 잠금해제상태 / 1 잠금상태 + * --보낼때-- + * 0잠금해제는 1잠금으로 + * 1잠금 문서는 0 잠금해제로 + */ + const handleEstimateLockController = (estimateRecoilState) => { + swalFire({ + text: estimateRecoilState.lockFlg === '0' ? getMessage('estimate.detail.lock.alertMsg') : getMessage('estimate.detail.unlock.alertMsg'), + type: 'confirm', + confirmFn: async () => { + setIsGlobalLoading(true) + const params = { + objectNo: estimateRecoilState.objectNo, + planNo: estimateRecoilState.planNo, + lockFlg: estimateRecoilState.lockFlg === '0' ? '1' : '0', + userId: sessionState.userId, + } + try { + await promisePost({ url: '/api/estimate/save-estimate-lock', data: params }).then((res) => { + if (res.status === 201) { + estimateRecoilState.lockFlg = estimateRecoilState.lockFlg === '0' ? '1' : '0' + if (estimateRecoilState?.createUser === 'T01') { + if (sessionState.userId !== 'T01') { + setButtonStyle1('none') + setButtonStyle2('none') + setButtonStyle3('none') + setButtonStyle4('none') + setButtonStyle5('none') + } + } else { + if (estimateRecoilState?.tempFlg === '1') { + setButtonStyle1('none') + setButtonStyle2('') + setButtonStyle3('none') + setButtonStyle4('none') + setButtonStyle5('none') + } else { + if (estimateRecoilState?.tempFlg === '0' && estimateRecoilState?.lockFlg === '0') { + setButtonStyle1('') + setButtonStyle2('') + setButtonStyle3('') + setButtonStyle4('') + setButtonStyle5('') + } else { + setButtonStyle1('') + setButtonStyle2('none') + setButtonStyle3('none') + setButtonStyle4('') + setButtonStyle5('') + } + } + } + } + setIsGlobalLoading(false) + }) + } catch (error) { + setIsGlobalLoading(false) + console.log('error::::::::::::', e.response.data.message) + } + }, + }) + } + + // 문서다운로드 팝업에서 다운로드 하면 문서 잠금 + const docDownPopLockFlg = () => { + setButtonStyle1('') + setButtonStyle2('none') + setButtonStyle3('none') + setButtonStyle4('') + setButtonStyle5('') + } + return (
num === menuNumber) ? 'active' : ''}`}>
@@ -406,16 +507,17 @@ export default function CanvasMenu(props) { {menuNumber === 5 && ( <>
- - )} -
@@ -463,7 +578,9 @@ export default function CanvasMenu(props) { {[2, 3, 4].some((num) => num === menuNumber) && }
{/* 견적서(menuNumber=== 5) 상세화면인경우 문서다운로드 팝업 */} - {estimatePopupOpen && } + {estimatePopupOpen && ( + + )} {/* 견적서(menuNumber ===5)복사 팝업 */} {estimateCopyPopupOpen && }
diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 767c9581..296d8b25 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -282,7 +282,7 @@ export default function StuffDetail() { onClick={() => { //mid:5(견적서), /pid:플랜번호 setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo }) - // router.push(`/floor-plan/estimate/5/${params.data.planNo}`) + setIsGlobalLoading(true) router.push(`/floor-plan/estimate/5?pid=${params.data.planNo}&objectNo=${params.data.objectNo}`) }} > @@ -1492,6 +1492,7 @@ export default function StuffDetail() { // 그리드 더블 클릭 const getCellDoubleClicked = (params) => { if (params?.column?.colId !== 'estimateDate') { + setIsGlobalLoading(true) if (params?.data?.planNo && params?.data?.objectNo) { let objectNo = params?.data?.objectNo let planNo = params?.data?.planNo diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index 981d81a2..ed7fcde4 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -61,6 +61,8 @@ export const useEstimateController = (planNo) => { res.data.originFiles = [] res.data.originFile = [] res.data.resetFlag = 'Y' + } else { + res.data.resetFlag = 'N' } if (res.data.itemList.length > 0) { res.data.itemList.map((item) => { @@ -160,16 +162,19 @@ export const useEstimateController = (planNo) => { let itemFlg = true if (estimateData?.charger === null || estimateData?.charger?.trim().length === 0) { flag = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredCharger')) } if (estimateData?.objectName === null || estimateData?.objectName?.trim().length === 0) { flag = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredObjectName')) } if (isNaN(Date.parse(estimateData.estimateDate))) { flag = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredEstimateDate')) } @@ -177,6 +182,7 @@ export const useEstimateController = (planNo) => { let pkgAsp = estimateData.pkgAsp if (pkgAsp === '0') { flag = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredPkgAsp')) } } @@ -204,6 +210,7 @@ export const useEstimateController = (planNo) => { if (fileFlg) { if (estimateData.fileFlg === '0') { fileFlg = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredFileUpload')) } } @@ -221,6 +228,7 @@ export const useEstimateController = (planNo) => { if (item.addFlg) { if (item.itemId === '') { itemFlg = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredItemId')) } } @@ -236,6 +244,7 @@ export const useEstimateController = (planNo) => { if (item.amount < 1) { itemFlg = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredAmount')) } @@ -247,6 +256,7 @@ export const useEstimateController = (planNo) => { if (item.openFlg !== '1') { if (item.salePrice < 1) { itemFlg = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredSalePrice')) } } @@ -257,6 +267,7 @@ export const useEstimateController = (planNo) => { if (item.pkgMaterialFlg === '1') { if (isNaN(item.salePrice)) { itemFlg = false + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredSalePrice')) } } @@ -274,6 +285,7 @@ export const useEstimateController = (planNo) => { } }) if (delCnt === estimateData.itemList.length) { + setIsGlobalLoading(false) return alert(getMessage('estimate.detail.save.requiredItem')) } } @@ -292,6 +304,7 @@ export const useEstimateController = (planNo) => { await post({ url: '/api/file/fileUpload', data: formData }).then((res) => { setFileList(res) + setIsGlobalLoading(false) }) } else { setFileList([]) @@ -360,15 +373,12 @@ export const useEstimateController = (planNo) => { } //2. 상세데이터 저장 - // return try { + setIsGlobalLoading(true) await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => { - setIsGlobalLoading(true) if (res.status === 201) { estimateData.newFileList = [] - //알럿창 변경 swalFire({ text: getMessage('estimate.detail.save.alertMsg'), type: 'alert' }) - // alert(getMessage('estimate.detail.save.alertMsg')) fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo) } }) @@ -401,7 +411,6 @@ export const useEstimateController = (planNo) => { userId: session.userId, } - // return await promisePost({ url: '/api/estimate/save-estimate-copy', data: params }).then((res) => { if (res.status === 201) { if (isObjectNotEmpty(res.data)) { diff --git a/src/locales/ja.json b/src/locales/ja.json index abf15ebc..00cd7e31 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -168,6 +168,7 @@ "plan.menu.estimate.reset": "初期化", "plan.menu.estimate.copy": "見積書のコピー", "plan.menu.estimate.unLock": "ロック解除", + "plan.menu.estimate.lock": "ロック", "plan.menu.simulation": "発展シミュレーション", "plan.menu.simulation.excel": "Excel", "plan.menu.simulation.pdf": "PDF", @@ -931,7 +932,10 @@ "estimate.detail.save.requiredItemId": "製品を選択してください.", "estimate.detail.save.requiredAmount": "数量は0より大きい値を入力してください.", "estimate.detail.save.requiredSalePrice": "単価は0より大きい値を入力してください.", + "estimate.detail.reset.alertMsg": "初期化されました.", "estimate.detail.reset.confirmMsg": "保存した見積書情報が初期化され、図面情報が反映されます。本当に初期化しますか?", + "estimate.detail.lock.alertMsg": "見積書を[ロック]すると、変更できません。見積もりを編集するには、ロックを解除してください.", + "estimate.detail.unlock.alertMsg": "見積書を修正して保存", "estimate.detail.alert.delFile": "添付ファイルを完全に削除するには[保存]ボタンをクリックしてください", "estimate.detail.alert.selectDelItem": "削除する商品を選択してください.", "simulator.title.sub1": "物件番号", diff --git a/src/locales/ko.json b/src/locales/ko.json index 72d6f194..2a6fd228 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -172,6 +172,7 @@ "plan.menu.estimate.reset": "초기화", "plan.menu.estimate.copy": "견적서 복사", "plan.menu.estimate.unLock": "잠금 해제", + "plan.menu.estimate.lock": "잠금", "plan.menu.simulation": "발전 시뮬레이션", "plan.menu.simulation.excel": "Excel", "plan.menu.simulation.pdf": "PDF", @@ -940,7 +941,10 @@ "estimate.detail.save.requiredItemId": "제품을 선택해주세요.", "estimate.detail.save.requiredAmount": "수량은 0보다 큰값을 입력해주세요.", "estimate.detail.save.requiredSalePrice": "단가는 0보다 큰값을 입력해주세요.", + "estimate.detail.reset.alertMsg": "초기화 되었습니다.", "estimate.detail.reset.confirmMsg": "수기 변경(저장)한 견적 정보가 초기화되고, 최근 저장된 도면정보가 반영됩니다. 정말로 초기화하시겠습니까?", + "estimate.detail.lock.alertMsg": "견적서를 [잠금]하면, 수정할 수 없습니다. 견적서를 수정하려면 잠금해제를 하십시오", + "estimate.detail.unlock.alertMsg": "견적서를 수정하고, 저장하십시오", "estimate.detail.alert.delFile": "첨부파일을 완전히 삭제하려면 [저장]버튼을 클릭하십시오.", "estimate.detail.alert.selectDelItem": "삭제할 제품을 선택하세요.", "simulator.title.sub1": "물건번호",