Merge branch 'dev' into feature/jaeyoung

This commit is contained in:
Jaeyoung Lee 2024-12-12 13:39:05 +09:00
commit 37a1c2ce39
31 changed files with 1127 additions and 635 deletions

View File

@ -55,6 +55,10 @@ export default async function RootLayout({ children }) {
redirect('/login') redirect('/login')
} }
if (headerPathname === '/login' && session.isLoggedIn) {
redirect('/')
}
return ( return (
<RecoilRootWrapper> <RecoilRootWrapper>
<html lang="en"> <html lang="en">

View File

@ -159,6 +159,7 @@ export const SAVE_KEY = [
'offset', 'offset',
'arrow', 'arrow',
'surfaceCompass', 'surfaceCompass',
'surfaceCompassType',
'moduleCompass', 'moduleCompass',
'isFixed', 'isFixed',
'modules', 'modules',

View File

@ -13,14 +13,14 @@ import ChangePasswordPop from './main/ChangePasswordPop'
import { searchState } from '@/store/boardAtom' import { searchState } from '@/store/boardAtom'
import { SessionContext } from '@/app/SessionProvider' import { SessionContext } from '@/app/SessionProvider'
import { QcastContext } from '@/app/QcastProvider' import { QcastContext } from '@/app/QcastProvider'
import { sessionStore } from '@/store/commonAtom'
import { isObjectNotEmpty } from '@/util/common-utils'
export default function MainPage() { export default function MainPage(mainPageProps) {
const [sessionState, setSessionState] = useRecoilState(sessionStore)
const [chagePasswordPopOpen, setChagePasswordPopOpen] = useState(false) const [chagePasswordPopOpen, setChagePasswordPopOpen] = useState(false)
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { promiseGet } = useAxios(globalLocaleState)
const router = useRouter() const router = useRouter()
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -74,10 +74,12 @@ export default function MainPage() {
} }
useEffect(() => { useEffect(() => {
if (session?.pwdInitYn !== 'Y') { if (isObjectNotEmpty(sessionState)) {
setChagePasswordPopOpen(true) if (sessionState?.pwdInitYn !== 'Y') {
setChagePasswordPopOpen(true)
}
} }
}, [session]) }, [sessionState])
return ( return (
<> <>

View File

@ -8,6 +8,7 @@ import { FaAnglesDown } from 'react-icons/fa6'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useMasterController } from '@/hooks/common/useMasterController'
import { convertDwgToPng } from '@/lib/cadAction' import { convertDwgToPng } from '@/lib/cadAction'
import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom' import { cadFileNameState, googleMapFileNameState, useCadFileState, useGoogleMapFileState } from '@/store/canvasAtom'
@ -35,6 +36,7 @@ export default function Playground() {
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { getRoofMaterialList, getModuleTypeItemList } = useMasterController()
const [color, setColor] = useState('#ff0000') const [color, setColor] = useState('#ff0000')
@ -156,6 +158,24 @@ export default function Playground() {
<> <>
<div className="container mx-auto p-4 m-4 border"> <div className="container mx-auto p-4 m-4 border">
<div className={styles.test}> 영역은 테스트입니다.</div> <div className={styles.test}> 영역은 테스트입니다.</div>
<div className="my-2">
<button
className="btn-frame deepgray"
onClick={() => {
getRoofMaterialList()
}}
>
지붕재 목록 조회 API 호출
</button>
<button
className="btn-frame deepgray"
onClick={() => {
getModuleTypeItemList('ROOF_ID_HIRA_SEME')
}}
>
모듈 타입별 아이템 목록 조회 API 호출
</button>
</div>
<div className="m-2"> <div className="m-2">
<button <button
className="btn-frame deepgray" className="btn-frame deepgray"

View File

@ -8,13 +8,28 @@ import { contextPopupPositionState } from '@/store/popupAtom'
export default function ColorPickerModal(props) { export default function ColorPickerModal(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState) // const contextPopupPosition = useRecoilValue(contextPopupPositionState) //
const { isShow, setIsShow, pos = contextPopupPosition, color, setColor, id, isConfig = false } = props //color = '#ff0000' const {
isShow,
setIsShow,
pos = contextPopupPosition,
color,
setColor,
id,
name,
isConfig = false,
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} = props //color = '#ff0000'
const [originColor, setOriginColor] = useState(color) const [originColor, setOriginColor] = useState(color)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
useEffect(() => { useEffect(() => {
setOriginColor(originColor) setOriginColor(originColor)
//
if (name !== 'DimensionLineColor') setSettingsDataSave({ ...settingsData })
}, [isShow]) }, [isShow])
return ( return (
@ -49,6 +64,13 @@ export default function ColorPickerModal(props) {
if (setColor) setColor(originColor) if (setColor) setColor(originColor)
if (setIsShow) setIsShow(false) if (setIsShow) setIsShow(false)
//
if (name !== 'DimensionLineColor')
setSettingsData({
...settingsData,
color: originColor,
})
closePopup(id, isConfig) closePopup(id, isConfig)
}} }}
> >

View File

@ -25,7 +25,6 @@ export default function Estimate({ params }) {
const [uniqueData, setUniqueData] = useState([]) const [uniqueData, setUniqueData] = useState([])
const [handlePricingFlag, setHandlePricingFlag] = useState(false) const [handlePricingFlag, setHandlePricingFlag] = useState(false)
const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false) const [specialNoteFirstFlg, setSpecialNoteFirstFlg] = useState(false)
const fixedKey = 'itemKey'
const [itemChangeYn, setItemChangeYn] = useState(false) const [itemChangeYn, setItemChangeYn] = useState(false)
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
const [objectNo, setObjectNo] = useState('') // const [objectNo, setObjectNo] = useState('') //
@ -147,14 +146,18 @@ export default function Estimate({ params }) {
} }
} }
}) })
//detail
//ATTR003,ATTR007
if (row.code === 'ATTR003') { if (row.code === 'ATTR003') {
//row.check = true //row.check = true
} }
if (row.code === 'ATTR007') { if (row.code === 'ATTR007') {
//row.check = true //row.check = true
} }
if (estimateContextState.estimateType === 'YJOD') {
if (row.code === 'ATTR002') {
row.check = true
}
}
}) })
setSpecialNoteList(res) setSpecialNoteList(res)
@ -1100,9 +1103,11 @@ export default function Estimate({ params }) {
<div className="input-wrap mr5" style={{ width: '610px' }}> <div className="input-wrap mr5" style={{ width: '610px' }}>
<input type="text" className="input-light" value={roofList} readOnly /> <input type="text" className="input-light" value={roofList} readOnly />
</div> </div>
<div className="input-wrap" style={{ width: '200px' }}> {constructSpecificationMulti ? (
<input type="text" className="input-light" value={constructSpecificationMulti[index]} readOnly /> <div className="input-wrap" style={{ width: '200px' }}>
</div> <input type="text" className="input-light" value={constructSpecificationMulti[index]} readOnly />
</div>
) : null}
</div> </div>
) )
})} })}
@ -1191,7 +1196,6 @@ export default function Estimate({ params }) {
{originFiles.map((originFile) => { {originFiles.map((originFile) => {
return ( return (
<li className="file-item" key={originFile.no}> <li className="file-item" key={originFile.no}>
{/* <li className="file-item" key={uuidv4()}> */}
<div className="file-item-wrap"> <div className="file-item-wrap">
<span <span
style={{ display: originFile.delFlg === '0' ? '' : 'none' }} style={{ display: originFile.delFlg === '0' ? '' : 'none' }}
@ -1254,7 +1258,6 @@ export default function Estimate({ params }) {
{specialNoteList.length > 0 && {specialNoteList.length > 0 &&
specialNoteList.map((row) => { specialNoteList.map((row) => {
return ( return (
// <div key={uuidv4()} className="special-note-check-item">
<div key={row.code} className="special-note-check-item"> <div key={row.code} className="special-note-check-item">
<div className="special-note-check-box"> <div className="special-note-check-box">
<div className="d-check-box light"> <div className="d-check-box light">

View File

@ -1,14 +1,12 @@
'use client' 'use client'
import { useContext, useRef } from 'react' import { useRef } from 'react'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { SessionContext } from '@/app/SessionProvider'
export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) { export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
const fileInputRef = useRef(null) const fileInputRef = useRef(null)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { session } = useContext(SessionContext)
const handleButtonClick = (e) => { const handleButtonClick = (e) => {
e.preventDefault() e.preventDefault()
@ -20,13 +18,32 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
return return
} }
const { files } = e.target const fileList = []
const file = files[0] let passFlag = true
const fileType = file.type Array.from(e.target.files).forEach((file) => {
if (!fileType.includes('image')) { let fileType = file.type
return alert(getMessage('estimate.detail.fileList.extCheck')) if (!fileType.includes('image')) {
passFlag = false
} else {
fileList.push({ data: file, id: uuidv4() })
}
})
if (!passFlag) {
alert(getMessage('estimate.detail.fileList.extCheck'))
} }
// const { files } = e.target
// const file = files[0]
// const fileType = file.type
// if (!fileType.includes('image')) {
// return alert(getMessage('estimate.detail.fileList.extCheck'))
// }
// setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }])
//
setUploadFiles([...uploadFiles, ...fileList])
e.target.value = ''
// const formData = new FormData() // const formData = new FormData()
// formData.append('file', e.target.files[0]) // formData.append('file', e.target.files[0])
// formData.append('objectNo', objectNo) // // formData.append('objectNo', objectNo) //
@ -37,8 +54,6 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
// await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => { // await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => {
// if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }]) // if (res.data > 0) setUploadFiles([...files, { name: e.target.files[0].name, id: uuidv4() }])
// }) // })
setUploadFiles([...uploadFiles, { data: e.target.files[0], id: uuidv4() }])
e.target.value = ''
} }
const deleteFile = (id) => { const deleteFile = (id) => {
@ -49,9 +64,21 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
e.preventDefault() e.preventDefault()
e.stopPropagation() e.stopPropagation()
const fileList = [] const fileList = []
let passFlag = true
Array.from(e.dataTransfer.files).forEach((file) => { Array.from(e.dataTransfer.files).forEach((file) => {
fileList.push({ data: file, id: uuidv4() }) let fileType = file.type
if (!fileType.includes('image')) {
passFlag = false
} else {
fileList.push({ data: file, id: uuidv4() })
}
}) })
if (!passFlag) {
alert(getMessage('estimate.detail.fileList.extCheck'))
}
setUploadFiles([...uploadFiles, ...fileList]) setUploadFiles([...uploadFiles, ...fileList])
} }
@ -76,7 +103,16 @@ export default function EstimateFileUploader({ uploadFiles, setUploadFiles }) {
<label className="file-upload" htmlFor="img" onClick={handleButtonClick}> <label className="file-upload" htmlFor="img" onClick={handleButtonClick}>
{getMessage('estimate.detail.fileList.btn')} {getMessage('estimate.detail.fileList.btn')}
</label> </label>
<input type="file" name="file" id="img" accept="image/*" ref={fileInputRef} style={{ display: 'none' }} onChange={(e) => onChangeFiles(e)} /> <input
type="file"
multiple
name="file"
id="img"
accept="image/*"
ref={fileInputRef}
style={{ display: 'none' }}
onChange={(e) => onChangeFiles(e)}
/>
</div> </div>
<div <div
className="drag-file-area" className="drag-file-area"

View File

@ -4,7 +4,7 @@ import { QLine } from '@/components/fabric/QLine'
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util' import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils' import { calculateAngle, drawGabledRoof, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils'
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import { LINE_TYPE } from '@/common/common' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
export const QPolygon = fabric.util.createClass(fabric.Polygon, { export const QPolygon = fabric.util.createClass(fabric.Polygon, {
type: 'QPolygon', type: 'QPolygon',
@ -689,6 +689,15 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
return intersects % 2 === 1 return intersects % 2 === 1
}, },
containsPoint: function (point) {
if (this.name === POLYGON_TYPE.ROOF && this.isFixed) {
const isInside = this.inPolygon(point)
this.set('selectable', isInside)
return isInside
} else {
return this.callSuper('containsPoint', point)
}
},
inPolygonABType(x, y, polygon) { inPolygonABType(x, y, polygon) {
let inside = false let inside = false

View File

@ -41,6 +41,7 @@ import { pwrGnrSimTypeState } from '@/store/simulatorAtom'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { isObjectNotEmpty } from '@/util/common-utils'
export default function CanvasMenu(props) { export default function CanvasMenu(props) {
const { menuNumber, setMenuNumber } = props const { menuNumber, setMenuNumber } = props
@ -78,6 +79,9 @@ export default function CanvasMenu(props) {
const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext) const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext)
const { restoreModuleInstArea } = useModuleBasicSetting() const { restoreModuleInstArea } = useModuleBasicSetting()
//
const [buttonStyle, setButtonStyle] = useState('')
const onClickNav = (menu) => { const onClickNav = (menu) => {
setMenuNumber(menu.index) setMenuNumber(menu.index)
setCurrentMenu(menu.title) setCurrentMenu(menu.title)
@ -241,6 +245,16 @@ export default function CanvasMenu(props) {
}) })
} }
useEffect(() => {
if (isObjectNotEmpty(estimateRecoilState)) {
if (estimateRecoilState?.createUser === 'T01') {
if (sessionState.userId !== 'T01') {
setButtonStyle('none')
}
}
}
}, [estimateRecoilState])
return ( return (
<div className={`canvas-menu-wrap ${[2, 3, 4].some((num) => num === menuNumber) ? 'active' : ''}`}> <div className={`canvas-menu-wrap ${[2, 3, 4].some((num) => num === menuNumber) ? 'active' : ''}`}>
<div className="canvas-menu-inner"> <div className="canvas-menu-inner">
@ -320,11 +334,12 @@ export default function CanvasMenu(props) {
<span className="ico ico01"></span> <span className="ico ico01"></span>
<span className="name">{getMessage('plan.menu.estimate.docDown')}</span> <span className="name">{getMessage('plan.menu.estimate.docDown')}</span>
</button> </button>
<button className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}> <button style={{ display: buttonStyle }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
<span className="ico ico02"></span> <span className="ico ico02"></span>
<span className="name">{getMessage('plan.menu.estimate.save')}</span> <span className="name">{getMessage('plan.menu.estimate.save')}</span>
</button> </button>
<button <button
style={{ display: buttonStyle }}
className="btn-frame gray ico-flx" className="btn-frame gray ico-flx"
onClick={() => { onClick={() => {
handleEstimateReset() handleEstimateReset()
@ -345,7 +360,7 @@ export default function CanvasMenu(props) {
<span className="name">{getMessage('plan.menu.estimate.copy')}</span> <span className="name">{getMessage('plan.menu.estimate.copy')}</span>
</button> </button>
)} )}
<button className="btn-frame gray ico-flx"> <button style={{ display: buttonStyle }} className="btn-frame gray ico-flx">
<span className="ico ico05"></span> <span className="ico ico05"></span>
<span className="name">{getMessage('plan.menu.estimate.unLock')}</span> <span className="name">{getMessage('plan.menu.estimate.unLock')}</span>
</button> </button>

View File

@ -1,17 +1,17 @@
import { forwardRef, useState, useEffect } from 'react' import { forwardRef, useState, useEffect } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
import { compasDegAtom } from '@/store/orientationAtom'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent'
const PitchPlacement = forwardRef((props, refs) => { const PitchPlacement = forwardRef((props, refs) => {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [setupLocation, setSetupLocation] = useState('south') const [setupLocation, setSetupLocation] = useState('south')
const { makeModuleInstArea } = useModuleBasicSetting() const { makeModuleInstArea } = useModuleBasicSetting()
const compasDeg = useRecoilValue(compasDegAtom)
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const { initEvent } = useEvent()
useEffect(() => { useEffect(() => {
makeModuleInstArea() makeModuleInstArea()
@ -45,6 +45,7 @@ const PitchPlacement = forwardRef((props, refs) => {
} }
const handleSetupLocation = (e) => { const handleSetupLocation = (e) => {
initEvent()
refs.setupLocation.current = e.target refs.setupLocation.current = e.target
setSetupLocation(e.target.value) setSetupLocation(e.target.value)
} }
@ -153,7 +154,7 @@ const PitchPlacement = forwardRef((props, refs) => {
value={'south'} value={'south'}
checked={setupLocation === 'south'} checked={setupLocation === 'south'}
defaultChecked defaultChecked
onChange={handleSetupLocation} onClick={handleSetupLocation}
/> />
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label> <label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
</div> </div>
@ -164,7 +165,7 @@ const PitchPlacement = forwardRef((props, refs) => {
id="ra02" id="ra02"
value={'excreta'} value={'excreta'}
checked={setupLocation === 'excreta'} checked={setupLocation === 'excreta'}
onChange={handleSetupLocation} onClick={handleSetupLocation}
/> />
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label> <label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
</div> </div>

View File

@ -5,9 +5,14 @@ import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom' import { contextPopupPositionState } from '@/store/popupAtom'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
import { FLOW_DIRECTION_TYPE, useFlowDirectionSetting } from '@/hooks/contextpopup/useFlowDirectionSetting'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { usePolygon } from '@/hooks/usePolygon'
const FLOW_DIRECTION_TYPE = {
EIGHT_AZIMUTH: 'eightAzimuth',
TWENTY_FOUR_AZIMUTH: 'twentyFourAzimuth',
}
export default function FlowDirectionSetting(props) { export default function FlowDirectionSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState) const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition, target } = props const { id, pos = contextPopupPosition, target } = props
@ -20,10 +25,9 @@ export default function FlowDirectionSetting(props) {
} }
}, []) }, [])
const [compasDeg, setCompasDeg] = useState(null) const [compasDeg, setCompasDeg] = useState(target.surfaceCompass ?? null)
const [flowDirection, setFlowDirection] = useState(target.direction) const [flowDirection, setFlowDirection] = useState(target.direction)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { changeSurfaceFlowDirection, type, setType } = useFlowDirectionSetting(id)
const orientations = [ const orientations = [
{ name: `${getMessage('commons.none')}`, value: 0 }, { name: `${getMessage('commons.none')}`, value: 0 },
@ -36,7 +40,27 @@ export default function FlowDirectionSetting(props) {
{ name: `${getMessage('commons.north')}${getMessage('commons.west')}`, value: 135 }, { name: `${getMessage('commons.north')}${getMessage('commons.west')}`, value: 135 },
{ name: `${getMessage('commons.north')}`, value: 180 }, { name: `${getMessage('commons.north')}`, value: 180 },
] ]
const [selectedOrientation, setSelectedOrientation] = useState(orientations[0])
const { drawDirectionArrow } = usePolygon()
const [type, setType] = useState(target.surfaceCompassType ?? FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH)
const changeSurfaceFlowDirection = (roof, direction, orientation) => {
roof.set({
direction: direction,
surfaceCompass: orientation,
surfaceCompassType: type,
})
drawDirectionArrow(roof)
canvas?.renderAll()
closePopup(id)
}
const [selectedOrientation, setSelectedOrientation] = useState(
target.surfaceCompassType !== null && target.surfaceCompassType === FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH
? orientations.find((item) => item.value === target.surfaceCompass)
: orientations[0],
)
return ( return (
<WithDraggable isShow={true} pos={pos}> <WithDraggable isShow={true} pos={pos}>
@ -84,9 +108,8 @@ export default function FlowDirectionSetting(props) {
</div> </div>
<div className="grid-select "> <div className="grid-select ">
<QSelectBox <QSelectBox
title={''} title={selectedOrientation.name}
options={orientations} options={orientations}
value={selectedOrientation}
onChange={(e) => { onChange={(e) => {
setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH) setType(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH)
setSelectedOrientation(e) setSelectedOrientation(e)
@ -116,7 +139,7 @@ export default function FlowDirectionSetting(props) {
{Array.from({ length: 180 / 15 + 1 }).map((dot, index) => ( {Array.from({ length: 180 / 15 + 1 }).map((dot, index) => (
<div <div
key={index} key={index}
className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`} className={`circle ${compasDeg === 15 * (12 + index) && type === FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH ? 'act' : ''}`}
onClick={() => { onClick={() => {
setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH)
setCompasDeg(15 * (12 + index)) setCompasDeg(15 * (12 + index))
@ -126,7 +149,7 @@ export default function FlowDirectionSetting(props) {
{Array.from({ length: 180 / 15 - 1 }).map((dot, index) => ( {Array.from({ length: 180 / 15 - 1 }).map((dot, index) => (
<div <div
key={index} key={index}
className={`circle ${compasDeg === 15 * (index + 1) ? 'act' : ''}`} className={`circle ${compasDeg === 15 * (index + 1) && type === FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH ? 'act' : ''}`}
onClick={() => { onClick={() => {
setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH) setType(FLOW_DIRECTION_TYPE.TWENTY_FOUR_AZIMUTH)
setCompasDeg(15 * (index + 1)) setCompasDeg(15 * (index + 1))

View File

@ -1,6 +1,6 @@
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import QSelectBox from '@/components/common/select/QSelectBox' import QSelectBox from '@/components/common/select/QSelectBox'
import { useEffect } from 'react' import { useEffect, useState } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
@ -17,27 +17,26 @@ const TYPE = {
export default function DotLineGrid(props) { export default function DotLineGrid(props) {
// const [modalOption, setModalOption] = useRecoilState(modalState); //modal state // const [modalOption, setModalOption] = useRecoilState(modalState); //modal state
//const interval = useRecoilValue(dotLineIntervalSelector) //const interval = useRecoilValue(dotLineIntervalSelector)
const { id, setIsShow, pos = { x: 840, y: -815 }, isConfig = false } = props const { id, setIsShow, pos = { x: 840, y: -815 }, isConfig = false, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { const [selectOption, setSelectOption] = useState()
selectOption,
setSelectOption, const { SelectOptions, currentSetting, setCurrentSetting, dotLineGridSettingState, setSettingModalGridOptions, setDotLineGridSettingState } =
SelectOptions, useCanvasSetting()
currentSetting,
setCurrentSetting,
dotLineGridSettingState,
setSettingModalGridOptions,
setDotLineGridSettingState,
} = useCanvasSetting()
// //
useEffect(() => { useEffect(() => {
console.log('DotLineGrid useEffect 실행') console.log('DotLineGrid useEffect 실행')
setSettingsDataSave({ ...settingsData })
// dimension
const matchedOption = SelectOptions.find((option) => option.value == currentSetting.INTERVAL.dimension)
setSelectOption(matchedOption)
return () => { return () => {
setSettingModalGridOptions((prev) => { setSettingModalGridOptions((prev) => {
@ -84,11 +83,23 @@ export default function DotLineGrid(props) {
}, },
DOT: currentSetting.DOT, DOT: currentSetting.DOT,
LINE: currentSetting.LINE, LINE: currentSetting.LINE,
flag: true,
} }
//setDotLineGridSettingState({ ...currentSetting }) //setDotLineGridSettingState({ ...currentSetting })
}) })
setSettingsData({
...settingsData,
INTERVAL: {
type: currentSetting.INTERVAL.type,
horizontalInterval: currentSetting.INTERVAL.horizontalInterval,
verticalInterval: currentSetting.INTERVAL.verticalInterval,
ratioInterval: currentSetting.INTERVAL.ratioInterval,
dimension: currentSetting.INTERVAL.dimension,
},
DOT: currentSetting.DOT,
LINE: currentSetting.LINE,
})
setIsShow(false) setIsShow(false)
closePopup(id, isConfig) closePopup(id, isConfig)
} }

View File

@ -8,68 +8,37 @@ import MaterialGuide from '@/components/floor-plan/modal/placementShape/Material
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useRecoilState, useRecoilValue } from 'recoil'
import { roofMaterialsAtom } from '@/store/settingAtom'
import { isObjectNotEmpty } from '@/util/common-utils'
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
const [showSizeGuideModal, setShowSizeGuidModal] = useState(false) const [showSizeGuideModal, setShowSizeGuidModal] = useState(false)
const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false) const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { getMessage } = useMessage() const { getMessage } = useMessage()
const roofMaterials = useRecoilValue(roofMaterialsAtom)
const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting() const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting()
const [currentRoofMaterial, setCurrentRoofMaterial] = useState(
isObjectNotEmpty(basicSetting.selectedRoofMaterial) ? basicSetting.selectedRoofMaterial : roofMaterials[0],
)
// //
useEffect(() => { useEffect(() => {
fetchBasicSettings() fetchBasicSettings()
}, []) }, [])
useEffect(() => {
console.log(currentRoofMaterial)
}, [roofMaterials])
// Function to update the roofType and corresponding values // Function to update the roofType and corresponding values
const handleRoofTypeChange = (index, value) => { const handleRoofTypeChange = (value) => {
const updatedRoofs = [...basicSetting.roofs] const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value)
const roofType = parseInt(value, 10) setCurrentRoofMaterial(selectedRoofMaterial)
/*const newBasicSetting = { ...basicSetting }
// Reset other values based on the selected roofType setBasicSettings({ ...newBasicSetting, selectedRoofMaterial: selectedRoofMaterial })*/
if (roofType === 1) {
updatedRoofs[index] = {
...updatedRoofs[index],
roofType: 1,
roofWidth: 265,
roofHeight: 235,
roofGap: 455,
roofHajebichi: 0,
}
} else if (roofType === 2) {
updatedRoofs[index] = {
...updatedRoofs[index],
roofType: 2,
roofGap: 265,
roofHajebichi: 265,
roofWidth: 0,
roofHeight: 0,
}
} else if (roofType === 3) {
updatedRoofs[index] = {
...updatedRoofs[index],
roofType: 3,
roofHajebichi: 265,
roofGap: 0,
roofWidth: 0,
roofHeight: 0,
}
} else if (roofType === 4) {
updatedRoofs[index] = {
...updatedRoofs[index],
roofType: 4,
roofHeight: 265,
roofGap: 265,
roofHajebichi: 0,
roofWidth: 0,
}
}
setBasicSettings({
...basicSetting,
roofs: updatedRoofs,
})
} }
return ( return (
@ -180,16 +149,19 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
<select <select
className="select-light dark" className="select-light dark"
name="roofType" name="roofType"
value={basicSetting.roofs[0].roofType} value={currentRoofMaterial.roofMatlCd}
onChange={(e) => handleRoofTypeChange(0, e.target.value)} onChange={(e) => handleRoofTypeChange(e.target.value)}
> >
<option value="1"> type A</option> {roofMaterials.map((roof, index) => {
<option value="2"> type B</option> return (
<option value="3"> type C</option> <option key={index} value={roof.roofMatlCd}>
<option value="4"> type D</option> {roof.roofMatlNm}
</option>
)
})}
</select> </select>
</div> </div>
{basicSetting.roofs[0].roofType === 1 ? ( {['R', 'C'].includes(currentRoofMaterial.widAuth) && (
<> <>
<div className="flex-ment"> <div className="flex-ment">
<span>W</span> <span>W</span>
@ -197,204 +169,67 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
<select <select
className="select-light dark" className="select-light dark"
name="roofWidth" name="roofWidth"
value={basicSetting.roofs[0].roofWidth}
onChange={(e) => { onChange={(e) => {
// //
setBasicSettings({ setCurrentRoofMaterial({ ...currentRoofMaterial, roofWidth: e.target.value })
...basicSetting,
roofs: [
{
...basicSetting.roofs[0],
roofWidth: e.target.value,
},
],
})
}} }}
> >
<option>265</option> <option value={parseInt(currentRoofMaterial.widBase)}>{parseInt(currentRoofMaterial.widBase)}</option>
</select>
</div>
</div>
<div className="flex-ment">
<span>L</span>
<div className="select-wrap" style={{ width: '84px' }}>
<select
className="select-light dark"
name="roofHeight"
value={basicSetting.roofs[0].roofHeight}
onChange={(e) => {
//
setBasicSettings({
...basicSetting,
roofs: [
{
...basicSetting.roofs[0],
roofHeight: e.target.value,
},
],
})
}}
>
<option>235</option>
</select>
</div>
</div>
<div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
<div className="select-wrap" style={{ width: '84px' }}>
<select
className="select-light dark"
name="roofGap"
value={basicSetting.roofs[0].roofGap}
onChange={(e) => {
//
setBasicSettings({
...basicSetting,
roofs: [
{
...basicSetting.roofs[0],
roofGap: e.target.value,
},
],
})
}}
>
<option>455</option>
</select> </select>
</div> </div>
</div> </div>
</> </>
) : basicSetting.roofs[0].roofType === 2 ? ( )}
<> {['R', 'C'].includes(currentRoofMaterial.lenAuth) && (
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('hajebichi')}</span> <span>L</span>
<div className="grid-select no-flx" style={{ width: '84px' }}> <div className="select-wrap" style={{ width: '84px' }}>
<select <select
className="select-light dark" className="select-light dark"
name="roofHajebichi" name="roofHeight"
value={basicSetting.roofs[0].roofHajebichi} onChange={(e) => {
onChange={(e) => { //
// setCurrentRoofMaterial({ ...currentRoofMaterial, roofHeight: e.target.value })
setBasicSettings({ }}
...basicSetting, >
roofs: [ <option value={parseInt(currentRoofMaterial.lenBase)}>{parseInt(currentRoofMaterial.lenBase)}</option>
{ </select>
...basicSetting.roofs[0],
roofHajebichi: e.target.value,
},
],
})
}}
>
<option>265</option>
</select>
</div>
</div> </div>
<div className="flex-ment"> </div>
<span>{getMessage('modal.placement.initial.setting.rafter')}</span> )}
<div className="grid-select no-flx right" style={{ width: '84px' }}> {['C', 'R'].includes(currentRoofMaterial.raftAuth) && (
<select <div className="flex-ment">
className="select-light dark" <span>{getMessage('modal.placement.initial.setting.rafter')}</span>
name="roofGap" <div className="select-wrap" style={{ width: '84px' }}>
value={basicSetting.roofs[0].roofGap} <select
onChange={(e) => { className="select-light dark"
// name="roofGap"
setBasicSettings({ onChange={(e) => {
...basicSetting, //
roofs: [ setCurrentRoofMaterial({ ...currentRoofMaterial, roofGap: e.target.value })
{ }}
...basicSetting.roofs[0], >
roofGap: e.target.value, <option>455</option>
}, </select>
],
})
}}
>
<option>265</option>
</select>
</div>
</div> </div>
</> </div>
) : basicSetting.roofs[0].roofType === 3 ? ( )}
<> {['C', 'R'].includes(currentRoofMaterial.roofPchAuth) && (
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('hajebichi')}</span> <span>{getMessage('hajebichi')}</span>
<div className="grid-select no-flx" style={{ width: '84px' }}> <div className="grid-select no-flx" style={{ width: '84px' }}>
<select <select
className="select-light dark" className="select-light dark"
name="roofHajebichi" name="roofHajebichi"
value={basicSetting.roofs[0].roofHajebichi} onChange={(e) => {
onChange={(e) => { //
// setCurrentRoofMaterial({ ...currentRoofMaterial, roofHajebichi: e.target.value })
setBasicSettings({ }}
...basicSetting, >
roofs: [ <option value={parseInt(currentRoofMaterial.roofPchBase)}>{parseInt(currentRoofMaterial.roofPchBase)}</option>
{ </select>
...basicSetting.roofs[0],
roofHajebichi: e.target.value,
},
],
})
}}
>
<option>265</option>
</select>
</div>
</div> </div>
</> </div>
) : basicSetting.roofs[0].roofType === 4 ? (
<>
<div className="flex-ment">
<span>L</span>
<div className="grid-select no-flx" style={{ width: '84px' }}>
<select
className="select-light dark"
name="roofHeight"
value={basicSetting.roofs[0].roofHeight}
onChange={(e) => {
//
setBasicSettings({
...basicSetting,
roofs: [
{
...basicSetting.roofs[0],
roofHeight: e.target.value,
},
],
})
}}
>
<option>265</option>
</select>
</div>
</div>
<div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
<div className="grid-select no-flx right" style={{ width: '84px' }}>
<select
className="select-light dark"
name="roofGap"
value={basicSetting.roofs[0].roofGap}
onChange={(e) => {
//
setBasicSettings({
...basicSetting,
roofs: [
{
...basicSetting.roofs[0],
roofGap: e.target.value,
},
],
})
}}
>
<option>265</option>
</select>
</div>
</div>
</>
) : (
''
)} )}
</div> </div>
</td> </td>

View File

@ -8,21 +8,22 @@ import { useEvent } from '@/hooks/useEvent'
export default function FirstOption(props) { export default function FirstOption(props) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
// const { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData } = useCanvasSetting() // const { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData } = useCanvasSetting()
let { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData } = props let { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props
const { option1, option2, dimensionDisplay } = settingModalFirstOptions const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { initEvent } = useEvent() const { initEvent } = useEvent()
// //
useEffect(() => { useEffect(() => {
console.log('FirstOption useEffect 실행') console.log('FirstOption useEffect 실행')
setSettingsDataSave({ ...settingsData })
}, []) }, [])
const onClickOption = async (item) => { const onClickOption = async (item) => {
// ( )
let dimensionDisplay = settingModalFirstOptions?.dimensionDisplay let dimensionDisplay = settingModalFirstOptions?.dimensionDisplay
let option1 = settingModalFirstOptions?.option1 let option1 = settingModalFirstOptions?.option1
let option2 = settingModalFirstOptions?.option2 let option2 = settingModalFirstOptions?.option2
// ( )
if (item.column === 'corridorDimension' || item.column === 'realDimension' || item.column === 'noneDimension') { if (item.column === 'corridorDimension' || item.column === 'realDimension' || item.column === 'noneDimension') {
dimensionDisplay = settingModalFirstOptions?.dimensionDisplay.map((option) => { dimensionDisplay = settingModalFirstOptions?.dimensionDisplay.map((option) => {
option.selected = option.id === item.id option.selected = option.id === item.id
@ -33,9 +34,9 @@ export default function FirstOption(props) {
// ( ) // ( )
} else if (item.column === 'onlyBorder' || item.column === 'lineHatch' || item.column === 'allPainted') { } else if (item.column === 'onlyBorder' || item.column === 'lineHatch' || item.column === 'allPainted') {
option2 = settingModalFirstOptions?.option2.map((option2) => { option2 = settingModalFirstOptions?.option2.map((option) => {
option2.selected = option2.id === item.id option.selected = option.id === item.id
return option2 return option
}) })
// setSettingModalFirstOptions({ ...settingModalFirstOptions, option2: [...options] }) // setSettingModalFirstOptions({ ...settingModalFirstOptions, option2: [...options] })
@ -47,11 +48,11 @@ export default function FirstOption(props) {
}) })
// ( ) // ( )
} else { } else {
option1 = settingModalFirstOptions?.option1.map((opt) => { option1 = settingModalFirstOptions?.option1.map((option) => {
if (opt.id === item.id) { if (option.id === item.id) {
opt.selected = !opt.selected option.selected = !option.selected
} }
return opt return option
}) })
// setSettingModalFirstOptions({ ...settingModalFirstOptions, option1: [...options] }) // setSettingModalFirstOptions({ ...settingModalFirstOptions, option1: [...options] })

View File

@ -28,8 +28,13 @@ export default function GridOption(props) {
const { initEvent } = useEvent() const { initEvent } = useEvent()
const { SelectOptions, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = useCanvasSetting()
useEffect(() => { useEffect(() => {
console.log('GridOption useEffect 실행') console.log('GridOption useEffect 실행')
}, [])
useEffect(() => {
setGridColor(color.hex) setGridColor(color.hex)
}, [color]) }, [color])
@ -96,7 +101,7 @@ export default function GridOption(props) {
} }
useEffect(() => { useEffect(() => {
console.log('🚀 ~ useEffect ~ initEvent:') //console.log('🚀 ~ useEffect ~ initEvent:')
initEvent() initEvent()
}, [gridOptions]) }, [gridOptions])
@ -108,10 +113,15 @@ export default function GridOption(props) {
x: 845, x: 845,
y: 180, y: 180,
}, },
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
const colorPickerProps = { const colorPickerProps = {
id: colorId, id: colorId,
name: 'gridOptionColor',
color: gridColor, color: gridColor,
setColor: setGridColor, setColor: setGridColor,
isShow: showColorPickerModal, isShow: showColorPickerModal,
@ -121,6 +131,10 @@ export default function GridOption(props) {
x: 785, x: 785,
y: 180, y: 180,
}, },
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
return ( return (

View File

@ -27,16 +27,6 @@ export default function SecondOption(props) {
const { initEvent } = useEvent() const { initEvent } = useEvent()
// const {
// fetchSettings,
// planSizeSettingMode,
// setPlanSizeSettingMode,
// settingModalSecondOptions,
// setSettingModalSecondOptions,
// adsorptionPointMode,
// setAdsorptionPointMode,
// setAdsorptionRange,
// } = useCanvasSetting()
const { const {
fetchSettings, fetchSettings,
planSizeSettingMode, planSizeSettingMode,
@ -46,12 +36,17 @@ export default function SecondOption(props) {
adsorptionPointMode, adsorptionPointMode,
setAdsorptionPointMode, setAdsorptionPointMode,
setAdsorptionRange, setAdsorptionRange,
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} = props } = props
const { option3, option4 } = settingModalSecondOptions const { option3, option4 } = settingModalSecondOptions
// //
useEffect(() => { useEffect(() => {
console.log('SecondOption useEffect 실행') console.log('SecondOption useEffect 실행')
setSettingsDataSave({ ...settingsData })
}, []) }, [])
const handlePopup = (type) => { const handlePopup = (type) => {
@ -142,18 +137,23 @@ export default function SecondOption(props) {
return { return {
...prev, ...prev,
[fontProps.type]: { [fontProps.type]: {
// fontFamily: font.fontFamily.value,
// fontWeight: font.fontWeight.value,
// fontSize: font.fontSize.value,
// fontColor: font.fontColor.value,
fontFamily: font.fontFamily, fontFamily: font.fontFamily,
fontWeight: font.fontWeight, fontWeight: font.fontWeight,
fontSize: font.fontSize, fontSize: font.fontSize,
fontColor: font.fontColor, fontColor: font.fontColor,
}, },
fontFlag: true,
} }
}) })
setSettingsData({
...settingsData,
[fontProps.type]: {
fontFamily: font.fontFamily,
fontWeight: font.fontWeight,
fontSize: font.fontSize,
fontColor: font.fontColor,
},
})
} }
const fontProps = { const fontProps = {
@ -168,6 +168,10 @@ export default function SecondOption(props) {
id: dimensionId, id: dimensionId,
isShow: showDimensionLineSettingModal, isShow: showDimensionLineSettingModal,
setIsShow: setShowDimensionLineSettingModal, setIsShow: setShowDimensionLineSettingModal,
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
const planSizeProps = { const planSizeProps = {
@ -177,9 +181,16 @@ export default function SecondOption(props) {
isShow: showPlanSizeSettingModal, isShow: showPlanSizeSettingModal,
setIsShow: setShowPlanSizeSettingModal, setIsShow: setShowPlanSizeSettingModal,
pos: { x: 1025, y: 180 }, pos: { x: 1025, y: 180 },
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
const onClickOption = async (item) => { const onClickOption = async (item) => {
let option4Data = settingModalSecondOptions?.option4
let adsorpPointData = adsorptionPointMode.adsorptionPoint
// ( ) // ( )
if ( if (
item.column === 'adsorpRangeSmall' || item.column === 'adsorpRangeSmall' ||
@ -189,21 +200,25 @@ export default function SecondOption(props) {
) { ) {
// option4 // option4
//const updatedOption4 = option4.map((option) => (option.id === item.id ? { ...option, selected: true } : { ...option, selected: false })) //const updatedOption4 = option4.map((option) => (option.id === item.id ? { ...option, selected: true } : { ...option, selected: false }))
const options = settingModalSecondOptions?.option4.map((option4) => { option4Data = settingModalSecondOptions?.option4.map((option) => {
option4.selected = option4.id === item.id option.selected = option.id === item.id
return option4 return option
}) })
setSettingModalSecondOptions({ ...settingModalSecondOptions, option3, option4, fontFlag: true }) //
setAdsorptionRange(item.range)
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: adsorpPointData })
} else if (item === 'adsorpPoint') { } else if (item === 'adsorpPoint') {
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: !adsorptionPointMode.adsorptionPoint, fontFlag: true }) setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: !adsorpPointData })
adsorpPointData = !adsorpPointData
} }
//setAdsorptionRange(item.range) //
setAdsorptionRange(50) setSettingsData({ ...settingsData, option4: [...option4Data], adsorptionPoint: adsorpPointData })
} }
useEffect(() => { useEffect(() => {
console.log('🚀 ~ useEffect ~ initEvent:') //console.log('🚀 ~ useEffect ~ initEvent:')
initEvent() initEvent()
}, [adsorptionPointMode]) }, [adsorptionPointMode])

View File

@ -24,7 +24,11 @@ export default function SettingModal01(props) {
setSettingModalFirstOptions, setSettingModalFirstOptions,
settingsData, settingsData,
setSettingsData, setSettingsData,
settingsDataSave,
setSettingsDataSave,
fetchSettings, fetchSettings,
globalFont,
setGlobalFont,
planSizeSettingMode, planSizeSettingMode,
setPlanSizeSettingMode, setPlanSizeSettingMode,
settingModalSecondOptions, settingModalSecondOptions,
@ -36,9 +40,19 @@ export default function SettingModal01(props) {
setGridColor, setGridColor,
color, color,
} = useCanvasSetting() } = useCanvasSetting()
const firstProps = { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData } const firstProps = {
canvas,
settingModalFirstOptions,
setSettingModalFirstOptions,
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
}
const secondProps = { const secondProps = {
fetchSettings, fetchSettings,
globalFont,
setGlobalFont,
planSizeSettingMode, planSizeSettingMode,
setPlanSizeSettingMode, setPlanSizeSettingMode,
settingModalSecondOptions, settingModalSecondOptions,
@ -46,6 +60,10 @@ export default function SettingModal01(props) {
adsorptionPointMode, adsorptionPointMode,
setAdsorptionPointMode, setAdsorptionPointMode,
setAdsorptionRange, setAdsorptionRange,
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
const gridProps = { gridColor, setGridColor, color } const gridProps = { gridColor, setGridColor, color }

View File

@ -33,7 +33,7 @@ const fontSizes = [
] ]
export default function DimensionLineSetting(props) { export default function DimensionLineSetting(props) {
const { isShow, setIsShow, id, pos = { x: 985, y: 180 } } = props const { isShow, setIsShow, id, pos = { x: 985, y: 180 }, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props
const { addPopup, closePopup, closePopups } = usePopup() const { addPopup, closePopup, closePopups } = usePopup()
const pixels = Array.from({ length: 5 }).map((_, index) => { const pixels = Array.from({ length: 5 }).map((_, index) => {
return { id: index, name: index + 1, value: index + 1 } return { id: index, name: index + 1, value: index + 1 }
@ -111,11 +111,16 @@ export default function DimensionLineSetting(props) {
color: originColor, color: originColor,
setColor: setOriginColor, setColor: setOriginColor,
id: colorModalId, id: colorModalId,
name: 'DimensionLineColor',
isConfig: true, isConfig: true,
pos: { pos: {
x: 495, x: 495,
y: 180, y: 180,
}, },
settingsData,
setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
const fontProps = { const fontProps = {
@ -157,9 +162,9 @@ export default function DimensionLineSetting(props) {
fontSize: originFontSize, fontSize: originFontSize,
fontColor: originFontColor, fontColor: originFontColor,
}, },
fontFlag: true,
} }
}) })
setDimensionLineSettings((prev) => { setDimensionLineSettings((prev) => {
return { return {
...prev, ...prev,
@ -167,6 +172,19 @@ export default function DimensionLineSetting(props) {
color: originColor, color: originColor,
} }
}) })
setSettingsData({
...settingsData,
dimensionLineText: {
fontFamily: originFont,
fontWeight: originFontWeight,
fontSize: originFontSize,
fontColor: originFontColor,
},
pixel: originPixel.name,
color: originColor,
})
setIsShow(false) setIsShow(false)
closePopups([fontModalId, colorModalId, id]) closePopups([fontModalId, colorModalId, id])
} }

View File

@ -8,7 +8,7 @@ import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { onlyNumberInputChange } from '@/util/input-utils' import { onlyNumberInputChange } from '@/util/input-utils'
export default function PlanSizeSetting(props) { export default function PlanSizeSetting(props) {
const { setIsShow, horizon, vertical, id, pos = { x: 985, y: 180 } } = props const { setIsShow, horizon, vertical, id, pos = { x: 985, y: 180 }, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -26,10 +26,15 @@ export default function PlanSizeSetting(props) {
...prev, ...prev,
originHorizon: Number(planSizeSettingMode.originHorizon), originHorizon: Number(planSizeSettingMode.originHorizon),
originVertical: Number(planSizeSettingMode.originVertical), originVertical: Number(planSizeSettingMode.originVertical),
flag: true,
} }
}) })
setSettingsData({
...settingsData,
originHorizon: Number(planSizeSettingMode.originHorizon),
originVertical: Number(planSizeSettingMode.originVertical),
})
canvas.setWidth(planSizeSettingMode.originHorizon) canvas.setWidth(planSizeSettingMode.originHorizon)
canvas.setHeight(planSizeSettingMode.originVertical) canvas.setHeight(planSizeSettingMode.originVertical)
canvas.renderAll() canvas.renderAll()
@ -40,12 +45,11 @@ export default function PlanSizeSetting(props) {
const changeInput = (value, e) => { const changeInput = (value, e) => {
const { name } = e.target const { name } = e.target
console.log('name', name, value)
setPlanSizeSettingMode((prev) => { setPlanSizeSettingMode((prev) => {
return { return {
...prev, ...prev,
[name]: Number(value), [name]: Number(value),
flag: false,
} }
}) })
} }

View File

@ -7,7 +7,7 @@ import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { setSession } from '@/lib/authActions' import { setSession } from '@/lib/authActions'
import { logout } from '@/lib/authActions'
export default function ChangePasswordPop(props) { export default function ChangePasswordPop(props) {
const globalLocaleState = useRecoilValue(globalLocaleStore) const globalLocaleState = useRecoilValue(globalLocaleStore)
@ -77,18 +77,21 @@ export default function ChangePasswordPop(props) {
if (res?.result?.code === 200) { if (res?.result?.code === 200) {
if (res?.result?.resultCode === 'S') { if (res?.result?.resultCode === 'S') {
alert(getMessage('main.popup.login.success')) alert(getMessage('main.popup.login.success'))
logout()
// setSessionState // setSessionState
// setSessionState({ ...sessionState, pwdInitYn: 'Y' }) // setSessionState({ ...sessionState, pwdInitYn: 'Y' })
props.setChagePasswordPopOpen(false) //props.setChagePasswordPopOpen(false)
router.push('/login') //router.push('/login')
} else { } else {
alert(res?.result?.resultMsg) alert(res?.result?.resultMsg)
} }
} else { } else {
logout()
console.log('code not 200 error') console.log('code not 200 error')
} }
}) })
.catch((error) => { .catch((error) => {
logout()
console.log('catch::::::::', error) console.log('catch::::::::', error)
}) })
} }
@ -165,7 +168,8 @@ export default function ChangePasswordPop(props) {
type="button" type="button"
className="btn-origin grey" className="btn-origin grey"
onClick={() => { onClick={() => {
router.push('/login') logout()
// router.push('/login')
}} }}
> >
{getMessage('main.popup.login.btn2')} {getMessage('main.popup.login.btn2')}

View File

@ -10,7 +10,7 @@ import { globalLocaleStore } from '@/store/localeAtom'
import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils' import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useForm } from 'react-hook-form' import { useForm } from 'react-hook-form'
import { useRecoilValue, useSetRecoilState, useResetRecoilState, useRecoilState } from 'recoil' import { useRecoilValue, useSetRecoilState, useResetRecoilState } from 'recoil'
import { SessionContext } from '@/app/SessionProvider' import { SessionContext } from '@/app/SessionProvider'
import FindAddressPop from './popup/FindAddressPop' import FindAddressPop from './popup/FindAddressPop'
import PlanRequestPop from './popup/PlanRequestPop' import PlanRequestPop from './popup/PlanRequestPop'
@ -41,7 +41,6 @@ export default function StuffDetail() {
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
const router = useRouter() const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams() const searchParams = useSearchParams()
const { getMessage } = useMessage() const { getMessage } = useMessage()
const globalLocaleState = useRecoilValue(globalLocaleStore) const globalLocaleState = useRecoilValue(globalLocaleStore)

View File

@ -1,6 +1,6 @@
'use client' 'use client'
import { useContext, useEffect } from 'react' import { useState, useContext, useEffect } from 'react'
import Link from 'next/link' import Link from 'next/link'
import Image from 'next/image' import Image from 'next/image'
@ -11,20 +11,37 @@ import { useSetRecoilState } from 'recoil'
import { QcastContext } from '@/app/QcastProvider' import { QcastContext } from '@/app/QcastProvider'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { queryStringFormatter } from '@/util/common-utils' import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
import { ManagementContext } from '@/app/management/ManagementProvider'
import { SessionContext } from '@/app/SessionProvider'
export default function StuffSubHeader({ type }) { export default function StuffSubHeader({ type }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const router = useRouter() const router = useRouter()
const { session } = useContext(SessionContext)
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState)
const { isGlobalLoading } = useContext(QcastContext) const { isGlobalLoading } = useContext(QcastContext)
const { managementState } = useContext(ManagementContext)
const [buttonStyle, setButtonStyle] = useState('')
useEffect(() => { useEffect(() => {
window.scrollTo(0, 0) window.scrollTo(0, 0)
}, []) }, [])
useEffect(() => {
if (isObjectNotEmpty(managementState)) {
if (managementState.createUser === 'T01') {
if (session.userId !== 'T01') {
setButtonStyle('none')
}
}
}
}, [managementState])
const searchParams = useSearchParams() const searchParams = useSearchParams()
const objectNo = searchParams.get('objectNo') //url set const objectNo = searchParams.get('objectNo') //url set
@ -98,7 +115,7 @@ export default function StuffSubHeader({ type }) {
{getMessage('stuff.temp.subTitle')} {getMessage('stuff.temp.subTitle')}
</Link> </Link>
</li> </li>
<li className="title-item"> <li className="title-item" style={{ display: buttonStyle }}>
<a className="sub-header-title" onClick={moveFloorPlan}> <a className="sub-header-title" onClick={moveFloorPlan}>
<span className="icon drawing"></span> <span className="icon drawing"></span>
{getMessage('stuff.temp.subTitle2')} {getMessage('stuff.temp.subTitle2')}

View File

@ -0,0 +1,88 @@
import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage'
import { useSwal } from '@/hooks/useSwal'
import { getQueryString } from '@/util/common-utils'
import axios from 'axios'
/**
* 마스터 컨트롤러
* @returns
*/
export function useMasterController() {
const { get } = useAxios()
const { getMessage } = useMessage()
const { swalFire } = useSwal()
/**
* 지붕재 목록 조회
* @returns
*/
const getRoofMaterialList = async () => {
return await get({ url: '/api/v1/master/getRoofMaterialList' }).then((res) => {
console.log('🚀🚀 ~ getRoofMaterialList ~ res:', res)
return res
})
}
/**
* 모듈 타입별 아이템 목록 조회
* @param {지붕재 코드} roofMatlCd
* @returns
*/
const getModuleTypeItemList = async (roofMatlCd) => {
if (!roofMatlCd || roofMatlCd.trim() === '') {
swalFire({ text: getMessage('master.moduletypeitem.message.error'), type: 'alert', icon: 'error' })
return null
}
const param = { roofMatlCd: roofMatlCd }
const paramString = getQueryString(param)
return await get({ url: `/api/v1/master/getModuleTypeItemList${paramString}` }).then((res) => {
console.log('🚀🚀 ~ getModuleTypeItemList ~ res:', res)
return res
})
}
/**
* 가대 목록 조회
* @param
* @returns
*/
const getTrestleList = async (params) => {
return await get({ url: `/api/v1/master/getTrestleList/${params}` }).then((res) => {
console.log('🚀🚀 ~ getTrestleList ~ res:', res)
return res
})
}
/**
* 모듈 시공법 목록 조회
* @param
* @returns
*/
const getConstructionList = async (params) => {
return await get({ url: `/api/v1/master/getConstructionList/${params}` }).then((res) => {
console.log('🚀🚀 ~ getConstructionList ~ res:', res)
return res
})
}
/**
* 가대 상세 조회
* @param
* @returns
*/
const getTrestleDetailList = async (params) => {
return await get({ url: `/api/v1/master/getTrestleDetailList/${params}` }).then((res) => {
console.log('🚀🚀 ~ getTrestleDetailList ~ res:', res)
return res
})
}
return {
getRoofMaterialList,
getModuleTypeItemList,
getTrestleList,
getConstructionList,
getTrestleDetailList,
}
}

View File

@ -1,30 +0,0 @@
import { canvasState } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil'
import { usePolygon } from '@/hooks/usePolygon'
import { useState } from 'react'
import { usePopup } from '@/hooks/usePopup'
export const FLOW_DIRECTION_TYPE = {
EIGHT_AZIMUTH: 'eightAzimuth',
TWENTY_FOUR_AZIMUTH: 'twentyFourAzimuth',
}
export function useFlowDirectionSetting(id) {
const canvas = useRecoilValue(canvasState)
const { drawDirectionArrow } = usePolygon()
const { closePopup } = usePopup()
const [type, setType] = useState(FLOW_DIRECTION_TYPE.EIGHT_AZIMUTH)
const changeSurfaceFlowDirection = (roof, direction, orientation) => {
roof.set({
direction: direction,
surfaceCompass: orientation,
})
drawDirectionArrow(roof)
canvas?.renderAll()
closePopup(id)
}
return { changeSurfaceFlowDirection, type, setType }
}

View File

@ -1,13 +1,14 @@
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useContext, useEffect, useReducer, useState } from 'react' import { useContext, useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { isObjectNotEmpty, isEmptyArray, isNotEmptyArray } from '@/util/common-utils' import { isObjectNotEmpty, isEmptyArray } from '@/util/common-utils'
import { SessionContext } from '@/app/SessionProvider' import { SessionContext } from '@/app/SessionProvider'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRouter } from 'next/navigation' import { useRouter } from 'next/navigation'
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider' import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
import { QcastContext } from '@/app/QcastProvider'
// Constants // Constants
const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의 const ESTIMATE_API_ENDPOINT = '/api/estimate' // API 엔드포인트 정의
@ -19,7 +20,7 @@ const updateItemInList = (itemList, dispOrder, updates) => {
export const useEstimateController = (planNo) => { export const useEstimateController = (planNo) => {
const [fileList, setFileList] = useState([]) const [fileList, setFileList] = useState([])
const [deleteFileList, setDeleteFileList] = useState([]) const { setIsGlobalLoading } = useContext(QcastContext)
const router = useRouter() const router = useRouter()
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
@ -52,6 +53,7 @@ export const useEstimateController = (planNo) => {
const fetchSetting = async (objectNo, planNo) => { const fetchSetting = async (objectNo, planNo) => {
try { try {
await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` }).then((res) => { await promiseGet({ url: `/api/estimate/${objectNo}/${planNo}/detail` }).then((res) => {
setIsGlobalLoading(true)
if (res.status === 200) { if (res.status === 200) {
if (isObjectNotEmpty(res.data)) { if (isObjectNotEmpty(res.data)) {
if (res.data.itemList.length > 0) { if (res.data.itemList.length > 0) {
@ -72,9 +74,11 @@ export const useEstimateController = (planNo) => {
} }
}) })
setIsLoading(true) setIsLoading(true)
setIsGlobalLoading(false)
} catch (error) { } catch (error) {
console.error('견적서 상세조회 Error: ', error) console.error('견적서 상세조회 Error: ', error)
setIsLoading(true) setIsLoading(true)
setIsGlobalLoading(false)
} }
} }
@ -354,15 +358,16 @@ export const useEstimateController = (planNo) => {
// return // return
try { try {
await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => { await promisePost({ url: `${ESTIMATE_API_ENDPOINT}/save-estimate`, data: estimateData }).then((res) => {
setIsGlobalLoading(true)
if (res.status === 201) { if (res.status === 201) {
estimateData.newFileList = [] estimateData.newFileList = []
// estimateData.originFiles = []
alert(getMessage('estimate.detail.save.alertMsg')) alert(getMessage('estimate.detail.save.alertMsg'))
//어디로 보낼지 //어디로 보낼지
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo) fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
} }
}) })
} catch (e) { } catch (e) {
setIsGlobalLoading(false)
console.log('error::::::::::::', e.response.data.message) console.log('error::::::::::::', e.response.data.message)
} }
} }

View File

@ -12,6 +12,7 @@ import { v4 as uuidv4 } from 'uuid'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { canvasSettingState } from '@/store/canvasAtom' import { canvasSettingState } from '@/store/canvasAtom'
import { compasDegAtom } from '@/store/orientationAtom' import { compasDegAtom } from '@/store/orientationAtom'
import { QLine } from '@/components/fabric/QLine'
export function useModuleBasicSetting() { export function useModuleBasicSetting() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -51,6 +52,7 @@ export function useModuleBasicSetting() {
const makeModuleInstArea = () => { const makeModuleInstArea = () => {
//지붕 객체 반환 //지붕 객체 반환
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20
if (!roofs) { if (!roofs) {
return return
@ -63,13 +65,11 @@ export function useModuleBasicSetting() {
} }
setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경 setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
const offsetPoints = offsetPolygon(roof.points, -20) //안쪽 offset const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
//모듈설치영역?? 생성 //모듈설치영역?? 생성
const surfaceId = uuidv4() const surfaceId = uuidv4()
console.log('roof.moduleCompass', roof.moduleCompass)
let setupSurface = new QPolygon(offsetPoints, { let setupSurface = new QPolygon(offsetPoints, {
stroke: 'red', stroke: 'red',
fill: 'transparent', fill: 'transparent',
@ -88,7 +88,10 @@ export function useModuleBasicSetting() {
flipX: roof.flipX, flipX: roof.flipX,
flipY: roof.flipY, flipY: roof.flipY,
surfaceId: surfaceId, surfaceId: surfaceId,
originX: 'center',
originY: 'center',
modules: [], modules: [],
// angle: -compasDeg,
}) })
setupSurface.setViewLengthText(false) setupSurface.setViewLengthText(false)
@ -102,6 +105,7 @@ export function useModuleBasicSetting() {
} }
setupSurface.set({ flowLines: flowLines }) setupSurface.set({ flowLines: flowLines })
flatRoofMakeSurface(roof, setupSurface)
//지붕면 선택 금지 //지붕면 선택 금지
roof.set({ roof.set({
@ -656,7 +660,7 @@ export function useModuleBasicSetting() {
} }
} }
const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, flowModuleLine, isCenter = false) => { const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, aaa, isCenter = false) => {
let startPoint = flowModuleLine.left let startPoint = flowModuleLine.left
//중앙배치일 경우에는 계산한다 //중앙배치일 경우에는 계산한다
@ -1206,9 +1210,10 @@ export function useModuleBasicSetting() {
return turf.polygon([coordinates]) return turf.polygon([coordinates])
} }
const polygonToTurfPolygon = (object) => { const polygonToTurfPolygon = (object, current = false) => {
let coordinates let coordinates
coordinates = object.points.map((point) => [point.x, point.y]) coordinates = object.points.map((point) => [point.x, point.y])
if (current) coordinates = object.getCurrentPoints().map((point) => [point.x, point.y])
coordinates.push(coordinates[0]) coordinates.push(coordinates[0])
return turf.polygon( return turf.polygon(
[coordinates], [coordinates],
@ -1526,17 +1531,18 @@ export function useModuleBasicSetting() {
let flatBatchType = placementFlatRef.setupLocation.current.value let flatBatchType = placementFlatRef.setupLocation.current.value
let excretaLinesAngle = [] let excretaLinesAngle = []
if (flatBatchType === 'south') { if (flatBatchType === 'excreta') {
applyAngle = compasDeg const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine')
} else {
const excretaLines = canvas.getObjects().filter((obj) => obj.name === 'flatExcretaLine' && obj.isSelected === true)
excretaLines.forEach((obj) => { excretaLines.forEach((obj) => {
const points1 = { x: obj.x1, y: obj.y1 } if (obj.isSelected) {
const points2 = { x: obj.x2, y: obj.y2 } const points1 = { x: obj.x1, y: obj.y1 }
excretaLinesAngle.push({ const points2 = { x: obj.x2, y: obj.y2 }
surfaceId: obj.surfaceId, excretaLinesAngle.push({
angle: calculateAngle(points1, points2), surfaceId: obj.surfaceId,
}) angle: calculateAngle(points1, points2),
})
}
canvas.remove(obj)
}) })
} }
@ -1591,8 +1597,6 @@ export function useModuleBasicSetting() {
return transformedCorners return transformedCorners
} }
function getSelectedExcretaLine() {}
if (moduleSetupSurfaces.length !== 0) { if (moduleSetupSurfaces.length !== 0) {
let tempModule let tempModule
let manualDrawModules = [] let manualDrawModules = []
@ -1606,7 +1610,7 @@ export function useModuleBasicSetting() {
const mousePoint = canvas.getPointer(e.e) const mousePoint = canvas.getPointer(e.e)
for (let i = 0; i < moduleSetupSurfaces.length; i++) { for (let i = 0; i < moduleSetupSurfaces.length; i++) {
turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i]) turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i], true)
trestlePolygon = moduleSetupSurfaces[i] trestlePolygon = moduleSetupSurfaces[i]
manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨 manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향 flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
@ -1616,18 +1620,11 @@ export function useModuleBasicSetting() {
if (tempLine) { if (tempLine) {
applyAngle = tempLine.angle applyAngle = tempLine.angle
} else { } else {
//혹시나 두개의 지붕을 그리고 한쪽면만 선택했을때 한면은 그냥 기본 기울기를 준다
applyAngle = compasDeg applyAngle = compasDeg
} }
} }
// const excretaLine = excretaLines.find((obj) => obj.isSelected === true && obj.surfaceId === trestlePolygon.surfaceId)
// console.log('excretaLine', excretaLine.x1, excretaLine.y1, excretaLine.x2, excretaLine.y2)
// applyAngle = calculateAngle(excretaLine.x1, excretaLine.y1, excretaLine.x2, excretaLine.y2)
// console.log('applyAngle', applyAngle)
let width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113 let width = flowDirection === 'south' || flowDirection === 'north' ? 172 : 113
let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172 let height = flowDirection === 'south' || flowDirection === 'north' ? 113 : 172
@ -1667,123 +1664,125 @@ export function useModuleBasicSetting() {
let snapDistance = 10 let snapDistance = 10
let cellSnapDistance = 20 let cellSnapDistance = 20
const trestleLeft = moduleSetupSurfaces[i].left // if (applyAngle === 90 || applyAngle === 180 || applyAngle === 270 || applyAngle === 0) {
const trestleTop = moduleSetupSurfaces[i].top // const trestleLeft = moduleSetupSurfaces[i].left
const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX // const trestleTop = moduleSetupSurfaces[i].top
const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY // const trestleRight = trestleLeft + moduleSetupSurfaces[i].width * moduleSetupSurfaces[i].scaleX
const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2 // const trestleBottom = trestleTop + moduleSetupSurfaces[i].height * moduleSetupSurfaces[i].scaleY
// const bigCenterY = (trestleTop + trestleTop + moduleSetupSurfaces[i].height) / 2
// 작은 폴리곤의 경계 좌표 계산 // // 작은 폴리곤의 경계 좌표 계산
const smallLeft = tempModule.left // const smallLeft = tempModule.left
const smallTop = tempModule.top // const smallTop = tempModule.top
const smallRight = smallLeft + tempModule.width * tempModule.scaleX // const smallRight = smallLeft + tempModule.width * tempModule.scaleX
const smallBottom = smallTop + tempModule.height * tempModule.scaleY // const smallBottom = smallTop + tempModule.height * tempModule.scaleY
const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2 // const smallCenterX = smallLeft + (tempModule.width * tempModule.scaleX) / 2
const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2 // const smallCenterY = smallTop + (tempModule.height * tempModule.scaleX) / 2
if (manualDrawModules) { // if (manualDrawModules) {
manualDrawModules.forEach((cell) => { // manualDrawModules.forEach((cell) => {
const holdCellLeft = cell.left // const holdCellLeft = cell.left
const holdCellTop = cell.top // const holdCellTop = cell.top
const holdCellRight = holdCellLeft + cell.width * cell.scaleX // const holdCellRight = holdCellLeft + cell.width * cell.scaleX
const holdCellBottom = holdCellTop + cell.height * cell.scaleY // const holdCellBottom = holdCellTop + cell.height * cell.scaleY
const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2 // const holdCellCenterX = holdCellLeft + (cell.width * cell.scaleX) / 2
const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2 // const holdCellCenterY = holdCellTop + (cell.height * cell.scaleY) / 2
//설치된 셀에 좌측에 스냅 // //설치된 셀에 좌측에 스냅
if (Math.abs(smallRight - holdCellLeft) < snapDistance) { // if (Math.abs(smallRight - holdCellLeft) < snapDistance) {
tempModule.left = holdCellLeft - width - 0.5 // tempModule.left = holdCellLeft - width - 0.5
} // }
//설치된 셀에 우측에 스냅 // //설치된 셀에 우측에 스냅
if (Math.abs(smallLeft - holdCellRight) < snapDistance) { // if (Math.abs(smallLeft - holdCellRight) < snapDistance) {
tempModule.left = holdCellRight + 0.5 // tempModule.left = holdCellRight + 0.5
} // }
//설치된 셀에 위쪽에 스냅 // //설치된 셀에 위쪽에 스냅
if (Math.abs(smallBottom - holdCellTop) < snapDistance) { // if (Math.abs(smallBottom - holdCellTop) < snapDistance) {
tempModule.top = holdCellTop - height - 0.5 // tempModule.top = holdCellTop - height - 0.5
} // }
//설치된 셀에 밑쪽에 스냅 // //설치된 셀에 밑쪽에 스냅
if (Math.abs(smallTop - holdCellBottom) < snapDistance) { // if (Math.abs(smallTop - holdCellBottom) < snapDistance) {
tempModule.top = holdCellBottom + 0.5 // tempModule.top = holdCellBottom + 0.5
} // }
//가운데 -> 가운데 // //가운데 -> 가운데
if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) { // if (Math.abs(smallCenterX - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX - width / 2 // tempModule.left = holdCellCenterX - width / 2
} // }
//왼쪽 -> 가운데 // //왼쪽 -> 가운데
if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) { // if (Math.abs(smallLeft - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX // tempModule.left = holdCellCenterX
} // }
// 오른쪽 -> 가운데 // // 오른쪽 -> 가운데
if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) { // if (Math.abs(smallRight - holdCellCenterX) < cellSnapDistance) {
tempModule.left = holdCellCenterX - width // tempModule.left = holdCellCenterX - width
} // }
//세로 가운데 -> 가운데 // //세로 가운데 -> 가운데
if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) { // if (Math.abs(smallCenterY - holdCellCenterY) < cellSnapDistance) {
tempModule.top = holdCellCenterY - height / 2 // tempModule.top = holdCellCenterY - height / 2
} // }
//위쪽 -> 가운데 // //위쪽 -> 가운데
if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) { // if (Math.abs(smallTop - holdCellCenterY) < cellSnapDistance) {
tempModule.top = holdCellCenterY // tempModule.top = holdCellCenterY
} // }
//아랫쪽 -> 가운데 // //아랫쪽 -> 가운데
if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) { // if (Math.abs(smallBottom - holdCellCenterY) < cellSnapDistance) {
tempModule.top = holdCellCenterY - height // tempModule.top = holdCellCenterY - height
} // }
}) // })
} // }
// 위쪽 변에 스냅 // // 위쪽 변에 스냅
if (Math.abs(smallTop - trestleTop) < snapDistance) { // if (Math.abs(smallTop - trestleTop) < snapDistance) {
tempModule.top = trestleTop // tempModule.top = trestleTop
} // }
// 아래쪽 변에 스냅 // // 아래쪽 변에 스냅
if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) { // if (Math.abs(smallTop + tempModule.height * tempModule.scaleY - (trestleTop + moduleSetupSurfaces[i].height)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY // tempModule.top = trestleTop + moduleSetupSurfaces[i].height - tempModule.height * tempModule.scaleY
} // }
// 왼쪽변에 스냅 // // 왼쪽변에 스냅
if (Math.abs(smallLeft - trestleLeft) < snapDistance) { // if (Math.abs(smallLeft - trestleLeft) < snapDistance) {
tempModule.left = trestleLeft // tempModule.left = trestleLeft
} // }
//오른쪽 변에 스냅 // //오른쪽 변에 스냅
if (Math.abs(smallRight - trestleRight) < snapDistance) { // if (Math.abs(smallRight - trestleRight) < snapDistance) {
tempModule.left = trestleRight - tempModule.width * tempModule.scaleX // tempModule.left = trestleRight - tempModule.width * tempModule.scaleX
} // }
if (flowDirection === 'south' || flowDirection === 'north') { // if (flowDirection === 'south' || flowDirection === 'north') {
// 모듈왼쪽이 세로중앙선에 붙게 스냅 // // 모듈왼쪽이 세로중앙선에 붙게 스냅
if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // if (Math.abs(smallLeft - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2
} // }
// 모듈이 가운데가 세로중앙선에 붙게 스냅 // // 모듈이 가운데가 세로중앙선에 붙게 스냅
if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // if (Math.abs(smallCenterX - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2 // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - (tempModule.width * tempModule.scaleX) / 2
} // }
// 모듈오른쪽이 세로중앙선에 붙게 스냅 // // 모듈오른쪽이 세로중앙선에 붙게 스냅
if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) { // if (Math.abs(smallRight - (trestleLeft + moduleSetupSurfaces[i].width / 2)) < snapDistance) {
tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX // tempModule.left = trestleLeft + moduleSetupSurfaces[i].width / 2 - tempModule.width * tempModule.scaleX
} // }
} else { // } else {
// 모듈이 가로중앙선에 스냅 // // 모듈이 가로중앙선에 스냅
if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) { // if (Math.abs(smallTop + tempModule.height / 2 - bigCenterY) < snapDistance) {
tempModule.top = bigCenterY - tempModule.height / 2 // tempModule.top = bigCenterY - tempModule.height / 2
} // }
if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { // if (Math.abs(smallTop - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2
} // }
// 모듈 밑면이 가로중앙선에 스냅 // // 모듈 밑면이 가로중앙선에 스냅
if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) { // if (Math.abs(smallBottom - (trestleTop + moduleSetupSurfaces[i].height / 2)) < snapDistance) {
tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY // tempModule.top = trestleTop + moduleSetupSurfaces[i].height / 2 - tempModule.height * tempModule.scaleY
} // }
} // }
// }
inside = true inside = true
break break
@ -1833,8 +1832,6 @@ export function useModuleBasicSetting() {
//마우스 클릭시 set으로 해당 위치에 셀을 넣음 //마우스 클릭시 set으로 해당 위치에 셀을 넣음
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
if (!isOverlap) { if (!isOverlap) {
console.log('tempModule.points', tempModule.points)
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions }) let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
canvas?.add(manualModule) canvas?.add(manualModule)
manualDrawModules.push(tempModule) manualDrawModules.push(tempModule)
@ -1849,7 +1846,411 @@ export function useModuleBasicSetting() {
} }
} }
const autoFlatroofModuleSetup = (placementFlatRef) => {} const autoFlatroofModuleSetup = (placementFlatRef) => {
initEvent() //마우스 이벤트 초기화
let flatBatchType = placementFlatRef.setupLocation.current.value
const moduleSetupSurfaces = moduleSetupSurface //선택 설치면
const notSelectedTrestlePolygons = canvas
?.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && !moduleSetupSurfaces.includes(obj)) //설치면이 아닌것
const batchObjects = canvas
?.getObjects()
.filter(
(obj) =>
obj.name === BATCH_TYPE.OPENING ||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
obj.name === BATCH_TYPE.PENTAGON_DORMER ||
obj.name === BATCH_TYPE.SHADOW,
) //도머s 객체
if (moduleSetupSurfaces.length === 0) {
alert('선택된 모듈 설치면이 없습니다.')
return
}
//어짜피 자동으로 누르면 선택안된데도 다 날아간다
canvas.getObjects().forEach((obj) => {
if (obj.name === 'module') {
canvas.remove(obj)
}
})
notSelectedTrestlePolygons.forEach((obj) => {
if (obj.modules) {
obj.modules.forEach((module) => {
canvas?.remove(module)
})
obj.modules = []
}
})
const moduleOptions = {
fill: '#BFFD9F',
stroke: 'black',
strokeWidth: 0.1,
selectable: false, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
parentId: moduleSetupSurface.parentId,
name: 'module',
}
let leftMargin, bottomMargin, square, chidoriLength
//선택된 지붕안에 오브젝트(도머, 개구등)이 있는지 확인하는 로직 포함되면 배열 반환
const objectsIncludeSurface = (turfModuleSetupSurface) => {
let containsBatchObjects = []
containsBatchObjects = batchObjects.filter((batchObject) => {
let convertBatchObject
if (batchObject.type === 'group') {
//도머는 그룹형태임
convertBatchObject = batchObjectGroupToTurfPolygon(batchObject)
} else {
//개구, 그림자
batchObject.set({ points: rectToPolygon(batchObject) })
canvas?.renderAll() // set된걸 바로 적용하기 위해
convertBatchObject = polygonToTurfPolygon(batchObject) //rect를 폴리곤으로 변환 -> turf 폴리곤으로 변환
}
// 폴리곤 안에 도머 폴리곤이 포함되어있는지 확인해서 반환하는 로직
return turf.booleanContains(turfModuleSetupSurface, convertBatchObject) || turf.booleanWithin(convertBatchObject, turfModuleSetupSurface)
})
return containsBatchObjects
}
/**
* 도머나 개구가 모듈에 걸치는지 확인하는 로직
* @param {*} squarePolygon
* @param {*} containsBatchObjects
* @returns
*/
const checkModuleDisjointObjects = (squarePolygon, containsBatchObjects) => {
let isDisjoint = false
if (containsBatchObjects.length > 0) {
let convertBatchObject
//도머가 있으면 적용되는 로직
isDisjoint = containsBatchObjects.every((batchObject) => {
if (batchObject.type === 'group') {
convertBatchObject = batchObjectGroupToTurfPolygon(batchObject)
} else {
convertBatchObject = polygonToTurfPolygon(batchObject)
}
/**
* 도머가 여러개일수있으므로 겹치는게 있다면...
* 안겹치는지 확인하는 로직이라 안겹치면 true를 반환
*/
return turf.booleanDisjoint(squarePolygon, convertBatchObject)
})
} else {
isDisjoint = true
}
return isDisjoint
}
/**
* 배치면 안에 있는지 확인
* @param {*} squarePolygon
* @param {*} turfModuleSetupSurface
* @returns
*/
const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => {
return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface)
}
let moduleGroup = []
const flatRoofDownFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.bottom
const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측
const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측
const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단
let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1
let totalTopEndPoint = maxTopEndPoint - startPoint.y1
let totalWidth = Math.ceil(Math.abs(maxRightEndPoint - maxLeftEndPoint) / width)
let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width)
let diffTopEndPoint = Math.abs(totalTopEndPoint / height)
let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1)
let tempMaxWidth = width //최대배치인지 확인하려고 넣음
for (let j = 0; j < diffTopEndPoint; j++) {
bottomMargin = marginHeight * j
for (let i = 0; i <= totalWidth; i++) {
leftMargin = marginWidth * i
square = [
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 - height * j - bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 - height * j - height - bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - height - bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 - height * j - bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
const flatRoofLeftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.left
const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측
const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단
const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단
let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌
let diffTopEndPoint = Math.abs(totalTopEndPoint / height)
let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height)
let totalWidth = Math.abs(startPoint.x1 - maxRightEndPoint) / width
let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint)
let tempMaxHeight = height //최대배치인지 확인하려고 넣음
for (let i = 0; i <= totalWidth; i++) {
bottomMargin = marginHeight * i
for (let j = 0; j < totalHeight; j++) {
leftMargin = marginWidth * j
square = [
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 + width * i + width + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 + width * i + leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
const flatRoofTopFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.top
const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측
const maxRightEndPoint = surfaceMaxLines.right.x1 //최 우측
const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단
let totalLeftEndPoint = maxLeftEndPoint - startPoint.x1
let totalRightEndPoint = maxLeftEndPoint - maxRightEndPoint
let totalBottomEndPoint = maxBottomEndPoint - startPoint.y1
let diffLeftEndPoint = Math.abs(totalLeftEndPoint / width)
let diffRightEndPoint = Math.ceil(Math.abs(totalRightEndPoint / width))
let diffBottomEndPoint = Math.ceil(Math.abs(totalBottomEndPoint / height))
let startColPoint = Math.abs(width * Math.ceil(diffLeftEndPoint) - startPoint.x1)
let tempMaxWidth = width //최대배치인지 확인하려고 넣음
for (let j = 0; j < diffBottomEndPoint; j++) {
bottomMargin = marginHeight * j
for (let i = 0; i < diffRightEndPoint; i++) {
leftMargin = marginWidth * i
square = [
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 + height * j + bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 + height * j + height + bottomMargin],
[startColPoint + tempMaxWidth * i + width + leftMargin, startPoint.y1 + height * j + bottomMargin],
[startColPoint + tempMaxWidth * i + leftMargin, startPoint.y1 + height * j + bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
const flatRoofRightFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight) => {
let startPoint = moduleSetupSurface.flowLines.right
const maxLeftEndPoint = surfaceMaxLines.left.x1 //최 좌측
const maxTopEndPoint = surfaceMaxLines.top.y1 //최 상단
const maxBottomEndPoint = surfaceMaxLines.bottom.y1 //최하단
let totalTopEndPoint = Math.abs(maxTopEndPoint - startPoint.y1) //전체 높이에서 현재 높이를 뺌
let diffTopEndPoint = Math.abs(totalTopEndPoint / height)
let totalHeight = Math.ceil(Math.abs(maxBottomEndPoint - maxTopEndPoint) / height)
let totalWidth = Math.abs(startPoint.x1 - maxLeftEndPoint) / width
let startRowPoint = startPoint.y1 - height * Math.ceil(diffTopEndPoint) - 3 // -3으로 위치살짝 보정
let tempMaxHeight = height //최대배치인지 확인하려고 넣음
for (let i = 0; i <= totalWidth; i++) {
bottomMargin = marginHeight * i
for (let j = 0; j < totalHeight; j++) {
leftMargin = marginWidth * j
square = [
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
[startPoint.x1 - width * i - width - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + height + bottomMargin],
[startPoint.x1 - width * i - leftMargin, startRowPoint + tempMaxHeight * j + bottomMargin],
]
let squarePolygon = turf.polygon([square])
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) {
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule)
moduleSetupArray.push(tempModule)
moduleGroup.push(tempModule)
}
}
}
moduleSetupSurfaces.forEach((moduleSetupSurface, index) => {
moduleSetupSurface.fire('mousedown')
const moduleSetupArray = []
let maxLengthLine = moduleSetupSurface.lines.reduce((acc, cur) => {
return acc.length > cur.length ? acc : cur
})
const turfModuleSetupSurface = polygonToTurfPolygon(moduleSetupSurface, true) //폴리곤을 turf 객체로 변환
const containsBatchObjects = objectsIncludeSurface(turfModuleSetupSurface) //배치면에 오브젝트(도머, 개구등)이 있는지 확인하는 로직
let width = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 172.2 : 113.4
let height = maxLengthLine.flowDirection === 'east' || maxLengthLine.flowDirection === 'west' ? 113.4 : 172.2
//배치면때는 방향쪽으로 패널이 넓게 누워져야함
if (moduleSetupSurface.flowDirection !== undefined) {
width = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 172.2 : 113.4
height = moduleSetupSurface.flowDirection === 'south' || moduleSetupSurface.flowDirection === 'north' ? 113.4 : 172.2
}
const surfaceMaxLines = findSetupSurfaceMaxLines(moduleSetupSurface)
const marginWidth = 0
const marginHeight = 0
canvas.renderAll()
if (compasDeg >= 0 && compasDeg < 90) {
flatRoofDownFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
} else if (compasDeg >= 90 && compasDeg < 180) {
flatRoofLeftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
} else if (compasDeg >= 180 && compasDeg < 270) {
flatRoofRightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
} else {
flatRoofTopFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, marginWidth, marginHeight)
}
const setupedModules = moduleSetupArray.filter((module, index) => {
let disjointFromTrestle = checkModuleDisjointSurface(module.turfPoints, turfModuleSetupSurface)
let isDisjoint = checkModuleDisjointObjects(module.turfPoints, containsBatchObjects)
if (!(disjointFromTrestle && isDisjoint)) {
canvas?.remove(module)
// module.set({ fill: 'rgba(255,190,41, 0.4)', stroke: 'black', strokeWidth: 1 })
return false
} else {
return module
}
})
canvas?.renderAll()
//나간애들 제외하고 설치된 애들로 겹친애들 삭제 하기
// setupedModules.forEach((module, index) => {
// if (isMaxSetup && index > 0) {
// const isOverlap = turf.booleanOverlap(polygonToTurfPolygon(setupedModules[index - 1]), polygonToTurfPolygon(module))
// //겹치는지 확인
// if (isOverlap) {
// //겹쳐있으면 삭제
// // canvas?.remove(module)
// module.set({ fill: 'rgba(72, 161, 250, 0.4)', stroke: 'black', strokeWidth: 0.1 })
// canvas.renderAll()
// setupedModules.splice(index, 1)
// return false
// }
// }
// })
moduleSetupSurface.set({ modules: setupedModules })
// const moduleArray = [...moduleIsSetup]
// moduleArray.push({
// surfaceId: moduleSetupSurface.surfaceId,
// moduleSetupArray: setupedModules,
// })
// setModuleIsSetup(moduleArray)
})
// console.log(calculateForApi())
}
const flatRoofMakeSurface = (roof, setupSurface) => {
setupSurface.angle = -compasDeg
roof.angle = -compasDeg
const roofPoints = roof.getCurrentPoints()
const roofLines = roofPoints.map((point, index) => {
const nextIndex = (index + 1) % roofPoints.length
const nextPoint = roofPoints[nextIndex]
return {
x1: point.x,
y1: point.y,
x2: nextPoint.x,
y2: nextPoint.y,
}
})
roof.set({ lines: roofLines })
roof.fire('modified')
const surfacePoints = setupSurface.getCurrentPoints()
const surfaceLines = surfacePoints.map((point, index) => {
const nextIndex = (index + 1) % surfacePoints.length
const nextPoint = surfacePoints[nextIndex]
return {
x1: point.x,
y1: point.y,
x2: nextPoint.x,
y2: nextPoint.y,
}
})
setupSurface.set({ lines: surfaceLines })
const flowLines = {
bottom: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'bottom'),
top: bottomTopFlowLine(setupSurface).find((obj) => obj.target === 'top'),
left: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'left'),
right: leftRightFlowLine(setupSurface).find((obj) => obj.target === 'right'),
}
setupSurface.set({ flowLines: flowLines })
setupSurface.fire('modified')
}
return { return {
makeModuleInstArea, makeModuleInstArea,

View File

@ -20,12 +20,14 @@ import {
settingModalGridOptionsState, settingModalGridOptionsState,
basicSettingState, basicSettingState,
settingsState, settingsState,
roofMaterialsAtom,
} from '@/store/settingAtom' } from '@/store/settingAtom'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { globalFontAtom } from '@/store/fontAtom' import { globalFontAtom } from '@/store/fontAtom'
import { dimensionLineSettingsState } from '@/store/commonUtilsAtom' import { dimensionLineSettingsState } from '@/store/commonUtilsAtom'
import { gridColorState } from '@/store/gridAtom' import { gridColorState } from '@/store/gridAtom'
import { useColor } from 'react-color-palette' import { useColor } from 'react-color-palette'
import { useMasterController } from '@/hooks/common/useMasterController'
const defaultDotLineGridSetting = { const defaultDotLineGridSetting = {
INTERVAL: { INTERVAL: {
@ -48,28 +50,15 @@ export function useCanvasSetting() {
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
// const [settingsData, setSettingsData] = useRecoilState(settingsState)
const [settingsData, setSettingsData] = useState({ ...settingModalFirstOptions, ...settingModalSecondOptions })
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { option4 } = settingModalSecondOptions
const corridorDimension = useRecoilValue(corridorDimensionSelector)
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get, post } = useAxios(globalLocaleState)
const { getMessage } = useMessage()
const { swalFire } = useSwal()
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState)
const [planSizeSettingMode, setPlanSizeSettingMode] = useRecoilState(planSizeSettingState)
//const setAdsorptionRange = useSetRecoilState(adsorptionRangeState)
const [selectedFont, setSelectedFont] = useState() const [selectedFont, setSelectedFont] = useState()
const [selectedFontWeight, setSelectedFontWeight] = useState() const [selectedFontWeight, setSelectedFontWeight] = useState()
const [selectedFontSize, setSelectedFontSize] = useState() const [selectedFontSize, setSelectedFontSize] = useState()
const [selectedFontColor, setSelectedFontColor] = useState() const [selectedFontColor, setSelectedFontColor] = useState()
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom) const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState)
const [planSizeSettingMode, setPlanSizeSettingMode] = useRecoilState(planSizeSettingState)
const [dimensionLineSettings, setDimensionLineSettings] = useRecoilState(dimensionLineSettingsState) const [dimensionLineSettings, setDimensionLineSettings] = useRecoilState(dimensionLineSettingsState)
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState) const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
@ -80,10 +69,31 @@ export function useCanvasSetting() {
) )
const [gridColor, setGridColor] = useRecoilState(gridColorState) const [gridColor, setGridColor] = useRecoilState(gridColorState)
const [color, setColor] = useColor(gridColor ?? '#FF0000') const [color, setColor] = useColor(gridColor ?? '#FF0000')
const [colorTemp, setColorTemp] = useState()
const [settingsData, setSettingsData] = useState({
...settingModalFirstOptions,
...settingModalSecondOptions,
...globalFont,
...dotLineGridSetting,
...planSizeSettingMode,
...dimensionLineSettings,
...color,
})
const [settingsDataSave, setSettingsDataSave] = useState()
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { option4 } = settingModalSecondOptions
const corridorDimension = useRecoilValue(corridorDimensionSelector)
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get, post } = useAxios(globalLocaleState)
const { getMessage } = useMessage()
const { swalFire } = useSwal()
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const { getRoofMaterialList } = useMasterController()
const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom)
const SelectOptions = [ const SelectOptions = [
{ id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 }, { id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 },
@ -91,7 +101,15 @@ export function useCanvasSetting() {
{ id: 3, name: '1/4', value: 1 / 4 }, { id: 3, name: '1/4', value: 1 / 4 },
{ id: 4, name: '1/10', value: 1 / 10 }, { id: 4, name: '1/10', value: 1 / 10 },
] ]
const [selectOption, setSelectOption] = useState(SelectOptions[0])
useEffect(() => {
addRoofMaterials()
}, [])
const addRoofMaterials = async () => {
const { data } = await getRoofMaterialList()
setRoofMaterials(data)
}
useEffect(() => { useEffect(() => {
if (!canvas) { if (!canvas) {
@ -132,58 +150,10 @@ export function useCanvasSetting() {
}, [canvasSetting]) }, [canvasSetting])
useEffect(() => { useEffect(() => {
console.log('🚀 ~ useEffect ~ settingsData:', settingsData) console.log('🚀 ~ useEffect ~ settingsDataSave:', settingsDataSave)
if (settingsDataSave !== undefined) onClickOption2()
}, [settingsData]) }, [settingsData])
//흡착점 ON/OFF 변경 시
// useEffect(() => {
// //console.log('useCanvasSetting 실행2', adsorptionPointMode.fontFlag, correntObjectNo)
// if (adsorptionPointMode.fontFlag) {
// onClickOption2()
// }
// }, [adsorptionPointMode])
// 1 과 2 변경 시
// useEffect(() => {
// //console.log('useCanvasSetting 실행3', settingModalFirstOptions.fontFlag, settingModalSecondOptions.fontFlag, correntObjectNo)
// if (settingModalFirstOptions.fontFlag || settingModalSecondOptions.fontFlag) {
// onClickOption2()
// }
// }, [settingModalFirstOptions, settingModalSecondOptions])
// 글꼴 변경 시
// useEffect(() => {
// //console.log('useCanvasSetting 실행4', globalFont.fontFlag, correntObjectNo)
// if (globalFont.fontFlag) {
// onClickOption2()
// }
// }, [globalFont])
// 도명크기 변경 시
// useEffect(() => {
// //console.log('useCanvasSetting 실행5', planSizeSettingMode.flag, correntObjectNo)
// if (planSizeSettingMode.flag) {
// onClickOption2()
// }
// }, [planSizeSettingMode])
// 점/선 그리드 변경 시
// useEffect(() => {
// //console.log('useCanvasSetting 실행6', dotLineGridSetting.flag)
// if (dotLineGridSetting.flag) {
// onClickOption2()
// }
// }, [dotLineGridSetting])
// 그리드 색 설정 변경 시
// useEffect(() => {
// console.log('useCanvasSetting 실행7', colorTemp, gridColor)
// //colorTemp는 변경 전.. 값이 있고 변경된 컬러와 다를 때 실행
// if (colorTemp !== undefined && colorTemp !== gridColor) {
// onClickOption2()
// }
// }, [color])
const getFonts = (itemValue) => { const getFonts = (itemValue) => {
if (!itemValue) return { id: 1, name: 'MS PGothic', value: 'MS PGothic' } if (!itemValue) return { id: 1, name: 'MS PGothic', value: 'MS PGothic' }
const data = [ const data = [
@ -329,7 +299,7 @@ export function useCanvasSetting() {
objectNo: correntObjectNo, objectNo: correntObjectNo,
roofSizeSet: basicSetting.roofSizeSet, roofSizeSet: basicSetting.roofSizeSet,
roofAngleSet: basicSetting.roofAngleSet, roofAngleSet: basicSetting.roofAngleSet,
roofMaterialsAddList: basicSetting.roofs, roofMaterialsAddList: basicSetting.roofs, // TODO : 선택된 roof로 변경해야함
} }
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => { await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
@ -357,18 +327,13 @@ export function useCanvasSetting() {
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item })) const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item }))
//흡착점 ON/OFF //흡착점 ON/OFF
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: res.adsorpPoint, fontFlag: false }) setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: res.adsorpPoint })
//치수선 설정 //치수선 설정
setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor }) setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor })
//도면크기 설정 //도면크기 설정
setPlanSizeSettingMode({ setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical })
...planSizeSettingMode,
originHorizon: res.originHorizon,
originVertical: res.originVertical,
flag: false,
})
// 데이터 설정 // 데이터 설정
setSettingModalFirstOptions({ setSettingModalFirstOptions({
@ -376,13 +341,11 @@ export function useCanvasSetting() {
option1: optionData1, option1: optionData1,
option2: optionData2, option2: optionData2,
dimensionDisplay: optionData5, dimensionDisplay: optionData5,
fontFlag: false,
}) })
setSettingModalSecondOptions({ setSettingModalSecondOptions({
...settingModalSecondOptions, ...settingModalSecondOptions,
option3: optionData3, option3: optionData3,
option4: optionData4, option4: optionData4,
fontFlag: false,
}) })
const fontPatternData = { const fontPatternData = {
@ -421,8 +384,6 @@ export function useCanvasSetting() {
fontSize: getFontSizes(res.lengthFontSize), fontSize: getFontSizes(res.lengthFontSize),
fontColor: getFontColors(res.lengthFontColor), fontColor: getFontColors(res.lengthFontColor),
}, },
//글꼴 설정 Flag
fontFlag: false,
} }
//조회된 글꼴 데이터 set //조회된 글꼴 데이터 set
@ -439,55 +400,43 @@ export function useCanvasSetting() {
}, },
DOT: res.dotGridDisplay, DOT: res.dotGridDisplay,
LINE: res.lineGridDisplay, LINE: res.lineGridDisplay,
flag: false,
} }
const matchedOption = SelectOptions.find((option) => option.value == res.gridDimen)
// dimension 값에 맞는 옵션을 선택
setSelectOption(matchedOption)
setDotLineGridSettingState(patternData) setDotLineGridSettingState(patternData)
//setCurrentSetting(patternData) //setCurrentSetting(patternData)
//그리드 색 설정 //그리드 색 설정
setGridColor(res.gridColor) setGridColor(res.gridColor)
setColorTemp(res.gridColor)
} else { } else {
//조회된 글꼴 데이터가 없는 경우 //조회된 글꼴 데이터가 없는 경우
//흡착점 ON/OFF //흡착점 ON/OFF
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false, fontFlag: false }) setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false })
//치수선 설정 //치수선 설정
setDimensionLineSettings({ ...dimensionLineSettings }) setDimensionLineSettings({ ...dimensionLineSettings })
//도면크기 설정 //도면크기 설정
setPlanSizeSettingMode({ setPlanSizeSettingMode({ ...planSizeSettingMode })
...planSizeSettingMode,
flag: false,
})
// 데이터 설정 // 데이터 설정
setSettingModalFirstOptions({ setSettingModalFirstOptions({
...settingModalFirstOptions, ...settingModalFirstOptions,
fontFlag: false,
}) })
setSettingModalSecondOptions({ setSettingModalSecondOptions({
...settingModalSecondOptions, ...settingModalSecondOptions,
fontFlag: false,
}) })
setGlobalFont({ ...globalFont, fontFlag: false }) setGlobalFont({ ...globalFont })
//점/선 그리드 //점/선 그리드
setDotLineGridSettingState({ ...defaultDotLineGridSetting, flag: false }) setDotLineGridSettingState({ ...defaultDotLineGridSetting })
//setCurrentSetting({ ...defaultDotLineGridSetting }) //setCurrentSetting({ ...defaultDotLineGridSetting })
//그리드 색 설정 //그리드 색 설정
setGridColor('#FF0000') setGridColor('#FF0000')
setColorTemp('#FF0000')
} }
frontSettings() frontSettings()
} catch (error) { } catch (error) {
console.error('Data fetching error:', error) console.error('Data fetching error:', error)
@ -513,9 +462,9 @@ export function useCanvasSetting() {
secondOption2: option4.map((item) => ({ secondOption2: option4.map((item) => ({
column: item.column, column: item.column,
selected: item.selected, selected: item.selected,
range: item.range,
})), })),
} }
// console.log('globalFont', globalFont)
const patternData = { const patternData = {
//견적서 번호 //견적서 번호
objectNo: correntObjectNo, objectNo: correntObjectNo,
@ -543,6 +492,7 @@ export function useCanvasSetting() {
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected, adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
adsorpRangeMedium: dataToSend.secondOption2[2].selected, adsorpRangeMedium: dataToSend.secondOption2[2].selected,
adsorpRangeLarge: dataToSend.secondOption2[3].selected, adsorpRangeLarge: dataToSend.secondOption2[3].selected,
//흡착점 ON/OFF //흡착점 ON/OFF
adsorpPoint: adsorptionPointMode.adsorptionPoint, adsorpPoint: adsorptionPointMode.adsorptionPoint,
//??: adsorptionRange, 사용여부 확인 필요 //??: adsorptionRange, 사용여부 확인 필요
@ -594,14 +544,11 @@ export function useCanvasSetting() {
gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10, gridRatio: dotLineGridSetting.INTERVAL.ratioInterval / 10,
gridDimen: dotLineGridSetting.INTERVAL.dimension, gridDimen: dotLineGridSetting.INTERVAL.dimension,
//gridColor: gridColor.gridColor,
gridColor: gridColor, gridColor: gridColor,
} }
console.log('patternData ', patternData) console.log('patternData ', patternData)
setColorTemp(gridColor)
// HTTP POST 요청 보내기 // HTTP POST 요청 보내기
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }) await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
.then((res) => { .then((res) => {
@ -719,15 +666,13 @@ export function useCanvasSetting() {
setDimensionLineSettings, setDimensionLineSettings,
planSizeSettingMode, planSizeSettingMode,
setPlanSizeSettingMode, setPlanSizeSettingMode,
selectOption,
setSelectOption,
SelectOptions, SelectOptions,
currentSetting, currentSetting,
setCurrentSetting, setCurrentSetting,
dotLineGridSettingState, dotLineGridSettingState,
setSettingModalGridOptions,
setDotLineGridSettingState, setDotLineGridSettingState,
resetDotLineGridSetting, resetDotLineGridSetting,
setSettingModalGridOptions,
gridColor, gridColor,
setGridColor, setGridColor,
color, color,
@ -740,5 +685,7 @@ export function useCanvasSetting() {
basicSettingSave, basicSettingSave,
settingsData, settingsData,
setSettingsData, setSettingsData,
settingsDataSave,
setSettingsDataSave,
} }
} }

View File

@ -840,7 +840,7 @@
"estimate.detail.fileFlg": "後日資料提出", "estimate.detail.fileFlg": "後日資料提出",
"estimate.detail.header.fileList1": "ファイル添付", "estimate.detail.header.fileList1": "ファイル添付",
"estimate.detail.fileList.btn": "ファイル選択", "estimate.detail.fileList.btn": "ファイル選択",
"estimate.detail.fileList.extCheck": "そのファイルはイメージファイルではありません", "estimate.detail.fileList.extCheck": "画像ファイルのみ添付可能.",
"estimate.detail.header.fileList2": "添付ファイル一覧", "estimate.detail.header.fileList2": "添付ファイル一覧",
"estimate.detail.fileList2.btn.return": "復元", "estimate.detail.fileList2.btn.return": "復元",
"estimate.detail.header.specialEstimate": "見積もりの具体的な", "estimate.detail.header.specialEstimate": "見積もりの具体的な",
@ -932,5 +932,6 @@
"simulator.table.sub8": "台", "simulator.table.sub8": "台",
"simulator.table.sub9": "予測発電量 (kWh)", "simulator.table.sub9": "予測発電量 (kWh)",
"simulator.notice.sub1": "Hanwha Japan 年間発電量", "simulator.notice.sub1": "Hanwha Japan 年間発電量",
"simulator.notice.sub2": "シミュレーション案内事項" "simulator.notice.sub2": "シミュレーション案内事項",
"master.moduletypeitem.message.error": "지붕재 코드를 입력하세요."
} }

View File

@ -850,7 +850,7 @@
"estimate.detail.fileFlg": "후일자료제출", "estimate.detail.fileFlg": "후일자료제출",
"estimate.detail.header.fileList1": "파일첨부", "estimate.detail.header.fileList1": "파일첨부",
"estimate.detail.fileList.btn": "파일선택", "estimate.detail.fileList.btn": "파일선택",
"estimate.detail.fileList.extCheck": "해당 파일은 이미지 파일이 아닙니다", "estimate.detail.fileList.extCheck": "이미지 파일만 첨부 가능합니다.",
"estimate.detail.header.fileList2": "첨부파일 목록", "estimate.detail.header.fileList2": "첨부파일 목록",
"estimate.detail.fileList2.btn.return": "복원", "estimate.detail.fileList2.btn.return": "복원",
"estimate.detail.header.specialEstimate": "견적특이사항", "estimate.detail.header.specialEstimate": "견적특이사항",
@ -942,5 +942,6 @@
"simulator.table.sub8": "대", "simulator.table.sub8": "대",
"simulator.table.sub9": "예측발전량 (kWh)", "simulator.table.sub9": "예측발전량 (kWh)",
"simulator.notice.sub1": "Hanwha Japan 연간 발전량", "simulator.notice.sub1": "Hanwha Japan 연간 발전량",
"simulator.notice.sub2": "시뮬레이션 안내사항" "simulator.notice.sub2": "시뮬레이션 안내사항",
"master.moduletypeitem.message.error": "지붕재 코드를 입력하세요."
} }

View File

@ -203,21 +203,16 @@ export const basicSettingState = atom({
default: { default: {
roofSizeSet: 1, roofSizeSet: 1,
roofAngleSet: 'slope', roofAngleSet: 'slope',
roofs: [ selectedRoofMaterial: {},
{
roofApply: true,
roofSeq: 1,
roofType: 1,
roofWidth: 200,
roofHeight: 200,
roofHajebichi: 200,
roofGap: 0,
roofLayout: 'parallel',
},
],
}, },
}) })
// db에 등록된 지붕재 목록
export const roofMaterialsAtom = atom({
key: 'roofMaterialState',
default: [],
})
/** /**
* 현재 선택된 물건 번호 * 현재 선택된 물건 번호
*/ */

View File

@ -117,3 +117,15 @@ export const calculateFlowDirection = (canvasAngle) => {
right: -90 - canvasAngle < -180 ? -90 - canvasAngle + 360 : -90 - canvasAngle, right: -90 - canvasAngle < -180 ? -90 - canvasAngle + 360 : -90 - canvasAngle,
} }
} }
/**
* 자바스크립트 객체로 쿼리스트링 생성
* @param {javascript object} o 쿼리스트링 생성할 객체
* @returns {string} 쿼리스트링
*/
export const getQueryString = (o) => {
const queryString = Object.keys(o)
.map((key) => `${key}=${o[key]}`)
.join('&')
return `?${queryString}`
}