Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
50d92065c0
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
import { correntObjectNoState } from '@/store/settingAtom'
|
import { correntObjectNoState } from '@/store/settingAtom'
|
||||||
import { notFound, usePathname, useSearchParams } from 'next/navigation'
|
import { notFound, usePathname, useSearchParams } from 'next/navigation'
|
||||||
// import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
|
|
||||||
// import ServerError from '../error'
|
|
||||||
import { createContext, useReducer, useState } from 'react'
|
import { createContext, useReducer, useState } from 'react'
|
||||||
import { useSetRecoilState } from 'recoil'
|
import { useSetRecoilState } from 'recoil'
|
||||||
|
|
||||||
|
|||||||
@ -3,15 +3,23 @@
|
|||||||
import FloorPlanProvider from './FloorPlanProvider'
|
import FloorPlanProvider from './FloorPlanProvider'
|
||||||
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
||||||
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
||||||
|
import { usePathname } from 'next/navigation'
|
||||||
|
|
||||||
export default function FloorPlanLayout({ children }) {
|
export default function FloorPlanLayout({ children }) {
|
||||||
console.log('🚀 ~ FloorPlanLayout ~ FloorPlanLayout:')
|
console.log('🚀 ~ FloorPlanLayout ~ FloorPlanLayout:')
|
||||||
|
const pathname = usePathname()
|
||||||
|
console.log('🚀 ~ FloorPlanLayout ~ pathname:', pathname)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FloorPlanProvider>
|
<FloorPlanProvider>
|
||||||
<FloorPlan>
|
<FloorPlan>
|
||||||
|
{pathname.includes('estimate') || pathname.includes('simulator') ? (
|
||||||
|
<div className="canvas-layout">{children}</div>
|
||||||
|
) : (
|
||||||
<CanvasLayout>{children}</CanvasLayout>
|
<CanvasLayout>{children}</CanvasLayout>
|
||||||
|
)}
|
||||||
|
{/* <CanvasLayout>{children}</CanvasLayout> */}
|
||||||
</FloorPlan>
|
</FloorPlan>
|
||||||
</FloorPlanProvider>
|
</FloorPlanProvider>
|
||||||
</>
|
</>
|
||||||
|
|||||||
18
src/app/management/stuff/tempReg/page.jsx
Normal file
18
src/app/management/stuff/tempReg/page.jsx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import StuffSubHeader from '@/components/management/StuffSubHeader'
|
||||||
|
import '@/styles/contents.scss'
|
||||||
|
import StuffDetail from '@/components/management/StuffDetail'
|
||||||
|
export default function ManagementStuffRegPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StuffSubHeader type={'temp'} />
|
||||||
|
<div className="sub-content">
|
||||||
|
<div className="sub-content-inner">
|
||||||
|
<div className="sub-content-box">
|
||||||
|
<StuffDetail />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useState, useContext } from 'react'
|
import { useEffect, useState, useContext } from 'react'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
@ -9,7 +9,7 @@ import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
|||||||
import EstimateFileUploader from './EstimateFileUploader'
|
import EstimateFileUploader from './EstimateFileUploader'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||||
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
||||||
@ -18,6 +18,8 @@ import Select, { components } from 'react-select'
|
|||||||
import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from '@/util/common-utils'
|
import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from '@/util/common-utils'
|
||||||
import ProductFeaturesPop from './popup/ProductFeaturesPop'
|
import ProductFeaturesPop from './popup/ProductFeaturesPop'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { correntObjectNoState } from '@/store/settingAtom'
|
||||||
|
import { useSearchParams } from 'next/navigation'
|
||||||
|
|
||||||
export default function Estimate({ params }) {
|
export default function Estimate({ params }) {
|
||||||
const [uniqueData, setUniqueData] = useState([])
|
const [uniqueData, setUniqueData] = useState([])
|
||||||
@ -74,6 +76,15 @@ export default function Estimate({ params }) {
|
|||||||
|
|
||||||
const { setMenuNumber } = useCanvasMenu()
|
const { setMenuNumber } = useCanvasMenu()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* objectNo 셋팅
|
||||||
|
* url로 넘어온 objectNo을 리코일에 세팅
|
||||||
|
*/
|
||||||
|
const setCurrentObjectNo = useSetRecoilState(correntObjectNoState)
|
||||||
|
const searchParams = useSearchParams()
|
||||||
|
const currentObjectNo = searchParams.get('objectNo')
|
||||||
|
setCurrentObjectNo(currentObjectNo)
|
||||||
|
|
||||||
//새로 추가한 첨부파일 props
|
//새로 추가한 첨부파일 props
|
||||||
const fileUploadProps = {
|
const fileUploadProps = {
|
||||||
uploadFiles: files,
|
uploadFiles: files,
|
||||||
@ -120,7 +131,6 @@ export default function Estimate({ params }) {
|
|||||||
let url = `/api/estimate/special-note-title-list`
|
let url = `/api/estimate/special-note-title-list`
|
||||||
get({ url: url }).then((res) => {
|
get({ url: url }).then((res) => {
|
||||||
if (isNotEmptyArray(res)) {
|
if (isNotEmptyArray(res)) {
|
||||||
//디테일 ATTR001、ATTR002、ATTR003、ATTR007、ATTR009、ATTR010、ATTR015、ATTR019
|
|
||||||
if (estimateContextState?.estimateOption) {
|
if (estimateContextState?.estimateOption) {
|
||||||
res.map((row) => {
|
res.map((row) => {
|
||||||
let estimateOption = estimateContextState?.estimateOption?.split('、')
|
let estimateOption = estimateContextState?.estimateOption?.split('、')
|
||||||
@ -140,10 +150,10 @@ export default function Estimate({ params }) {
|
|||||||
//detail과 상관없이 디폴트 체크목록
|
//detail과 상관없이 디폴트 체크목록
|
||||||
//ATTR003,ATTR007
|
//ATTR003,ATTR007
|
||||||
if (row.code === 'ATTR003') {
|
if (row.code === 'ATTR003') {
|
||||||
row.check = true
|
//row.check = true
|
||||||
}
|
}
|
||||||
if (row.code === 'ATTR007') {
|
if (row.code === 'ATTR007') {
|
||||||
row.check = true
|
//row.check = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -191,9 +201,8 @@ export default function Estimate({ params }) {
|
|||||||
}, [specialNoteList])
|
}, [specialNoteList])
|
||||||
|
|
||||||
// 견적특이사항 remark 보여주기
|
// 견적특이사항 remark 보여주기
|
||||||
const settingShowContent = (code, event) => {
|
const settingShowContent = (code) => {
|
||||||
setShowContentCode(code)
|
setShowContentCode(code)
|
||||||
event.stopPropagation()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 추가한 첨부파일 estimateContextState에 넣기
|
// 추가한 첨부파일 estimateContextState에 넣기
|
||||||
@ -203,49 +212,62 @@ export default function Estimate({ params }) {
|
|||||||
files.map((row) => {
|
files.map((row) => {
|
||||||
fileList.push(row.data)
|
fileList.push(row.data)
|
||||||
setEstimateContextState({ fileList: row.data, newFileList: fileList })
|
setEstimateContextState({ fileList: row.data, newFileList: fileList })
|
||||||
|
// setEstimateContextState({ fileList: row.data })
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
setEstimateContextState({ fileList: [] })
|
setEstimateContextState({ fileList: [], newFileList: [] })
|
||||||
}
|
}
|
||||||
}, [files])
|
}, [files])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (originFiles.length > 0) {
|
|
||||||
setEstimateContextState({
|
|
||||||
originFiles: originFiles,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}, [originFiles])
|
|
||||||
|
|
||||||
//상세에서 내려온 첨부파일 set 만들기
|
//상세에서 내려온 첨부파일 set 만들기
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isNotEmptyArray(estimateContextState.fileList)) {
|
if (isNotEmptyArray(estimateContextState.fileList)) {
|
||||||
//드래그영역 비워주기
|
//드래그영역 비워주기
|
||||||
setFiles([])
|
setFiles([])
|
||||||
setOriginFiles(estimateContextState.fileList)
|
setOriginFiles(estimateContextState.fileList)
|
||||||
|
} else {
|
||||||
|
if (originFiles.length > 0) {
|
||||||
|
if (isEmptyArray(files)) {
|
||||||
|
let file
|
||||||
|
file = originFiles.filter((item) => item.delFlg === '0')
|
||||||
|
setEstimateContextState({
|
||||||
|
originFiles: file,
|
||||||
|
})
|
||||||
|
setOriginFiles(file)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [estimateContextState?.fileList])
|
}, [estimateContextState?.fileList])
|
||||||
|
|
||||||
// 기존첨부파일 삭제 (플래그값 추가?) 저장할때 플래그값에 따라 진짜 삭제
|
// 삭제누른 첨부파일 복원
|
||||||
const deleteOriginFile = async (objectNo, no) => {
|
const returnOriginFile = (no) => {
|
||||||
const delParams = {
|
originFiles.map((file) => {
|
||||||
userId: session.userId,
|
if (file.no === no) {
|
||||||
objectNo: objectNo,
|
file.delFlg = '0'
|
||||||
no: no,
|
|
||||||
}
|
}
|
||||||
alert(getMessage('estimate.detail.alert.delFile'))
|
})
|
||||||
// await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => {
|
setOriginFiles((prev) => {
|
||||||
// if (res.status === 204) {
|
return [...prev]
|
||||||
// setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no))
|
})
|
||||||
// setEstimateContextState({
|
setEstimateContextState({
|
||||||
// fileList: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
|
originFiles: originFiles,
|
||||||
// originFiles: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
|
})
|
||||||
// newFileList: originFiles.filter((file) => file.objectNo === objectNo && file.no !== no),
|
}
|
||||||
// })
|
// 기존첨부파일 삭제 (플래그값 추가?) 저장할때 플래그값에 따라 진짜 삭제
|
||||||
|
const deleteOriginFile = (no) => {
|
||||||
|
originFiles.map((file) => {
|
||||||
|
if (file.no === no) {
|
||||||
|
file.delFlg = '1'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// alert(getMessage('plan.message.delete'))
|
setOriginFiles((prev) => {
|
||||||
// }
|
return [...prev]
|
||||||
// })
|
})
|
||||||
|
setEstimateContextState({
|
||||||
|
originFiles: originFiles,
|
||||||
|
})
|
||||||
|
alert(getMessage('estimate.detail.alert.delFile'))
|
||||||
}
|
}
|
||||||
|
|
||||||
//가격표시 option 목록 최초세팅 && 주문분류 변경시
|
//가격표시 option 목록 최초세팅 && 주문분류 변경시
|
||||||
@ -408,24 +430,26 @@ export default function Estimate({ params }) {
|
|||||||
if (isNotEmptyArray(data.data2)) {
|
if (isNotEmptyArray(data.data2)) {
|
||||||
estimateContextState.itemList.map((item) => {
|
estimateContextState.itemList.map((item) => {
|
||||||
let checkYn = false
|
let checkYn = false
|
||||||
data.data2.map((item2) => {
|
for (let i = 0; i < data.data2.length; i++) {
|
||||||
if (item2) {
|
if (data.data2[i]) {
|
||||||
if (item2.itemId === item.itemId) {
|
if (data.data2[i].itemId === item.itemId) {
|
||||||
updateList.push({
|
updateList.push({
|
||||||
...item,
|
...item,
|
||||||
openFlg: item2.unitPrice === '0.0' ? '1' : '0',
|
openFlg: data.data2[i].unitPrice === '0.0' ? '1' : '0',
|
||||||
salePrice: item2.unitPrice === null ? '0' : item2.unitPrice,
|
salePrice: data.data2[i].unitPrice === null ? '0' : data.data2[i].unitPrice,
|
||||||
saleTotPrice: (item.amount * item2.unitPrice).toString(),
|
saleTotPrice: (item.amount * data.data2[i].unitPrice).toString(),
|
||||||
})
|
})
|
||||||
checkYn = true
|
checkYn = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
if (!checkYn) {
|
if (!checkYn) {
|
||||||
updateList.push({ ...item, salePrice: '0', saleTotPrice: '0' })
|
updateList.push({ ...item, salePrice: '0', saleTotPrice: '0' })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setEstimateContextState({
|
setEstimateContextState({
|
||||||
priceCd: showPriceCd,
|
priceCd: showPriceCd,
|
||||||
itemList: updateList,
|
itemList: updateList,
|
||||||
@ -472,7 +496,7 @@ export default function Estimate({ params }) {
|
|||||||
//주택PKG input 변경
|
//주택PKG input 변경
|
||||||
const onChangePkgAsp = (value) => {
|
const onChangePkgAsp = (value) => {
|
||||||
if (estimateContextState.estimateType === 'YJSS') {
|
if (estimateContextState.estimateType === 'YJSS') {
|
||||||
let pkgAsp = Number(value.replace(/[^0-9]/g, '').replaceAll(',', ''))
|
let pkgAsp = Number(value.replace(/[^-\.0-9]/g, '').replaceAll(',', ''))
|
||||||
if (isNaN(pkgAsp)) {
|
if (isNaN(pkgAsp)) {
|
||||||
pkgAsp = 0
|
pkgAsp = 0
|
||||||
} else {
|
} else {
|
||||||
@ -485,7 +509,7 @@ export default function Estimate({ params }) {
|
|||||||
|
|
||||||
setEstimateContextState({
|
setEstimateContextState({
|
||||||
pkgAsp: pkgAsp,
|
pkgAsp: pkgAsp,
|
||||||
pkgTotPrice: pkgTotPrice.toFixed(3),
|
pkgTotPrice: pkgTotPrice.toFixed(2),
|
||||||
})
|
})
|
||||||
//아이템들 중 조건에 맞는애들 뽑아서 상단 공급가액 부가세 총액 수정
|
//아이템들 중 조건에 맞는애들 뽑아서 상단 공급가액 부가세 총액 수정
|
||||||
setItemChangeYn(true)
|
setItemChangeYn(true)
|
||||||
@ -496,6 +520,7 @@ export default function Estimate({ params }) {
|
|||||||
const onChangeAmount = (value, dispOrder, index) => {
|
const onChangeAmount = (value, dispOrder, index) => {
|
||||||
//itemChangeFlg = 1, partAdd = 0 셋팅
|
//itemChangeFlg = 1, partAdd = 0 셋팅
|
||||||
let amount = Number(value.replace(/[^0-9]/g, '').replaceAll(',', ''))
|
let amount = Number(value.replace(/[^0-9]/g, '').replaceAll(',', ''))
|
||||||
|
|
||||||
if (isNaN(amount)) {
|
if (isNaN(amount)) {
|
||||||
amount = '0'
|
amount = '0'
|
||||||
} else {
|
} else {
|
||||||
@ -584,14 +609,12 @@ export default function Estimate({ params }) {
|
|||||||
updates.pkgMaterialFlg = res.pkgMaterialFlg
|
updates.pkgMaterialFlg = res.pkgMaterialFlg
|
||||||
updates.pnowW = res.pnowW
|
updates.pnowW = res.pnowW
|
||||||
updates.salePrice = res.salePrice
|
updates.salePrice = res.salePrice
|
||||||
// updates.salePrice = ''
|
|
||||||
updates.specification = res.specification
|
updates.specification = res.specification
|
||||||
updates.unit = res.unit
|
updates.unit = res.unit
|
||||||
updates.specialNoteCd = res.spnAttrCds
|
updates.specialNoteCd = res.spnAttrCds
|
||||||
updates.itemGroup = res.itemGroup
|
updates.itemGroup = res.itemGroup
|
||||||
updates.delFlg = '0' // 삭제플래그 0
|
updates.delFlg = '0' // 삭제플래그 0
|
||||||
updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString()
|
updates.saleTotPrice = (res.salePrice * estimateContextState.itemList[index].amount).toString()
|
||||||
// updates.saleTotPrice = ''
|
|
||||||
updates.amount = ''
|
updates.amount = ''
|
||||||
updates.openFlg = res.openFlg
|
updates.openFlg = res.openFlg
|
||||||
|
|
||||||
@ -622,7 +645,6 @@ export default function Estimate({ params }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (item.paDispOrder === dispOrder) {
|
} else if (item.paDispOrder === dispOrder) {
|
||||||
//봄제품을 바꿨을떄
|
|
||||||
return { ...item, delFlg: '1' }
|
return { ...item, delFlg: '1' }
|
||||||
} else {
|
} else {
|
||||||
return item
|
return item
|
||||||
@ -639,12 +661,14 @@ export default function Estimate({ params }) {
|
|||||||
bomItem.salePrice = '0'
|
bomItem.salePrice = '0'
|
||||||
bomItem.saleTotPrice = '0'
|
bomItem.saleTotPrice = '0'
|
||||||
bomItem.unitPrice = '0'
|
bomItem.unitPrice = '0'
|
||||||
|
bomItem.showSalePrice = '0'
|
||||||
} else {
|
} else {
|
||||||
bomItem.dispOrder = (index + 1 + Number(dispOrder)).toString()
|
bomItem.dispOrder = (index + 1 + Number(dispOrder)).toString()
|
||||||
bomItem.paDispOrder = dispOrder
|
bomItem.paDispOrder = dispOrder
|
||||||
bomItem.salePrice = '0'
|
bomItem.salePrice = '0'
|
||||||
bomItem.saleTotPrice = '0'
|
bomItem.saleTotPrice = '0'
|
||||||
bomItem.unitPrice = '0'
|
bomItem.unitPrice = '0'
|
||||||
|
bomItem.showSalePrice = '0'
|
||||||
}
|
}
|
||||||
|
|
||||||
bomItem.delFlg = '0'
|
bomItem.delFlg = '0'
|
||||||
@ -653,6 +677,7 @@ export default function Estimate({ params }) {
|
|||||||
bomItem.addFlg = true //봄 추가시도 addFlg
|
bomItem.addFlg = true //봄 추가시도 addFlg
|
||||||
})
|
})
|
||||||
|
|
||||||
|
updateList = updateList.filter((item) => item.delFlg === '0')
|
||||||
setEstimateContextState({
|
setEstimateContextState({
|
||||||
itemList: [...updateList, ...bomList],
|
itemList: [...updateList, ...bomList],
|
||||||
})
|
})
|
||||||
@ -729,15 +754,24 @@ export default function Estimate({ params }) {
|
|||||||
delete item.showSaleTotPrice
|
delete item.showSaleTotPrice
|
||||||
if (item.delFlg === '0') {
|
if (item.delFlg === '0') {
|
||||||
let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0
|
let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0
|
||||||
let price = Number(item.saleTotPrice?.replaceAll(',', '')) || 0
|
let price
|
||||||
|
if (amount === 0) {
|
||||||
|
price = 0
|
||||||
|
} else {
|
||||||
|
price = Number(item.saleTotPrice?.replaceAll(',', '')) || 0
|
||||||
|
}
|
||||||
|
|
||||||
if (item.moduleFlg === '1') {
|
if (item.moduleFlg === '1') {
|
||||||
const volKw = (item.pnowW * amount) / 1000
|
const volKw = (item.pnowW * amount) / 1000
|
||||||
totals.totVolKw += volKw
|
totals.totVolKw += volKw
|
||||||
}
|
}
|
||||||
totals.totAmount += amount
|
|
||||||
totals.supplyPrice += price
|
totals.supplyPrice += price
|
||||||
|
totals.totAmount += amount
|
||||||
|
|
||||||
|
if (item.paDispOrder) {
|
||||||
|
item.showSalePrice = '0'
|
||||||
|
item.showSaleTotPrice = '0'
|
||||||
|
}
|
||||||
if (item.openFlg === '1') {
|
if (item.openFlg === '1') {
|
||||||
item.showSalePrice = '0'
|
item.showSalePrice = '0'
|
||||||
item.showSaleTotPrice = '0'
|
item.showSaleTotPrice = '0'
|
||||||
@ -755,12 +789,16 @@ export default function Estimate({ params }) {
|
|||||||
itemList.forEach((item) => {
|
itemList.forEach((item) => {
|
||||||
if (item.delFlg === '0') {
|
if (item.delFlg === '0') {
|
||||||
let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0
|
let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0
|
||||||
let salePrice = Number(item.salePrice?.replaceAll(',', '')) || 0
|
let salePrice
|
||||||
|
|
||||||
if (item.moduleFlg === '1') {
|
if (item.moduleFlg === '1') {
|
||||||
const volKw = (item.pnowW * amount) / 1000
|
const volKw = (item.pnowW * amount) / 1000
|
||||||
totals.totVolKw += volKw
|
totals.totVolKw += volKw
|
||||||
}
|
}
|
||||||
|
if (amount === 0) {
|
||||||
|
salePrice = 0
|
||||||
|
} else {
|
||||||
|
salePrice = Number(item.salePrice?.replaceAll(',', '')) || 0
|
||||||
|
}
|
||||||
|
|
||||||
totals.totAmount += amount
|
totals.totAmount += amount
|
||||||
if (item.pkgMaterialFlg === '1') {
|
if (item.pkgMaterialFlg === '1') {
|
||||||
@ -773,6 +811,14 @@ export default function Estimate({ params }) {
|
|||||||
item.showSalePrice = '0'
|
item.showSalePrice = '0'
|
||||||
item.showSaleTotPrice = '0'
|
item.showSaleTotPrice = '0'
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
item.showSalePrice = '0'
|
||||||
|
item.showSaleTotPrice = '0'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.openFlg === '1') {
|
||||||
|
item.showSalePrice = '0'
|
||||||
|
item.showSaleTotPrice = '0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -782,25 +828,24 @@ export default function Estimate({ params }) {
|
|||||||
totals.vatPrice = totals.supplyPrice * 0.1
|
totals.vatPrice = totals.supplyPrice * 0.1
|
||||||
totals.totPrice = totals.supplyPrice + totals.vatPrice
|
totals.totPrice = totals.supplyPrice + totals.vatPrice
|
||||||
}
|
}
|
||||||
|
|
||||||
if (estimateContextState.estimateType === 'YJOD') {
|
if (estimateContextState.estimateType === 'YJOD') {
|
||||||
calculateYJODTotals(estimateContextState.itemList)
|
calculateYJODTotals(estimateContextState.itemList)
|
||||||
setEstimateContextState({
|
setEstimateContextState({
|
||||||
totAmount: totals.totAmount,
|
totAmount: totals.totAmount,
|
||||||
totVolKw: totals.totVolKw.toFixed(3),
|
totVolKw: totals.totVolKw.toFixed(2),
|
||||||
supplyPrice: totals.supplyPrice.toFixed(3),
|
supplyPrice: totals.supplyPrice.toFixed(0), //소수첫자리에서 반올림
|
||||||
vatPrice: totals.vatPrice.toFixed(3),
|
vatPrice: totals.vatPrice.toFixed(0), //소수첫자리에서 반올림
|
||||||
totPrice: totals.totPrice.toFixed(3),
|
totPrice: totals.totPrice.toFixed(0), //소수첫자리에서 반올림
|
||||||
})
|
})
|
||||||
} else if (estimateContextState.estimateType === 'YJSS') {
|
} else if (estimateContextState.estimateType === 'YJSS') {
|
||||||
calculateYJSSTotals(estimateContextState.itemList)
|
calculateYJSSTotals(estimateContextState.itemList)
|
||||||
setEstimateContextState({
|
setEstimateContextState({
|
||||||
pkgTotPrice: totals.pkgTotPrice,
|
pkgTotPrice: totals.pkgTotPrice,
|
||||||
totAmount: totals.totAmount,
|
totAmount: totals.totAmount,
|
||||||
totVolKw: totals.totVolKw.toFixed(3),
|
totVolKw: totals.totVolKw.toFixed(2),
|
||||||
supplyPrice: totals.supplyPrice.toFixed(3),
|
supplyPrice: totals.supplyPrice.toFixed(0), //소수첫자리에서 반올림
|
||||||
vatPrice: totals.vatPrice.toFixed(3),
|
vatPrice: totals.vatPrice.toFixed(0), //소수첫자리에서 반올림
|
||||||
totPrice: totals.totPrice.toFixed(3),
|
totPrice: totals.totPrice.toFixed(0), //소수첫자리에서 반올림
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,16 +1059,14 @@ export default function Estimate({ params }) {
|
|||||||
let constructSpecificationMulti = estimateContextState?.constructSpecificationMulti?.split('、')
|
let constructSpecificationMulti = estimateContextState?.constructSpecificationMulti?.split('、')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className={`form-flex-wrap ${style}`} key={`roof_${row}`}>
|
||||||
<div className={`form-flex-wrap ${style}`} key={fixedKey}>
|
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
||||||
<div className="input-wrap mr5" style={{ width: '610px' }} key={`roof${index}`}>
|
|
||||||
<input type="text" className="input-light" value={roofList} readOnly />
|
<input type="text" className="input-light" value={roofList} readOnly />
|
||||||
</div>
|
</div>
|
||||||
<div className="input-wrap" style={{ width: '200px' }}>
|
<div className="input-wrap" style={{ width: '200px' }}>
|
||||||
<input type="text" className="input-light" value={constructSpecificationMulti[index]} readOnly />
|
<input type="text" className="input-light" value={constructSpecificationMulti[index]} readOnly />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</td>
|
</td>
|
||||||
@ -1110,18 +1153,38 @@ export default function Estimate({ params }) {
|
|||||||
<ul className="file-list">
|
<ul className="file-list">
|
||||||
{originFiles.map((originFile) => {
|
{originFiles.map((originFile) => {
|
||||||
return (
|
return (
|
||||||
<li className="file-item" key={uuidv4()}>
|
<li className="file-item" key={originFile.no}>
|
||||||
<span onClick={() => handleEstimateFileDownload(originFile)}>
|
{/* <li className="file-item" key={uuidv4()}> */}
|
||||||
|
<div className="file-item-wrap">
|
||||||
|
<span
|
||||||
|
style={{ display: originFile.delFlg === '0' ? '' : 'none' }}
|
||||||
|
onClick={() => handleEstimateFileDownload(originFile)}
|
||||||
|
>
|
||||||
{originFile.faileName}
|
{originFile.faileName}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="delete"
|
className="delete"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
deleteOriginFile(originFile.objectNo, originFile.no)
|
deleteOriginFile(originFile.no)
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
</span>
|
</span>
|
||||||
|
<div className="return-wrap" style={{ display: originFile.delFlg !== '0' ? '' : 'none' }}>
|
||||||
|
<span className="return">{originFile.faileName}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="return-btn"
|
||||||
|
onClick={(e) => {
|
||||||
|
returnOriginFile(originFile.no)
|
||||||
|
e.stopPropagation()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<i className="return-ico"></i>
|
||||||
|
{getMessage('estimate.detail.fileList2.btn.return')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
@ -1154,22 +1217,31 @@ export default function Estimate({ params }) {
|
|||||||
{specialNoteList.length > 0 &&
|
{specialNoteList.length > 0 &&
|
||||||
specialNoteList.map((row) => {
|
specialNoteList.map((row) => {
|
||||||
return (
|
return (
|
||||||
<div key={uuidv4()} className="special-note-check-item">
|
// <div key={uuidv4()} className="special-note-check-item">
|
||||||
|
<div key={row.code} className="special-note-check-item">
|
||||||
|
<div className="special-note-check-box">
|
||||||
<div className="d-check-box light">
|
<div className="d-check-box light">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id={row.code}
|
id={row.code}
|
||||||
checked={!!row.check}
|
checked={!!row.check}
|
||||||
disabled={row.code === 'ATTR001' ? true : false}
|
disabled={row.code === 'ATTR001' || row.pkgYn === '1' ? true : false}
|
||||||
onChange={(event) => {
|
onChange={() => {
|
||||||
setSpecialNoteList((specialNote) =>
|
setSpecialNoteList((specialNote) =>
|
||||||
specialNote.map((temp) => (temp.code === row.code ? { ...temp, check: !temp.check } : temp)),
|
specialNote.map((temp) => (temp.code === row.code ? { ...temp, check: !temp.check } : temp)),
|
||||||
)
|
)
|
||||||
|
|
||||||
settingShowContent(row.code, event)
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={row.code}>{row.codeNm}</label>
|
<label htmlFor={row.code}></label>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className="check-name"
|
||||||
|
onClick={() => {
|
||||||
|
settingShowContent(row.code)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{row.codeNm}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -1185,7 +1257,7 @@ export default function Estimate({ params }) {
|
|||||||
|
|
||||||
if (isObjectNotEmpty(showcontent)) {
|
if (isObjectNotEmpty(showcontent)) {
|
||||||
return (
|
return (
|
||||||
<dl key={uuidv4()}>
|
<dl key={row.code}>
|
||||||
<dt>{showcontent.codeNm}</dt>
|
<dt>{showcontent.codeNm}</dt>
|
||||||
<dd dangerouslySetInnerHTML={{ __html: showcontent.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
<dd dangerouslySetInnerHTML={{ __html: showcontent.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
||||||
</dl>
|
</dl>
|
||||||
@ -1200,12 +1272,23 @@ export default function Estimate({ params }) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
return pushData.map((item) => (
|
//제품에 있는 특이사항만 보여주기 제품에 특이사항이 없으면 전부
|
||||||
<dl key={uuidv4()}>
|
let filterData = pushData.filter((item) => uniqueData.includes(item.code))
|
||||||
|
if (filterData.length > 0) {
|
||||||
|
return filterData.map((item) => (
|
||||||
|
<dl key={item.code}>
|
||||||
<dt>{item.codeNm}</dt>
|
<dt>{item.codeNm}</dt>
|
||||||
<dd dangerouslySetInnerHTML={{ __html: item.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
<dd dangerouslySetInnerHTML={{ __html: item.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
||||||
</dl>
|
</dl>
|
||||||
))
|
))
|
||||||
|
} else {
|
||||||
|
return pushData.map((item) => (
|
||||||
|
<dl key={item.code}>
|
||||||
|
<dt>{item.codeNm}</dt>
|
||||||
|
<dd dangerouslySetInnerHTML={{ __html: item.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
||||||
|
</dl>
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})}
|
})}
|
||||||
@ -1231,19 +1314,19 @@ export default function Estimate({ params }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="estimate-box">
|
<div className="estimate-box">
|
||||||
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totVolKw')}</div>
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totVolKw')}</div>
|
||||||
<div className="estimate-name blue">{convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 3)}</div>
|
<div className="estimate-name blue">{convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 2)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="estimate-box">
|
<div className="estimate-box">
|
||||||
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.supplyPrice')}</div>
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.supplyPrice')}</div>
|
||||||
<div className="estimate-name blue">{convertNumberToPriceDecimal(estimateContextState?.supplyPrice)}</div>
|
<div className="estimate-name blue">{convertNumberToPriceDecimalToFixed(estimateContextState?.supplyPrice, 0)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="estimate-box">
|
<div className="estimate-box">
|
||||||
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vatPrice')}</div>
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vatPrice')}</div>
|
||||||
<div className="estimate-name blue">{convertNumberToPriceDecimal(estimateContextState?.vatPrice)}</div>
|
<div className="estimate-name blue">{convertNumberToPriceDecimalToFixed(estimateContextState?.vatPrice, 0)}</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="estimate-box">
|
<div className="estimate-box">
|
||||||
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPrice')}</div>
|
<div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPrice')}</div>
|
||||||
<div className="estimate-name red">{convertNumberToPriceDecimal(estimateContextState?.totPrice)}</div>
|
<div className="estimate-name red">{convertNumberToPriceDecimalToFixed(estimateContextState?.totPrice, 0)}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1277,7 +1360,7 @@ export default function Estimate({ params }) {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
|
||||||
<td>{convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 3)}</td>
|
<td>{convertNumberToPriceDecimalToFixed(estimateContextState?.totVolKw, 2)}</td>
|
||||||
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
|
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
|
||||||
<td>{convertNumberToPriceDecimal(estimateContextState?.pkgTotPrice)}</td>
|
<td>{convertNumberToPriceDecimal(estimateContextState?.pkgTotPrice)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -1292,14 +1375,19 @@ export default function Estimate({ params }) {
|
|||||||
<div className="select-wrap">
|
<div className="select-wrap">
|
||||||
{session?.storeLvl === '1' ? (
|
{session?.storeLvl === '1' ? (
|
||||||
<select
|
<select
|
||||||
key={uuidv4()}
|
// key={uuidv4()}
|
||||||
className="select-light"
|
className="select-light"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
onChangeStorePriceList(e.target.value)
|
onChangeStorePriceList(e.target.value)
|
||||||
}}
|
}}
|
||||||
value={showPriceCd}
|
value={showPriceCd}
|
||||||
>
|
>
|
||||||
{storePriceList.length > 0 && storePriceList.map((row) => <option value={row.priceCd}>{row.priceNm}</option>)}
|
{storePriceList.length > 0 &&
|
||||||
|
storePriceList.map((row) => (
|
||||||
|
<option key={row.priceCd} value={row.priceCd}>
|
||||||
|
{row.priceNm}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
</select>
|
</select>
|
||||||
) : (
|
) : (
|
||||||
<select key={uuidv4()} className="select-light">
|
<select key={uuidv4()} className="select-light">
|
||||||
@ -1409,7 +1497,7 @@ export default function Estimate({ params }) {
|
|||||||
<div className="form-flex-wrap">
|
<div className="form-flex-wrap">
|
||||||
<div className="select-wrap mr5">
|
<div className="select-wrap mr5">
|
||||||
<Select
|
<Select
|
||||||
id="long-value-select1"
|
name="long-value-select1"
|
||||||
instanceId="long-value-select1"
|
instanceId="long-value-select1"
|
||||||
className="react-select-custom"
|
className="react-select-custom"
|
||||||
classNamePrefix="custom"
|
classNamePrefix="custom"
|
||||||
@ -1477,7 +1565,9 @@ export default function Estimate({ params }) {
|
|||||||
className="input-light al-r"
|
className="input-light al-r"
|
||||||
value={convertNumberToPriceDecimal(item?.showSalePrice === '0' ? null : item?.salePrice?.replaceAll(',', ''))}
|
value={convertNumberToPriceDecimal(item?.showSalePrice === '0' ? null : item?.salePrice?.replaceAll(',', ''))}
|
||||||
disabled={
|
disabled={
|
||||||
estimateContextState?.estimateType === 'YJSS'
|
item.openFlg === '1'
|
||||||
|
? true
|
||||||
|
: estimateContextState?.estimateType === 'YJSS'
|
||||||
? item?.paDispOrder
|
? item?.paDispOrder
|
||||||
? true
|
? true
|
||||||
: item.pkgMaterialFlg !== '1'
|
: item.pkgMaterialFlg !== '1'
|
||||||
@ -1501,7 +1591,15 @@ export default function Estimate({ params }) {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="al-r">
|
<td className="al-r">
|
||||||
{convertNumberToPriceDecimal(item?.showSaleTotPrice === '0' ? null : item?.saleTotPrice?.replaceAll(',', ''))}
|
{convertNumberToPriceDecimal(
|
||||||
|
item?.showSaleTotPrice === '0'
|
||||||
|
? null
|
||||||
|
: item?.amount === ''
|
||||||
|
? null
|
||||||
|
: item?.saleTotPrice === '0'
|
||||||
|
? null
|
||||||
|
: item?.saleTotPrice?.replaceAll(',', ''),
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -40,9 +40,8 @@ export default function ProductFeaturesPop({ popShowSpecialNoteList, showProduct
|
|||||||
{showSpecialNoteList.length > 0 &&
|
{showSpecialNoteList.length > 0 &&
|
||||||
showSpecialNoteList.map((row) => {
|
showSpecialNoteList.map((row) => {
|
||||||
return (
|
return (
|
||||||
<dl>
|
<dl key={row.code}>
|
||||||
<dt>{row.codeNm}</dt>
|
<dt>{row.codeNm}</dt>
|
||||||
{/* <dd dangerouslySetInnerHTML={{ __html: row.remarks }}></dd> */}
|
|
||||||
<dd dangerouslySetInnerHTML={{ __html: row.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
<dd dangerouslySetInnerHTML={{ __html: row.remarks }} style={{ whiteSpace: 'pre-wrap' }}></dd>
|
||||||
</dl>
|
</dl>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -318,11 +318,11 @@ export default function CanvasMenu(props) {
|
|||||||
<div className="ico-btn-from">
|
<div className="ico-btn-from">
|
||||||
<button className="btn-frame gray ico-flx" onClick={() => setEstimatePopupOpen(true)}>
|
<button className="btn-frame gray ico-flx" onClick={() => setEstimatePopupOpen(true)}>
|
||||||
<span className="ico ico01"></span>
|
<span className="ico ico01"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.docDown')}</span>
|
<span className="name">{getMessage('plan.menu.estimate.docDown')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
<button className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
||||||
<span className="ico ico02"></span>
|
<span className="ico ico02"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.save')}</span>
|
<span className="name">{getMessage('plan.menu.estimate.save')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn-frame gray ico-flx"
|
className="btn-frame gray ico-flx"
|
||||||
@ -331,7 +331,7 @@ export default function CanvasMenu(props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="ico ico03"></span>
|
<span className="ico ico03"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.reset')}</span>
|
<span className="name">{getMessage('plan.menu.estimate.reset')}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{estimateRecoilState?.docNo !== null && (sessionState.storeId === 'T01' || sessionState.storeLvl === '1') && (
|
{estimateRecoilState?.docNo !== null && (sessionState.storeId === 'T01' || sessionState.storeLvl === '1') && (
|
||||||
@ -342,9 +342,13 @@ export default function CanvasMenu(props) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="ico ico04"></span>
|
<span className="ico ico04"></span>
|
||||||
<span>{getMessage('plan.menu.estimate.copy')}</span>
|
<span className="name">{getMessage('plan.menu.estimate.copy')}</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
<button className="btn-frame gray ico-flx">
|
||||||
|
<span className="ico ico05"></span>
|
||||||
|
<span className="name">{getMessage('plan.menu.estimate.unLock')}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
const orientationRef = useRef(null)
|
const orientationRef = useRef(null)
|
||||||
const { initEvent } = useEvent()
|
const { initEvent } = useEvent()
|
||||||
// const { initEvent } = useContext(EventContext)
|
// const { initEvent } = useContext(EventContext)
|
||||||
const { makeModuleInstArea, manualModuleSetup, autoModuleSetup } = useModuleBasicSetting()
|
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting()
|
||||||
const handleBtnNextStep = () => {
|
const handleBtnNextStep = () => {
|
||||||
if (tabNum === 1) {
|
if (tabNum === 1) {
|
||||||
orientationRef.current.handleNextStep()
|
orientationRef.current.handleNextStep()
|
||||||
@ -28,20 +28,16 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
setTabNum(tabNum + 1)
|
setTabNum(tabNum + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
makeModuleInstArea() //기붕 모듈설치면 생성
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
initEvent() //모듈설치면 선택 이벤트 삭제
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const placementRef = {
|
const placementRef = {
|
||||||
isChidori: useRef('false'),
|
isChidori: useRef('false'),
|
||||||
setupLocation: useRef('center'),
|
setupLocation: useRef('center'),
|
||||||
isMaxSetup: useRef('false'),
|
isMaxSetup: useRef('false'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const placementFlatRef = {
|
||||||
|
setupLocation: useRef('south'),
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap lx-2`}>
|
<div className={`modal-pop-wrap lx-2`}>
|
||||||
@ -66,7 +62,9 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
|
|
||||||
{/*배치면 초기설정 - 입력방법: 육지붕*/}
|
{/*배치면 초기설정 - 입력방법: 육지붕*/}
|
||||||
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && tabNum === 2 && <PitchModule setTabNum={setTabNum} />}
|
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && tabNum === 2 && <PitchModule setTabNum={setTabNum} />}
|
||||||
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && tabNum === 3 && <PitchPlacement setTabNum={setTabNum} />}
|
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet == 3 && tabNum === 3 && (
|
||||||
|
<PitchPlacement setTabNum={setTabNum} ref={placementFlatRef} />
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
{tabNum !== 1 && (
|
{tabNum !== 1 && (
|
||||||
@ -80,7 +78,10 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
Next
|
Next
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{tabNum === 3 && (
|
{tabNum === 3 && (
|
||||||
|
<>
|
||||||
|
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet != 3 && (
|
||||||
<>
|
<>
|
||||||
<button className="btn-frame modal mr5" onClick={manualModuleSetup}>
|
<button className="btn-frame modal mr5" onClick={manualModuleSetup}>
|
||||||
{getMessage('modal.module.basic.setting.passivity.placement')}
|
{getMessage('modal.module.basic.setting.passivity.placement')}
|
||||||
@ -90,6 +91,18 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{canvasSetting.roofSizeSet && canvasSetting.roofSizeSet === 3 && (
|
||||||
|
<>
|
||||||
|
<button className="btn-frame modal mr5" onClick={() => manualFlatroofModuleSetup(placementFlatRef)}>
|
||||||
|
{getMessage('modal.module.basic.setting.passivity.placement')}
|
||||||
|
</button>
|
||||||
|
<button className="btn-frame modal act" onClick={() => autoFlatroofModuleSetup(placementFlatRef)}>
|
||||||
|
{getMessage('modal.module.basic.setting.auto.placement')}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
|
import { forwardRef, useEffect, useState } from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { forwardRef, useState } from 'react'
|
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||||
|
|
||||||
const Placement = forwardRef((props, refs) => {
|
const Placement = forwardRef((props, refs) => {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
@ -7,6 +8,12 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
const [setupLocation, setSetupLocation] = useState('center')
|
const [setupLocation, setSetupLocation] = useState('center')
|
||||||
const [isMaxSetup, setIsMaxSetup] = useState('false')
|
const [isMaxSetup, setIsMaxSetup] = useState('false')
|
||||||
|
|
||||||
|
const { makeModuleInstArea } = useModuleBasicSetting()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
makeModuleInstArea()
|
||||||
|
}, [])
|
||||||
|
|
||||||
const moduleData = {
|
const moduleData = {
|
||||||
header: [
|
header: [
|
||||||
{ type: 'check', name: '', prop: 'check', width: 70 },
|
{ type: 'check', name: '', prop: 'check', width: 70 },
|
||||||
|
|||||||
@ -1,7 +1,26 @@
|
|||||||
|
import { forwardRef, useState, useEffect } from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||||
|
import { compasDegAtom } from '@/store/orientationAtom'
|
||||||
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
export default function PitchPlacement() {
|
const PitchPlacement = forwardRef((props, refs) => {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
const [setupLocation, setSetupLocation] = useState('south')
|
||||||
|
const { makeModuleInstArea } = useModuleBasicSetting()
|
||||||
|
const compasDeg = useRecoilValue(compasDegAtom)
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
makeModuleInstArea()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
handleChangeSetupLocation()
|
||||||
|
}, [setupLocation])
|
||||||
|
|
||||||
const moduleData = {
|
const moduleData = {
|
||||||
header: [
|
header: [
|
||||||
{ type: 'check', name: '', prop: 'check', width: 70 },
|
{ type: 'check', name: '', prop: 'check', width: 70 },
|
||||||
@ -24,6 +43,45 @@ export default function PitchPlacement() {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleSetupLocation = (e) => {
|
||||||
|
refs.setupLocation.current = e.target
|
||||||
|
setSetupLocation(e.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeSetupLocation = () => {
|
||||||
|
if (setupLocation === 'south') {
|
||||||
|
canvas.getObjects().forEach((obj) => obj.name === 'flatExcretaLine' && canvas.remove(obj))
|
||||||
|
return null
|
||||||
|
} else {
|
||||||
|
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
|
||||||
|
moduleSetupSurfaces.forEach((surface, index) => {
|
||||||
|
console.log(`surface ${index} : `, surface)
|
||||||
|
|
||||||
|
const excretaLine = surface.lines
|
||||||
|
|
||||||
|
excretaLine.forEach((line) => {
|
||||||
|
line.set({
|
||||||
|
stroke: '#642EFB',
|
||||||
|
strokeWidth: 5,
|
||||||
|
surfaceId: surface.surfaceId,
|
||||||
|
name: 'flatExcretaLine',
|
||||||
|
})
|
||||||
|
canvas.add(line)
|
||||||
|
|
||||||
|
line.on('selected', () => {
|
||||||
|
excretaLine.forEach((obj) => obj.set({ stroke: '#642EFB', isSelected: false }))
|
||||||
|
if (!line.isSelected) {
|
||||||
|
line.set({ stroke: 'red', isSelected: true })
|
||||||
|
} else {
|
||||||
|
line.set({ stroke: '#642EFB', isSelected: false })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="module-table-box mb10">
|
<div className="module-table-box mb10">
|
||||||
@ -88,11 +146,26 @@ export default function PitchPlacement() {
|
|||||||
<div className="hexagonal-item">
|
<div className="hexagonal-item">
|
||||||
<div className="pop-form-radio">
|
<div className="pop-form-radio">
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio01" id="ra01" />
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id="ra01"
|
||||||
|
value={'south'}
|
||||||
|
checked={setupLocation === 'south'}
|
||||||
|
defaultChecked
|
||||||
|
onChange={handleSetupLocation}
|
||||||
|
/>
|
||||||
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
|
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="d-check-radio pop">
|
<div className="d-check-radio pop">
|
||||||
<input type="radio" name="radio01" id="ra02" />
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="radio01"
|
||||||
|
id="ra02"
|
||||||
|
value={'excreta'}
|
||||||
|
checked={setupLocation === 'excreta'}
|
||||||
|
onChange={handleSetupLocation}
|
||||||
|
/>
|
||||||
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
|
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -102,4 +175,6 @@ export default function PitchPlacement() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
|
export default PitchPlacement
|
||||||
|
|||||||
@ -1,113 +1,26 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRecoilState } from 'recoil'
|
|
||||||
|
|
||||||
import { canvasSettingState } from '@/store/canvasAtom'
|
|
||||||
import { basicSettingState } from '@/store/settingAtom'
|
|
||||||
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide'
|
import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide'
|
||||||
import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide'
|
import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
|
|
||||||
|
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
||||||
|
|
||||||
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
|
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
|
||||||
const [objectNo, setObjectNo] = useState('test123241008001') // 후에 삭제 필요
|
|
||||||
const [showSizeGuideModal, setShowSizeGuidModal] = useState(false)
|
const [showSizeGuideModal, setShowSizeGuidModal] = useState(false)
|
||||||
const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false)
|
const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false)
|
||||||
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(1)
|
|
||||||
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
|
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { get, post } = useAxios()
|
|
||||||
const { swalFire } = useSwal()
|
const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting()
|
||||||
|
|
||||||
// 데이터를 최초 한 번만 조회
|
// 데이터를 최초 한 번만 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('PlacementShapeSetting useEffect 실행')
|
fetchBasicSettings()
|
||||||
|
}, [])
|
||||||
fetchSettings()
|
|
||||||
}, [objectNo])
|
|
||||||
|
|
||||||
// PlacementShapeSetting 조회 및 초기화
|
|
||||||
const fetchSettings = async () => {
|
|
||||||
try {
|
|
||||||
await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${objectNo}` }).then((res) => {
|
|
||||||
if (res.length == 0) return
|
|
||||||
|
|
||||||
// 'roofs' 배열을 생성하여 각 항목을 추가
|
|
||||||
const roofsRow = res.map((item) => {
|
|
||||||
return {
|
|
||||||
roofSizeSet: item.roofSizeSet,
|
|
||||||
roofAngleSet: item.roofAngleSet,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const roofsArray = res.some((item) => !item.roofSeq)
|
|
||||||
? //최초 지붕재 추가 정보의 경우 roofsArray를 초기화 설정
|
|
||||||
res.map(() => ({
|
|
||||||
roofApply: true,
|
|
||||||
roofSeq: 1,
|
|
||||||
roofType: 1,
|
|
||||||
roofWidth: 200,
|
|
||||||
roofHeight: 200,
|
|
||||||
roofHajebichi: 200,
|
|
||||||
roofGap: 0,
|
|
||||||
roofLayout: 'parallel',
|
|
||||||
}))
|
|
||||||
: res.map((item) => ({
|
|
||||||
roofApply: item.roofApply === '' || item.roofApply === false ? false : true,
|
|
||||||
roofSeq: item.roofSeq,
|
|
||||||
roofType: item.roofType,
|
|
||||||
roofWidth: item.roofWidth,
|
|
||||||
roofHeight: item.roofHeight,
|
|
||||||
roofHajebichi: item.roofHajebichi,
|
|
||||||
roofGap: item.roofGap,
|
|
||||||
roofLayout: item.roofLayout,
|
|
||||||
}))
|
|
||||||
console.log('roofsArray ', roofsArray)
|
|
||||||
// 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음
|
|
||||||
const patternData = {
|
|
||||||
roofSizeSet: roofsRow[0].roofSizeSet, // 첫 번째 항목의 값을 사용
|
|
||||||
roofAngleSet: roofsRow[0].roofAngleSet, // 첫 번째 항목의 값을 사용
|
|
||||||
roofs: roofsArray, // 만들어진 roofs 배열
|
|
||||||
}
|
|
||||||
|
|
||||||
// 데이터 설정
|
|
||||||
setBasicSettings({ ...patternData })
|
|
||||||
})
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Data fetching error:', error)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
|
|
||||||
setBasicSettings({ ...canvasSetting })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitCanvasConfig = async () => {
|
|
||||||
try {
|
|
||||||
const patternData = {
|
|
||||||
objectNo,
|
|
||||||
roofSizeSet: basicSetting.roofSizeSet,
|
|
||||||
roofAngleSet: basicSetting.roofAngleSet,
|
|
||||||
roofMaterialsAddList: basicSetting.roofs,
|
|
||||||
}
|
|
||||||
|
|
||||||
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
|
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
|
||||||
})
|
|
||||||
|
|
||||||
//Recoil 설정
|
|
||||||
setCanvasSetting({ ...basicSetting })
|
|
||||||
} catch (error) {
|
|
||||||
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to update the roofType and corresponding values
|
// Function to update the roofType and corresponding values
|
||||||
const handleRoofTypeChange = (index, value) => {
|
const handleRoofTypeChange = (index, value) => {
|
||||||
@ -122,7 +35,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
|||||||
roofWidth: 265,
|
roofWidth: 265,
|
||||||
roofHeight: 235,
|
roofHeight: 235,
|
||||||
roofGap: 455,
|
roofGap: 455,
|
||||||
hajebichi: 0,
|
roofHajebichi: 0,
|
||||||
}
|
}
|
||||||
} else if (roofType === 2) {
|
} else if (roofType === 2) {
|
||||||
updatedRoofs[index] = {
|
updatedRoofs[index] = {
|
||||||
@ -490,7 +403,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
<button className="btn-frame modal act" onClick={() => submitCanvasConfig()}>
|
<button className="btn-frame modal act" onClick={() => basicSettingSave()}>
|
||||||
{getMessage('modal.common.save')}
|
{getMessage('modal.common.save')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -14,7 +14,7 @@ export default function SizeGuide({ setShowSizeGuidModal }) {
|
|||||||
<div className="placement-table light">
|
<div className="placement-table light">
|
||||||
<table>
|
<table>
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style={{ width: '60px' }} />
|
<col style={{ width: '65px' }} />
|
||||||
<col />
|
<col />
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
@ -96,7 +96,8 @@ export default function Header(props) {
|
|||||||
name: 'header.menus.management',
|
name: 'header.menus.management',
|
||||||
url: '',
|
url: '',
|
||||||
children: [
|
children: [
|
||||||
{ id: 3, name: 'header.menus.management.newStuff', url: '/management/stuff/tempdetail', children: [] },
|
// { id: 3, name: 'header.menus.management.newStuff', url: '/management/stuff/tempdetail', children: [] },
|
||||||
|
{ id: 3, name: 'header.menus.management.newStuff', url: '/management/stuff/tempReg', children: [] },
|
||||||
{ id: 4, name: 'header.menus.management.stuffList', url: '/management/stuff', children: [] },
|
{ id: 4, name: 'header.menus.management.stuffList', url: '/management/stuff', children: [] },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -154,7 +155,9 @@ export default function Header(props) {
|
|||||||
onMouseEnter={(e) => ToggleonMouse(e, 'add', 'li > ul')}
|
onMouseEnter={(e) => ToggleonMouse(e, 'add', 'li > ul')}
|
||||||
onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'li > ul')}
|
onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'li > ul')}
|
||||||
>
|
>
|
||||||
<Link href={m.url}>{getMessage(m.name)}</Link>
|
<Link scroll={false} href={m.url}>
|
||||||
|
{getMessage(m.name)}
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -128,9 +128,9 @@ export default function MainContents() {
|
|||||||
className="recently-item"
|
className="recently-item"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (row.tempFlg === '0') {
|
if (row.tempFlg === '0') {
|
||||||
router.push(`/management/stuff/detail?objectNo=${row.objectNo.toString()}`)
|
router.push(`/management/stuff/detail?objectNo=${row.objectNo.toString()}`, { scroll: false })
|
||||||
} else {
|
} else {
|
||||||
router.push(`/management/stuff/tempdetail?objectNo=${row.objectNo.toString()}`)
|
router.push(`/management/stuff/tempdetail?objectNo=${row.objectNo.toString()}`, { scroll: false })
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -75,7 +75,7 @@ export default function StuffDetail() {
|
|||||||
installHeight: '', //설치높이
|
installHeight: '', //설치높이
|
||||||
conType: '0', //계약조건(잉여 / 전량)
|
conType: '0', //계약조건(잉여 / 전량)
|
||||||
remarks: '', //메모
|
remarks: '', //메모
|
||||||
tempFlag: 'T', //임시저장(1) 저장(0)
|
tempFlg: 'T', //임시저장(1) 저장(0)
|
||||||
}
|
}
|
||||||
const { register, setValue, getValues, handleSubmit, resetField, control, watch } = useForm({
|
const { register, setValue, getValues, handleSubmit, resetField, control, watch } = useForm({
|
||||||
defaultValues: formInitValue,
|
defaultValues: formInitValue,
|
||||||
@ -108,7 +108,6 @@ export default function StuffDetail() {
|
|||||||
|
|
||||||
const [editMode, setEditMode] = useState('NEW')
|
const [editMode, setEditMode] = useState('NEW')
|
||||||
const { managementState, setManagementState } = useContext(ManagementContext)
|
const { managementState, setManagementState } = useContext(ManagementContext)
|
||||||
|
|
||||||
const [planGridProps, setPlanGridProps] = useState({
|
const [planGridProps, setPlanGridProps] = useState({
|
||||||
planGridData: [],
|
planGridData: [],
|
||||||
isPageable: false,
|
isPageable: false,
|
||||||
@ -135,6 +134,7 @@ export default function StuffDetail() {
|
|||||||
field: 'moduleModel',
|
field: 'moduleModel',
|
||||||
headerName: getMessage('stuff.detail.planGridHeader.moduleModel'),
|
headerName: getMessage('stuff.detail.planGridHeader.moduleModel'),
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
wrapText: true,
|
||||||
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/ },
|
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/ },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -283,6 +283,7 @@ export default function StuffDetail() {
|
|||||||
{getMessage('stuff.detail.planGrid.btn1')}
|
{getMessage('stuff.detail.planGrid.btn1')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
style={buttonStyle}
|
||||||
type="button"
|
type="button"
|
||||||
className="grid-btn"
|
className="grid-btn"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -321,7 +322,7 @@ export default function StuffDetail() {
|
|||||||
} else {
|
} else {
|
||||||
setManagementState({})
|
setManagementState({})
|
||||||
alert(getMessage('stuff.detail.header.notExistObjectNo'))
|
alert(getMessage('stuff.detail.header.notExistObjectNo'))
|
||||||
router.push('/management/stuff')
|
router.push('/management/stuff', { scroll: false })
|
||||||
}
|
}
|
||||||
if (isNotEmptyArray(res.data.planList)) {
|
if (isNotEmptyArray(res.data.planList)) {
|
||||||
setPlanGridProps({ ...planGridProps, planGridData: res.data.planList })
|
setPlanGridProps({ ...planGridProps, planGridData: res.data.planList })
|
||||||
@ -333,7 +334,7 @@ export default function StuffDetail() {
|
|||||||
setPlanGridProps({ ...planGridProps, planGridData: [] })
|
setPlanGridProps({ ...planGridProps, planGridData: [] })
|
||||||
|
|
||||||
alert(getMessage('stuff.detail.header.notExistObjectNo'))
|
alert(getMessage('stuff.detail.header.notExistObjectNo'))
|
||||||
router.push('/management/stuff')
|
router.push('/management/stuff', { scroll: false })
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
@ -516,7 +517,6 @@ export default function StuffDetail() {
|
|||||||
firstList = res
|
firstList = res
|
||||||
favList = res.filter((row) => row.priority !== 'B')
|
favList = res.filter((row) => row.priority !== 'B')
|
||||||
otherList = res.filter((row) => row.firstAgentYn === 'N')
|
otherList = res.filter((row) => row.firstAgentYn === 'N')
|
||||||
|
|
||||||
setSaleStoreList(firstList)
|
setSaleStoreList(firstList)
|
||||||
setFavoriteStoreList(firstList)
|
setFavoriteStoreList(firstList)
|
||||||
setShowSaleStoreList(firstList)
|
setShowSaleStoreList(firstList)
|
||||||
@ -547,6 +547,9 @@ export default function StuffDetail() {
|
|||||||
form.setValue('otherSaleStoreLevel', managementState.saleStoreLevel)
|
form.setValue('otherSaleStoreLevel', managementState.saleStoreLevel)
|
||||||
|
|
||||||
form.setValue('saleStoreLevel', '1')
|
form.setValue('saleStoreLevel', '1')
|
||||||
|
|
||||||
|
form.setValue('saleStoreId', managementState.firstAgentId)
|
||||||
|
setSelOptions(managementState.firstAgentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
//설계의뢰No.
|
//설계의뢰No.
|
||||||
@ -896,6 +899,8 @@ export default function StuffDetail() {
|
|||||||
|
|
||||||
//팝업에서 넘어온 설계의뢰 정보로 바꾸기
|
//팝업에서 넘어온 설계의뢰 정보로 바꾸기
|
||||||
const setPlanReqInfo = (info) => {
|
const setPlanReqInfo = (info) => {
|
||||||
|
// console.log('session 정보:::::::', session)
|
||||||
|
// console.log('설계의뢰에서 넘어온 정보:::::::', info)
|
||||||
form.setValue('planReqNo', info.planReqNo)
|
form.setValue('planReqNo', info.planReqNo)
|
||||||
form.setValue('objectStatusId', info.building)
|
form.setValue('objectStatusId', info.building)
|
||||||
setSelectObjectStatusId(info.building)
|
setSelectObjectStatusId(info.building)
|
||||||
@ -1376,7 +1381,7 @@ export default function StuffDetail() {
|
|||||||
} else {
|
} else {
|
||||||
resetStuffRecoil()
|
resetStuffRecoil()
|
||||||
}
|
}
|
||||||
router.push('/management/stuff')
|
router.push('/management/stuff', { scroll: false })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2032,8 +2037,8 @@ export default function StuffDetail() {
|
|||||||
onChange={onSelectionChange}
|
onChange={onSelectionChange}
|
||||||
getOptionLabel={(x) => x.saleStoreName}
|
getOptionLabel={(x) => x.saleStoreName}
|
||||||
getOptionValue={(x) => x.saleStoreId}
|
getOptionValue={(x) => x.saleStoreId}
|
||||||
isClearable={managementState.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false}
|
isClearable={managementState?.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false}
|
||||||
isDisabled={managementState.tempFlg === '0' ? true : session?.storeLvl !== '1' ? true : false}
|
isDisabled={managementState?.tempFlg === '0' ? true : session?.storeLvl !== '1' ? true : false}
|
||||||
value={saleStoreList.filter(function (option) {
|
value={saleStoreList.filter(function (option) {
|
||||||
return option.saleStoreId === selOptions
|
return option.saleStoreId === selOptions
|
||||||
})}
|
})}
|
||||||
@ -2066,7 +2071,7 @@ export default function StuffDetail() {
|
|||||||
getOptionValue={(x) => x.saleStoreId}
|
getOptionValue={(x) => x.saleStoreId}
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
isDisabled={
|
isDisabled={
|
||||||
managementState.tempFlg === '0'
|
managementState?.tempFlg === '0'
|
||||||
? true
|
? true
|
||||||
: session?.storeLvl !== '1'
|
: session?.storeLvl !== '1'
|
||||||
? true
|
? true
|
||||||
@ -2151,9 +2156,13 @@ export default function StuffDetail() {
|
|||||||
getOptionLabel={(x) => x.saleStoreName}
|
getOptionLabel={(x) => x.saleStoreName}
|
||||||
getOptionValue={(x) => x.saleStoreId}
|
getOptionValue={(x) => x.saleStoreId}
|
||||||
isDisabled={
|
isDisabled={
|
||||||
managementState.tempFlg === '0' ? true : session?.storeLvl === '1' && form.watch('saleStoreId') != '' ? false : true
|
managementState?.tempFlg === '0'
|
||||||
|
? true
|
||||||
|
: session?.storeLvl === '1' && form.watch('saleStoreId') != ''
|
||||||
|
? false
|
||||||
|
: true
|
||||||
}
|
}
|
||||||
isClearable={managementState.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false}
|
isClearable={managementState?.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false}
|
||||||
value={otherSaleStoreList.filter(function (option) {
|
value={otherSaleStoreList.filter(function (option) {
|
||||||
return option.saleStoreId === otherSelOptions
|
return option.saleStoreId === otherSelOptions
|
||||||
})}
|
})}
|
||||||
|
|||||||
@ -564,7 +564,8 @@ export default function StuffSearchCondition() {
|
|||||||
<h3>{getMessage('stuff.search.title')}</h3>
|
<h3>{getMessage('stuff.search.title')}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="left-unit-box">
|
<div className="left-unit-box">
|
||||||
<Link href="/management/stuff/tempdetail" scroll={false}>
|
<Link href="/management/stuff/tempReg" scroll={false}>
|
||||||
|
{/* <Link href="/management/stuff/tempdetail" scroll={false}> */}
|
||||||
<button type="button" className="btn-origin navy mr5">
|
<button type="button" className="btn-origin navy mr5">
|
||||||
{getMessage('stuff.search.btn.register')}
|
{getMessage('stuff.search.btn.register')}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useContext, useEffect, useReducer, useState } from 'react'
|
|||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty, isEmptyArray, isNotEmptyArray } from '@/util/common-utils'
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useRouter } from 'next/navigation'
|
import { useRouter } from 'next/navigation'
|
||||||
@ -18,6 +18,9 @@ const updateItemInList = (itemList, dispOrder, updates) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useEstimateController = (planNo) => {
|
export const useEstimateController = (planNo) => {
|
||||||
|
const [fileList, setFileList] = useState([])
|
||||||
|
const [deleteFileList, setDeleteFileList] = useState([])
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
@ -39,6 +42,12 @@ export const useEstimateController = (planNo) => {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (fileList.length > 0) {
|
||||||
|
realSave(fileList)
|
||||||
|
}
|
||||||
|
}, [fileList])
|
||||||
|
|
||||||
// 상세 조회
|
// 상세 조회
|
||||||
const fetchSetting = async (objectNo, planNo) => {
|
const fetchSetting = async (objectNo, planNo) => {
|
||||||
try {
|
try {
|
||||||
@ -50,6 +59,7 @@ export const useEstimateController = (planNo) => {
|
|||||||
item.delFlg = '0'
|
item.delFlg = '0'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
setEstimateContextState(res.data)
|
setEstimateContextState(res.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,19 +156,22 @@ export const useEstimateController = (planNo) => {
|
|||||||
return alert(getMessage('estimate.detail.save.requiredEstimateDate'))
|
return alert(getMessage('estimate.detail.save.requiredEstimateDate'))
|
||||||
}
|
}
|
||||||
|
|
||||||
//첨부파일을 첨부안했는데
|
//기존에 첨부된 파일이 있으면 파일첨부관련 통과
|
||||||
//아이템 fileUploadFlg가1(첨부파일 필수)이 1개라도 있는데 후일 자료 제출(fileFlg) 체크안했으면(0) alert 저장안돼
|
|
||||||
console.log('새로추가첨부파일:::', estimateData.newFileList)
|
|
||||||
console.log('기존첨부파일:::', estimateData.originFiles)
|
|
||||||
|
|
||||||
// return
|
|
||||||
|
|
||||||
if (estimateData?.originFiles?.length > 0) {
|
if (estimateData?.originFiles?.length > 0) {
|
||||||
|
let cnt = estimateData.originFiles.filter((file) => file.delFlg === '0').length
|
||||||
|
|
||||||
|
if (cnt == 0) {
|
||||||
|
originFileFlg = false
|
||||||
|
} else {
|
||||||
originFileFlg = true
|
originFileFlg = true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (flag) {
|
if (flag) {
|
||||||
if (!originFileFlg) {
|
if (!originFileFlg) {
|
||||||
if (estimateData.newFileList?.length < 1) {
|
//기존에 첨부된 파일이 없으면
|
||||||
|
if (isEmptyArray(estimateData.newFileList)) {
|
||||||
|
//새로 첨부한 파일이 없으면
|
||||||
if (estimateData.itemList.length > 1) {
|
if (estimateData.itemList.length > 1) {
|
||||||
estimateData.itemList.map((row) => {
|
estimateData.itemList.map((row) => {
|
||||||
if (row.delFlg === '0') {
|
if (row.delFlg === '0') {
|
||||||
@ -181,9 +194,8 @@ export const useEstimateController = (planNo) => {
|
|||||||
estimateData.itemList.map((item) => {
|
estimateData.itemList.map((item) => {
|
||||||
if (item.delFlg === '0') {
|
if (item.delFlg === '0') {
|
||||||
item.amount = item.amount?.replaceAll(',', '')
|
item.amount = item.amount?.replaceAll(',', '')
|
||||||
item.salePrice = parseFloat(item.salePrice?.replaceAll(',', '')).toFixed(2)
|
item.salePrice = Number(item.salePrice?.replaceAll(',', '')).toFixed(2)
|
||||||
item.saleTotPrice = parseFloat(item.saleTotPrice?.replaceAll(',', '')).toFixed(2)
|
item.saleTotPrice = Number(item.saleTotPrice?.replaceAll(',', '')).toFixed(2)
|
||||||
|
|
||||||
if (!item.paDispOrder) {
|
if (!item.paDispOrder) {
|
||||||
if (itemFlg) {
|
if (itemFlg) {
|
||||||
if (isNaN(item.amount)) {
|
if (isNaN(item.amount)) {
|
||||||
@ -214,6 +226,17 @@ export const useEstimateController = (planNo) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
estimateData.itemList = estimateData.itemList.filter((item) => item.delFlg === '0' || !item.addFlg)
|
||||||
|
|
||||||
|
let delCnt = 0
|
||||||
|
estimateData.itemList.map((item) => {
|
||||||
|
if (item.delFlg === '1') {
|
||||||
|
delCnt++
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (delCnt === estimateData.itemList.length) {
|
||||||
|
return alert(getMessage('estimate.detail.save.requiredItem'))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag && fileFlg && itemFlg) {
|
if (flag && fileFlg && itemFlg) {
|
||||||
@ -228,24 +251,18 @@ export const useEstimateController = (planNo) => {
|
|||||||
formData.append('category', '10')
|
formData.append('category', '10')
|
||||||
formData.append('userId', estimateData.userId)
|
formData.append('userId', estimateData.userId)
|
||||||
|
|
||||||
await post({ url: '/api/file/fileUpload', data: formData })
|
await post({ url: '/api/file/fileUpload', data: formData }).then((res) => {
|
||||||
}
|
setFileList(res)
|
||||||
|
|
||||||
//첨부파일저장끝
|
|
||||||
|
|
||||||
//제품라인 추가했는데 아이템 안고르고 저장하면itemId=''은 날리고 나머지 저장하기
|
|
||||||
// estimateData.itemList = estimateData.itemList.filter((item) => item.itemId !== '')
|
|
||||||
estimateData.itemList = estimateData.itemList.filter((item) => item.delFlg === '0' || !item.addFlg)
|
|
||||||
|
|
||||||
let delCnt = 0
|
|
||||||
estimateData.itemList.map((item) => {
|
|
||||||
if (item.delFlg === '1') {
|
|
||||||
delCnt++
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
if (delCnt === estimateData.itemList.length) {
|
} else {
|
||||||
return alert(getMessage('estimate.detail.save.requiredItem'))
|
setFileList([])
|
||||||
|
realSave()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const realSave = async (fileList) => {
|
||||||
|
//첨부파일저장끝
|
||||||
|
|
||||||
let option = []
|
let option = []
|
||||||
estimateData.itemList.forEach((item) => {
|
estimateData.itemList.forEach((item) => {
|
||||||
@ -287,13 +304,30 @@ export const useEstimateController = (planNo) => {
|
|||||||
estimateOptions = estimateOptionsArray.join('、')
|
estimateOptions = estimateOptionsArray.join('、')
|
||||||
|
|
||||||
estimateData.estimateOption = estimateOptions
|
estimateData.estimateOption = estimateOptions
|
||||||
console.log('최종아이템:::', estimateData.itemList)
|
// console.log('최종아이템:::', estimateData.itemList)
|
||||||
|
if (fileList?.length > 0) {
|
||||||
|
estimateData.fileList = fileList
|
||||||
|
} else {
|
||||||
|
estimateData.fileList = []
|
||||||
|
}
|
||||||
|
if (estimateData.originFiles?.length > 0) {
|
||||||
|
estimateData.deleteFileList = estimateData.originFiles?.filter((item) => item.delFlg === '1')
|
||||||
|
} else {
|
||||||
|
estimateData.deleteFileList = []
|
||||||
|
}
|
||||||
|
|
||||||
|
if (estimateData.estimateType === 'YJSS') {
|
||||||
|
estimateData.pkgAsp = estimateData.pkgAsp.replaceAll(',', '')
|
||||||
|
}
|
||||||
|
|
||||||
console.log('최종저장::', estimateData)
|
console.log('최종저장::', estimateData)
|
||||||
//2. 상세데이터 저장
|
//2. 상세데이터 저장
|
||||||
// return
|
// return
|
||||||
try {
|
try {
|
||||||
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
|
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
|
||||||
if (res.status === 201) {
|
if (res.status === 201) {
|
||||||
|
estimateData.newFileList = []
|
||||||
|
// estimateData.originFiles = []
|
||||||
alert(getMessage('estimate.detail.save.alertMsg'))
|
alert(getMessage('estimate.detail.save.alertMsg'))
|
||||||
//어디로 보낼지
|
//어디로 보낼지
|
||||||
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
|
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
|
||||||
@ -303,7 +337,6 @@ export const useEstimateController = (planNo) => {
|
|||||||
console.log('error::::::::::::', e.response.data.message)
|
console.log('error::::::::::::', e.response.data.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 견적서 복사버튼
|
* 견적서 복사버튼
|
||||||
|
|||||||
@ -2,21 +2,27 @@ import { useRecoilState, useRecoilValue } from 'recoil'
|
|||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { rectToPolygon, setSurfaceShapePattern } from '@/util/canvas-util'
|
import { rectToPolygon, setSurfaceShapePattern } from '@/util/canvas-util'
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||||
import offsetPolygon from '@/util/qpolygon-utils'
|
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
|
||||||
import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom'
|
import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
|
import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
|
import { canvasSettingState } from '@/store/canvasAtom'
|
||||||
|
import { compasDegAtom } from '@/store/orientationAtom'
|
||||||
|
|
||||||
export function useModuleBasicSetting() {
|
export function useModuleBasicSetting() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||||
const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState)
|
const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState)
|
||||||
// const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState)
|
const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState)
|
||||||
const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useEvent()
|
const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useEvent()
|
||||||
|
const { swalFire } = useSwal()
|
||||||
|
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||||
|
const compasDeg = useRecoilValue(compasDegAtom)
|
||||||
|
|
||||||
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
|
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
|
||||||
let selectedModuleInstSurfaceArray = []
|
let selectedModuleInstSurfaceArray = []
|
||||||
|
|
||||||
@ -62,6 +68,8 @@ export function useModuleBasicSetting() {
|
|||||||
|
|
||||||
const surfaceId = uuidv4()
|
const surfaceId = uuidv4()
|
||||||
|
|
||||||
|
console.log('roof.moduleCompass', roof.moduleCompass)
|
||||||
|
|
||||||
let setupSurface = new QPolygon(offsetPoints, {
|
let setupSurface = new QPolygon(offsetPoints, {
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
@ -440,6 +448,7 @@ export function useModuleBasicSetting() {
|
|||||||
|
|
||||||
//자동 모듈 설치(그리드 방식)
|
//자동 모듈 설치(그리드 방식)
|
||||||
const autoModuleSetup = (placementRef) => {
|
const autoModuleSetup = (placementRef) => {
|
||||||
|
initEvent() //마우스 이벤트 초기화
|
||||||
const isChidori = placementRef.isChidori.current === 'true' ? true : false
|
const isChidori = placementRef.isChidori.current === 'true' ? true : false
|
||||||
const setupLocation = placementRef.setupLocation.current
|
const setupLocation = placementRef.setupLocation.current
|
||||||
const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false
|
const isMaxSetup = placementRef.isMaxSetup.current === 'true' ? true : false
|
||||||
@ -472,14 +481,20 @@ export function useModuleBasicSetting() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
moduleSetupSurfaces.forEach((obj) => {
|
// console.log('moduleIsSetup', moduleIsSetup)
|
||||||
if (obj.modules) {
|
|
||||||
obj.modules.forEach((module) => {
|
// if (moduleIsSetup.length > 0) {
|
||||||
canvas?.remove(module)
|
// swalFire({ text: 'alert 아이콘 테스트입니다.', icon: 'error' })
|
||||||
})
|
// }
|
||||||
obj.modules = []
|
|
||||||
}
|
// moduleSetupSurfaces.forEach((obj) => {
|
||||||
})
|
// if (obj.modules) {
|
||||||
|
// obj.modules.forEach((module) => {
|
||||||
|
// canvas?.remove(module)
|
||||||
|
// })
|
||||||
|
// obj.modules = []
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
notSelectedTrestlePolygons.forEach((obj) => {
|
notSelectedTrestlePolygons.forEach((obj) => {
|
||||||
if (obj.modules) {
|
if (obj.modules) {
|
||||||
@ -614,20 +629,20 @@ export function useModuleBasicSetting() {
|
|||||||
if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
|
if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
|
||||||
|
|
||||||
for (let j = 0; j < diffTopEndPoint; j++) {
|
for (let j = 0; j < diffTopEndPoint; j++) {
|
||||||
bottomMargin = j === 0 ? 1 : 0
|
bottomMargin = j === 0 ? 1 : 2
|
||||||
for (let i = 0; i <= totalWidth; i++) {
|
for (let i = 0; i <= totalWidth; i++) {
|
||||||
leftMargin = i === 0 ? 1.1 : 0 //숫자가 0이면 0, 1이면 1로 바꾸기
|
leftMargin = i === 0 ? 1 : 2
|
||||||
chidoriLength = 0
|
chidoriLength = 0
|
||||||
if (isChidori) {
|
if (isChidori) {
|
||||||
chidoriLength = j % 2 === 0 ? 0 : width / 2
|
chidoriLength = j % 2 === 0 ? 0 : width / 2
|
||||||
}
|
}
|
||||||
|
|
||||||
square = [
|
square = [
|
||||||
[startColPoint + tempMaxWidth * i - chidoriLength, startPoint.y1 - height * j - bottomMargin],
|
[startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i + width - chidoriLength, startPoint.y1 - height * j - bottomMargin],
|
[startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i + width - chidoriLength, startPoint.y1 - height * j - height - bottomMargin],
|
[startColPoint + tempMaxWidth * i + width - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i - chidoriLength, startPoint.y1 - height * j - height - bottomMargin],
|
[startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - height - bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i - chidoriLength, startPoint.y1 - height * j - bottomMargin],
|
[startColPoint + tempMaxWidth * i - chidoriLength + leftMargin, startPoint.y1 - height * j - bottomMargin],
|
||||||
]
|
]
|
||||||
|
|
||||||
let squarePolygon = turf.polygon([square])
|
let squarePolygon = turf.polygon([square])
|
||||||
@ -674,9 +689,9 @@ export function useModuleBasicSetting() {
|
|||||||
if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사
|
if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사
|
||||||
|
|
||||||
for (let i = 0; i <= totalWidth; i++) {
|
for (let i = 0; i <= totalWidth; i++) {
|
||||||
bottomMargin = i === 0 ? 1 : 0.1
|
bottomMargin = i === 0 ? 1 : 2
|
||||||
for (let j = 0; j < totalHeight; j++) {
|
for (let j = 0; j < totalHeight; j++) {
|
||||||
leftMargin = i === 0 ? 0 : 0.5 * i
|
leftMargin = i === 0 ? 1 : 2
|
||||||
chidoriLength = 0
|
chidoriLength = 0
|
||||||
if (isChidori) {
|
if (isChidori) {
|
||||||
chidoriLength = i % 2 === 0 ? 0 : height / 2
|
chidoriLength = i % 2 === 0 ? 0 : height / 2
|
||||||
@ -746,17 +761,19 @@ export function useModuleBasicSetting() {
|
|||||||
if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
|
if (isMaxSetup) diffRightEndPoint = diffRightEndPoint * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
|
||||||
|
|
||||||
for (let j = 0; j < diffBottomEndPoint; j++) {
|
for (let j = 0; j < diffBottomEndPoint; j++) {
|
||||||
|
bottomMargin = j === 0 ? 1 : 2
|
||||||
for (let i = 0; i < diffRightEndPoint; i++) {
|
for (let i = 0; i < diffRightEndPoint; i++) {
|
||||||
|
leftMargin = i === 0 ? 1 : 2
|
||||||
chidoriLength = 0
|
chidoriLength = 0
|
||||||
if (isChidori) {
|
if (isChidori) {
|
||||||
chidoriLength = j % 2 === 0 ? 0 : width / 2
|
chidoriLength = j % 2 === 0 ? 0 : width / 2
|
||||||
}
|
}
|
||||||
square = [
|
square = [
|
||||||
[startColPoint + tempMaxWidth * i + chidoriLength, startPoint.y1 + height * j + 1],
|
[startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i + chidoriLength, startPoint.y1 + height * j + height + 1],
|
[startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i + width + chidoriLength, startPoint.y1 + height * j + height + 1],
|
[startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i + width + chidoriLength, startPoint.y1 + height * j + 1],
|
[startColPoint + tempMaxWidth * i + width + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin],
|
||||||
[startColPoint + tempMaxWidth * i + chidoriLength, startPoint.y1 + height * j + 1],
|
[startColPoint + tempMaxWidth * i + chidoriLength + leftMargin, startPoint.y1 + height * j + bottomMargin],
|
||||||
]
|
]
|
||||||
|
|
||||||
let squarePolygon = turf.polygon([square])
|
let squarePolygon = turf.polygon([square])
|
||||||
@ -804,9 +821,9 @@ export function useModuleBasicSetting() {
|
|||||||
if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사
|
if (isMaxSetup) totalHeight = totalHeight * 2 //최대배치시 2배로 늘려서 반씩 검사
|
||||||
|
|
||||||
for (let i = 0; i <= totalWidth; i++) {
|
for (let i = 0; i <= totalWidth; i++) {
|
||||||
|
bottomMargin = i === 0 ? 1 : 2
|
||||||
for (let j = 0; j < totalHeight; j++) {
|
for (let j = 0; j < totalHeight; j++) {
|
||||||
bottomMargin = j === 0 ? 0.5 : 0.5 * j
|
leftMargin = j === 0 ? 1 : 2
|
||||||
leftMargin = i === 0 ? 0 : 0.5 * i
|
|
||||||
chidoriLength = 0
|
chidoriLength = 0
|
||||||
if (isChidori) {
|
if (isChidori) {
|
||||||
chidoriLength = i % 2 === 0 ? 0 : height / 2
|
chidoriLength = i % 2 === 0 ? 0 : height / 2
|
||||||
@ -912,11 +929,12 @@ export function useModuleBasicSetting() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
canvas?.renderAll()
|
||||||
|
|
||||||
//나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기
|
//나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기
|
||||||
setupedModules.forEach((module, index) => {
|
setupedModules.forEach((module, index) => {
|
||||||
if (isMaxSetup && index > 0) {
|
if (isMaxSetup && index > 0) {
|
||||||
const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module))
|
const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module))
|
||||||
|
|
||||||
//겹치는지 확인
|
//겹치는지 확인
|
||||||
if (isOverlap) {
|
if (isOverlap) {
|
||||||
//겹쳐있으면 삭제
|
//겹쳐있으면 삭제
|
||||||
@ -930,30 +948,36 @@ export function useModuleBasicSetting() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
moduleSetupSurface.set({ modules: setupedModules })
|
moduleSetupSurface.set({ modules: setupedModules })
|
||||||
// setModuleIsSetup(moduleSetupArray)
|
|
||||||
|
// const moduleArray = [...moduleIsSetup]
|
||||||
|
// moduleArray.push({
|
||||||
|
// surfaceId: moduleSetupSurface.surfaceId,
|
||||||
|
// moduleSetupArray: setupedModules,
|
||||||
|
// })
|
||||||
|
// setModuleIsSetup(moduleArray)
|
||||||
})
|
})
|
||||||
|
calculateForApi()
|
||||||
}
|
}
|
||||||
|
|
||||||
const calculateForApi = (moduleSetupArray) => {
|
const calculateForApi = () => {
|
||||||
// TODO : 현재는 남쪽기준. 동,서,북 분기처리 필요
|
const moduleSufaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
|
|
||||||
|
const results = []
|
||||||
|
|
||||||
|
moduleSufaces.forEach((moduleSurface) => {
|
||||||
const centerPoints = []
|
const centerPoints = []
|
||||||
moduleSetupArray.forEach((module, index) => {
|
const direction = moduleSurface.direction
|
||||||
|
const modules = moduleSurface.modules
|
||||||
|
|
||||||
|
modules.forEach((module, index) => {
|
||||||
module.tempIndex = index
|
module.tempIndex = index
|
||||||
const { x, y } = module.getCenterPoint()
|
const { x, y } = module.getCenterPoint()
|
||||||
const { width, height } = module
|
const { width, height } = module
|
||||||
centerPoints.push({ x, y, width, height, index })
|
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
|
||||||
const circle = new fabric.Circle({
|
|
||||||
radius: 5,
|
|
||||||
fill: 'red',
|
|
||||||
name: 'redCircle',
|
|
||||||
left: x - 5,
|
|
||||||
top: y - 5,
|
|
||||||
index: index,
|
|
||||||
selectable: false,
|
|
||||||
})
|
|
||||||
canvas.add(circle)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (centerPoints.length === 0) return
|
||||||
|
|
||||||
//완전 노출 하면
|
//완전 노출 하면
|
||||||
let exposedBottom = 0
|
let exposedBottom = 0
|
||||||
// 반 노출 하면
|
// 반 노출 하면
|
||||||
@ -970,28 +994,48 @@ export function useModuleBasicSetting() {
|
|||||||
centerPoints.forEach((centerPoint, index) => {
|
centerPoints.forEach((centerPoint, index) => {
|
||||||
const { x, y, width, height } = centerPoint
|
const { x, y, width, height } = centerPoint
|
||||||
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
|
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
|
||||||
const bottomCell = centerPoints.filter((centerPoint) => centerPoint.x === x && Math.abs(centerPoint.y - (y + height)) < 2)
|
let bottomCell
|
||||||
if (bottomCell.length === 1) {
|
let bottomLeftPoint
|
||||||
touchDimension++
|
let bottomRightPoint
|
||||||
return
|
let leftBottomCnt
|
||||||
|
let rightBottomCnt
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case 'south':
|
||||||
|
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||||
|
bottomLeftPoint = { x: x - width / 2, y: y + height }
|
||||||
|
bottomRightPoint = { x: x + width / 2, y: y + height }
|
||||||
|
break
|
||||||
|
case 'north':
|
||||||
|
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||||
|
bottomLeftPoint = { x: x + width / 2, y: y - height }
|
||||||
|
bottomRightPoint = { x: x - width / 2, y: y - height }
|
||||||
|
break
|
||||||
|
case 'east':
|
||||||
|
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||||
|
bottomLeftPoint = { x: x + width, y: y + height / 2 }
|
||||||
|
bottomRightPoint = { x: x + width, y: y - height / 2 }
|
||||||
|
break
|
||||||
|
case 'west':
|
||||||
|
bottomCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||||
|
bottomLeftPoint = { x: x - width, y: y - height / 2 }
|
||||||
|
bottomRightPoint = { x: x - width, y: y + height / 2 }
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
const bottomLeftPoint = { x: x - width / 2, y: y + height }
|
if (bottomCell.length === 1) {
|
||||||
const bottomRightPoint = { x: x + width / 2, y: y + height }
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
|
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
|
||||||
const leftBottomCnt = centerPoints.filter(
|
leftBottomCnt = centerPoints.filter(
|
||||||
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
|
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
|
||||||
).length
|
).length
|
||||||
const rightBottomCnt = centerPoints.filter(
|
rightBottomCnt = centerPoints.filter(
|
||||||
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
|
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
|
||||||
).length
|
).length
|
||||||
if (leftBottomCnt + rightBottomCnt === 2) {
|
|
||||||
touchDimension++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (leftBottomCnt + rightBottomCnt === 1) {
|
if (leftBottomCnt + rightBottomCnt === 1) {
|
||||||
halfTouchDimension++
|
|
||||||
exposedHalfBottom++
|
exposedHalfBottom++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1000,28 +1044,60 @@ export function useModuleBasicSetting() {
|
|||||||
|
|
||||||
centerPoints.forEach((centerPoint, index) => {
|
centerPoints.forEach((centerPoint, index) => {
|
||||||
const { x, y, width, height } = centerPoint
|
const { x, y, width, height } = centerPoint
|
||||||
const topCell = centerPoints.filter((centerPoint) => centerPoint.x === x && Math.abs(centerPoint.y - (y - height)) < 2)
|
|
||||||
|
let topCell
|
||||||
|
let topLeftPoint
|
||||||
|
let topRightPoint
|
||||||
|
let leftTopCnt
|
||||||
|
let rightTopCnt
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case 'south':
|
||||||
|
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||||
|
topLeftPoint = { x: x - width / 2, y: y - height }
|
||||||
|
topRightPoint = { x: x + width / 2, y: y - height }
|
||||||
|
break
|
||||||
|
case 'north':
|
||||||
|
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||||
|
topLeftPoint = { x: x + width / 2, y: y + height }
|
||||||
|
topRightPoint = { x: x - width / 2, y: y + height }
|
||||||
|
break
|
||||||
|
case 'east':
|
||||||
|
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||||
|
topLeftPoint = { x: x - width, y: y + height / 2 }
|
||||||
|
topRightPoint = { x: x - width, y: y - height / 2 }
|
||||||
|
break
|
||||||
|
case 'west':
|
||||||
|
topCell = centerPoints.filter((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||||
|
topLeftPoint = { x: x + width, y: y - height / 2 }
|
||||||
|
topRightPoint = { x: x + width, y: y + height / 2 }
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if (topCell.length === 1) {
|
if (topCell.length === 1) {
|
||||||
|
touchDimension++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const topLeftPoint = { x: x - width / 2, y: y - height }
|
leftTopCnt = centerPoints.filter(
|
||||||
const topRightPoint = { x: x + width / 2, y: y - height }
|
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2,
|
||||||
|
|
||||||
const leftTopCnt = centerPoints.filter(
|
|
||||||
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
|
||||||
).length
|
).length
|
||||||
const rightTopCnt = centerPoints.filter(
|
rightTopCnt = centerPoints.filter(
|
||||||
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
||||||
).length
|
).length
|
||||||
|
|
||||||
|
if (leftTopCnt + rightTopCnt === 2) {
|
||||||
|
touchDimension++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (leftTopCnt + rightTopCnt === 1) {
|
if (leftTopCnt + rightTopCnt === 1) {
|
||||||
exposedHalfTop++
|
exposedHalfTop++
|
||||||
|
halfTouchDimension++
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (leftTopCnt + rightTopCnt === 0) {
|
if (leftTopCnt + rightTopCnt === 0) {
|
||||||
exposedTop++
|
exposedTop++
|
||||||
return
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 완전 노출 하면 계산
|
// 완전 노출 하면 계산
|
||||||
@ -1030,42 +1106,73 @@ export function useModuleBasicSetting() {
|
|||||||
const points = cells.map((cell) => {
|
const points = cells.map((cell) => {
|
||||||
return cell.getCenterPoint()
|
return cell.getCenterPoint()
|
||||||
})*/
|
})*/
|
||||||
const groupPoints = groupCoordinates(centerPoints)
|
const groupPoints = groupCoordinates(centerPoints, modules[0], direction)
|
||||||
|
|
||||||
groupPoints.forEach((group) => {
|
groupPoints.forEach((group) => {
|
||||||
// 각 그룹에서 y값이 큰 값을 찾는다.
|
let maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
|
||||||
// 그리고 그 y값과 같은 값을 가지는 centerPoint를 찾는다.
|
let minY = group.reduce((acc, cur) => (acc.y < cur.y ? acc : cur)).y
|
||||||
const maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
|
let maxX = group.reduce((acc, cur) => (acc.x > cur.x ? acc : cur)).x
|
||||||
const maxYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
|
let minX = group.reduce((acc, cur) => (acc.x < cur.x ? acc : cur)).x
|
||||||
|
|
||||||
|
let maxYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
|
||||||
|
let minYCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.y - minY) < 2)
|
||||||
|
let maxXCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.x - maxX) < 2)
|
||||||
|
let minXCenterPoint = group.filter((centerPoint) => Math.abs(centerPoint.x - minX) < 2)
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case 'south':
|
||||||
exposedBottom += maxYCenterPoint.length
|
exposedBottom += maxYCenterPoint.length
|
||||||
|
break
|
||||||
|
case 'north':
|
||||||
|
exposedBottom += minYCenterPoint.length
|
||||||
|
break
|
||||||
|
case 'east':
|
||||||
|
exposedBottom += maxXCenterPoint.length
|
||||||
|
break
|
||||||
|
case 'west':
|
||||||
|
exposedBottom += minXCenterPoint.length
|
||||||
|
break
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
results.push({
|
||||||
exposedBottom,
|
exposedBottom,
|
||||||
exposedHalfBottom,
|
exposedHalfBottom,
|
||||||
exposedTop,
|
exposedTop,
|
||||||
exposedHalfTop,
|
exposedHalfTop,
|
||||||
touchDimension,
|
touchDimension,
|
||||||
halfTouchDimension,
|
halfTouchDimension,
|
||||||
}
|
})
|
||||||
|
console.log({
|
||||||
|
direction,
|
||||||
|
exposedBottom,
|
||||||
|
exposedHalfBottom,
|
||||||
|
exposedTop,
|
||||||
|
exposedHalfTop,
|
||||||
|
touchDimension,
|
||||||
|
halfTouchDimension,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return results
|
||||||
}
|
}
|
||||||
|
|
||||||
// polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환
|
// polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환
|
||||||
const groupCoordinates = (points) => {
|
const groupCoordinates = (points, moduleExample, direction) => {
|
||||||
const groups = []
|
const groups = []
|
||||||
const visited = new Set()
|
const visited = new Set()
|
||||||
const width = 100
|
const width = Math.floor(moduleExample.width)
|
||||||
const height = 100
|
const height = Math.floor(moduleExample.height)
|
||||||
const horizonPadding = 5 // 가로 패딩
|
const horizonPadding = 0 // 가로 패딩
|
||||||
const verticalPadding = 3 // 세로 패딩
|
const verticalPadding = 0 // 세로 패딩
|
||||||
|
|
||||||
function isAdjacent(p1, p2) {
|
function isAdjacent(p1, p2) {
|
||||||
const dx = Math.abs(p1.x - p2.x)
|
const dx = Math.abs(p1.x - p2.x)
|
||||||
const dy = Math.abs(p1.y - p2.y)
|
const dy = Math.abs(p1.y - p2.y)
|
||||||
return (
|
return (
|
||||||
(dx === width + horizonPadding && dy === 0) ||
|
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
|
||||||
(dx === 0 && dy === height + verticalPadding) ||
|
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
|
||||||
(dx === width / 2 + horizonPadding / 2 && dy === height + verticalPadding)
|
(Math.abs(dx - width / 2 + horizonPadding / 2) < 2 && Math.abs(dy - height + verticalPadding) < 2)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1182,7 +1289,7 @@ export function useModuleBasicSetting() {
|
|||||||
const angle2 = Math.abs(Math.round(Math.atan(height2 / adjust2) * (180 / Math.PI) * 1000) / 1000)
|
const angle2 = Math.abs(Math.round(Math.atan(height2 / adjust2) * (180 / Math.PI) * 1000) / 1000)
|
||||||
const angle3 = 180 - (angle1 + angle2)
|
const angle3 = 180 - (angle1 + angle2)
|
||||||
|
|
||||||
const charlie = 173.3 + 3 // 평행선길이 약간 여유를 줌
|
const charlie = 173.3 // 평행선길이 약간 여유를 줌
|
||||||
const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180)
|
const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180)
|
||||||
const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180))
|
const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180))
|
||||||
const h = beta * Math.sin((angle1 * Math.PI) / 180) // 높이
|
const h = beta * Math.sin((angle1 * Math.PI) / 180) // 높이
|
||||||
@ -1297,7 +1404,7 @@ export function useModuleBasicSetting() {
|
|||||||
const angle2 = Math.abs(Math.round(Math.atan(adjust2 / height2) * (180 / Math.PI) * 1000) / 1000)
|
const angle2 = Math.abs(Math.round(Math.atan(adjust2 / height2) * (180 / Math.PI) * 1000) / 1000)
|
||||||
const angle3 = 180 - (angle1 + angle2)
|
const angle3 = 180 - (angle1 + angle2)
|
||||||
|
|
||||||
const charlie = 173.3 + 3 // 평행선길이 약간 여유를줌
|
const charlie = 173.3 // 평행선길이 약간 여유를줌
|
||||||
const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180)
|
const alpha = (charlie * Math.sin((angle1 * Math.PI) / 180)) / Math.sin((angle3 * Math.PI) / 180)
|
||||||
const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180))
|
const beta = Math.sqrt(alpha ** 2 + charlie ** 2 - 2 * alpha * charlie * Math.cos((angle2 * Math.PI) / 180))
|
||||||
|
|
||||||
@ -1413,10 +1520,343 @@ export function useModuleBasicSetting() {
|
|||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const manualFlatroofModuleSetup = (placementFlatRef) => {
|
||||||
|
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
|
||||||
|
let applyAngle
|
||||||
|
let flatBatchType = placementFlatRef.setupLocation.current.value
|
||||||
|
let excretaLinesAngle = []
|
||||||
|
|
||||||
|
if (flatBatchType === 'south') {
|
||||||
|
applyAngle = compasDeg
|
||||||
|
} else {
|
||||||
|
const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine' && obj.isSelected === true)
|
||||||
|
excretaLines.forEach((obj) => {
|
||||||
|
const points1 = { x: obj.x1, y: obj.y1 }
|
||||||
|
const points2 = { x: obj.x2, y: obj.y2 }
|
||||||
|
excretaLinesAngle.push({
|
||||||
|
surfaceId: obj.surfaceId,
|
||||||
|
angle: calculateAngle(points1, points2),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//calculateAngle
|
||||||
|
|
||||||
|
const batchObjects = canvas
|
||||||
|
?.getObjects()
|
||||||
|
.filter(
|
||||||
|
(obj) =>
|
||||||
|
obj.name === BATCH_TYPE.OPENING ||
|
||||||
|
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||||
|
obj.name === BATCH_TYPE.PENTAGON_DORMER ||
|
||||||
|
obj.name === BATCH_TYPE.SHADOW,
|
||||||
|
) //도머s 객체
|
||||||
|
|
||||||
|
const moduleOptions = {
|
||||||
|
fill: '#BFFD9F',
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 0.1,
|
||||||
|
selectable: false, // 선택 가능하게 설정
|
||||||
|
lockMovementX: true, // X 축 이동 잠금
|
||||||
|
lockMovementY: true, // Y 축 이동 잠금
|
||||||
|
lockRotation: true, // 회전 잠금
|
||||||
|
lockScalingX: true, // X 축 크기 조정 잠금
|
||||||
|
lockScalingY: true, // Y 축 크기 조정 잠금
|
||||||
|
opacity: 0.8,
|
||||||
|
parentId: moduleSetupSurface.parentId,
|
||||||
|
name: 'module',
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRotatedCorners(rect) {
|
||||||
|
// 사각형의 중심점
|
||||||
|
const center = rect.getCenterPoint()
|
||||||
|
|
||||||
|
// 사각형의 원래 꼭짓점 좌표 (로컬 좌표 기준)
|
||||||
|
const halfWidth = (rect.width / 2) * rect.scaleX
|
||||||
|
const halfHeight = (rect.height / 2) * rect.scaleY
|
||||||
|
|
||||||
|
const corners = [
|
||||||
|
{ x: -halfWidth, y: -halfHeight }, // 좌상단
|
||||||
|
{ x: halfWidth, y: -halfHeight }, // 우상단
|
||||||
|
{ x: halfWidth, y: halfHeight }, // 우하단
|
||||||
|
{ x: -halfWidth, y: halfHeight }, // 좌하단
|
||||||
|
]
|
||||||
|
|
||||||
|
// 각 꼭짓점 좌표를 캔버스 좌표로 변환
|
||||||
|
const transformedCorners = corners.map((corner) => {
|
||||||
|
const point = new fabric.Point(corner.x, corner.y)
|
||||||
|
return fabric.util.transformPoint(point, rect.calcTransformMatrix())
|
||||||
|
})
|
||||||
|
|
||||||
|
return transformedCorners
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedExcretaLine() {}
|
||||||
|
|
||||||
|
if (moduleSetupSurfaces.length !== 0) {
|
||||||
|
let tempModule
|
||||||
|
let manualDrawModules = []
|
||||||
|
let inside = false
|
||||||
|
let turfPolygon
|
||||||
|
let flowDirection
|
||||||
|
let trestlePolygon
|
||||||
|
|
||||||
|
addCanvasMouseEventListener('mouse:move', (e) => {
|
||||||
|
//마우스 이벤트 삭제 후 재추가
|
||||||
|
const mousePoint = canvas.getPointer(e.e)
|
||||||
|
|
||||||
|
for (let i = 0; i < moduleSetupSurfaces.length; i++) {
|
||||||
|
turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i])
|
||||||
|
trestlePolygon = moduleSetupSurfaces[i]
|
||||||
|
manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
|
||||||
|
flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
|
||||||
|
|
||||||
|
if (flatBatchType === 'excreta') {
|
||||||
|
const tempLine = excretaLinesAngle.find((obj) => obj.surfaceId === trestlePolygon.surfaceId)
|
||||||
|
if (tempLine) {
|
||||||
|
applyAngle = tempLine.angle
|
||||||
|
} else {
|
||||||
|
applyAngle = compasDeg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// const excretaLine = excretaLines.find((obj) => obj.isSelected === true && obj.surfaceId === trestlePolygon.surfaceId)
|
||||||
|
|
||||||
|
// console.log('excretaLine', excretaLine.x1, excretaLine.y1, excretaLine.x2, excretaLine.y2)
|
||||||
|
|
||||||
|
// applyAngle = calculateAngle(excretaLine.x1, excretaLine.y1, excretaLine.x2, excretaLine.y2)
|
||||||
|
|
||||||
|
// console.log('applyAngle', applyAngle)
|
||||||
|
|
||||||
|
let width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113
|
||||||
|
let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172
|
||||||
|
|
||||||
|
const angledModule = new fabric.Rect({
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
left: mousePoint.x - width / 2,
|
||||||
|
top: mousePoint.y - height / 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
const center = angledModule.getCenterPoint()
|
||||||
|
angledModule.set('angle', applyAngle)
|
||||||
|
angledModule.setPositionByOrigin(center, 'center', 'center')
|
||||||
|
|
||||||
|
const points = getRotatedCorners(angledModule) //
|
||||||
|
const turfPoints = coordToTurfPolygon(points)
|
||||||
|
|
||||||
|
if (turf.booleanWithin(turfPoints, turfPolygon)) {
|
||||||
|
let isDrawing = false
|
||||||
|
|
||||||
|
if (isDrawing) return
|
||||||
|
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule')) //움직일때 일단 지워가면서 움직임
|
||||||
|
|
||||||
|
tempModule = new QPolygon(points, {
|
||||||
|
fill: 'white',
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 0.3,
|
||||||
|
name: 'tempModule',
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas?.add(tempModule) //움직여가면서 추가됨
|
||||||
|
canvas?.renderAll()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 스냅기능
|
||||||
|
*/
|
||||||
|
let snapDistance = 10
|
||||||
|
let cellSnapDistance = 20
|
||||||
|
|
||||||
|
const trestleLeft = moduleSetupSurfaces[i].left
|
||||||
|
const trestleTop = moduleSetupSurfaces[i].top
|
||||||
|
const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX
|
||||||
|
const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY
|
||||||
|
const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2
|
||||||
|
|
||||||
|
// 작은 폴리곤의 경계 좌표 계산
|
||||||
|
const smallLeft = tempModule.left
|
||||||
|
const smallTop = tempModule.top
|
||||||
|
const smallRight = smallLeft + tempModule.width * tempModule.scaleX
|
||||||
|
const smallBottom = smallTop + tempModule.height * tempModule.scaleY
|
||||||
|
const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2
|
||||||
|
const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2
|
||||||
|
|
||||||
|
if (manualDrawModules) {
|
||||||
|
manualDrawModules.forEach((cell) => {
|
||||||
|
const holdCellLeft = cell.left
|
||||||
|
const holdCellTop = cell.top
|
||||||
|
const holdCellRight = holdCellLeft + cell.width * cell.scaleX
|
||||||
|
const holdCellBottom = holdCellTop + cell.height * cell.scaleY
|
||||||
|
const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2
|
||||||
|
const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2
|
||||||
|
|
||||||
|
//설치된 셀에 좌측에 스냅
|
||||||
|
if (Math.abs(smallRight - holdCellLeft) < snapDistance) {
|
||||||
|
tempModule.left = holdCellLeft - width - 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
//설치된 셀에 우측에 스냅
|
||||||
|
if (Math.abs(smallLeft - holdCellRight) < snapDistance) {
|
||||||
|
tempModule.left = holdCellRight + 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
//설치된 셀에 위쪽에 스냅
|
||||||
|
if (Math.abs(smallBottom - holdCellTop) < snapDistance) {
|
||||||
|
tempModule.top = holdCellTop - height - 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
//설치된 셀에 밑쪽에 스냅
|
||||||
|
if (Math.abs(smallTop - holdCellBottom) < snapDistance) {
|
||||||
|
tempModule.top = holdCellBottom + 0.5
|
||||||
|
}
|
||||||
|
//가운데 -> 가운데
|
||||||
|
if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) {
|
||||||
|
tempModule.left = holdCellCenterX - width / 2
|
||||||
|
}
|
||||||
|
//왼쪽 -> 가운데
|
||||||
|
if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) {
|
||||||
|
tempModule.left = holdCellCenterX
|
||||||
|
}
|
||||||
|
// 오른쪽 -> 가운데
|
||||||
|
if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) {
|
||||||
|
tempModule.left = holdCellCenterX - width
|
||||||
|
}
|
||||||
|
//세로 가운데 -> 가운데
|
||||||
|
if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) {
|
||||||
|
tempModule.top = holdCellCenterY - height / 2
|
||||||
|
}
|
||||||
|
//위쪽 -> 가운데
|
||||||
|
if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) {
|
||||||
|
tempModule.top = holdCellCenterY
|
||||||
|
}
|
||||||
|
//아랫쪽 -> 가운데
|
||||||
|
if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) {
|
||||||
|
tempModule.top = holdCellCenterY - height
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 위쪽 변에 스냅
|
||||||
|
if (Math.abs(smallTop - trestleTop) < snapDistance) {
|
||||||
|
tempModule.top = trestleTop
|
||||||
|
}
|
||||||
|
|
||||||
|
// 아래쪽 변에 스냅
|
||||||
|
if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) {
|
||||||
|
tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY
|
||||||
|
}
|
||||||
|
|
||||||
|
// 왼쪽변에 스냅
|
||||||
|
if (Math.abs(smallLeft - trestleLeft) < snapDistance) {
|
||||||
|
tempModule.left = trestleLeft
|
||||||
|
}
|
||||||
|
//오른쪽 변에 스냅
|
||||||
|
if (Math.abs(smallRight - trestleRight) < snapDistance) {
|
||||||
|
tempModule.left = trestleRight - tempModule.width * tempModule.scaleX
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flowDirection === 'south' || flowDirection === 'north') {
|
||||||
|
// 모듈왼쪽이 세로중앙선에 붙게 스냅
|
||||||
|
if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
|
||||||
|
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// 모듈이 가운데가 세로중앙선에 붙게 스냅
|
||||||
|
if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
|
||||||
|
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// 모듈오른쪽이 세로중앙선에 붙게 스냅
|
||||||
|
if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
|
||||||
|
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 모듈이 가로중앙선에 스냅
|
||||||
|
if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) {
|
||||||
|
tempModule.top = bigCenterY - tempModule.height / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
|
||||||
|
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2
|
||||||
|
}
|
||||||
|
// 모듈 밑면이 가로중앙선에 스냅
|
||||||
|
if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
|
||||||
|
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inside = true
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
inside = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inside) {
|
||||||
|
// tempModule.set({ fill: 'red' })
|
||||||
|
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === 'tempModule'))
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||||
|
let isIntersection = true
|
||||||
|
if (!inside) return
|
||||||
|
if (tempModule) {
|
||||||
|
const tempTurfModule = polygonToTurfPolygon(tempModule)
|
||||||
|
|
||||||
|
//도머 객체를 가져옴
|
||||||
|
if (batchObjects) {
|
||||||
|
batchObjects.forEach((object) => {
|
||||||
|
let dormerTurfPolygon
|
||||||
|
|
||||||
|
if (object.type === 'group') {
|
||||||
|
//도머는 그룹형태임
|
||||||
|
dormerTurfPolygon = batchObjectGroupToTurfPolygon(object)
|
||||||
|
} else {
|
||||||
|
//개구, 그림자
|
||||||
|
dormerTurfPolygon = polygonToTurfPolygon(rectToPolygon(object))
|
||||||
|
}
|
||||||
|
|
||||||
|
const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인
|
||||||
|
//겹치면 안됨
|
||||||
|
if (intersection) {
|
||||||
|
alert('도머위에 모듈을 올릴 수 없습니다.')
|
||||||
|
isIntersection = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isIntersection) return
|
||||||
|
|
||||||
|
if (turf.booleanWithin(tempTurfModule, turfPolygon)) {
|
||||||
|
//마우스 클릭시 set으로 해당 위치에 셀을 넣음
|
||||||
|
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
|
||||||
|
if (!isOverlap) {
|
||||||
|
console.log('tempModule.points', tempModule.points)
|
||||||
|
|
||||||
|
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
|
||||||
|
canvas?.add(manualModule)
|
||||||
|
manualDrawModules.push(tempModule)
|
||||||
|
} else {
|
||||||
|
alert('셀끼리 겹치면 안되죠?')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert('나갔죠?!!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const autoFlatroofModuleSetup = (placementFlatRef) => {}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
makeModuleInstArea,
|
makeModuleInstArea,
|
||||||
manualModuleSetup,
|
manualModuleSetup,
|
||||||
autoModuleSetup,
|
autoModuleSetup,
|
||||||
restoreModuleInstArea,
|
restoreModuleInstArea,
|
||||||
|
manualFlatroofModuleSetup,
|
||||||
|
autoFlatroofModuleSetup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import { adsorptionPointModeState, adsorptionRangeState, canvasState, planSizeSettingState, dotLineGridSettingState } from '@/store/canvasAtom'
|
import {
|
||||||
|
adsorptionPointModeState,
|
||||||
|
adsorptionRangeState,
|
||||||
|
canvasState,
|
||||||
|
planSizeSettingState,
|
||||||
|
dotLineGridSettingState,
|
||||||
|
canvasSettingState,
|
||||||
|
} from '@/store/canvasAtom'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
@ -11,6 +18,7 @@ import {
|
|||||||
settingModalFirstOptionsState,
|
settingModalFirstOptionsState,
|
||||||
settingModalSecondOptionsState,
|
settingModalSecondOptionsState,
|
||||||
settingModalGridOptionsState,
|
settingModalGridOptionsState,
|
||||||
|
basicSettingState,
|
||||||
} from '@/store/settingAtom'
|
} from '@/store/settingAtom'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { globalFontAtom } from '@/store/fontAtom'
|
import { globalFontAtom } from '@/store/fontAtom'
|
||||||
@ -70,6 +78,9 @@ export function useCanvasSetting() {
|
|||||||
const [color, setColor] = useColor(gridColor ?? '#FF0000')
|
const [color, setColor] = useColor(gridColor ?? '#FF0000')
|
||||||
const [colorTemp, setColorTemp] = useState()
|
const [colorTemp, setColorTemp] = useState()
|
||||||
|
|
||||||
|
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
||||||
|
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
|
||||||
|
|
||||||
const SelectOptions = [
|
const SelectOptions = [
|
||||||
{ id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 },
|
{ id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 },
|
||||||
{ id: 2, name: '1/2', value: 1 / 2 },
|
{ id: 2, name: '1/2', value: 1 / 2 },
|
||||||
@ -112,6 +123,14 @@ export function useCanvasSetting() {
|
|||||||
console.log('useCanvasSetting 실행1', correntObjectNo)
|
console.log('useCanvasSetting 실행1', correntObjectNo)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// 배치면 초기설정 변경 시
|
||||||
|
useEffect(() => {
|
||||||
|
//console.log('useCanvasSetting canvasSetting 실행', canvasSetting)
|
||||||
|
if (canvasSetting.flag) {
|
||||||
|
basicSettingSave()
|
||||||
|
}
|
||||||
|
}, [canvasSetting])
|
||||||
|
|
||||||
//흡착점 ON/OFF 변경 시
|
//흡착점 ON/OFF 변경 시
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//console.log('useCanvasSetting 실행2', adsorptionPointMode.fontFlag, correntObjectNo)
|
//console.log('useCanvasSetting 실행2', adsorptionPointMode.fontFlag, correntObjectNo)
|
||||||
@ -232,6 +251,95 @@ export function useCanvasSetting() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 기본설정(PlacementShapeSetting) 조회 및 초기화
|
||||||
|
const fetchBasicSettings = async () => {
|
||||||
|
try {
|
||||||
|
await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}` }).then((res) => {
|
||||||
|
console.log('fetchBasicSettings res ', res)
|
||||||
|
if (res.length == 0) return
|
||||||
|
|
||||||
|
// 'roofs' 배열을 생성하여 각 항목을 추가
|
||||||
|
const roofsRow = res.map((item) => {
|
||||||
|
return {
|
||||||
|
roofSizeSet: item.roofSizeSet,
|
||||||
|
roofAngleSet: item.roofAngleSet,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const roofsArray = res.some((item) => !item.roofSeq)
|
||||||
|
? //최초 지붕재 추가 정보의 경우 roofsArray를 초기화 설정
|
||||||
|
res.map(() => ({
|
||||||
|
flag: false,
|
||||||
|
roofApply: true,
|
||||||
|
roofSeq: 1,
|
||||||
|
roofType: 1,
|
||||||
|
roofWidth: 265,
|
||||||
|
roofHeight: 235,
|
||||||
|
roofHajebichi: 0,
|
||||||
|
roofGap: 455,
|
||||||
|
// roofType: 1,
|
||||||
|
// roofWidth: 200,
|
||||||
|
// roofHeight: 200,
|
||||||
|
// roofHajebichi: 200,
|
||||||
|
// roofGap: 0,
|
||||||
|
roofLayout: 'parallel',
|
||||||
|
}))
|
||||||
|
: res.map((item) => ({
|
||||||
|
flag: false,
|
||||||
|
roofApply: item.roofApply === '' || item.roofApply === false ? false : true,
|
||||||
|
roofSeq: item.roofSeq,
|
||||||
|
roofType: item.roofType,
|
||||||
|
roofWidth: item.roofWidth,
|
||||||
|
roofHeight: item.roofHeight,
|
||||||
|
roofHajebichi: item.roofHajebichi,
|
||||||
|
roofGap: item.roofGap,
|
||||||
|
roofLayout: item.roofLayout,
|
||||||
|
}))
|
||||||
|
console.log('roofsArray ', roofsArray)
|
||||||
|
// 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음
|
||||||
|
const patternData = {
|
||||||
|
roofSizeSet: roofsRow[0].roofSizeSet, // 첫 번째 항목의 값을 사용
|
||||||
|
roofAngleSet: roofsRow[0].roofAngleSet, // 첫 번째 항목의 값을 사용
|
||||||
|
roofs: roofsArray, // 만들어진 roofs 배열
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.error('patternData', patternData)
|
||||||
|
|
||||||
|
// 데이터 설정
|
||||||
|
setBasicSettings({ ...patternData })
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Data fetching error:', error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
|
||||||
|
setBasicSettings({ ...canvasSetting })
|
||||||
|
}
|
||||||
|
//setCanvasSetting({ ...basicSetting })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 기본설정(PlacementShapeSetting) 저장
|
||||||
|
const basicSettingSave = async () => {
|
||||||
|
try {
|
||||||
|
const patternData = {
|
||||||
|
objectNo: correntObjectNo,
|
||||||
|
roofSizeSet: basicSetting.roofSizeSet,
|
||||||
|
roofAngleSet: basicSetting.roofAngleSet,
|
||||||
|
roofMaterialsAddList: basicSetting.roofs,
|
||||||
|
}
|
||||||
|
|
||||||
|
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
|
||||||
|
swalFire({ text: getMessage(res.returnMessage) })
|
||||||
|
})
|
||||||
|
|
||||||
|
//Recoil 설정
|
||||||
|
setCanvasSetting({ ...basicSetting, flag: false })
|
||||||
|
} catch (error) {
|
||||||
|
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CanvasSetting 조회 및 초기화
|
||||||
const fetchSettings = async () => {
|
const fetchSettings = async () => {
|
||||||
try {
|
try {
|
||||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${correntObjectNo}` })
|
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${correntObjectNo}` })
|
||||||
@ -382,7 +490,7 @@ export function useCanvasSetting() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 옵션 클릭 후 저장
|
// CanvasSetting 옵션 클릭 후 저장
|
||||||
const onClickOption2 = useCallback(async () => {
|
const onClickOption2 = useCallback(async () => {
|
||||||
// 서버에 전송할 데이터
|
// 서버에 전송할 데이터
|
||||||
const dataToSend = {
|
const dataToSend = {
|
||||||
@ -592,7 +700,6 @@ export function useCanvasSetting() {
|
|||||||
adsorptionRange,
|
adsorptionRange,
|
||||||
setAdsorptionRange,
|
setAdsorptionRange,
|
||||||
fetchSettings,
|
fetchSettings,
|
||||||
//onClickOption,
|
|
||||||
frontSettings,
|
frontSettings,
|
||||||
globalFont,
|
globalFont,
|
||||||
setGlobalFont,
|
setGlobalFont,
|
||||||
@ -621,5 +728,11 @@ export function useCanvasSetting() {
|
|||||||
setGridColor,
|
setGridColor,
|
||||||
color,
|
color,
|
||||||
setColor,
|
setColor,
|
||||||
|
canvasSetting,
|
||||||
|
setCanvasSetting,
|
||||||
|
basicSetting,
|
||||||
|
setBasicSettings,
|
||||||
|
fetchBasicSettings,
|
||||||
|
basicSettingSave,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { v4 as uuidv4, validate as isValidUUID } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { canvasState, currentCanvasPlanState, plansState, modifiedPlansState, modifiedPlanFlagState } from '@/store/canvasAtom'
|
import { canvasState, currentCanvasPlanState, plansState, modifiedPlansState, modifiedPlanFlagState } from '@/store/canvasAtom'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
@ -179,7 +179,7 @@ export function usePlan() {
|
|||||||
* objectNo에 해당하는 canvas 목록을 조회
|
* objectNo에 해당하는 canvas 목록을 조회
|
||||||
*/
|
*/
|
||||||
const getCanvasByObjectNo = async (userId, objectNo) => {
|
const getCanvasByObjectNo = async (userId, objectNo) => {
|
||||||
return get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) =>
|
return await get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) =>
|
||||||
res.map((item, index) => ({
|
res.map((item, index) => ({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
userId: item.userId,
|
userId: item.userId,
|
||||||
@ -237,15 +237,15 @@ export function usePlan() {
|
|||||||
/**
|
/**
|
||||||
* id에 해당하는 canvas 데이터를 삭제
|
* id에 해당하는 canvas 데이터를 삭제
|
||||||
*/
|
*/
|
||||||
const delCanvasById = (id) => {
|
const delCanvasById = async (id) => {
|
||||||
return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-id/${id}` })
|
return await promiseDel({ url: `/api/canvas-management/canvas-statuses/by-id/${id}` })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* objectNo에 해당하는 canvas 데이터들을 삭제
|
* objectNo에 해당하는 canvas 데이터들을 삭제
|
||||||
*/
|
*/
|
||||||
const delCanvasByObjectNo = (objectNo) => {
|
const delCanvasByObjectNo = async (objectNo) => {
|
||||||
return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}` })
|
return await promiseDel({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}` })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,19 +282,19 @@ export function usePlan() {
|
|||||||
* 새로운 plan 생성
|
* 새로운 plan 생성
|
||||||
* 현재 plan의 데이터가 있을 경우 복제 여부를 확인
|
* 현재 plan의 데이터가 있을 경우 복제 여부를 확인
|
||||||
*/
|
*/
|
||||||
const handleAddPlan = (userId, objectNo) => {
|
const handleAddPlan = async (userId, objectNo) => {
|
||||||
JSON.parse(currentCanvasData()).objects.length > 0
|
JSON.parse(currentCanvasData()).objects.length > 0
|
||||||
? swalFire({
|
? swalFire({
|
||||||
text: `Plan ${currentCanvasPlan.ordering} ` + getMessage('plan.message.confirm.copy'),
|
text: `Plan ${currentCanvasPlan.ordering} ` + getMessage('plan.message.confirm.copy'),
|
||||||
type: 'confirm',
|
type: 'confirm',
|
||||||
confirmFn: () => {
|
confirmFn: async () => {
|
||||||
postCanvasStatus(userId, objectNo, currentCanvasData())
|
await postCanvasStatus(userId, objectNo, currentCanvasData())
|
||||||
},
|
},
|
||||||
denyFn: () => {
|
denyFn: async () => {
|
||||||
postCanvasStatus(userId, objectNo, '')
|
await postCanvasStatus(userId, objectNo, '')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
: postCanvasStatus(userId, objectNo, '')
|
: await postCanvasStatus(userId, objectNo, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,10 +317,10 @@ export function usePlan() {
|
|||||||
/**
|
/**
|
||||||
* plan 삭제
|
* plan 삭제
|
||||||
*/
|
*/
|
||||||
const handleDeletePlan = (e, id) => {
|
const handleDeletePlan = async (e, id) => {
|
||||||
e.stopPropagation() // 이벤트 버블링 방지
|
e.stopPropagation() // 이벤트 버블링 방지
|
||||||
|
|
||||||
delCanvasById(id)
|
await delCanvasById(id)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
setPlans((plans) => plans.filter((plan) => plan.id !== id))
|
setPlans((plans) => plans.filter((plan) => plan.id !== id))
|
||||||
setModifiedPlans((modifiedPlans) => modifiedPlans.filter((planId) => planId !== currentCanvasPlan.id))
|
setModifiedPlans((modifiedPlans) => modifiedPlans.filter((planId) => planId !== currentCanvasPlan.id))
|
||||||
@ -344,8 +344,8 @@ export function usePlan() {
|
|||||||
/**
|
/**
|
||||||
* plan 조회
|
* plan 조회
|
||||||
*/
|
*/
|
||||||
const loadCanvasPlanData = (userId, objectNo, pid) => {
|
const loadCanvasPlanData = async (userId, objectNo, pid) => {
|
||||||
getCanvasByObjectNo(userId, objectNo).then((res) => {
|
await getCanvasByObjectNo(userId, objectNo).then((res) => {
|
||||||
// console.log('canvas 목록 ', res)
|
// console.log('canvas 목록 ', res)
|
||||||
if (res.length > 0) {
|
if (res.length > 0) {
|
||||||
setPlans(res)
|
setPlans(res)
|
||||||
|
|||||||
@ -3,8 +3,8 @@ export const defaultSession = {}
|
|||||||
export const sessionOptions = {
|
export const sessionOptions = {
|
||||||
password: process.env.SESSION_SECRET,
|
password: process.env.SESSION_SECRET,
|
||||||
cookieName: 'lama-session',
|
cookieName: 'lama-session',
|
||||||
cookieOptions: {
|
// cookieOptions: {
|
||||||
httpOnly: true,
|
// httpOnly: true,
|
||||||
secure: process.env.NODE_ENV === 'production',
|
// secure: process.env.NODE_ENV === 'production',
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
|
|||||||
@ -164,6 +164,7 @@
|
|||||||
"plan.menu.estimate.save": "保存",
|
"plan.menu.estimate.save": "保存",
|
||||||
"plan.menu.estimate.reset": "初期化",
|
"plan.menu.estimate.reset": "初期化",
|
||||||
"plan.menu.estimate.copy": "見積書のコピー",
|
"plan.menu.estimate.copy": "見積書のコピー",
|
||||||
|
"plan.menu.estimate.unLock": "ロック解除",
|
||||||
"plan.menu.simulation": "発展シミュレーション",
|
"plan.menu.simulation": "発展シミュレーション",
|
||||||
"plan.menu.simulation.excel": "Excel",
|
"plan.menu.simulation.excel": "Excel",
|
||||||
"plan.menu.simulation.pdf": "PDF",
|
"plan.menu.simulation.pdf": "PDF",
|
||||||
@ -841,6 +842,7 @@
|
|||||||
"estimate.detail.fileList.btn": "ファイル選択",
|
"estimate.detail.fileList.btn": "ファイル選択",
|
||||||
"estimate.detail.fileList.extCheck": "そのファイルはイメージファイルではありません",
|
"estimate.detail.fileList.extCheck": "そのファイルはイメージファイルではありません",
|
||||||
"estimate.detail.header.fileList2": "添付ファイル一覧",
|
"estimate.detail.header.fileList2": "添付ファイル一覧",
|
||||||
|
"estimate.detail.fileList2.btn.return": "復元",
|
||||||
"estimate.detail.header.specialEstimate": "見積もりの具体的な",
|
"estimate.detail.header.specialEstimate": "見積もりの具体的な",
|
||||||
"estimate.detail.header.specialEstimateProductInfo": "製品情報",
|
"estimate.detail.header.specialEstimateProductInfo": "製品情報",
|
||||||
"estimate.detail.sepcialEstimateProductInfo.totAmount": "数量 (PCS)",
|
"estimate.detail.sepcialEstimateProductInfo.totAmount": "数量 (PCS)",
|
||||||
|
|||||||
@ -168,6 +168,7 @@
|
|||||||
"plan.menu.estimate.save": "저장",
|
"plan.menu.estimate.save": "저장",
|
||||||
"plan.menu.estimate.reset": "초기화",
|
"plan.menu.estimate.reset": "초기화",
|
||||||
"plan.menu.estimate.copy": "견적서 복사",
|
"plan.menu.estimate.copy": "견적서 복사",
|
||||||
|
"plan.menu.estimate.unLock": "잠금 해제",
|
||||||
"plan.menu.simulation": "발전 시뮬레이션",
|
"plan.menu.simulation": "발전 시뮬레이션",
|
||||||
"plan.menu.simulation.excel": "Excel",
|
"plan.menu.simulation.excel": "Excel",
|
||||||
"plan.menu.simulation.pdf": "PDF",
|
"plan.menu.simulation.pdf": "PDF",
|
||||||
@ -851,6 +852,7 @@
|
|||||||
"estimate.detail.fileList.btn": "파일선택",
|
"estimate.detail.fileList.btn": "파일선택",
|
||||||
"estimate.detail.fileList.extCheck": "해당 파일은 이미지 파일이 아닙니다",
|
"estimate.detail.fileList.extCheck": "해당 파일은 이미지 파일이 아닙니다",
|
||||||
"estimate.detail.header.fileList2": "첨부파일 목록",
|
"estimate.detail.header.fileList2": "첨부파일 목록",
|
||||||
|
"estimate.detail.fileList2.btn.return": "복원",
|
||||||
"estimate.detail.header.specialEstimate": "견적특이사항",
|
"estimate.detail.header.specialEstimate": "견적특이사항",
|
||||||
"estimate.detail.header.specialEstimateProductInfo": "제품정보",
|
"estimate.detail.header.specialEstimateProductInfo": "제품정보",
|
||||||
"estimate.detail.sepcialEstimateProductInfo.totAmount": "수량 (PCS)",
|
"estimate.detail.sepcialEstimateProductInfo.totAmount": "수량 (PCS)",
|
||||||
|
|||||||
@ -113,7 +113,7 @@ export const calculateFlowDirection = (canvasAngle) => {
|
|||||||
return {
|
return {
|
||||||
down: -canvasAngle,
|
down: -canvasAngle,
|
||||||
up: 180 - canvasAngle,
|
up: 180 - canvasAngle,
|
||||||
left: 90 - canvasAngle,
|
left: 90 - canvasAngle < 180 ? 90 - canvasAngle : 90 - canvasAngle - 360,
|
||||||
right: -90 - canvasAngle,
|
right: -90 - canvasAngle < -180 ? -90 - canvasAngle + 360 : -90 - canvasAngle,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user