Merge branch 'dev' of ssh://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into qcast-pub
# Conflicts: # src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx
This commit is contained in:
commit
187f670442
@ -38,6 +38,7 @@
|
||||
"recoil": "^0.7.7",
|
||||
"sweetalert2": "^11.14.1",
|
||||
"sweetalert2-react-content": "^5.0.7",
|
||||
"swr": "^2.3.0",
|
||||
"usehooks-ts": "^3.1.0",
|
||||
"uuid": "^10.0.0"
|
||||
},
|
||||
|
||||
25
src/app/api/swr-tutorial/route.js
Normal file
25
src/app/api/swr-tutorial/route.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
const defaultData = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'John Doe',
|
||||
email: 'john.doe@example.com',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Jane Lee',
|
||||
email: 'jane.lee@example.com',
|
||||
},
|
||||
]
|
||||
|
||||
export async function GET(req, res) {
|
||||
return NextResponse.json(defaultData)
|
||||
}
|
||||
|
||||
export const POST = async (req, res) => {
|
||||
const { id, name, email } = await req.json()
|
||||
const newData = { id, name, email }
|
||||
console.log('🚀 ~ POST ~ newData:', newData)
|
||||
return NextResponse.json([...defaultData, newData])
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import { correntObjectNoState } from '@/store/settingAtom'
|
||||
import { notFound, usePathname, useSearchParams } from 'next/navigation'
|
||||
import { createContext, useReducer, useState } from 'react'
|
||||
import { createContext, useReducer, useState, useEffect } from 'react'
|
||||
import { useSetRecoilState } from 'recoil'
|
||||
|
||||
const reducer = (prevState, nextState) => {
|
||||
@ -48,12 +48,14 @@ const FloorPlanProvider = ({ children }) => {
|
||||
const objectNo = searchParams.get('objectNo')
|
||||
const pid = searchParams.get('pid')
|
||||
|
||||
if (pathname === '/floor-plan') {
|
||||
if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) {
|
||||
notFound()
|
||||
useEffect(() => { // 오류 발생으로 useEffect 사용
|
||||
if (pathname === '/floor-plan') {
|
||||
if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) {
|
||||
notFound()
|
||||
}
|
||||
setCurrentObjectNo(objectNo)
|
||||
}
|
||||
setCurrentObjectNo(objectNo)
|
||||
}
|
||||
}, [pid, objectNo])
|
||||
|
||||
const [floorPlanState, setFloorPlanState] = useState({
|
||||
// 플랜 파일 업로드 모달 오픈 제어
|
||||
|
||||
@ -164,6 +164,11 @@ export const SAVE_KEY = [
|
||||
'moduleCompass',
|
||||
'isFixed',
|
||||
'modules',
|
||||
'rackLen',
|
||||
'itemId',
|
||||
'supFitQty',
|
||||
'supFitIntvlPct',
|
||||
'rackLen',
|
||||
]
|
||||
|
||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
|
||||
|
||||
@ -23,6 +23,8 @@ import QSelectBox from './common/select/QSelectBox'
|
||||
import SampleReducer from './sample/SampleReducer'
|
||||
|
||||
import styles from './playground.module.css'
|
||||
import useSWR from 'swr'
|
||||
import useSWRMutation from 'swr/mutation'
|
||||
|
||||
export default function Playground() {
|
||||
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
||||
@ -32,7 +34,7 @@ export default function Playground() {
|
||||
const fileRef = useRef(null)
|
||||
const queryRef = useRef(null)
|
||||
const [zoom, setZoom] = useState(20)
|
||||
const { get, promiseGet, promisePost } = useAxios()
|
||||
const { get, promiseGet, post, promisePost, getFetcher, postFetcher } = useAxios()
|
||||
const testVar = process.env.NEXT_PUBLIC_TEST
|
||||
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
|
||||
const { getMessage } = useMessage()
|
||||
@ -252,6 +254,19 @@ export default function Playground() {
|
||||
})
|
||||
}
|
||||
|
||||
const [callFlag, setCallFlag] = useState(false)
|
||||
// const { data: tutoData, error, isLoading } = useSWR('http://localhost:8080/api/tutorial', getFetcher)
|
||||
const { data: tutoData, error, isLoading } = useSWR(callFlag ? 'http://localhost:8080/api/tutorial' : null, getFetcher)
|
||||
const { trigger, isMutating } = useSWRMutation('http://localhost:8080/api/tutorial', postFetcher)
|
||||
|
||||
if (isLoading) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div>Error...</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="container mx-auto p-4 m-4 border">
|
||||
@ -548,14 +563,30 @@ export default function Playground() {
|
||||
<div className="my-2">
|
||||
<Button onClick={() => setManagementState({})}>GlobalDataProvider 초기화</Button>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
{/* <div className="my-2">
|
||||
<p>{managementStateLoaded?.objectNo}</p>
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="my-2">
|
||||
<Button onClick={() => swalFire({ text: 'alert 테스트입니다.', type: 'alert', confirmFn: () => console.log('Alert!!!') })}>
|
||||
Sweetalert - alert
|
||||
</Button>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
{tutoData &&
|
||||
tutoData.map((item) => (
|
||||
<div key={item.id}>
|
||||
{item.name} / {item.email}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="my-2">
|
||||
<Button onClick={() => setCallFlag(true)}>getFetcher call</Button>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
<Button disabled={isMutating} onClick={() => trigger({ id: 3, name: 'seulda kim', email: 'seulda.kim@interplug.co.kr' })}>
|
||||
insert data
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
|
||||
@ -74,7 +74,6 @@ export default function Estimate({}) {
|
||||
const { estimateContextState, setEstimateContextState, addItem, handleEstimateFileDownload } = useEstimateController(currentPid)
|
||||
|
||||
const { selectedPlan } = usePlan()
|
||||
const router = useRouter()
|
||||
|
||||
//견적특이사항 List
|
||||
const [specialNoteList, setSpecialNoteList] = useState([])
|
||||
@ -299,12 +298,16 @@ export default function Estimate({}) {
|
||||
} else {
|
||||
if (originFiles.length > 0) {
|
||||
if (isEmptyArray(files)) {
|
||||
let file
|
||||
file = originFiles.filter((item) => item.delFlg === '0')
|
||||
setEstimateContextState({
|
||||
originFiles: file,
|
||||
})
|
||||
setOriginFiles(file)
|
||||
if (originFiles[0].planNo !== estimateContextState.planNo) {
|
||||
setOriginFiles([])
|
||||
} else {
|
||||
let file
|
||||
file = originFiles.filter((item) => item.delFlg === '0')
|
||||
setEstimateContextState({
|
||||
originFiles: file,
|
||||
})
|
||||
setOriginFiles(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1002,6 +1005,7 @@ export default function Estimate({}) {
|
||||
<div className="estimate-box">
|
||||
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
||||
<div className="estimate-name">
|
||||
{/* {objectNo} (Plan No: {estimateContextState.planNo}) */}
|
||||
{objectNo} (Plan No: {planNo})
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,11 +4,14 @@ import { useMessage } from '@/hooks/useMessage'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { floorPlanObjectState, estimateState } from '@/store/floorPlanObjectAtom'
|
||||
import { usePathname } from 'next/navigation'
|
||||
|
||||
export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDownPopLockFlg }) {
|
||||
const { getMessage } = useMessage()
|
||||
const { promisePost } = useAxios()
|
||||
|
||||
const pathName = usePathname()
|
||||
|
||||
//EXCEL, PDF 구분
|
||||
const [schDownload, setSchDownload] = useState('EXCEL')
|
||||
//다운로드 파일 EXCEL
|
||||
@ -62,6 +65,7 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown
|
||||
}
|
||||
|
||||
const options = { responseType: 'blob' }
|
||||
|
||||
await promisePost({ url: url, data: params, option: options })
|
||||
.then((resultData) => {
|
||||
if (resultData) {
|
||||
@ -85,7 +89,9 @@ export default function DocDownOptionPop({ planNo, setEstimatePopupOpen, docDown
|
||||
window.URL.revokeObjectURL(fileUrl)
|
||||
//문서 다운받으면 lockFlg = 1 잠금상태로!
|
||||
estimateRecoilState.lockFlg = '1'
|
||||
docDownPopLockFlg()
|
||||
if (pathName.includes('/floor-plan')) {
|
||||
docDownPopLockFlg()
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
|
||||
@ -282,7 +282,8 @@ export default function EstimateCopyPop({ planNo, setEstimateCopyPopupOpen }) {
|
||||
type="text"
|
||||
className="input-light"
|
||||
required
|
||||
defaultValue={estimateContextState?.charger}
|
||||
// defaultValue={estimateContextState?.charger}
|
||||
defaultValue={session?.userNm}
|
||||
onChange={(e) => {
|
||||
setCopyReceiveUser(e.target.value)
|
||||
}}
|
||||
@ -292,18 +293,18 @@ export default function EstimateCopyPop({ planNo, setEstimateCopyPopupOpen }) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-btn-wrap">
|
||||
<button type="button" className="btn-origin grey mr5" onClick={() => setEstimateCopyPopupOpen(false)}>
|
||||
{getMessage('estimate.detail.estimateCopyPopup.close')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin navy"
|
||||
className="btn-origin navy mr5"
|
||||
onClick={() => {
|
||||
handleEstimateCopy(sendPlanNo, copyReceiveUser, saleStoreId, otherSaleStoreId)
|
||||
}}
|
||||
>
|
||||
{getMessage('estimate.detail.estimateCopyPopup.copyBtn')}
|
||||
</button>
|
||||
<button type="button" className="btn-origin grey" onClick={() => setEstimateCopyPopupOpen(false)}>
|
||||
{getMessage('estimate.detail.estimateCopyPopup.close')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import { usePathname, useRouter, useSearchParams } from 'next/navigation'
|
||||
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
|
||||
@ -34,7 +34,7 @@ import { addedRoofsState, basicSettingState, selectedRoofMaterialSelector, setti
|
||||
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
|
||||
import { commonUtilsState } from '@/store/commonUtilsAtom'
|
||||
import { menusState, menuTypeState } from '@/store/menuAtom'
|
||||
import { estimateState } from '@/store/floorPlanObjectAtom'
|
||||
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
import { pwrGnrSimTypeState } from '@/store/simulatorAtom'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
|
||||
@ -63,7 +63,7 @@ export default function CanvasMenu(props) {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { handleZoomClear, handleZoom } = useCanvasEvent()
|
||||
const { handleMenu } = useMenu()
|
||||
|
||||
// const urlParams = useSearchParams()
|
||||
const { handleEstimateSubmit, fetchSetting } = useEstimateController()
|
||||
const estimateRecoilState = useRecoilValue(estimateState)
|
||||
const [estimatePopupOpen, setEstimatePopupOpen] = useState(false)
|
||||
@ -91,6 +91,8 @@ export default function CanvasMenu(props) {
|
||||
const [buttonStyle4, setButtonStyle4] = useState('') //견적서 복사 버튼
|
||||
const [buttonStyle5, setButtonStyle5] = useState('') //잠금 버튼
|
||||
|
||||
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //견적서 화면용 물건번호리코일
|
||||
|
||||
// 발전시뮬레이션 메뉴 이동
|
||||
const { objectNo, pid } = floorPlanState
|
||||
|
||||
@ -147,7 +149,7 @@ export default function CanvasMenu(props) {
|
||||
text: getMessage('stuff.detail.move.confirmMsg'),
|
||||
type: 'confirm',
|
||||
confirmFn: () => {
|
||||
router.push(`/management/stuff/detail?objectNo=${objectNo}`)
|
||||
router.push(`/management/stuff/detail?objectNo=${objectNo}`, { scroll: false })
|
||||
},
|
||||
})
|
||||
break
|
||||
@ -170,9 +172,20 @@ export default function CanvasMenu(props) {
|
||||
setType('module')
|
||||
break
|
||||
case 5:
|
||||
setMenuNumber(menu.index)
|
||||
setCurrentMenu(menu.title)
|
||||
router.push(`/floor-plan/estimate/5?pid=${pid}&objectNo=${objectNo}`)
|
||||
// let pid = urlParams.get('pid')
|
||||
promiseGet({ url: `/api/estimate/${objectNo}/${pid}/detail` }).then((res) => {
|
||||
if (res.status === 200) {
|
||||
const estimateDetail = res.data
|
||||
if (estimateDetail.docNo) {
|
||||
setMenuNumber(menu.index)
|
||||
setCurrentMenu(menu.title)
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
||||
router.push(`/floor-plan/estimate/5?pid=${pid}&objectNo=${objectNo}`)
|
||||
} else {
|
||||
swalFire({ text: getMessage('estimate.menu.move.valid1') })
|
||||
}
|
||||
}
|
||||
})
|
||||
break
|
||||
case 6:
|
||||
promiseGet({ url: `/api/estimate/${objectNo}/${pid}/detail` }).then((res) => {
|
||||
@ -190,7 +203,7 @@ export default function CanvasMenu(props) {
|
||||
break
|
||||
}
|
||||
|
||||
if (menu.index !== 6 && menu.index !== 0) {
|
||||
if (menu.index !== 6 && menu.index !== 0 && menu.index !== 5) {
|
||||
setMenuNumber(menu.index)
|
||||
setCurrentMenu(menu.title)
|
||||
}
|
||||
@ -296,10 +309,9 @@ export default function CanvasMenu(props) {
|
||||
}, [type, globalLocale])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ useEffect ~ basicSetting:', basicSetting)
|
||||
if (Object.keys(basicSetting).length === 0 || !basicSetting.roofSizeSet) return
|
||||
|
||||
// setMenuNumber(1)
|
||||
if (!selectedRoofMaterial) return
|
||||
//if (Object.keys(basicSetting).length === 0 || !basicSetting.roofSizeSet) return
|
||||
setMenuNumber(1)
|
||||
// if ([2, 3].some((num) => num === canvasSetting?.roofSizeSet)) {
|
||||
// setMenuNumber(3)
|
||||
// setType('surface')
|
||||
@ -309,7 +321,8 @@ export default function CanvasMenu(props) {
|
||||
// setType('outline')
|
||||
// setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||
// }
|
||||
}, [basicSetting])
|
||||
}, [selectedRoofMaterial])
|
||||
|
||||
const checkMenuState = (menu) => {
|
||||
return (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && menu.index === 2)
|
||||
}
|
||||
@ -510,17 +523,20 @@ export default function CanvasMenu(props) {
|
||||
{menuNumber === 5 && (
|
||||
<>
|
||||
<div className="ico-btn-from">
|
||||
{/* <button className="btn-frame gray ico-flx" onClick={() => setEstimatePopupOpen(true)}> */}
|
||||
<button type="button" style={{ display: buttonStyle1 }} className="btn-frame gray ico-flx" onClick={() => setEstimatePopupOpen(true)}>
|
||||
<span className="ico ico01"></span>
|
||||
<span className="name">{getMessage('plan.menu.estimate.docDown')}</span>
|
||||
</button>
|
||||
<button type="button" style={{ display: buttonStyle2 }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
||||
{/* <button type="button" style={{ display: buttonStyle }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}> */}
|
||||
<span className="ico ico02"></span>
|
||||
<span className="name">{getMessage('plan.menu.estimate.save')}</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
style={{ display: buttonStyle3 }}
|
||||
// style={{ display: buttonStyle }}
|
||||
className="btn-frame gray ico-flx"
|
||||
onClick={() => {
|
||||
handleEstimateReset()
|
||||
@ -534,6 +550,7 @@ export default function CanvasMenu(props) {
|
||||
<button
|
||||
type="button"
|
||||
style={{ display: buttonStyle4 }}
|
||||
// style={{ display: buttonStyle }}
|
||||
className="btn-frame gray ico-flx"
|
||||
onClick={() => {
|
||||
setEstimateCopyPopupOpen(true)
|
||||
@ -546,11 +563,11 @@ export default function CanvasMenu(props) {
|
||||
<button
|
||||
type="button"
|
||||
style={{ display: buttonStyle5 }}
|
||||
// style={{ display: buttonStyle }}
|
||||
className="btn-frame gray ico-flx"
|
||||
onClick={() => {
|
||||
//시연준비
|
||||
alert('작업중입니다')
|
||||
// handleEstimateLockController(estimateRecoilState)
|
||||
handleEstimateLockController(estimateRecoilState)
|
||||
}}
|
||||
>
|
||||
<span className="ico ico05"></span>
|
||||
|
||||
@ -9,7 +9,7 @@ import ModuleTabContents from './ModuleTabContents'
|
||||
import { useDebounceCallback, useDebounceValue } from 'usehooks-ts'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
|
||||
export default function Module({}) {
|
||||
export default function Module({ setTabNum }) {
|
||||
const { getMessage } = useMessage()
|
||||
const addedRoofs = useRecoilValue(addedRoofsState) //지붕재 선택
|
||||
const [roofTab, setRoofTab] = useState(0) //지붕재 탭
|
||||
@ -92,8 +92,8 @@ export default function Module({}) {
|
||||
<QSelectBox
|
||||
options={moduleList}
|
||||
value={moduleSelectionInitParams}
|
||||
targetKey={'moduleTpCd'}
|
||||
sourceKey={'itemTp'}
|
||||
targetKey={'moduleItemId'}
|
||||
sourceKey={'itemId'}
|
||||
showKey={'itemNm'}
|
||||
onChange={handleChangeModule}
|
||||
/>
|
||||
|
||||
@ -20,8 +20,6 @@ export default function ModuleTabContents({
|
||||
const { getMessage } = useMessage()
|
||||
const canvasSetting = useRecoilValue(canvasSettingState) //캔버스 기본 셋팅
|
||||
const [roofMaterial, setRoofMaterial] = useState(addRoof) //지붕재`
|
||||
|
||||
const globalPitch = useRecoilValue(pitchSelector) //피치
|
||||
const globalPitchText = useRecoilValue(pitchTextSelector) //피치 텍스트
|
||||
|
||||
const { findCommonCode } = useCommonCode()
|
||||
@ -55,10 +53,6 @@ export default function ModuleTabContents({
|
||||
|
||||
const [isExistData, setIsExistData] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
console.log('addRoof', addRoof)
|
||||
}, [])
|
||||
|
||||
//서까래간격 변경
|
||||
const handleChangeRaftBase = (option) => {
|
||||
setSelectedRaftBase(option)
|
||||
@ -88,6 +82,7 @@ export default function ModuleTabContents({
|
||||
...moduleSelectionInitParams,
|
||||
...roofBaseParams,
|
||||
roofBaseCd: option.roofBaseCd,
|
||||
inclCd: addRoof.pitch,
|
||||
})
|
||||
setSelectedRoofBase(option)
|
||||
}
|
||||
@ -158,7 +153,12 @@ export default function ModuleTabContents({
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
|
||||
const newRoofConstructions = { roofIndex: roofTab, trestle: selectedRoofBase, construction: selectedConstruction }
|
||||
const newRoofConstructions = {
|
||||
roofIndex: roofTab,
|
||||
addRoof: addRoof,
|
||||
trestle: selectedRoofBase,
|
||||
construction: selectedConstruction,
|
||||
}
|
||||
const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === roofTab)
|
||||
|
||||
if (index > -1) {
|
||||
@ -196,6 +196,7 @@ export default function ModuleTabContents({
|
||||
...moduleSelectionInitParams,
|
||||
...roofBaseParams,
|
||||
roofBaseCd: selectedRoofBase.roofBaseCd,
|
||||
inclCd: addRoof.pitch,
|
||||
})
|
||||
}
|
||||
}, [selectedRoofBase])
|
||||
@ -280,26 +281,11 @@ export default function ModuleTabContents({
|
||||
<div className="module-table-flex-wrap tab2">
|
||||
<div className="module-flex-item">
|
||||
<div className="module-flex-item-tit">
|
||||
{getMessage('modal.module.basic.setting.module.roof.material')}:{roofMaterial.nameJp}({globalPitch}
|
||||
{getMessage('modal.module.basic.setting.module.roof.material')}:{roofMaterial.nameJp}(
|
||||
{addRoof.roofAngleSet === 'slope' ? roofMaterial.pitch : roofMaterial.angle}
|
||||
{globalPitchText})
|
||||
</div>
|
||||
<div className="eaves-keraba-table">
|
||||
<div className="eaves-keraba-item">
|
||||
<div className="eaves-keraba-th">マンドンピッチ</div>
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="grid-select">
|
||||
<QSelectBox
|
||||
options={raftCodes}
|
||||
value={addRoof}
|
||||
sourceKey={'clCode'}
|
||||
targetKey={'raftBaseCd'}
|
||||
showKey={'clCodeNm'}
|
||||
disabled={roofMaterial.raftAuth === 'R' ? true : false}
|
||||
onChange={handleChangeRaftBase}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="eaves-keraba-item">
|
||||
{roofMaterial && ['C'].includes(roofMaterial.lenAuth) && (
|
||||
<>
|
||||
@ -461,7 +447,7 @@ export default function ModuleTabContents({
|
||||
type="checkbox"
|
||||
id={`ch01_${roofTab}`}
|
||||
disabled={cvrYn === 'N' ? true : false}
|
||||
checked={cvrChecked}
|
||||
defaultChecked={cvrChecked}
|
||||
onChange={handleCvrChecked}
|
||||
/>
|
||||
<label htmlFor={`ch01_${roofTab}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
|
||||
@ -471,7 +457,7 @@ export default function ModuleTabContents({
|
||||
type="checkbox"
|
||||
id={`ch02_${roofTab}`}
|
||||
disabled={snowGdPossYn === 'N' ? true : false}
|
||||
checked={snowGdChecked}
|
||||
defaultChecked={snowGdChecked}
|
||||
onChange={handleSnowGdChecked}
|
||||
/>
|
||||
<label htmlFor={`ch02_${roofTab}`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
|
||||
|
||||
@ -4,17 +4,19 @@ import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||
import { checkedModuleState } from '@/store/canvasAtom'
|
||||
import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil'
|
||||
import { selectedModuleState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { useModulePlace } from '@/hooks/module/useModulePlace'
|
||||
|
||||
const Placement = forwardRef((props, refs) => {
|
||||
const { getMessage } = useMessage()
|
||||
const selectedModules = useRecoilValue(selectedModuleState)
|
||||
const [isChidori, setIsChidori] = useState('false')
|
||||
const [setupLocation, setSetupLocation] = useState('center')
|
||||
const [isMaxSetup, setIsMaxSetup] = useState('false')
|
||||
const { makeModuleInstArea } = useModuleBasicSetting()
|
||||
const [selectedItems, setSelectedItems] = useState({})
|
||||
const setCheckedModules = useSetRecoilState(checkedModuleState)
|
||||
|
||||
const { makeModuleInstArea } = useModuleBasicSetting()
|
||||
const { selectedModules } = useModulePlace()
|
||||
|
||||
const setCheckedModules = useSetRecoilState(checkedModuleState)
|
||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
||||
|
||||
//모듈 배치면 생성
|
||||
@ -92,9 +94,9 @@ const Placement = forwardRef((props, refs) => {
|
||||
</thead>
|
||||
<tbody>
|
||||
{selectedModules.itemList &&
|
||||
selectedModules.itemList.map((item) => (
|
||||
selectedModules.itemList.map((item, index) => (
|
||||
<>
|
||||
<tr>
|
||||
<tr key={index}>
|
||||
<td className="al-c">
|
||||
<div className="d-check-box no-text pop">
|
||||
<input type="checkbox" id={item.itemId} name={item.itemId} onChange={handleSelectedItem} />
|
||||
|
||||
@ -12,14 +12,13 @@ import { get } from 'react-hook-form'
|
||||
import { correntObjectNoState } from '@/store/settingAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { modelState, pcsCheckState, powerConditionalState } from '@/store/circuitTrestleAtom'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
|
||||
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||
|
||||
const ALLOCATION_TYPE = {
|
||||
AUTO: 'auto',
|
||||
|
||||
@ -41,15 +41,35 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
hajebichi: useRef(null),
|
||||
}
|
||||
|
||||
//치수 입력방법(복시도입력/실측값입력/육지붕)
|
||||
const roofSizeSetArray = [
|
||||
{ id: 'ra01', name: 'roofSizeSet', value: '1', message: 'modal.placement.initial.setting.size.roof' },
|
||||
{ id: 'ra02', name: 'roofSizeSet', value: '2', message: 'modal.placement.initial.setting.size.actual' },
|
||||
{ id: 'ra03', name: 'roofSizeSet', value: '3', message: 'modal.placement.initial.setting.size.none.pitch' },
|
||||
]
|
||||
|
||||
//지붕각도 설정(경사/각도)
|
||||
const roofAngleSetArray = [
|
||||
{ id: 'ra04', name: 'roofAngleSet', value: 'slope', message: 'modal.placement.initial.setting.roof.pitch'},
|
||||
{ id: 'ra05', name: 'roofAngleSet', value: 'flat', message: 'modal.placement.initial.setting.roof.angle' },
|
||||
]
|
||||
|
||||
// 데이터를 최초 한 번만 조회
|
||||
useEffect(() => {
|
||||
if (!basicSetting || !currentRoof || Object.keys(currentRoof).length === 0 || Object.keys(basicSetting).length === 0) return
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
setRaftCodes(raftCodeList)
|
||||
setCurrentRoof({ ...currentRoof, roofSizeSet: basicSetting.roofMaterials.roofSizeSet, roofAngleSet: basicSetting.roofMaterials.roofAngleSet })
|
||||
|
||||
if (addedRoofs[0].roofAngleSet && addedRoofs[0].roofAngleSet?.length > 0) {
|
||||
setCurrentRoof({ ...currentRoof, roofSizeSet: String(addedRoofs[0].roofSizeSet), roofAngleSet: addedRoofs[0].roofAngleSet })
|
||||
} else if (basicSetting.roofAngleSet && basicSetting.roofAngleSet?.length > 0) {
|
||||
setCurrentRoof({ ...currentRoof, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ fetchBasicSettings ~ currentRoof :', currentRoof)
|
||||
if(!currentRoof) return
|
||||
setBasicSettings({
|
||||
...basicSetting,
|
||||
roofSizeSet: String(currentRoof.roofSizeSet),
|
||||
@ -110,10 +130,8 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
}
|
||||
|
||||
const newAddedRoofs = [...addedRoofs]
|
||||
if (addedRoofs.length === 1) {
|
||||
newAddedRoofs[0] = { ...roofInfo }
|
||||
setAddedRoofs(newAddedRoofs)
|
||||
}
|
||||
newAddedRoofs[0] = { ...roofInfo }
|
||||
setAddedRoofs(newAddedRoofs)
|
||||
|
||||
console.log('save Info', {
|
||||
...basicSetting,
|
||||
@ -178,74 +196,42 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
</div>
|
||||
</th>
|
||||
<td>
|
||||
<div className="pop-form-radio">
|
||||
<div className="d-check-radio pop">
|
||||
<input
|
||||
type="radio"
|
||||
name="roofSizeSet"
|
||||
id="ra01"
|
||||
value="1" // roofSizeSet 값이 '1'인 경우
|
||||
checked={currentRoof?.roofSizeSet === '1'} // 선택 여부 확인
|
||||
//onChange={(e) => setBasicSettings({ ...basicSetting, roofSizeSet: e.target.value })} // 상태 업데이트
|
||||
onClick={() => handleRoofSizeSetChange('1')}
|
||||
/>
|
||||
<label htmlFor="ra01">{getMessage('modal.placement.initial.setting.size.roof')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio pop">
|
||||
<input
|
||||
type="radio"
|
||||
name="roofSizeSet"
|
||||
id="ra02"
|
||||
value="2" // roofSizeSet 값이 '2'인 경우
|
||||
checked={currentRoof?.roofSizeSet === '2'} // 선택 여부 확인
|
||||
//onChange={(e) => setBasicSettings({ ...basicSetting, roofSizeSet: e.target.value })} // 상태 업데이트
|
||||
onClick={() => handleRoofSizeSetChange('2')}
|
||||
/>
|
||||
<label htmlFor="ra02">{getMessage('modal.placement.initial.setting.size.actual')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio pop">
|
||||
<input
|
||||
type="radio"
|
||||
name="roofSizeSet"
|
||||
id="ra03"
|
||||
value="3" // roofSizeSet 값이 '3'인 경우
|
||||
checked={currentRoof?.roofSizeSet === '3'} // 선택 여부 확인
|
||||
//onChange={(e) => setBasicSettings({ ...basicSetting, roofSizeSet: e.target.value })} // 상태 업데이트
|
||||
onClick={() => handleRoofSizeSetChange('3')}
|
||||
/>
|
||||
<label htmlFor="ra03">{getMessage('modal.placement.initial.setting.size.none.pitch')}</label>
|
||||
</div>
|
||||
<div className="pop-form-radio">
|
||||
{currentRoof &&
|
||||
roofSizeSetArray.map((item) => (
|
||||
<div className="d-check-radio pop" key={item.id}>
|
||||
<input type="radio"
|
||||
id={item.id}
|
||||
name={item.name}
|
||||
value={item.value}
|
||||
checked={currentRoof?.roofSizeSet === item.value}
|
||||
onChange={(e) => setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })}
|
||||
/>
|
||||
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{getMessage('modal.placement.initial.setting.roof.angle.setting')}</th>
|
||||
<td>
|
||||
<div className="pop-form-radio">
|
||||
<div className="d-check-radio pop">
|
||||
<input
|
||||
type="radio"
|
||||
name="roofAngleSet"
|
||||
id="ra04"
|
||||
value="slope" // 첫 번째 라디오 버튼의 값
|
||||
checked={currentRoof?.roofAngleSet === 'slope'} // 현재 선택된 값인지 확인
|
||||
//onChange={(e) => setBasicSettings({ ...basicSetting, roofAngleSet: e.target.value })} // 상태 업데이트
|
||||
onClick={() => handleRoofAngleSetChange('slope')}
|
||||
/>
|
||||
<label htmlFor="ra04">{getMessage('modal.placement.initial.setting.roof.pitch')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio pop">
|
||||
<input
|
||||
type="radio"
|
||||
name="roofAngleSet"
|
||||
id="ra05"
|
||||
value="flat" // 두 번째 라디오 버튼의 값
|
||||
checked={currentRoof?.roofAngleSet === 'flat'} // 현재 선택된 값인지 확인
|
||||
//onChange={(e) => setBasicSettings({ ...basicSetting, roofAngleSet: e.target.value })} // 상태 업데이트
|
||||
onClick={() => handleRoofAngleSetChange('flat')}
|
||||
/>
|
||||
<label htmlFor="ra05">{getMessage('modal.placement.initial.setting.roof.angle')}</label>
|
||||
</div>
|
||||
<div className="pop-form-radio">
|
||||
{currentRoof &&
|
||||
roofAngleSetArray.map((item) => (
|
||||
<div className="d-check-radio pop" key={item.id}>
|
||||
<input type="radio"
|
||||
id={item.id}
|
||||
name={item.name}
|
||||
value={item.value}
|
||||
checked={currentRoof?.roofAngleSet === item.value}
|
||||
onChange={(e) => setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })}
|
||||
/>
|
||||
<label htmlFor={item.id}>{getMessage(item.message)}</label>
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -264,7 +250,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
currentRoof?.roofSizeSet === '3' ? getMessage('modal.placement.initial.setting.size.none.pitch') : currentRoof?.roofMatlNm
|
||||
}
|
||||
ref={roofRef.roofCd}
|
||||
options={roofMaterials.map((roof, index) => {
|
||||
options={roofMaterials.map((roof) => {
|
||||
return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp }
|
||||
})}
|
||||
value={currentRoof?.roofSizeSet === '3' ? null : currentRoof?.roofMatlCd}
|
||||
|
||||
@ -19,6 +19,8 @@ import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { stuffSearchState } from '@/store/stuffAtom'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
|
||||
export const ToggleonMouse = (e, act, target) => {
|
||||
const listWrap = e.target.closest(target)
|
||||
const ListItem = Array.from(listWrap.childNodes)
|
||||
@ -39,6 +41,8 @@ export default function Header(props) {
|
||||
|
||||
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
|
||||
|
||||
const { closeAll } = usePopup()
|
||||
|
||||
const { userSession } = props
|
||||
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||
const { getMessage } = useMessage()
|
||||
@ -176,6 +180,9 @@ export default function Header(props) {
|
||||
onClick={() => {
|
||||
// moveHome()
|
||||
removeStuffRecoil(menu)
|
||||
if (pathName === '/') {
|
||||
window.location.reload()
|
||||
}
|
||||
}}
|
||||
>
|
||||
{getMessage(menu.name)}
|
||||
@ -226,6 +233,9 @@ export default function Header(props) {
|
||||
...stuffSearch,
|
||||
code: 'DELETE',
|
||||
})
|
||||
if (pathName === '/') {
|
||||
window.location.reload()
|
||||
}
|
||||
}}
|
||||
></Link>
|
||||
</h1>
|
||||
@ -239,6 +249,7 @@ export default function Header(props) {
|
||||
href="#"
|
||||
onClick={() => {
|
||||
setUserInfoModal(true)
|
||||
closeAll()
|
||||
}}
|
||||
>
|
||||
<button className="profile">{userSession.userNm}</button>
|
||||
|
||||
@ -272,7 +272,7 @@ export default function Stuff() {
|
||||
stuffSearchParams.pageNo = stuffSearchParams.pageNo
|
||||
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(stuffSearchParams)}`
|
||||
await get({ url: apiUrl }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
|
||||
@ -302,7 +302,7 @@ export default function Stuff() {
|
||||
setPageNo(1)
|
||||
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(stuffSearchParams)}`
|
||||
await get({ url: apiUrl }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
|
||||
|
||||
@ -10,7 +10,7 @@ import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useRecoilValue, useSetRecoilState, useResetRecoilState, useRecoilState } from 'recoil'
|
||||
import { useRecoilValue, useSetRecoilState, useRecoilState } from 'recoil'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
import FindAddressPop from './popup/FindAddressPop'
|
||||
import PlanRequestPop from './popup/PlanRequestPop'
|
||||
@ -19,18 +19,16 @@ import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import StuffPlanQGrid from './StuffPlanQGrid'
|
||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
// import { ManagementContext } from '@/app/management/ManagementProvider'
|
||||
import DocDownOptionPop from '../estimate/popup/DocDownOptionPop'
|
||||
import { stuffSearchState } from '@/store/stuffAtom'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
|
||||
export default function StuffDetail() {
|
||||
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
|
||||
const { swalFire } = useSwal()
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
|
||||
const stuffSearchParams = useRecoilValue(stuffSearchState)
|
||||
|
||||
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //견적서 화면용 물건번호리코일
|
||||
@ -41,6 +39,8 @@ export default function StuffDetail() {
|
||||
|
||||
const [showButton, setShowButton] = useState('') //임시저장, 저장, 삭제 버튼 컨트롤
|
||||
|
||||
const { setMenuNumber } = useCanvasMenu()
|
||||
|
||||
//공통코드
|
||||
const { commonCode, findCommonCode } = useCommonCode()
|
||||
const [selOptions, setSelOptions] = useState('') //선택한 1차점
|
||||
@ -123,13 +123,13 @@ export default function StuffDetail() {
|
||||
field: 'planNo',
|
||||
headerName: getMessage('stuff.detail.planGridHeader.planNo'),
|
||||
width: 100,
|
||||
cellStyle: { justifyContent: 'center', cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'center', cursor: 'pointer' },
|
||||
},
|
||||
{
|
||||
field: 'orderFlg',
|
||||
headerName: getMessage('stuff.detail.planGridHeader.orderFlg'),
|
||||
width: 80,
|
||||
cellStyle: { justifyContent: 'center', cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'center', cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
//1일때만 동그라미
|
||||
let orderFlg
|
||||
@ -142,31 +142,30 @@ export default function StuffDetail() {
|
||||
headerName: getMessage('stuff.detail.planGridHeader.moduleModel'),
|
||||
flex: 1,
|
||||
wrapText: true,
|
||||
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
// cellRenderer: (params) => {
|
||||
// let origin = params.value
|
||||
// console.log('모듈:::', origin)
|
||||
// if (origin !== null) {
|
||||
// return (
|
||||
// <>
|
||||
// {origin?.split('、').map((it, idx) => (
|
||||
// <span key={idx} className="block">
|
||||
// {it}
|
||||
// <br />
|
||||
// </span>
|
||||
// ))}
|
||||
// </>
|
||||
// )
|
||||
// } else {
|
||||
// return null
|
||||
// }
|
||||
// },
|
||||
cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
let origin = params.value
|
||||
if (origin !== null) {
|
||||
return (
|
||||
<>
|
||||
{origin?.split('、').map((it, idx) => (
|
||||
<span key={idx} className="block">
|
||||
{it}
|
||||
<br />
|
||||
</span>
|
||||
))}
|
||||
</>
|
||||
)
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'capacity',
|
||||
headerName: getMessage('stuff.detail.planGridHeader.capacity'),
|
||||
width: 120,
|
||||
cellStyle: { justifyContent: 'flex-end' /* 우측정렬*/, cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'flex-end' /* 우측정렬*/, cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
let origin = params.value
|
||||
let capacity
|
||||
@ -185,7 +184,7 @@ export default function StuffDetail() {
|
||||
width: 140,
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
let origin = params.value
|
||||
if (origin !== null) {
|
||||
@ -209,7 +208,7 @@ export default function StuffDetail() {
|
||||
headerName: getMessage('stuff.detail.planGridHeader.constructSpecificationMulti'),
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
let origin = params.value
|
||||
if (origin !== null) {
|
||||
@ -233,7 +232,7 @@ export default function StuffDetail() {
|
||||
headerName: getMessage('stuff.detail.planGridHeader.supportMethodIdMulti'),
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
let origin = params.value
|
||||
if (origin !== null) {
|
||||
@ -258,7 +257,7 @@ export default function StuffDetail() {
|
||||
flex: 1,
|
||||
wrapText: true,
|
||||
autoHeight: true,
|
||||
cellStyle: { justifyContent: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellStyle: { alignItems: 'flex-start' /* 좌측정렬*/, cursor: 'pointer' },
|
||||
cellRenderer: (params) => {
|
||||
let origin = params.value
|
||||
if (origin !== null) {
|
||||
@ -290,10 +289,10 @@ export default function StuffDetail() {
|
||||
display: 'none',
|
||||
}
|
||||
}
|
||||
if (managementState?.createUser === 'T01' && session?.userId !== 'T01') {
|
||||
//createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 적용할지 미정!!!!!!!!
|
||||
//buttonStyle = { display: 'none' }
|
||||
}
|
||||
// if (managementState?.createUser === 'T01' && session?.userId !== 'T01') {
|
||||
//createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 적용할지 미정!!!!!!!!
|
||||
//buttonStyle = { display: 'none' }
|
||||
// }
|
||||
return (
|
||||
<>
|
||||
<div className="grid-cell-btn">
|
||||
@ -649,7 +648,8 @@ export default function StuffDetail() {
|
||||
//염해지역용아이템사용 saltAreaFlg 1이면 true
|
||||
form.setValue('saltAreaFlg', managementState.saltAreaFlg === '1' ? true : false)
|
||||
//설치높이
|
||||
form.setValue('installHeight', managementState.installHeight)
|
||||
let installHeight = managementState.installHeight ? managementState.installHeight.split('.')[0] : '0'
|
||||
form.setValue('installHeight', installHeight)
|
||||
//계약조건 null로 내려오면 0으로 디폴트셋팅
|
||||
if (managementState.conType === null) {
|
||||
form.setValue('conType', '0')
|
||||
@ -983,7 +983,10 @@ export default function StuffDetail() {
|
||||
} else {
|
||||
form.setValue('saltAreaFlg', false)
|
||||
}
|
||||
form.setValue('installHeight', info.installHeight)
|
||||
|
||||
let installHeight = info.installHeight ? info.installHeight.split('.')[0] : '0'
|
||||
|
||||
form.setValue('installHeight', installHeight)
|
||||
form.setValue('remarks', info.remarks)
|
||||
|
||||
if (info.saleStoreLevel === '1') {
|
||||
@ -1582,16 +1585,20 @@ export default function StuffDetail() {
|
||||
)
|
||||
}
|
||||
|
||||
// 그리드 더블 클릭
|
||||
// 그리드 더블 클릭 해당플랜의 도면작성 화면으로 이동
|
||||
const getCellDoubleClicked = (params) => {
|
||||
if (params.data.estimateDate != null) {
|
||||
if (params?.column?.colId !== 'estimateDate') {
|
||||
if (params?.data?.planNo && params?.data?.objectNo) {
|
||||
setIsGlobalLoading(true)
|
||||
let objectNo = params?.data?.objectNo
|
||||
let planNo = params?.data?.planNo
|
||||
router.push(`/floor-plan/estimate/5?pid=${planNo}&objectNo=${objectNo}`)
|
||||
if (params?.column?.colId !== 'estimateDate') {
|
||||
if (params?.data?.planNo && params?.data?.objectNo) {
|
||||
let objectNo = params?.data?.objectNo
|
||||
let planNo = params?.data?.planNo
|
||||
|
||||
const param = {
|
||||
pid: planNo,
|
||||
objectNo: objectNo,
|
||||
}
|
||||
setMenuNumber(null)
|
||||
const url = `/floor-plan?${queryStringFormatter(param)}`
|
||||
router.push(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -705,6 +705,18 @@ export default function StuffSearchCondition() {
|
||||
stuffSearch.pageSize = 100
|
||||
setSchSelSaleStoreId('')
|
||||
setOtherSaleStoreId('')
|
||||
} else {
|
||||
setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||
setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
|
||||
setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
|
||||
setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
|
||||
setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
|
||||
setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
|
||||
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
||||
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
||||
setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
|
||||
setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
|
||||
setMyDataCheck(stuffSearch.schMyDataCheck)
|
||||
}
|
||||
} else {
|
||||
setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||
|
||||
@ -12,9 +12,9 @@ import { QcastContext } from '@/app/QcastProvider'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
// import { ManagementContext } from '@/app/management/ManagementProvider'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
|
||||
export default function StuffSubHeader({ type }) {
|
||||
@ -29,6 +29,9 @@ export default function StuffSubHeader({ type }) {
|
||||
const { managementState } = useContext(GlobalDataContext)
|
||||
|
||||
const [buttonStyle, setButtonStyle] = useState('')
|
||||
|
||||
const { setMenuNumber } = useCanvasMenu()
|
||||
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0)
|
||||
}, [])
|
||||
@ -55,6 +58,8 @@ export default function StuffSubHeader({ type }) {
|
||||
pid: '1',
|
||||
objectNo: objectNo,
|
||||
}
|
||||
|
||||
setMenuNumber(null)
|
||||
const url = `/floor-plan?${queryStringFormatter(param)}`
|
||||
|
||||
router.push(url)
|
||||
|
||||
@ -169,13 +169,13 @@ export default function PlanRequestPop(props) {
|
||||
gridData: [],
|
||||
isPageable: false,
|
||||
gridColumns: [
|
||||
// {
|
||||
// field: 'planStatName',
|
||||
// headerName: getMessage('stuff.planReqPopup.gridHeader.planStatName'),
|
||||
// minWidth: 150,
|
||||
// checkboxSelection: true,
|
||||
// showDisabledCheckboxes: true,
|
||||
// },
|
||||
{
|
||||
field: '',
|
||||
headerName: '',
|
||||
minWidth: 50,
|
||||
checkboxSelection: true,
|
||||
showDisabledCheckboxes: true,
|
||||
},
|
||||
{
|
||||
field: 'planReqNo',
|
||||
headerName: getMessage('stuff.planReqPopup.gridHeader.planReqNo'),
|
||||
|
||||
@ -107,10 +107,8 @@ export function useMasterController() {
|
||||
* @returns
|
||||
*/
|
||||
const getTrestleDetailList = async (params) => {
|
||||
const paramString = getQueryString(params)
|
||||
console.log('🚀🚀 ~ getTrestleDetailList ~ paramString:', paramString)
|
||||
return await get({ url: '/api/v1/master/getTrestleDetailList' + paramString }).then((res) => {
|
||||
console.log('🚀🚀 ~ getTrestleDetailList ~ res:', res)
|
||||
// const paramString = getQueryString(params)
|
||||
return await post({ url: '/api/v1/master/getTrestleDetailList', data: params }).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom
|
||||
import { isObjectNotEmpty, isEmptyArray } from '@/util/common-utils'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
@ -35,11 +35,14 @@ export const useEstimateController = (planNo) => {
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const { estimateContextState, setEstimateContextState } = useContext(FloorPlanContext)
|
||||
|
||||
const searchParams = useSearchParams()
|
||||
useEffect(() => {
|
||||
if (planNo && !isLoading) {
|
||||
if (objectRecoil.floorPlanObjectNo && planNo) {
|
||||
fetchSetting(objectRecoil.floorPlanObjectNo, planNo)
|
||||
//견적서 화면에서 새로고침시 리코일 사라지는 현상 대응
|
||||
let recoilObjectNo = objectRecoil.floorPlanObjectNo ? objectRecoil.floorPlanObjectNo : searchParams.get('objectNo')
|
||||
|
||||
if (recoilObjectNo && planNo) {
|
||||
fetchSetting(recoilObjectNo, planNo)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
@ -85,6 +88,8 @@ export const useEstimateController = (planNo) => {
|
||||
setIsGlobalLoading(false)
|
||||
} catch (error) {
|
||||
console.error('견적서 상세조회 Error: ', error)
|
||||
|
||||
swalFire({ text: getMessage('estimate.menu.move.valid1') })
|
||||
setIsLoading(true)
|
||||
setIsGlobalLoading(false)
|
||||
}
|
||||
|
||||
@ -129,6 +129,8 @@ export function useModuleBasicSetting() {
|
||||
|
||||
//설치 범위 지정 클릭 이벤트
|
||||
const toggleSelection = (setupSurface) => {
|
||||
console.log('setupSurface', setupSurface)
|
||||
|
||||
const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
|
||||
//최초 선택일때
|
||||
if (!isExist) {
|
||||
@ -1122,7 +1124,7 @@ export function useModuleBasicSetting() {
|
||||
}
|
||||
})
|
||||
|
||||
// moduleSetupSurface.set({ modules: moduleSetupArray })
|
||||
moduleSetupSurface.set({ modules: moduleSetupArray })
|
||||
|
||||
// const moduleArray = [...moduleIsSetup]
|
||||
// moduleArray.push({
|
||||
@ -1134,247 +1136,6 @@ export function useModuleBasicSetting() {
|
||||
// calculateForApi()
|
||||
}
|
||||
|
||||
const calculateForApi = () => {
|
||||
const moduleSufaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||
|
||||
const results = []
|
||||
|
||||
moduleSufaces.forEach((moduleSurface) => {
|
||||
const centerPoints = []
|
||||
const direction = moduleSurface.direction
|
||||
const modules = moduleSurface.modules
|
||||
|
||||
modules.forEach((module, index) => {
|
||||
module.tempIndex = index
|
||||
const { x, y } = module.getCenterPoint()
|
||||
const { width, height } = module
|
||||
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
|
||||
})
|
||||
|
||||
if (centerPoints.length === 0) return
|
||||
|
||||
//완전 노출 하면
|
||||
let exposedBottom = 0
|
||||
// 반 노출 하면
|
||||
let exposedHalfBottom = 0
|
||||
// 완전 노출 상면
|
||||
let exposedTop = 0
|
||||
//반 노출 상면
|
||||
let exposedHalfTop = 0
|
||||
// 완전 접면
|
||||
let touchDimension = 0
|
||||
//반접면
|
||||
let halfTouchDimension = 0
|
||||
// 노출하면 체크
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
|
||||
let bottomCell
|
||||
let bottomLeftPoint
|
||||
let bottomRightPoint
|
||||
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
|
||||
}
|
||||
|
||||
if (bottomCell.length === 1) {
|
||||
return
|
||||
}
|
||||
|
||||
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
|
||||
leftBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
|
||||
).length
|
||||
rightBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftBottomCnt + rightBottomCnt === 1) {
|
||||
exposedHalfBottom++
|
||||
return
|
||||
}
|
||||
})
|
||||
// 노출상면 체크
|
||||
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
|
||||
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) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
leftTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2,
|
||||
).length
|
||||
rightTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 2) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 1) {
|
||||
exposedHalfTop++
|
||||
halfTouchDimension++
|
||||
return
|
||||
}
|
||||
if (leftTopCnt + rightTopCnt === 0) {
|
||||
exposedTop++
|
||||
}
|
||||
})
|
||||
// 완전 노출 하면 계산
|
||||
|
||||
/*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
|
||||
const points = cells.map((cell) => {
|
||||
return cell.getCenterPoint()
|
||||
})*/
|
||||
const groupPoints = groupCoordinates(centerPoints, modules[0], direction)
|
||||
|
||||
groupPoints.forEach((group) => {
|
||||
let maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
|
||||
let minY = group.reduce((acc, cur) => (acc.y < cur.y ? acc : cur)).y
|
||||
let maxX = group.reduce((acc, cur) => (acc.x > cur.x ? acc : cur)).x
|
||||
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
|
||||
break
|
||||
case 'north':
|
||||
exposedBottom += minYCenterPoint.length
|
||||
break
|
||||
case 'east':
|
||||
exposedBottom += maxXCenterPoint.length
|
||||
break
|
||||
case 'west':
|
||||
exposedBottom += minXCenterPoint.length
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
results.push({
|
||||
exposedBottom,
|
||||
exposedHalfBottom,
|
||||
exposedTop,
|
||||
exposedHalfTop,
|
||||
touchDimension,
|
||||
halfTouchDimension,
|
||||
})
|
||||
console.log({
|
||||
direction,
|
||||
exposedBottom,
|
||||
exposedHalfBottom,
|
||||
exposedTop,
|
||||
exposedHalfTop,
|
||||
touchDimension,
|
||||
halfTouchDimension,
|
||||
})
|
||||
})
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환
|
||||
const groupCoordinates = (points, moduleExample, direction) => {
|
||||
const groups = []
|
||||
const visited = new Set()
|
||||
const width = Math.floor(moduleExample.width)
|
||||
const height = Math.floor(moduleExample.height)
|
||||
const horizonPadding = 0 // 가로 패딩
|
||||
const verticalPadding = 0 // 세로 패딩
|
||||
|
||||
function isAdjacent(p1, p2) {
|
||||
const dx = Math.abs(p1.x - p2.x)
|
||||
const dy = Math.abs(p1.y - p2.y)
|
||||
return (
|
||||
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
|
||||
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
|
||||
(Math.abs(dx - width / 2 + horizonPadding / 2) < 2 && Math.abs(dy - height + verticalPadding) < 2)
|
||||
)
|
||||
}
|
||||
|
||||
function dfs(point, group) {
|
||||
visited.add(`${point.x},${point.y}`)
|
||||
group.push(point)
|
||||
|
||||
for (const nextPoint of points) {
|
||||
const key = `${nextPoint.x},${nextPoint.y}`
|
||||
if (!visited.has(key) && isAdjacent(point, nextPoint)) {
|
||||
dfs(nextPoint, group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const point of points) {
|
||||
const key = `${point.x},${point.y}`
|
||||
if (!visited.has(key)) {
|
||||
const group = []
|
||||
dfs(point, group)
|
||||
groups.push(group)
|
||||
}
|
||||
}
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
const coordToTurfPolygon = (points) => {
|
||||
const coordinates = points.map((point) => [point.x, point.y])
|
||||
coordinates.push(coordinates[0])
|
||||
|
||||
@ -1,184 +1,84 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
|
||||
import { selectedModuleState, moduleSelectionInitParamsState } from '@/store/selectedModuleOptions'
|
||||
import { pitchSelector } from '@/store/canvasAtom'
|
||||
|
||||
export function useModuleSelection(props) {
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
const globalPitch = useRecoilValue(pitchSelector) //피치
|
||||
|
||||
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
|
||||
const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록
|
||||
const [moduleList, setModuleList] = useState([{}]) //모듈 목록
|
||||
|
||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
|
||||
const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도
|
||||
const [installHeight, setInstallHeight] = useState('0') //설치 높이
|
||||
const [standardWindSpeed, setStandardWindSpeed] = useState({}) //기준풍속
|
||||
const [verticalSnowCover, setVerticalSnowCover] = useState('0') //수직적설량
|
||||
const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
|
||||
|
||||
const { getModuleTypeItemList } = useMasterController()
|
||||
|
||||
const { findCommonCode } = useCommonCode()
|
||||
|
||||
//탭별 파라메터 초기화
|
||||
useEffect(() => {
|
||||
setInstallHeight(managementState?.installHeight)
|
||||
setStandardWindSpeed(managementState?.standardWindSpeedId)
|
||||
setVerticalSnowCover(managementState?.verticalSnowCover)
|
||||
setSelectedSurfaceType(managementState?.surfaceType)
|
||||
|
||||
const initParams = {
|
||||
illuminationTp: managementState?.surfaceTypeValue, //면조도
|
||||
instHt: managementState?.installHeight, //설치높이
|
||||
stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
|
||||
stdSnowLd: managementState?.verticalSnowCover, //기준적설량
|
||||
inclCd: globalPitch,
|
||||
}
|
||||
setModuleSelectionInitParams(initParams)
|
||||
}, [managementState])
|
||||
export function useModulePlace() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
const [trestleDetailParams, setTrestleDetailParams] = useState([])
|
||||
const [trestleDetailList, setTrestleDetailList] = useState([])
|
||||
const selectedModules = useRecoilValue(selectedModuleState)
|
||||
const { getTrestleDetailList } = useMasterController()
|
||||
|
||||
useEffect(() => {
|
||||
// 113700 면조도
|
||||
const roughnessCodeList = findCommonCode('113700')
|
||||
roughnessCodeList.forEach((obj) => {
|
||||
obj.name = obj.clCodeNm
|
||||
obj.id = obj.clCode
|
||||
})
|
||||
setRoughnessCodes(roughnessCodeList)
|
||||
|
||||
// 202000 풍속
|
||||
const windCodeList = findCommonCode('202000')
|
||||
windCodeList.forEach((obj) => {
|
||||
obj.name = obj.clCodeNm
|
||||
obj.id = obj.clCode
|
||||
})
|
||||
setWindSpeedCodes(windCodeList)
|
||||
|
||||
//지붕재 선택
|
||||
const roofsIds = props.addedRoofs.filter((obj) => obj.roofMatlCd).map((obj) => obj.roofMatlCd)
|
||||
|
||||
if (roofsIds.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
//새로고침시 데이터 날아가는거 방지
|
||||
if (!managementState) {
|
||||
setManagementState(managementStateLoaded)
|
||||
}
|
||||
|
||||
getModuleData(roofsIds)
|
||||
console.log('🚀 ~ useModulePlace ~ moduleSelectionData:', moduleSelectionData)
|
||||
}, [])
|
||||
|
||||
const getModuleData = async (roofsIds) => {
|
||||
const list = await getModuleTypeItemList(roofsIds)
|
||||
//selectbox에 이름을 넣는다
|
||||
list.data.forEach((item) => {
|
||||
item.name = item.itemNm
|
||||
useEffect(() => {
|
||||
const common = moduleSelectionData.common
|
||||
const roofConstructions = moduleSelectionData.roofConstructions
|
||||
|
||||
const listParams = roofConstructions.map((item) => {
|
||||
return {
|
||||
...common,
|
||||
moduleTpCd: selectedModules.itemTp,
|
||||
roofMatlCd: item.trestle.roofMatlCd,
|
||||
trestleMkrCd: item.trestle.trestleMkrCd,
|
||||
constMthdCd: item.trestle.constMthdCd,
|
||||
roofBaseCd: item.trestle.roofBaseCd,
|
||||
constTp: item.construction.constTp,
|
||||
mixMatlNo: selectedModules.mixMatlNo,
|
||||
roofPitch: selectedModules.roofPchBase ? selectedModules.roofPchBase : null,
|
||||
inclCd: String(item.addRoof.pitch),
|
||||
roofIndex: item.addRoof.index,
|
||||
}
|
||||
})
|
||||
//셀렉트박스 데이터 초기화
|
||||
setModuleList(list.data)
|
||||
}
|
||||
|
||||
const handleChangeModule = (option) => {
|
||||
//선택된 모듈
|
||||
setSelectedModules(option) //선택값 저장
|
||||
setTrestleDetailParams(listParams)
|
||||
}, [moduleSelectionData])
|
||||
|
||||
//init 데이터에 선택된 모듈 추가
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
moduleTpCd: option.itemTp,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeSurfaceType = (option) => {
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
illuminationTp: option.clCode,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeWindSpeed = (option) => {
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
surfaceType: option.clCode,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeInstallHeight = (option) => {
|
||||
setInstallHeight(option)
|
||||
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
instHt: option,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeVerticalSnowCover = (option) => {
|
||||
setVerticalSnowCover(option)
|
||||
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
stdSnowLd: option,
|
||||
})
|
||||
const getTrestleDetailListData = async () => {
|
||||
const trestleDetailList = await getTrestleDetailList(trestleDetailParams)
|
||||
setTrestleDetailList(trestleDetailList)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('installHeight', installHeight)
|
||||
}, [installHeight])
|
||||
if (trestleDetailParams.length > 0) {
|
||||
getTrestleDetailListData(trestleDetailParams)
|
||||
}
|
||||
}, [trestleDetailParams])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('verticalSnowCover', verticalSnowCover)
|
||||
}, [verticalSnowCover])
|
||||
console.log('🚀 ~ useModulePlace ~ trestleDetailList:', trestleDetailList)
|
||||
|
||||
//TODO: 설치높이, 기준적설량 debounce 적용해서 추가해야됨
|
||||
//지붕을 가져옴
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((roof) => roof.name === 'roof')
|
||||
.forEach((roof) => {
|
||||
const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
|
||||
trestleDetailList.forEach((detail) => {
|
||||
if (Number(detail.data.roofIndex) === roofIndex) {
|
||||
//roof에 상세 데이터 추가
|
||||
roof.set({ trestleDetail: detail.data })
|
||||
|
||||
// useEffect(() => {
|
||||
// getConstructionListData(constructionListParams)
|
||||
// }, [constructionListParams])
|
||||
//surface에 상세 데이터 추가
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((surface) => surface.name === 'moduleSetupSurface' && surface.parentId === roof.id)
|
||||
.forEach((surface) => {
|
||||
surface.set({ trestleDetail: detail.data })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// const getConstructionListData = async (params) => {
|
||||
// if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
|
||||
// const optionsList = await getConstructionList(params)
|
||||
// console.log('optionsList', optionsList)
|
||||
// setConstructionList(optionsList.data)
|
||||
// }
|
||||
// }
|
||||
|
||||
//state 배열에 데이터 추가 함수
|
||||
// const addRoofTabParams = (key, value, excludeArray = []) => {
|
||||
// const index = roofTabParams.findIndex((obj) => obj.roofTab === roofTab)
|
||||
// if (index !== -1) {
|
||||
// roofTabParams[index][key] = value
|
||||
// if (excludeArray.length > 0) {
|
||||
// excludeArray.forEach((exclude) => {
|
||||
// roofTabParams[index][exclude] = ''
|
||||
// })
|
||||
// }
|
||||
// setRoofTabParams((prev) => [...prev.slice(0, index), roofTabParams[index], ...prev.slice(index + 1)])
|
||||
// }
|
||||
// }
|
||||
console.log('roof', roof)
|
||||
})
|
||||
}, [trestleDetailList])
|
||||
|
||||
return {
|
||||
moduleSelectionInitParams,
|
||||
selectedModules,
|
||||
roughnessCodes,
|
||||
windSpeedCodes,
|
||||
managementState,
|
||||
moduleList,
|
||||
selectedSurfaceType,
|
||||
installHeight,
|
||||
standardWindSpeed,
|
||||
verticalSnowCover,
|
||||
handleChangeModule,
|
||||
handleChangeSurfaceType,
|
||||
handleChangeWindSpeed,
|
||||
handleChangeInstallHeight,
|
||||
handleChangeVerticalSnowCover,
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,6 @@ export function useModuleSelection(props) {
|
||||
instHt: managementState?.installHeight, //설치높이
|
||||
stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
|
||||
stdSnowLd: managementState?.verticalSnowCover, //기준적설량
|
||||
inclCd: globalPitch,
|
||||
}
|
||||
setModuleSelectionInitParams(initParams)
|
||||
}, [managementState])
|
||||
@ -93,6 +92,7 @@ export function useModuleSelection(props) {
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
moduleTpCd: option.itemTp,
|
||||
moduleItemId: option.itemId,
|
||||
})
|
||||
}
|
||||
|
||||
@ -129,11 +129,11 @@ export function useModuleSelection(props) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('installHeight', installHeight)
|
||||
// console.log('installHeight', installHeight)
|
||||
}, [installHeight])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('verticalSnowCover', verticalSnowCover)
|
||||
// console.log('verticalSnowCover', verticalSnowCover)
|
||||
}, [verticalSnowCover])
|
||||
|
||||
//TODO: 설치높이, 기준적설량 debounce 적용해서 추가해야됨
|
||||
|
||||
988
src/hooks/module/useTrestle.js
Normal file
988
src/hooks/module/useTrestle.js
Normal file
@ -0,0 +1,988 @@
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
|
||||
// 회로 및 가대설정
|
||||
export const useTrestle = () => {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
|
||||
const apply = () => {
|
||||
//처마력바가 체크되어 있는 경우 exposedBottomPoints를 이용해 처마력바 그려줘야함.
|
||||
// exposedBottomPoints는 노출 최하면 들의 centerPoint 배열.
|
||||
|
||||
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||
// 기존 eaveBar를 삭제
|
||||
canvas.getObjects().forEach((obj) => {
|
||||
if (obj.name === 'eaveBar' || obj.name === 'rack') {
|
||||
canvas.remove(obj)
|
||||
}
|
||||
})
|
||||
|
||||
surfaces.forEach((surface) => {
|
||||
const parent = canvas.getObjects().find((obj) => obj.id === surface.parentId)
|
||||
const roofMaterialIndex = parent.roofMaterial.index
|
||||
const construction = moduleSelectionData.roofConstructions.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
||||
let isEaveBar = construction.setupCover
|
||||
let isSnowGuard = construction.setupSnowCover
|
||||
const direction = parent.direction
|
||||
|
||||
const rack = surface.trestleDetail.rack
|
||||
let { rackQty, rackIntvlPct } = surface.trestleDetail
|
||||
|
||||
const rackInfos = Object.keys(rack).map((key) => {
|
||||
return { key, value: rack[key] }
|
||||
})
|
||||
|
||||
const result = calculateForApi(surface)
|
||||
const centerPoints = result.centerPoints
|
||||
|
||||
const exposedBottomModules = [] // 아래 두면이 모두 노출 되어있는 경우
|
||||
const leftExposedHalfBottomModules = [] // 왼쪽 면만 노출되어있는 경우
|
||||
const rightExposedHalfBottomPoints = [] // 오른쪽 면만 노출되어 있는 경우
|
||||
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
modules.forEach((module) => {
|
||||
const { x, y } = module.getCenterPoint()
|
||||
const isExposedBottom = result.exposedBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
|
||||
const isLeftExposedHalfBottom = result.leftExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
|
||||
const isRightExposedHalfBottom = result.rightExposedHalfBottomPoints.some((point) => Math.abs(point.x - x) < 2 && Math.abs(point.y - y) < 2)
|
||||
if (isExposedBottom) {
|
||||
exposedBottomModules.push(module)
|
||||
}
|
||||
if (isLeftExposedHalfBottom) {
|
||||
leftExposedHalfBottomModules.push(module)
|
||||
}
|
||||
if (isRightExposedHalfBottom) {
|
||||
rightExposedHalfBottomPoints.push(module)
|
||||
}
|
||||
})
|
||||
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === 'eaveBar')
|
||||
.forEach((obj) => {
|
||||
canvas.remove(obj)
|
||||
})
|
||||
|
||||
if (isEaveBar) {
|
||||
// 처마력바설치 true인 경우 설치
|
||||
exposedBottomModules.forEach((module) => {
|
||||
//TODO : 방향별로 처마력바 설치해야함
|
||||
const bottomPoints = findTopTwoPoints([...module.points], direction)
|
||||
if (!bottomPoints) return
|
||||
const eaveBar = new fabric.Line([bottomPoints[0].x, bottomPoints[0].y, bottomPoints[1].x, bottomPoints[1].y], {
|
||||
name: 'eaveBar',
|
||||
stroke: 'blue',
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
})
|
||||
canvas.add(eaveBar)
|
||||
canvas.renderAll()
|
||||
})
|
||||
}
|
||||
// 가대 설치를 위한 가장 아래 모듈로부터 위로 몇단인지 계산
|
||||
// 오른쪽,왼쪽 둘 다 아래에 아무것도 없는, 처마 커버를 필요로 하는 모듈
|
||||
exposedBottomModules.forEach((module) => {
|
||||
const { width, height } = module
|
||||
let { x: startX, y: startY } = { ...module.getCenterPoint() }
|
||||
let { x, y } = { ...module.getCenterPoint() }
|
||||
//TODO : 방향별로 가대 설치해야함
|
||||
|
||||
let leftRows = 1
|
||||
let rightRows = 1
|
||||
let centerRows = 1
|
||||
let hasNextModule = true
|
||||
let findLeft = true
|
||||
let findRight = true
|
||||
|
||||
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findLeft) {
|
||||
nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
|
||||
findLeft = false
|
||||
} else {
|
||||
nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
|
||||
findLeft = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasNextModule = true
|
||||
x = startX
|
||||
y = startY
|
||||
|
||||
// 오른쪽 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findRight) {
|
||||
nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
|
||||
findRight = false
|
||||
} else {
|
||||
nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
|
||||
findRight = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasNextModule = true
|
||||
x = startX
|
||||
y = startY
|
||||
|
||||
// 센터 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
centerRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
|
||||
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const leftRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === leftRows
|
||||
})?.value.racks
|
||||
|
||||
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const rightRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === rightRows
|
||||
})?.value.racks
|
||||
// 해당 rack으로 그려준다.
|
||||
|
||||
const centerRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === centerRows
|
||||
})?.value.racks
|
||||
|
||||
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L')
|
||||
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R')
|
||||
|
||||
if (rackQty === 3) {
|
||||
//rack 갯수가 3개인 경우는 중간렉도 추가해줘야함
|
||||
drawRacks(centerRacks, rackQty, rackIntvlPct, module, direction, 'C')
|
||||
}
|
||||
})
|
||||
// 왼쪽아래에 모듈이 없는 모듈들
|
||||
leftExposedHalfBottomModules.forEach((module) => {
|
||||
const { width, height } = module
|
||||
let { x: startX, y: startY } = { ...module.getCenterPoint() }
|
||||
let { x, y } = { ...module.getCenterPoint() }
|
||||
//TODO : 방향별로 가대 설치해야함
|
||||
|
||||
let leftRows = 1
|
||||
let hasNextModule = true
|
||||
let findLeft = true
|
||||
|
||||
//우선 절반을 나눈 뒤 왼쪽부터 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findLeft) {
|
||||
nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
|
||||
findLeft = false
|
||||
} else {
|
||||
nextModule = nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
|
||||
findLeft = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
leftRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모듈의 왼쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const leftRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === leftRows
|
||||
})?.value.racks
|
||||
|
||||
drawRacks(leftRacks, rackQty, rackIntvlPct, module, direction, 'L')
|
||||
})
|
||||
// 오른쪽 아래에 모듈이 없는 모듈들
|
||||
rightExposedHalfBottomPoints.forEach((module) => {
|
||||
const { width, height } = module
|
||||
let { x: startX, y: startY } = { ...module.getCenterPoint() }
|
||||
let { x, y } = { ...module.getCenterPoint() }
|
||||
//TODO : 방향별로 가대 설치해야함
|
||||
|
||||
let rightRows = 1
|
||||
let hasNextModule = true
|
||||
let findRight = true
|
||||
|
||||
// 오른쪽 찾는다.
|
||||
while (hasNextModule) {
|
||||
//바로 위에 있는지 확인한다.
|
||||
let nextModule = findNextModule({ x, y, width, height }, centerPoints, direction)
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
// 바로 위가 없을 경우 먼저 왼쪽위가 있는지 확인 한다.
|
||||
if (findRight) {
|
||||
nextModule = findNextRightModule({ x, y, width, height }, centerPoints, direction)
|
||||
findRight = false
|
||||
} else {
|
||||
nextModule = findNextLeftModule({ x, y, width, height }, centerPoints, direction)
|
||||
findRight = true
|
||||
}
|
||||
|
||||
if (nextModule) {
|
||||
// 바로 위 모듈을 찾는다.
|
||||
rightRows++
|
||||
x = nextModule.x
|
||||
y = nextModule.y
|
||||
} else {
|
||||
hasNextModule = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 모듈의 오른쪽 부터 그릴 랙 정보를 가져온다.
|
||||
const rightRacks = rackInfos.find((rack) => {
|
||||
return rack.value.moduleRows === rightRows
|
||||
})?.value.racks
|
||||
// 해당 rack으로 그려준다.
|
||||
|
||||
drawRacks(rightRacks, rackQty, rackIntvlPct, module, direction, 'R')
|
||||
})
|
||||
})
|
||||
|
||||
/*switch (rackYn) {
|
||||
case 'Y': {
|
||||
// rack이 Y일 경우 rackQty가 필요함
|
||||
|
||||
break
|
||||
}
|
||||
case 'N': {
|
||||
break
|
||||
}
|
||||
}*/
|
||||
// 지지금구 설치
|
||||
installBracket()
|
||||
}
|
||||
|
||||
const findNextModule = (currentPoint, centerPoints, direction) => {
|
||||
let { x, y, width, height } = currentPoint
|
||||
width = Math.floor(width)
|
||||
height = Math.floor(height)
|
||||
|
||||
let result
|
||||
switch (direction) {
|
||||
case 'south': {
|
||||
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y - height)) < 2)
|
||||
break
|
||||
}
|
||||
case 'north': {
|
||||
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - x) < 2 && Math.abs(centerPoint.y - (y + height)) < 2)
|
||||
break
|
||||
}
|
||||
case 'east': {
|
||||
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x - width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
break
|
||||
}
|
||||
case 'west': {
|
||||
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - (x + width)) < 2 && Math.abs(centerPoint.y - y) < 2)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const findNextLeftModule = (currentPoint, centerPoints, direction) => {
|
||||
const { x, y, width, height } = currentPoint
|
||||
let result
|
||||
let topLeftPoint
|
||||
|
||||
switch (direction) {
|
||||
case 'south': {
|
||||
topLeftPoint = { x: x - width / 2, y: y - height }
|
||||
break
|
||||
}
|
||||
case 'north': {
|
||||
topLeftPoint = { x: x + width / 2, y: y + height }
|
||||
break
|
||||
}
|
||||
case 'east': {
|
||||
topLeftPoint = { x: x - width, y: y + height / 2 }
|
||||
break
|
||||
}
|
||||
case 'west': {
|
||||
topLeftPoint = { x: x + width, y: y - height / 2 }
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2)
|
||||
|
||||
return result
|
||||
}
|
||||
const findNextRightModule = (currentPoint, centerPoints, direction) => {
|
||||
const { x, y, width, height } = currentPoint
|
||||
let result
|
||||
let topRightPoint
|
||||
|
||||
switch (direction) {
|
||||
case 'south': {
|
||||
topRightPoint = { x: x + width / 2, y: y - height }
|
||||
break
|
||||
}
|
||||
case 'north': {
|
||||
topRightPoint = { x: x - width / 2, y: y + height }
|
||||
break
|
||||
}
|
||||
case 'east': {
|
||||
topRightPoint = { x: x - width, y: y - height / 2 }
|
||||
break
|
||||
}
|
||||
case 'west': {
|
||||
topRightPoint = { x: x + width, y: y + height / 2 }
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
result = centerPoints.find((centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
const drawRacks = (rackInfos, rackQty, rackIntvlPct, module, direction, l) => {
|
||||
const { width, height } = module
|
||||
|
||||
let startPointX, startPointY
|
||||
|
||||
switch (l) {
|
||||
case 'L': {
|
||||
// 왼쪽부분 시작 점
|
||||
if (direction === 'south') {
|
||||
startPointX = module.left + width / rackIntvlPct
|
||||
startPointY = module.top + module.height
|
||||
break
|
||||
} else if (direction === 'east') {
|
||||
startPointX = module.left + width
|
||||
startPointY = module.top + height - height / rackIntvlPct
|
||||
break
|
||||
} else if (direction === 'west') {
|
||||
startPointX = module.left
|
||||
startPointY = module.top + height / rackIntvlPct
|
||||
break
|
||||
} else if (direction === 'north') {
|
||||
startPointX = module.left + width - width / rackIntvlPct
|
||||
startPointY = module.top
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case 'R': {
|
||||
// 오른쪽부분 시작 점
|
||||
if (direction === 'south') {
|
||||
startPointX = module.left + module.width - width / rackIntvlPct
|
||||
startPointY = module.top + module.height / 2 + height / 2
|
||||
break
|
||||
} else if (direction === 'east') {
|
||||
startPointX = module.left + width
|
||||
startPointY = module.top + height / rackIntvlPct
|
||||
break
|
||||
} else if (direction === 'west') {
|
||||
startPointX = module.left
|
||||
startPointY = module.top + height - height / rackIntvlPct
|
||||
break
|
||||
} else if (direction === 'north') {
|
||||
startPointX = module.left + width / rackIntvlPct
|
||||
startPointY = module.top
|
||||
break
|
||||
}
|
||||
}
|
||||
case 'C': {
|
||||
// 중간부분 시작점
|
||||
if (direction === 'south') {
|
||||
const x = module.left + module.width / 2
|
||||
const y = module.top + module.height / 2
|
||||
startPointX = x
|
||||
startPointY = y + height / 2
|
||||
break
|
||||
} else if (direction === 'east') {
|
||||
const x = module.left + width
|
||||
const y = module.top + module.height / 2
|
||||
startPointX = x
|
||||
startPointY = y
|
||||
break
|
||||
} else if (direction === 'west') {
|
||||
const x = module.left
|
||||
const y = module.top + module.height / 2
|
||||
startPointX = x
|
||||
startPointY = y
|
||||
break
|
||||
} else if (direction === 'north') {
|
||||
const x = module.left + module.width / 2
|
||||
const y = module.top
|
||||
startPointX = x
|
||||
startPointY = y
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (direction) {
|
||||
case 'south': {
|
||||
rackInfos.forEach((rackInfo) => {
|
||||
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
|
||||
|
||||
const rackLength = rackLen / 10
|
||||
|
||||
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY - rackLength], {
|
||||
name: 'rack',
|
||||
stroke: 'red',
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
fill: 'red',
|
||||
shadow: {
|
||||
color: 'black', // Outline color
|
||||
blur: 10,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
},
|
||||
supFitQty,
|
||||
supFitIntvlPct,
|
||||
rackLen,
|
||||
rackId: itemId,
|
||||
direction: 'top',
|
||||
})
|
||||
|
||||
canvas.add(rack)
|
||||
canvas.renderAll()
|
||||
|
||||
startPointY -= rackLength + 3
|
||||
})
|
||||
|
||||
break
|
||||
}
|
||||
case 'east': {
|
||||
rackInfos.forEach((rackInfo) => {
|
||||
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
|
||||
|
||||
const rackLength = rackLen / 10
|
||||
|
||||
const rack = new fabric.Line([startPointX, startPointY, startPointX - rackLength, startPointY], {
|
||||
name: 'rack',
|
||||
stroke: 'red',
|
||||
shadow: {
|
||||
color: 'black', // Outline color
|
||||
blur: 10,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
},
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
supFitQty,
|
||||
supFitIntvlPct,
|
||||
rackLen,
|
||||
rackId: itemId,
|
||||
direction: 'left',
|
||||
})
|
||||
|
||||
canvas.add(rack)
|
||||
canvas.renderAll()
|
||||
|
||||
startPointX -= rackLength + 3
|
||||
})
|
||||
break
|
||||
}
|
||||
|
||||
case 'west': {
|
||||
rackInfos.forEach((rackInfo) => {
|
||||
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
|
||||
|
||||
const rackLength = rackLen / 10
|
||||
|
||||
const rack = new fabric.Line([startPointX, startPointY, startPointX + rackLength, startPointY], {
|
||||
name: 'rack',
|
||||
stroke: 'red',
|
||||
shadow: {
|
||||
color: 'black', // Outline color
|
||||
blur: 10,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
},
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
supFitQty,
|
||||
supFitIntvlPct,
|
||||
rackLen,
|
||||
rackId: itemId,
|
||||
direction: 'right',
|
||||
})
|
||||
|
||||
canvas.add(rack)
|
||||
canvas.renderAll()
|
||||
|
||||
startPointX += rackLength + 3
|
||||
})
|
||||
break
|
||||
}
|
||||
case 'north': {
|
||||
rackInfos.forEach((rackInfo) => {
|
||||
const { rackLen, itemId, supFitQty, supFitIntvlPct } = rackInfo
|
||||
|
||||
const rackLength = rackLen / 10
|
||||
|
||||
const rack = new fabric.Line([startPointX, startPointY, startPointX, startPointY + rackLength], {
|
||||
name: 'rack',
|
||||
stroke: 'red',
|
||||
shadow: {
|
||||
color: 'black', // Outline color
|
||||
blur: 10,
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
},
|
||||
strokeWidth: 4,
|
||||
selectable: false,
|
||||
supFitQty,
|
||||
supFitIntvlPct,
|
||||
rackLen,
|
||||
rackId: itemId,
|
||||
direction: 'bottom',
|
||||
})
|
||||
|
||||
canvas.add(rack)
|
||||
canvas.renderAll()
|
||||
|
||||
startPointY += rackLength + 3
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const installBracket = () => {
|
||||
const racks = canvas.getObjects().filter((obj) => obj.name === 'rack')
|
||||
// name이 bracket인 객체를 찾아서 삭제
|
||||
canvas.getObjects().forEach((obj) => {
|
||||
if (obj.name === 'bracket') {
|
||||
canvas.remove(obj)
|
||||
}
|
||||
})
|
||||
canvas.renderAll()
|
||||
|
||||
racks.forEach((rack) => {
|
||||
const { x1, y1, x2, y2, direction, supFitQty, supFitIntvlPct, rackLen } = rack
|
||||
|
||||
const moduleLength = 10
|
||||
|
||||
if (direction === 'top') {
|
||||
const result = getBracketPoints(supFitQty, supFitIntvlPct)
|
||||
|
||||
result.forEach((percent) => {
|
||||
const bracket = new fabric.Rect({
|
||||
left: x2 - moduleLength / 3,
|
||||
top: y2 + (rackLen / 10) * percent,
|
||||
fill: 'green',
|
||||
name: 'bracket',
|
||||
width: moduleLength,
|
||||
height: moduleLength,
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
canvas.add(bracket)
|
||||
})
|
||||
canvas.renderAll()
|
||||
} else if (direction === 'left') {
|
||||
const result = getBracketPoints(supFitQty, supFitIntvlPct)
|
||||
|
||||
result.forEach((percent) => {
|
||||
const bracket = new fabric.Rect({
|
||||
left: x2 + (rackLen / 10) * percent,
|
||||
top: y2 - moduleLength / 3,
|
||||
fill: 'green',
|
||||
name: 'bracket',
|
||||
width: moduleLength,
|
||||
height: moduleLength,
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
canvas.add(bracket)
|
||||
})
|
||||
canvas.renderAll()
|
||||
} else if (direction === 'right') {
|
||||
const result = getBracketPoints(supFitQty, supFitIntvlPct)
|
||||
|
||||
result.forEach((percent) => {
|
||||
const bracket = new fabric.Rect({
|
||||
left: x2 - (rackLen / 10) * percent,
|
||||
top: y2 - moduleLength / 3,
|
||||
fill: 'green',
|
||||
name: 'bracket',
|
||||
width: moduleLength,
|
||||
height: moduleLength,
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
canvas.add(bracket)
|
||||
})
|
||||
canvas.renderAll()
|
||||
} else if (direction === 'bottom') {
|
||||
const result = getBracketPoints(supFitQty, supFitIntvlPct)
|
||||
|
||||
result.forEach((percent) => {
|
||||
const bracket = new fabric.Rect({
|
||||
left: x2 - moduleLength / 3,
|
||||
top: y2 - (rackLen / 10) * percent,
|
||||
fill: 'green',
|
||||
name: 'bracket',
|
||||
width: moduleLength,
|
||||
height: moduleLength,
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
canvas.add(bracket)
|
||||
})
|
||||
canvas.renderAll()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getBracketPoints = (n, percent) => {
|
||||
if (n < 2) {
|
||||
throw new Error('Number of points must be at least 2')
|
||||
}
|
||||
|
||||
const points = []
|
||||
const topY = percent / 100 // 맨 위의 점의 y 좌표 (10%)
|
||||
const bottomY = 1 - percent / 100 // 맨 아래의 점의 y 좌표 (90%)
|
||||
|
||||
// 맨 위의 점 추가
|
||||
points.push(topY)
|
||||
|
||||
// 중간 점들 추가
|
||||
const interval = (bottomY - topY) / (n - 1)
|
||||
for (let i = 1; i < n - 1; i++) {
|
||||
points.push(topY + i * interval)
|
||||
}
|
||||
|
||||
// 맨 아래의 점 추가
|
||||
points.push(bottomY)
|
||||
|
||||
return points
|
||||
}
|
||||
|
||||
function findTopTwoPoints(points, direction) {
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
points.sort((a, b) => b.y - a.y)
|
||||
break
|
||||
case 'north':
|
||||
points.sort((a, b) => a.y - b.y)
|
||||
break
|
||||
case 'east':
|
||||
points.sort((a, b) => b.x - a.x)
|
||||
break
|
||||
case 'west':
|
||||
points.sort((a, b) => a.x - b.x)
|
||||
break
|
||||
}
|
||||
|
||||
return points.slice(0, 2)
|
||||
}
|
||||
|
||||
const calculateForApi = (moduleSurface) => {
|
||||
const centerPoints = []
|
||||
const direction = moduleSurface.direction
|
||||
const modules = moduleSurface.modules
|
||||
|
||||
modules.forEach((module, index) => {
|
||||
module.tempIndex = index
|
||||
const { x, y } = module.getCenterPoint()
|
||||
const { width, height } = module
|
||||
centerPoints.push({ x, y, width: Math.floor(width), height: Math.floor(height), index })
|
||||
})
|
||||
|
||||
if (centerPoints.length === 0) return
|
||||
|
||||
//완전 노출 하면
|
||||
let exposedBottom = 0
|
||||
// 반 노출 하면
|
||||
let exposedHalfBottom = 0
|
||||
// 완전 노출 상면
|
||||
let exposedTop = 0
|
||||
//반 노출 상면
|
||||
let exposedHalfTop = 0
|
||||
// 완전 접면
|
||||
let touchDimension = 0
|
||||
//반접면
|
||||
let halfTouchDimension = 0
|
||||
|
||||
// 노출bottom면의 points
|
||||
let exposedBottomPoints = []
|
||||
|
||||
// 반노출 bottom면의 points
|
||||
let leftExposedHalfBottomPoints = []
|
||||
let rightExposedHalfBottomPoints = []
|
||||
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
// centerPoints중에 현재 centerPoint와 x값이 같고, y값이 y-height값과 같은 centerPoint가 있는지 확인
|
||||
let bottomCell
|
||||
let bottomLeftPoint
|
||||
let bottomRightPoint
|
||||
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
|
||||
}
|
||||
|
||||
if (bottomCell.length === 1) {
|
||||
return
|
||||
}
|
||||
|
||||
// 바로 아래에 셀이 없는 경우 물떼세 배치가 왼쪽 되어있는 셀을 찾는다.
|
||||
leftBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomLeftPoint.x) < 2 && Math.abs(centerPoint.y - bottomLeftPoint.y) < 2,
|
||||
).length
|
||||
rightBottomCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - bottomRightPoint.x) < 2 && Math.abs(centerPoint.y - bottomRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftBottomCnt + rightBottomCnt === 1) {
|
||||
exposedHalfBottom++
|
||||
if (leftBottomCnt === 1) {
|
||||
rightExposedHalfBottomPoints.push(centerPoint)
|
||||
}
|
||||
if (rightBottomCnt === 1) {
|
||||
leftExposedHalfBottomPoints.push(centerPoint)
|
||||
}
|
||||
} else if (leftBottomCnt + rightBottomCnt === 0) {
|
||||
exposedBottomPoints.push(centerPoint)
|
||||
}
|
||||
})
|
||||
// 노출상면 및 접면 체크
|
||||
|
||||
centerPoints.forEach((centerPoint, index) => {
|
||||
const { x, y, width, height } = centerPoint
|
||||
|
||||
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) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
leftTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topLeftPoint.x) < 2 && Math.abs(centerPoint.y - topLeftPoint.y) < 2,
|
||||
).length
|
||||
rightTopCnt = centerPoints.filter(
|
||||
(centerPoint) => Math.abs(centerPoint.x - topRightPoint.x) < 2 && Math.abs(centerPoint.y - topRightPoint.y) < 2,
|
||||
).length
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 2) {
|
||||
touchDimension++
|
||||
return
|
||||
}
|
||||
|
||||
if (leftTopCnt + rightTopCnt === 1) {
|
||||
exposedHalfTop++
|
||||
halfTouchDimension++
|
||||
return
|
||||
}
|
||||
if (leftTopCnt + rightTopCnt === 0) {
|
||||
exposedTop++
|
||||
}
|
||||
})
|
||||
// 완전 노출 하면 계산
|
||||
|
||||
/*const cells = canvas.getObjects().filter((obj) => polygon.id === obj.parentId)
|
||||
const points = cells.map((cell) => {
|
||||
return cell.getCenterPoint()
|
||||
})*/
|
||||
const groupPoints = groupCoordinates(centerPoints, modules[0], direction)
|
||||
|
||||
groupPoints.forEach((group) => {
|
||||
let maxY = group.reduce((acc, cur) => (acc.y > cur.y ? acc : cur)).y
|
||||
let minY = group.reduce((acc, cur) => (acc.y < cur.y ? acc : cur)).y
|
||||
let maxX = group.reduce((acc, cur) => (acc.x > cur.x ? acc : cur)).x
|
||||
let minX = group.reduce((acc, cur) => (acc.x < cur.x ? acc : cur)).x
|
||||
|
||||
let maxYCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.y - maxY) < 2)
|
||||
let minYCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.y - minY) < 2)
|
||||
let maxXCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.x - maxX) < 2)
|
||||
let minXCenterPoints = group.filter((centerPoint) => Math.abs(centerPoint.x - minX) < 2)
|
||||
|
||||
switch (direction) {
|
||||
case 'south':
|
||||
exposedBottom += maxYCenterPoints.length
|
||||
break
|
||||
case 'north':
|
||||
exposedBottom += minYCenterPoints.length
|
||||
break
|
||||
case 'east':
|
||||
exposedBottom += maxXCenterPoints.length
|
||||
break
|
||||
case 'west':
|
||||
exposedBottom += minXCenterPoints.length
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
exposedBottom,
|
||||
exposedHalfBottom,
|
||||
exposedTop,
|
||||
exposedHalfTop,
|
||||
touchDimension,
|
||||
halfTouchDimension,
|
||||
exposedBottomPoints,
|
||||
leftExposedHalfBottomPoints,
|
||||
rightExposedHalfBottomPoints,
|
||||
centerPoints,
|
||||
}
|
||||
}
|
||||
|
||||
// polygon 내부 cell들의 centerPoint 배열을 그룹화 해서 반환
|
||||
const groupCoordinates = (points, moduleExample, direction) => {
|
||||
const groups = []
|
||||
const visited = new Set()
|
||||
const width = Math.floor(moduleExample.width)
|
||||
const height = Math.floor(moduleExample.height)
|
||||
const horizonPadding = 0 // 가로 패딩
|
||||
const verticalPadding = 0 // 세로 패딩
|
||||
|
||||
function isAdjacent(p1, p2) {
|
||||
const dx = Math.abs(p1.x - p2.x)
|
||||
const dy = Math.abs(p1.y - p2.y)
|
||||
return (
|
||||
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
|
||||
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
|
||||
(Math.abs(dx - width / 2 + horizonPadding / 2) < 2 && Math.abs(dy - height + verticalPadding) < 2)
|
||||
)
|
||||
}
|
||||
|
||||
function dfs(point, group) {
|
||||
visited.add(`${point.x},${point.y}`)
|
||||
group.push(point)
|
||||
|
||||
for (const nextPoint of points) {
|
||||
const key = `${nextPoint.x},${nextPoint.y}`
|
||||
if (!visited.has(key) && isAdjacent(point, nextPoint)) {
|
||||
dfs(nextPoint, group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const point of points) {
|
||||
const key = `${point.x},${point.y}`
|
||||
if (!visited.has(key)) {
|
||||
const group = []
|
||||
dfs(point, group)
|
||||
groups.push(group)
|
||||
}
|
||||
}
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
return { apply }
|
||||
}
|
||||
@ -326,35 +326,37 @@ export function useCanvasSetting() {
|
||||
]
|
||||
}
|
||||
|
||||
// 데이터 설정
|
||||
// 데이터 설정
|
||||
const addRoofs = []
|
||||
roofMaterials?.map((material) => {
|
||||
if (material.roofMatlCd === roofsArray[0].roofMatlCd) {
|
||||
addRoofs.push({
|
||||
...material,
|
||||
selected: true,
|
||||
index: 0,
|
||||
width: roofsArray[0].roofWidth,
|
||||
length: roofsArray[0].roofHeight,
|
||||
hajebichi: roofsArray[0].roofHajebichi,
|
||||
raft: roofsArray[0].roofGap,
|
||||
layout: roofsArray[0].roofLayout,
|
||||
roofSizeSet: roofsRow[0].roofSizeSet,
|
||||
roofAngleSet: roofsRow[0].roofAngleSet,
|
||||
pitch: roofsArray[0].roofPitch,
|
||||
angle: roofsArray[0].roofAngle,
|
||||
})
|
||||
|
||||
setAddedRoofs(addRoofs)
|
||||
setBasicSettings({
|
||||
...basicSetting,
|
||||
roofMaterials: addRoofs[0],
|
||||
roofSizeSet: roofsRow[0].roofSizeSet,
|
||||
roofAngleSet: roofsRow[0].roofAngleSet,
|
||||
roofsData: roofsArray,
|
||||
selectedRoofMaterial: addRoofs[0],
|
||||
})
|
||||
}
|
||||
for (let i = 0; i < roofsArray.length; i++) {
|
||||
roofMaterials?.map((material) => {
|
||||
if (material.roofMatlCd === roofsArray[i].roofMatlCd) {
|
||||
addRoofs.push({
|
||||
...material,
|
||||
selected: roofsArray[i].roofApply,
|
||||
index: i,
|
||||
width: roofsArray[i].roofWidth,
|
||||
length: roofsArray[i].roofHeight,
|
||||
hajebichi: roofsArray[i].roofHajebichi,
|
||||
raft: roofsArray[i].roofGap,
|
||||
layout: roofsArray[i].roofLayout,
|
||||
roofSizeSet: roofsRow[i].roofSizeSet,
|
||||
roofAngleSet: roofsRow[i].roofAngleSet,
|
||||
pitch: roofsArray[i].roofPitch,
|
||||
angle: roofsArray[i].roofAngle,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log('🚀 ~ fetchBasicSettings ~ addRoofs:', addRoofs)
|
||||
setAddedRoofs(addRoofs)
|
||||
setBasicSettings({
|
||||
...basicSetting,
|
||||
roofMaterials: addRoofs[0],
|
||||
roofSizeSet: roofsRow[0].roofSizeSet,
|
||||
roofAngleSet: roofsRow[0].roofAngleSet,
|
||||
roofsData: roofsArray,
|
||||
selectedRoofMaterial: addRoofs[0],
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
|
||||
@ -151,11 +151,18 @@ export function useRoofAllocationSetting(id) {
|
||||
pitch: roofsArray[i].roofPitch,
|
||||
angle: roofsArray[i].roofAngle,
|
||||
})
|
||||
setCurrentRoofList(selectRoofs)
|
||||
}
|
||||
})
|
||||
}
|
||||
setBasicSetting({ ...basicSetting, roofsData: roofsArray })
|
||||
|
||||
setCurrentRoofList(selectRoofs)
|
||||
//setBasicSetting({ ...basicSetting, roofsData: roofsArray })
|
||||
setBasicSetting({
|
||||
...basicSetting,
|
||||
roofSizeSet: res[0].roofSizeSet,
|
||||
roofAngleSet: res[0].roofAngleSet,
|
||||
roofsData: roofsArray,
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Data fetching error:', error)
|
||||
|
||||
@ -95,5 +95,17 @@ export function useAxios(lang = '') {
|
||||
return await getInstances(url).delete(url, option)
|
||||
}
|
||||
|
||||
return { get, promiseGet, post, promisePost, put, promisePut, patch, promisePatch, del, promiseDel }
|
||||
const getFetcher = async (url) => {
|
||||
const res = await get({ url })
|
||||
console.log('🚀 ~ getFetcher ~ res:', res)
|
||||
return res
|
||||
}
|
||||
|
||||
const postFetcher = async (url, { arg }) => {
|
||||
const res = await post({ url, data: arg })
|
||||
console.log('🚀 ~ postFetcher ~ res:', res)
|
||||
return res
|
||||
}
|
||||
|
||||
return { get, promiseGet, post, promisePost, put, promisePut, patch, promisePatch, del, promiseDel, getFetcher, postFetcher }
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ import { useCanvas } from '@/hooks/useCanvas'
|
||||
import { SAVE_KEY } from '@/common/common'
|
||||
import { readImage, removeImage } from '@/lib/fileAction'
|
||||
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
||||
|
||||
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
||||
export function usePlan(params = {}) {
|
||||
const { floorPlanState } = useContext(FloorPlanContext)
|
||||
|
||||
@ -31,8 +31,9 @@ export function usePlan(params = {}) {
|
||||
|
||||
const { swalFire } = useSwal()
|
||||
const { getMessage } = useMessage()
|
||||
const { get, promisePost, promisePut, promiseDel } = useAxios()
|
||||
const { get, promisePost, promisePut, promiseDel, promiseGet } = useAxios()
|
||||
|
||||
const { setEstimateContextState } = useEstimateController()
|
||||
/**
|
||||
* 마우스 포인터의 가이드라인을 제거합니다.
|
||||
*/
|
||||
@ -203,12 +204,44 @@ export function usePlan(params = {}) {
|
||||
* 현재 plan의 작업상태를 저장 후 이동
|
||||
*/
|
||||
const handleCurrentPlan = async (newCurrentId) => {
|
||||
if (pathname === '/floor-plan') {
|
||||
if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
|
||||
await saveCanvas()
|
||||
}
|
||||
}
|
||||
updateCurrentPlan(newCurrentId)
|
||||
const orderingNo = plans?.find((obj) => obj.id === newCurrentId).ordering
|
||||
const objectNo = floorPlanState.objectNo
|
||||
await promiseGet({ url: `/api/estimate/${objectNo}/${orderingNo}/detail` })
|
||||
.then((res) => {
|
||||
if (res.status === 200) {
|
||||
const estimateDetail = res.data
|
||||
if (estimateDetail.docNo) {
|
||||
res.data.resetFlag = 'N'
|
||||
|
||||
if (res.data.itemList.length > 0) {
|
||||
res.data.itemList.map((item) => {
|
||||
item.delFlg = '0'
|
||||
})
|
||||
}
|
||||
if (res.data.pkgAsp === null || res.data.pkgAsp == undefined) {
|
||||
res.data.pkgAsp = '0.00'
|
||||
} else {
|
||||
const number = parseFloat(res.data.pkgAsp)
|
||||
const roundedNumber = isNaN(number) ? '0.00' : number.toFixed(2)
|
||||
|
||||
res.data.pkgAsp = roundedNumber.toString()
|
||||
}
|
||||
setEstimateContextState(res.data)
|
||||
|
||||
if (pathname === '/floor-plan') {
|
||||
if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
|
||||
saveCanvas()
|
||||
}
|
||||
}
|
||||
updateCurrentPlan(newCurrentId)
|
||||
} else {
|
||||
swalFire({ text: getMessage('estimate.menu.move.valid1') })
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
swalFire({ text: getMessage('estimate.menu.move.valid1') })
|
||||
})
|
||||
}
|
||||
|
||||
const updateCurrentPlan = (newCurrentId) => {
|
||||
|
||||
@ -938,6 +938,7 @@
|
||||
"estimate.detail.unlock.alertMsg": "見積書を修正して保存",
|
||||
"estimate.detail.alert.delFile": "添付ファイルを完全に削除するには[保存]ボタンをクリックしてください",
|
||||
"estimate.detail.alert.selectDelItem": "削除する商品を選択してください.",
|
||||
"estimate.menu.move.valid1": "回路を分割していないため、見積もりを呼び出すことはできません.",
|
||||
"simulator.title.sub1": "物件番号",
|
||||
"simulator.title.sub2": "作成日",
|
||||
"simulator.title.sub3": "システム容量",
|
||||
|
||||
@ -947,6 +947,7 @@
|
||||
"estimate.detail.unlock.alertMsg": "견적서를 수정하고, 저장하십시오",
|
||||
"estimate.detail.alert.delFile": "첨부파일을 완전히 삭제하려면 [저장]버튼을 클릭하십시오.",
|
||||
"estimate.detail.alert.selectDelItem": "삭제할 제품을 선택하세요.",
|
||||
"estimate.menu.move.valid1": "회로를 나누지 않았기 때문에 견적서를 호출할 수 없습니다.",
|
||||
"simulator.title.sub1": "물건번호",
|
||||
"simulator.title.sub2": "작성일",
|
||||
"simulator.title.sub3": "시스템 용량",
|
||||
|
||||
@ -712,7 +712,7 @@ export const drawShedRoof = (roofId, canvas) => {
|
||||
|
||||
export const drawRidgeRoof = (roofId, canvas) => {
|
||||
const roof = canvas?.getObjects().find((object) => object.id === roofId)
|
||||
const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
|
||||
const hasNonParallelLines = roof.lines.filter((line) => Math.abs(line.x1 - line.x2) > 1 && Math.abs(line.y1 - line.y2) > 1)
|
||||
if (hasNonParallelLines.length > 0) {
|
||||
alert('대각선이 존재합니다.')
|
||||
return
|
||||
@ -721,6 +721,7 @@ export const drawRidgeRoof = (roofId, canvas) => {
|
||||
drawHips(roof, canvas)
|
||||
connectLinePoint(roof, canvas)
|
||||
modifyRidge(roof, canvas)
|
||||
drawCenterLine(roof, canvas)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1532,7 +1533,8 @@ const changeEavesRoof = (currentRoof, canvas) => {
|
||||
line.name !== LINE_TYPE.SUBLINE.RIDGE &&
|
||||
line.name !== LINE_TYPE.SUBLINE.HIP &&
|
||||
line.name !== LINE_TYPE.SUBLINE.VALLEY &&
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE,
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
|
||||
line.name !== 'wallLine',
|
||||
)
|
||||
.forEach((line) => {
|
||||
roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
|
||||
@ -1704,7 +1706,8 @@ const changeGableRoof = (currentRoof, canvas) => {
|
||||
line.name !== LINE_TYPE.SUBLINE.RIDGE &&
|
||||
line.name !== LINE_TYPE.SUBLINE.HIP &&
|
||||
line.name !== LINE_TYPE.SUBLINE.VALLEY &&
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE,
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
|
||||
line.name !== 'wallLine',
|
||||
)
|
||||
.forEach((line) => {
|
||||
roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
|
||||
@ -1890,7 +1893,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
||||
line.name !== LINE_TYPE.SUBLINE.RIDGE &&
|
||||
line.name !== LINE_TYPE.SUBLINE.HIP &&
|
||||
line.name !== LINE_TYPE.SUBLINE.VALLEY &&
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE,
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
|
||||
line.name !== 'wallLine',
|
||||
)
|
||||
.forEach((line) => {
|
||||
roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
|
||||
@ -2127,7 +2131,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
||||
line.name !== LINE_TYPE.SUBLINE.RIDGE &&
|
||||
line.name !== LINE_TYPE.SUBLINE.HIP &&
|
||||
line.name !== LINE_TYPE.SUBLINE.VALLEY &&
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE,
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
|
||||
line.name !== 'wallLine',
|
||||
)
|
||||
.forEach((line) => {
|
||||
roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
|
||||
@ -2407,7 +2412,8 @@ const changeWallRoof = (currentRoof, canvas) => {
|
||||
line.name !== LINE_TYPE.SUBLINE.RIDGE &&
|
||||
line.name !== LINE_TYPE.SUBLINE.HIP &&
|
||||
line.name !== LINE_TYPE.SUBLINE.VALLEY &&
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE,
|
||||
line.name !== OUTER_LINE_TYPE.OUTER_LINE &&
|
||||
line.name !== 'wallLine',
|
||||
)
|
||||
.forEach((line) => {
|
||||
roof.innerLines = roof.innerLines.filter((l) => l.id !== line.id)
|
||||
@ -2702,6 +2708,187 @@ const reDrawPolygon = (polygon, canvas) => {
|
||||
return newPolygon
|
||||
}
|
||||
|
||||
const drawCenterLine = (roof, canvas) => {
|
||||
const roofLines = roof.lines
|
||||
roofLines.forEach((currentRoof) => {
|
||||
const hips = roof.innerLines.filter(
|
||||
(line) => (currentRoof.x1 === line.x1 && currentRoof.y1 === line.y1) || (currentRoof.x2 === line.x1 && currentRoof.y2 === line.y1),
|
||||
)
|
||||
const ridge = roof.innerLines
|
||||
.filter((line) => line.name === LINE_TYPE.SUBLINE.RIDGE)
|
||||
.filter((line) => {
|
||||
if (currentRoof.x1 === currentRoof.x2) {
|
||||
if (line.x1 === line.x2) {
|
||||
return line
|
||||
}
|
||||
} else {
|
||||
if (line.y1 === line.y2) {
|
||||
return line
|
||||
}
|
||||
}
|
||||
})
|
||||
.reduce((prev, current) => {
|
||||
let currentDistance, prevDistance
|
||||
if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) {
|
||||
currentDistance = Math.abs(currentRoof.y1 - current.y1)
|
||||
prevDistance = prev ? Math.abs(currentRoof.y1 - prev.y1) : Infinity
|
||||
} else {
|
||||
currentDistance = Math.abs(currentRoof.y1 - current.y2)
|
||||
prevDistance = prev ? Math.abs(currentRoof.y1 - current.y2) : Infinity
|
||||
}
|
||||
return prevDistance < currentDistance ? prev : current
|
||||
}, null)
|
||||
let points = []
|
||||
if (hips.length === 2 && Math.abs(hips[0].x2 - hips[1].x2) < 1 && Math.abs(hips[0].y2 - hips[1].y2) < 1) {
|
||||
// console.log('삼각')
|
||||
const x1 = (currentRoof.x1 + currentRoof.x2) / 2
|
||||
const y1 = (currentRoof.y1 + currentRoof.y2) / 2
|
||||
points.push(x1, y1, hips[0].x2, hips[0].y2)
|
||||
} else {
|
||||
// console.log('삼각 아님')
|
||||
if (
|
||||
((ridge.x1 === hips[0].x2 && ridge.y1 === hips[0].y2) || (ridge.x2 === hips[0].x2 && ridge.y2 === hips[0].y2)) &&
|
||||
((ridge.x1 === hips[1].x2 && ridge.y1 === hips[1].y2) || (ridge.x2 === hips[1].x2 && ridge.y2 === hips[1].y2))
|
||||
) {
|
||||
//사각이면 마루와 현재 라인 사이에 길이를 구한다
|
||||
// console.log('사각')
|
||||
if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) {
|
||||
const yPoints = [currentRoof.y1, currentRoof.y2, ridge.y1, ridge.y2].sort((a, b) => a - b)
|
||||
const x1 = (currentRoof.x1 + currentRoof.x2) / 2
|
||||
const x2 = (ridge.x1 + ridge.x2) / 2
|
||||
const y = (yPoints[1] + yPoints[2]) / 2
|
||||
if (
|
||||
((currentRoof.y1 <= y && y <= currentRoof.y2) || (currentRoof.y2 <= y && y <= currentRoof.y1)) &&
|
||||
((ridge.y1 <= y && y <= ridge.y2) || (ridge.y2 <= y && y <= ridge.y1))
|
||||
) {
|
||||
points.push(x1, y, x2, y)
|
||||
}
|
||||
} else {
|
||||
const xPoints = [currentRoof.x1, currentRoof.x2, ridge.x1, ridge.x2].sort((a, b) => a - b)
|
||||
const y1 = (currentRoof.y1 + currentRoof.y2) / 2
|
||||
const y2 = (ridge.y1 + ridge.y2) / 2
|
||||
const x = (xPoints[1] + xPoints[2]) / 2
|
||||
if (
|
||||
((currentRoof.x1 <= x && x <= currentRoof.x2) || (currentRoof.x2 <= x && x <= currentRoof.x1)) &&
|
||||
((ridge.x1 <= x && x <= ridge.x2) || (ridge.x2 <= x && x <= ridge.x1))
|
||||
) {
|
||||
points.push(x, y1, x, y2)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//사각 아님
|
||||
if (Math.sign(currentRoof.x1 - currentRoof.x2) === 0) {
|
||||
let xPoints = []
|
||||
xPoints.push(ridge?.x1, ridge?.x2)
|
||||
hips.forEach((hip) => {
|
||||
xPoints.push(hip.x2)
|
||||
})
|
||||
let maxPoint = xPoints.reduce((prev, current) => {
|
||||
const currentDistance = Math.abs(currentRoof.x1 - current)
|
||||
const prevDistance = prev ? Math.abs(currentRoof.x1 - prev) : 0
|
||||
return prevDistance > currentDistance ? prev : current
|
||||
}, null)
|
||||
|
||||
xPoints = xPoints.filter((point) => point === maxPoint)
|
||||
|
||||
let oppositeLine
|
||||
if (xPoints.length === 1) {
|
||||
if (ridge?.x1 === xPoints[0] || ridge?.x2 === xPoints[0]) {
|
||||
oppositeLine = ridge
|
||||
}
|
||||
if (oppositeLine === undefined) {
|
||||
oppositeLine = hips.find((hip) => hip.x2 === xPoints[0])
|
||||
}
|
||||
points.push(currentRoof.x1, oppositeLine.y2, oppositeLine.x2, oppositeLine.y2)
|
||||
} else if (xPoints.length > 1) {
|
||||
xPoints = [...new Set(xPoints)] // 중복제거
|
||||
if (ridge.length > 0) {
|
||||
let boolX1 = xPoints.some((x) => x === ridge.x1)
|
||||
let boolX2 = xPoints.some((x) => x === ridge.x2)
|
||||
if (boolX1 && boolX2) {
|
||||
oppositeLine = ridge
|
||||
}
|
||||
if (oppositeLine) {
|
||||
const sortPoints = [currentRoof.y1, currentRoof.y2, oppositeLine.y1, oppositeLine.y2].sort((a, b) => a - b)
|
||||
const y = (sortPoints[1] + sortPoints[2]) / 2
|
||||
if (
|
||||
((currentRoof.y1 <= y && y <= currentRoof.y2) || (currentRoof.y2 <= y && y <= currentRoof.y1)) &&
|
||||
((oppositeLine.y1 <= y && y <= oppositeLine.y2) || (oppositeLine.y2 <= y && y <= oppositeLine.y1))
|
||||
) {
|
||||
points.push(currentRoof.x1, y, oppositeLine.x1, y)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let yPoints = []
|
||||
yPoints.push(ridge?.y1, ridge?.y2)
|
||||
hips.forEach((hip) => {
|
||||
yPoints.push(hip.y2)
|
||||
})
|
||||
const maxPoint = yPoints.reduce((prev, current) => {
|
||||
const currentDistance = Math.abs(currentRoof.y1 - current)
|
||||
const prevDistance = prev ? Math.abs(currentRoof.y1 - prev) : 0
|
||||
return prevDistance > currentDistance ? prev : current
|
||||
})
|
||||
yPoints = yPoints.filter((y) => y === maxPoint)
|
||||
|
||||
let oppositeLine
|
||||
if (yPoints.length === 1) {
|
||||
if (ridge?.y1 === yPoints[0] || ridge?.y2 === yPoints[0]) {
|
||||
oppositeLine = ridge
|
||||
}
|
||||
if (oppositeLine === undefined) {
|
||||
oppositeLine = hips.find((hip) => hip.y2 === yPoints[0])
|
||||
}
|
||||
points.push(oppositeLine.x2, currentRoof.y1, oppositeLine.x2, oppositeLine.y2)
|
||||
} else if (yPoints.length > 1) {
|
||||
let boolY1 = yPoints.some((y) => y === ridge.y1)
|
||||
let boolY2 = yPoints.some((y) => y === ridge.y2)
|
||||
if (boolY1 && boolY2) {
|
||||
oppositeLine = ridge
|
||||
}
|
||||
if (oppositeLine) {
|
||||
const sortPoints = [currentRoof.x1, currentRoof.x2, oppositeLine.x1, oppositeLine.x2].sort((a, b) => a - b)
|
||||
const x = (sortPoints[1] + sortPoints[2]) / 2
|
||||
if (
|
||||
((currentRoof.x1 <= x && x <= currentRoof.x2) || (currentRoof.x2 <= x && x <= currentRoof.x1)) &&
|
||||
((oppositeLine.x1 <= x && x <= oppositeLine.x2) || (oppositeLine.x2 <= x && x <= oppositeLine.x1))
|
||||
) {
|
||||
points.push(x, currentRoof.y1, x, oppositeLine.y1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (points !== null) {
|
||||
const pitchSizeLine = new QLine(points, {
|
||||
stroke: '#000000',
|
||||
strokeWidth: 2,
|
||||
strokeDashArray: [5, 5],
|
||||
selectable: false,
|
||||
fontSize: roof.fontSize,
|
||||
attributes: {
|
||||
roofId: roof.id,
|
||||
type: 'pitchSizeLine',
|
||||
},
|
||||
})
|
||||
canvas.add(pitchSizeLine)
|
||||
canvas.renderAll()
|
||||
|
||||
const adjust = Math.sqrt(
|
||||
Math.pow(Math.round(Math.abs(pitchSizeLine.x1 - pitchSizeLine.x2) * 10), 2) +
|
||||
Math.pow(Math.round(Math.abs(pitchSizeLine.y1 - pitchSizeLine.y2) * 10), 2),
|
||||
)
|
||||
const currentDegree = currentRoof.attributes.pitch > 0 ? getDegreeByChon(currentRoof.attributes.pitch) : currentRoof.attributes.degree
|
||||
const height = Math.tan(currentDegree * (Math.PI / 180)) * adjust
|
||||
const lengthText = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2)))
|
||||
pitchSizeLine.setLengthText(lengthText)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function createRoofMarginPolygon(polygon, lines, arcSegments = 0) {
|
||||
const offsetEdges = []
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user