Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
1430b187fa
@ -12,7 +12,7 @@ export default function QContextMenu(props) {
|
||||
let contextType = ''
|
||||
|
||||
if (activeObject) {
|
||||
if (activeObject.initOptions) {
|
||||
if (activeObject.initOptions && activeObject.initOptions.name) {
|
||||
//이건 바뀔 가능성이 있음
|
||||
if (activeObject.initOptions?.name?.indexOf('guide') > -1) {
|
||||
contextType = 'surface' //면형상
|
||||
|
||||
@ -4,20 +4,34 @@ import { useEffect, useState } from 'react'
|
||||
import MenuDepth01 from './MenuDepth01'
|
||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { post } from '@/lib/Axios'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
|
||||
import { canvasZoomState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
||||
import { canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
||||
import { MENU } from '@/common/common'
|
||||
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { toastUp } from '@/hooks/useToast'
|
||||
|
||||
import KO from '@/locales/ko.json'
|
||||
import JA from '@/locales/ja.json'
|
||||
|
||||
export default function CanvasMenu(props) {
|
||||
const [objectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||
const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props
|
||||
const [menuNumber, setMenuNumber] = useState(null)
|
||||
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
|
||||
const [vertical, setVertical] = useState(true)
|
||||
const [type, setType] = useState('')
|
||||
const { getMessage } = useMessage()
|
||||
const canvasZoom = useRecoilValue(canvasZoomState)
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||
const setPoints = useSetRecoilState(outerLinePointsState)
|
||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
||||
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
|
||||
const { post } = useAxios()
|
||||
|
||||
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
||||
const onClickNav = (number) => {
|
||||
setMenuNumber(number)
|
||||
@ -33,7 +47,13 @@ export default function CanvasMenu(props) {
|
||||
const firstOptions = useRecoilState(settingModalFirstOptionsState)
|
||||
const secondOptions = useRecoilState(settingModalSecondOptionsState)
|
||||
|
||||
useEffect(() => {}, [menuNumber, type])
|
||||
useEffect(() => {
|
||||
if (globalLocale === 'ko') {
|
||||
setAppMessageState(KO)
|
||||
} else {
|
||||
setAppMessageState(JA)
|
||||
}
|
||||
}, [menuNumber, type, globalLocale])
|
||||
|
||||
// 저장버튼(btn08) 클릭 시 호출되는 함수
|
||||
const handleSaveSettings = async () => {
|
||||
@ -60,6 +80,7 @@ export default function CanvasMenu(props) {
|
||||
|
||||
const patternData = {
|
||||
objectNo,
|
||||
//디스플레이 설정(다중)
|
||||
assignDisplay: dataToSend.firstOption1[0].selected,
|
||||
drawDisplay: dataToSend.firstOption1[1].selected,
|
||||
gridDisplay: dataToSend.firstOption1[2].selected,
|
||||
@ -71,9 +92,11 @@ export default function CanvasMenu(props) {
|
||||
trestleDisplay: dataToSend.firstOption1[8].selected,
|
||||
coordiDisplay: dataToSend.firstOption1[9].selected,
|
||||
drawConverDisplay: dataToSend.firstOption1[10].selected,
|
||||
//화면 표시(다중)
|
||||
onlyBorder: dataToSend.firstOption2[0].selected,
|
||||
lineHatch: dataToSend.firstOption2[1].selected,
|
||||
allPainted: dataToSend.firstOption2[2].selected,
|
||||
//흡착범위 설정(단건)
|
||||
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
|
||||
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
|
||||
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
|
||||
@ -81,16 +104,19 @@ export default function CanvasMenu(props) {
|
||||
}
|
||||
|
||||
// HTTP POST 요청 보내기
|
||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
|
||||
|
||||
// 응답 처리
|
||||
alert('설정이 저장되었습니다.')
|
||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
|
||||
toastUp({ message: res.returnMessage, type: 'success' })
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('설정을 저장하는 동안 오류가 발생했습니다:', error)
|
||||
alert('설정을 저장하는 중 오류가 발생했습니다.')
|
||||
toastUp({ message: res.returnMessage, type: 'error' })
|
||||
}
|
||||
}
|
||||
|
||||
const handleClear = () => {
|
||||
setPoints([])
|
||||
canvas?.clear()
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||
<div className="canvas-menu-inner">
|
||||
@ -111,6 +137,7 @@ export default function CanvasMenu(props) {
|
||||
className={`canvas-menu-item ${menuNumber === 2 ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
onClickNav(2)
|
||||
setCurrentMenu(MENU.ROOF_COVERING.DEFAULT)
|
||||
}}
|
||||
>
|
||||
<button>
|
||||
@ -118,25 +145,49 @@ export default function CanvasMenu(props) {
|
||||
{getMessage('plan.menu.roof.cover')}
|
||||
</button>
|
||||
</li>
|
||||
<li className={`canvas-menu-item ${menuNumber === 3 ? 'active' : ''}`} onClick={() => onClickNav(3)}>
|
||||
<li
|
||||
className={`canvas-menu-item ${menuNumber === 3 ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
onClickNav(3)
|
||||
setCurrentMenu(MENU.BATCH_CANVAS.DEFAULT)
|
||||
}}
|
||||
>
|
||||
<button>
|
||||
<span className="menu-icon con03"></span>
|
||||
{getMessage('plan.menu.placement.surface')}
|
||||
</button>
|
||||
</li>
|
||||
<li className={`canvas-menu-item ${menuNumber === 4 ? 'active' : ''}`} onClick={() => onClickNav(4)}>
|
||||
<li
|
||||
className={`canvas-menu-item ${menuNumber === 4 ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
onClickNav(4)
|
||||
setCurrentMenu(MENU.MODULE_CIRCUIT_SETTING.DEFAULT)
|
||||
}}
|
||||
>
|
||||
<button>
|
||||
<span className="menu-icon con04"></span>
|
||||
{getMessage('plan.menu.module.circuit.setting')}
|
||||
</button>
|
||||
</li>
|
||||
<li className={`canvas-menu-item ${menuNumber === 5 ? 'active' : ''}`} onClick={() => onClickNav(5)}>
|
||||
<li
|
||||
className={`canvas-menu-item ${menuNumber === 5 ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
onClickNav(5)
|
||||
setCurrentMenu(MENU.ESTIMATE.DEFAULT)
|
||||
}}
|
||||
>
|
||||
<button>
|
||||
<span className="menu-icon con06"></span>
|
||||
{getMessage('plan.menu.estimate')}
|
||||
</button>
|
||||
</li>
|
||||
<li className={`canvas-menu-item ${menuNumber === 6 ? 'active' : ''}`} onClick={() => onClickNav(6)}>
|
||||
<li
|
||||
className={`canvas-menu-item ${menuNumber === 6 ? 'active' : ''}`}
|
||||
onClick={() => {
|
||||
onClickNav(6)
|
||||
setCurrentMenu(MENU.POWER_GENERATION_SIMULATION.DEFAULT)
|
||||
}}
|
||||
>
|
||||
<button>
|
||||
<span className="menu-icon con05"></span>
|
||||
{getMessage('plan.menu.simulation')}
|
||||
@ -171,7 +222,7 @@ export default function CanvasMenu(props) {
|
||||
<button className="control-btn plus"></button>
|
||||
</div>
|
||||
<div className="btn-from">
|
||||
<button className="btn07"></button>
|
||||
<button className="btn07" onClick={handleClear}></button>
|
||||
<button className="btn08" onClick={handleSaveSettings}></button>
|
||||
<button className="btn09"></button>
|
||||
</div>
|
||||
|
||||
@ -3,14 +3,19 @@
|
||||
import { ToggleonMouse } from '@/components/header/Header'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { MENU } from '@/common/common'
|
||||
import { currentMenuState } from '@/store/canvasAtom'
|
||||
import { useSetRecoilState } from 'recoil'
|
||||
|
||||
export default function MenuDepth01(props) {
|
||||
const { setShowOutlineModal, type } = props
|
||||
const { getMessage } = useMessage()
|
||||
const [activeMenu, setActiveMenu] = useState()
|
||||
const onClickMenu = (menuNum) => {
|
||||
setActiveMenu(menuNum)
|
||||
setShowOutlineModal(menuNum === 0)
|
||||
const setCurrentMenu = useSetRecoilState(currentMenuState)
|
||||
const onClickMenu = ({ id, menu, name }) => {
|
||||
setActiveMenu(menu)
|
||||
setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
|
||||
setCurrentMenu(menu)
|
||||
}
|
||||
|
||||
const menus = [
|
||||
@ -26,21 +31,21 @@ export default function MenuDepth01(props) {
|
||||
const menuInfo = {
|
||||
outline: [
|
||||
// 지붕덮개
|
||||
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing' },
|
||||
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting' },
|
||||
{ id: 2, name: 'plan.menu.roof.cover.roof.shape.edit' },
|
||||
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing' },
|
||||
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
|
||||
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
|
||||
{ id: 2, name: 'plan.menu.roof.cover.roof.shape.edit', menu: MENU.ROOF_COVERING.ROOF_SHAPE_EDITING },
|
||||
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
|
||||
],
|
||||
surface: [
|
||||
// 배치면
|
||||
{ id: 0, name: 'plan.menu.placement.surface.drawing' },
|
||||
{ id: 1, name: 'plan.menu.placement.surface.surface' },
|
||||
{ id: 2, name: 'plan.menu.placement.surface.object' },
|
||||
{ id: 0, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
|
||||
{ id: 1, name: 'plan.menu.placement.surface.surface', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
|
||||
{ id: 2, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
|
||||
],
|
||||
module: [
|
||||
// 모듈, 회로 구성
|
||||
{ id: 0, name: 'plan.menu.module.circuit.setting.default' },
|
||||
{ id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting' },
|
||||
{ id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING },
|
||||
{ id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting', menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING },
|
||||
],
|
||||
}
|
||||
|
||||
@ -54,8 +59,8 @@ export default function MenuDepth01(props) {
|
||||
<ul className="canvas-depth2-list">
|
||||
{menuInfo[type].map((menu) => {
|
||||
return (
|
||||
<li key={menu.id} className={`canvas-depth2-item ${menu.id === activeMenu ? 'active' : ''}`}>
|
||||
<button onClick={() => onClickMenu(menu.id)}>{getMessage(menu.name)}</button>
|
||||
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === activeMenu ? 'active' : ''}`}>
|
||||
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
|
||||
@ -8,6 +8,7 @@ import { useEvent } from '@/hooks/useEvent'
|
||||
import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom'
|
||||
import {
|
||||
OUTER_LINE_TYPE,
|
||||
outerLineAngle1State,
|
||||
outerLineArrow1State,
|
||||
outerLineArrow2State,
|
||||
outerLineLength1State,
|
||||
@ -18,16 +19,19 @@ import {
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { useLine } from '@/hooks/useLine'
|
||||
import { distanceBetweenPoints } from '@/util/canvas-util'
|
||||
import { calculateAngle } from '@/util/qpolygon-utils'
|
||||
|
||||
export default function OuterLineWall(props) {
|
||||
const { setShowOutlineModal } = props
|
||||
const { getMessage } = useMessage()
|
||||
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners } = useEvent()
|
||||
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
|
||||
useEvent()
|
||||
const { addLineText, removeLineText } = useLine()
|
||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||
|
||||
const length1Ref = useRef(null)
|
||||
const length2Ref = useRef(null)
|
||||
const angle1Ref = useRef(null)
|
||||
const [length1, setLength1] = useRecoilState(outerLineLength1State)
|
||||
const [length2, setLength2] = useRecoilState(outerLineLength2State)
|
||||
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
|
||||
@ -37,11 +41,16 @@ export default function OuterLineWall(props) {
|
||||
const arrow1Ref = useRef(arrow1)
|
||||
const arrow2Ref = useRef(arrow2)
|
||||
|
||||
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State)
|
||||
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
|
||||
useEffect(() => {
|
||||
removeAllMouseEventListeners()
|
||||
removeMouseEvent('mouse:down', mouseDown)
|
||||
addCanvasMouseEventListener('mouse:down', mouseDown)
|
||||
return () => {
|
||||
removeAllMouseEventListeners()
|
||||
}
|
||||
}, [verticalHorizontalMode, points])
|
||||
|
||||
useEffect(() => {
|
||||
@ -164,6 +173,24 @@ export default function OuterLineWall(props) {
|
||||
}
|
||||
|
||||
if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
|
||||
let isAllRightAngle = true
|
||||
|
||||
const firstPoint = points[0]
|
||||
|
||||
points.forEach((point, idx) => {
|
||||
if (idx === 0 || !isAllRightAngle) {
|
||||
return
|
||||
}
|
||||
|
||||
const angle = calculateAngle(point, firstPoint)
|
||||
if (angle % 90 !== 0) {
|
||||
isAllRightAngle = false
|
||||
}
|
||||
})
|
||||
|
||||
if (isAllRightAngle) {
|
||||
return
|
||||
}
|
||||
const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
|
||||
stroke: 'grey',
|
||||
strokeWidth: 1,
|
||||
@ -423,7 +450,25 @@ export default function OuterLineWall(props) {
|
||||
console.log('leegubae')
|
||||
},
|
||||
angle: (e) => {
|
||||
console.log('angle')
|
||||
const key = e.key
|
||||
switch (key) {
|
||||
case 'Enter': {
|
||||
setPoints((prev) => {
|
||||
if (prev.length === 0) {
|
||||
return []
|
||||
}
|
||||
const lastPoint = prev[prev.length - 1]
|
||||
const length = length1Ref.current.value / 10
|
||||
const angle = angle1Ref.current.value
|
||||
//lastPoint로부터 angle1만큼의 각도로 length1만큼의 길이를 가지는 선을 그림
|
||||
const radian = (angle * Math.PI) / 180
|
||||
|
||||
const x = lastPoint.x + length * Math.cos(radian)
|
||||
const y = lastPoint.y - length * Math.sin(radian)
|
||||
return [...prev, { x, y }]
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
diagonalLine: (e) => {
|
||||
console.log('diagonalLine')
|
||||
@ -442,6 +487,27 @@ export default function OuterLineWall(props) {
|
||||
if (points.length < 3) {
|
||||
return
|
||||
}
|
||||
|
||||
let isAllRightAngle = true
|
||||
|
||||
const firstPoint = points[0]
|
||||
|
||||
points.forEach((point, idx) => {
|
||||
if (idx === 0 || !isAllRightAngle) {
|
||||
return
|
||||
}
|
||||
|
||||
const angle = calculateAngle(point, firstPoint)
|
||||
if (angle % 90 !== 0) {
|
||||
isAllRightAngle = false
|
||||
}
|
||||
})
|
||||
|
||||
if (isAllRightAngle) {
|
||||
alert('부정확한 다각형입니다.')
|
||||
return
|
||||
}
|
||||
|
||||
setPoints((prev) => {
|
||||
if (prev.length === 0) {
|
||||
return []
|
||||
@ -449,6 +515,7 @@ export default function OuterLineWall(props) {
|
||||
return [...prev, { x: prev[0].x, y: prev[0].y }]
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={{ x: 50, y: -1000 + 50 }}>
|
||||
<div className={`modal-pop-wrap ssm`}>
|
||||
@ -501,7 +568,8 @@ export default function OuterLineWall(props) {
|
||||
value={length1}
|
||||
ref={length1Ref}
|
||||
onChange={(e) => {
|
||||
setLength1(e.target.value.replace(/[^-0-9]/g, ''))
|
||||
const value = e.target.value.replace(/^0+/, '')
|
||||
setLength1(value.replace(/[^-0-9]/g, ''))
|
||||
}}
|
||||
placeholder="3000"
|
||||
/>
|
||||
@ -521,7 +589,8 @@ export default function OuterLineWall(props) {
|
||||
value={length1}
|
||||
ref={length1Ref}
|
||||
onChange={(e) => {
|
||||
setLength1(e.target.value.replace(/[^-0-9]/g, ''))
|
||||
const value = e.target.value.replace(/^0+/, '')
|
||||
setLength1(value.replace(/[^-0-9]/g, ''))
|
||||
}}
|
||||
placeholder="3000"
|
||||
/>
|
||||
@ -538,7 +607,8 @@ export default function OuterLineWall(props) {
|
||||
value={length2}
|
||||
ref={length2Ref}
|
||||
onChange={(e) => {
|
||||
setLength2(e.target.value.replace(/[^-0-9]/g, ''))
|
||||
const value = e.target.value.replace(/^0+/, '')
|
||||
setLength2(value.replace(/[^-0-9]/g, ''))
|
||||
}}
|
||||
placeholder="3000"
|
||||
/>
|
||||
@ -548,6 +618,44 @@ export default function OuterLineWall(props) {
|
||||
<input type="text" readOnly={true} value={arrow2} className="input-origin block" />
|
||||
</div>
|
||||
</div>
|
||||
) : type === OUTER_LINE_TYPE.ANGLE ? (
|
||||
<div className="outer-line-wrap">
|
||||
<div className="form-input">
|
||||
<label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={length1}
|
||||
ref={length1Ref}
|
||||
onChange={(e) => {
|
||||
const value = e.target.value.replace(/^0+/, '')
|
||||
setLength1(value.replace(/[^-0-9]/g, ''))
|
||||
}}
|
||||
placeholder="3000"
|
||||
/>
|
||||
</div>
|
||||
<div className="form-input">
|
||||
<label htmlFor="">{getMessage('modal.cover.outline.angle')}</label>
|
||||
<input
|
||||
type="text"
|
||||
value={angle1}
|
||||
ref={angle1Ref}
|
||||
onChange={(e) => {
|
||||
const val = e.target.value
|
||||
// const pattern = /(^\d+$)|(^\d{1,}.\d{0,2}$)/
|
||||
const pattern = /^-?(\d{1,3}([.]\d{0,2})?)?$/
|
||||
if (!pattern.test(val)) {
|
||||
// prev에서 마지막 자리 제거
|
||||
setAngle1(val.slice(0, val.length - 1))
|
||||
return
|
||||
}
|
||||
|
||||
setAngle1(val)
|
||||
}}
|
||||
className="input-origin block"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
@ -1,28 +1,24 @@
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { get } from '@/lib/Axios'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
|
||||
export default function FirstOption() {
|
||||
const [objectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
|
||||
const { option1, option2 } = settingsModalOptions
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
|
||||
const { get } = useAxios()
|
||||
|
||||
// 데이터를 최초 한 번만 조회
|
||||
useEffect(() => {
|
||||
console.log('FirstOption useEffect 실행')
|
||||
if (!isFetched) {
|
||||
// 조회가 안 되었을 때만 fetchSettings 실행
|
||||
fetchSettings()
|
||||
}
|
||||
}, [isFetched]) // isFetched 상태가 변할 때마다 확인
|
||||
fetchSettings()
|
||||
}, [objectNo])
|
||||
|
||||
// Canvas Setting 조회 및 초기화
|
||||
const fetchSettings = async () => {
|
||||
const fetchSettings = useCallback(async () => {
|
||||
try {
|
||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
||||
|
||||
@ -49,12 +45,10 @@ export default function FirstOption() {
|
||||
option1,
|
||||
option2,
|
||||
})
|
||||
|
||||
setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
|
||||
} catch (error) {
|
||||
console.error('Data fetching error:', error)
|
||||
}
|
||||
}
|
||||
}, [objectNo])
|
||||
|
||||
const onClickOption = (option) => {
|
||||
option.selected = !option.selected
|
||||
@ -67,23 +61,25 @@ export default function FirstOption() {
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title light">{getMessage('modal.canvas.setting.first.option.info')}</h3>
|
||||
<div className="flex-check-box for2">
|
||||
{settingsModalOptions?.option1?.map((item) => (
|
||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
{settingsModalOptions &&
|
||||
settingsModalOptions.option1.map((item) => (
|
||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.first.option.display')}</h3>
|
||||
<div className="flex-check-box for-line">
|
||||
{settingsModalOptions?.option2?.map((item) => (
|
||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
{settingsModalOptions &&
|
||||
settingsModalOptions.option2.map((item) => (
|
||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -1,27 +1,24 @@
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { settingModalSecondOptionsState } from '@/store/settingAtom'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { get } from '@/lib/Axios'
|
||||
import React, { useCallback, useEffect, useState } from 'react'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
|
||||
export default function SecondOption() {
|
||||
const [objectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
|
||||
const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
|
||||
const { option1, option2 } = settingsModalOptions
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
|
||||
const { get } = useAxios()
|
||||
|
||||
// 데이터를 최초 한 번만 조회
|
||||
useEffect(() => {
|
||||
console.log('SecondOption useEffect 실행')
|
||||
if (!isFetched) {
|
||||
// 조회가 안 되었을 때만 fetchSettings 실행
|
||||
fetchSettings()
|
||||
}
|
||||
}, [isFetched]) // isFetched 상태가 변할 때마다 확인
|
||||
fetchSettings()
|
||||
}, [objectNo])
|
||||
|
||||
const fetchSettings = async () => {
|
||||
// Canvas Setting 조회 및 초기화
|
||||
const fetchSettings = useCallback(async () => {
|
||||
try {
|
||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
|
||||
|
||||
@ -36,12 +33,10 @@ export default function SecondOption() {
|
||||
option1,
|
||||
option2,
|
||||
})
|
||||
|
||||
setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
|
||||
} catch (error) {
|
||||
console.error('Data fetching error:', error)
|
||||
}
|
||||
}
|
||||
}, [objectNo])
|
||||
|
||||
const onClickOption = (option) => {
|
||||
// option2에서 한 개만 선택 가능하도록 처리
|
||||
@ -54,22 +49,24 @@ export default function SecondOption() {
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.edit')}</h3>
|
||||
<div className="flex-check-box for2">
|
||||
{settingsModalOptions.option1.map((item, index) => (
|
||||
<button key={item.id || index} className="arr-btn">
|
||||
<span>{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
{settingsModalOptions &&
|
||||
settingsModalOptions.option1.map((item) => (
|
||||
<button key={item.id} className="arr-btn">
|
||||
<span>{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-check-btn-wrap">
|
||||
<h3 className="check-wrap-title">{getMessage('modal.canvas.setting.font.plan.absorption')}</h3>
|
||||
<div className="flex-check-box for-line">
|
||||
{settingsModalOptions.option2.map((item, index) => (
|
||||
<button key={item.id || index} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={() => onClickOption(item)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
{settingsModalOptions &&
|
||||
settingsModalOptions.option2.map((item) => (
|
||||
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={() => onClickOption(item)}>
|
||||
<span className="check-area"></span>
|
||||
<span className="title-area">{getMessage(item.name)}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="flex-check-box for-line">
|
||||
<button className="arr-btn">
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { canvasState, canvasZoomState, currentMenuState } from '@/store/canvasAtom'
|
||||
import { fabric } from 'fabric'
|
||||
|
||||
@ -8,7 +8,7 @@ export function useEvent() {
|
||||
const currentMenu = useRecoilValue(currentMenuState)
|
||||
const keyboardEventListeners = useRef([])
|
||||
const mouseEventListeners = useRef([])
|
||||
const setCanvasZoom = useSetRecoilState(canvasZoomState)
|
||||
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||
|
||||
useEffect(() => {
|
||||
if (!canvas) {
|
||||
@ -16,6 +16,13 @@ export function useEvent() {
|
||||
}
|
||||
removeAllMouseEventListeners()
|
||||
removeAllDocumentEventListeners()
|
||||
|
||||
/**
|
||||
* wheelEvent
|
||||
*/
|
||||
canvas?.off('mouse:wheel')
|
||||
canvas?.on('mouse:wheel', wheelEvent)
|
||||
|
||||
addDefaultEvent()
|
||||
}, [currentMenu, canvas])
|
||||
|
||||
@ -23,7 +30,7 @@ export function useEvent() {
|
||||
//default Event 추가
|
||||
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
||||
addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent)
|
||||
addCanvasMouseEventListener('mouse:wheel', wheelEvent)
|
||||
|
||||
addDocumentEventListener('keydown', document, defaultKeyboardEvent)
|
||||
}
|
||||
|
||||
@ -126,10 +133,21 @@ export function useEvent() {
|
||||
keyboardEventListeners.current.length = 0 // 배열 초기화
|
||||
}
|
||||
|
||||
const removeMouseEvent = (type, handler) => {
|
||||
mouseEventListeners.current = mouseEventListeners.current.filter((event) => {
|
||||
if (event.type === type && event.handler === handler) {
|
||||
canvas.off(type, handler)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
addDocumentEventListener,
|
||||
addCanvasMouseEventListener,
|
||||
removeAllMouseEventListeners,
|
||||
removeAllDocumentEventListeners,
|
||||
removeMouseEvent,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1280,13 +1280,44 @@ export function useMode() {
|
||||
}
|
||||
|
||||
const templateSideMode = () => {
|
||||
changeMode(canvas, Mode.EDIT)
|
||||
|
||||
if (historyPoints.current.length >= 4) {
|
||||
const wall = drawWallPolygon()
|
||||
setWall(wall)
|
||||
const firstPoint = historyPoints.current[0]
|
||||
const lastPoint = historyPoints.current[historyPoints.current.length - 1]
|
||||
historyPoints.current.forEach((point) => {
|
||||
canvas?.remove(point)
|
||||
})
|
||||
drawLineWithLength(lastPoint, firstPoint)
|
||||
|
||||
console.log('sideWall', wall)
|
||||
// 캔버스에서 모든 라인 객체를 찾습니다.
|
||||
const lines = historyLines.current
|
||||
historyLines.current = []
|
||||
|
||||
// 각 라인의 시작점과 끝점을 사용하여 다각형의 점 배열을 생성합니다.
|
||||
const points = lines.map((line) => ({ x: line.x1, y: line.y1 }))
|
||||
|
||||
// 모든 라인 객체를 캔버스에서 제거합니다.
|
||||
lines.forEach((line) => {
|
||||
canvas?.remove(line)
|
||||
})
|
||||
|
||||
// 점 배열을 사용하여 새로운 다각형 객체를 생성합니다.
|
||||
const polygon = new QPolygon(
|
||||
points,
|
||||
{
|
||||
stroke: 'black',
|
||||
fill: 'transparent',
|
||||
viewLengthText: true,
|
||||
fontSize: 15,
|
||||
selectable: true,
|
||||
},
|
||||
canvas,
|
||||
)
|
||||
|
||||
// 새로운 다각형 객체를 캔버스에 추가합니다.
|
||||
canvas.add(polygon)
|
||||
|
||||
changeMode(canvas, Mode.DEFAULT)
|
||||
return polygon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user