qcast-front/src/hooks/roofcover/useEavesGableEdit.js
2025-05-22 13:31:55 +09:00

247 lines
7.6 KiB
JavaScript

import { useEffect, useRef, useState } from 'react'
import { useRecoilValue } from 'recoil'
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
import { useMessage } from '@/hooks/useMessage'
import { useEvent } from '@/hooks/useEvent'
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
import { useLine } from '@/hooks/useLine'
import { useMode } from '@/hooks/useMode'
import { outerLineFixState } from '@/store/outerLineAtom'
import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup'
import { getChonByDegree } from '@/util/canvas-util'
import { settingModalFirstOptionsState } from '@/store/settingAtom'
// 처마.케라바 변경
export function useEavesGableEdit(id) {
const canvas = useRecoilValue(canvasState)
const { getMessage } = useMessage()
const { addCanvasMouseEventListener, initEvent } = useEvent()
// const { addCanvasMouseEventListener, initEvent } = useContext(EventContext)
const { closePopup } = usePopup()
const TYPES = {
EAVES: 'eaves',
GABLE: 'gable',
WALL_MERGE: 'wall.merge',
SHED: 'shed',
}
const [type, setType] = useState(TYPES.EAVES)
const typeRef = useRef(TYPES.EAVES)
const { removeLine, addPitchTextsByOuterLines } = useLine()
const { swalFire } = useSwal()
const { drawRoofPolygon } = useMode()
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const pitchRef = useRef(null)
const offsetRef = useRef(null)
const widthRef = useRef(null)
const radioTypeRef = useRef('1') // 각 페이지에서 사용하는 radio type
const outerLineFix = useRecoilValue(outerLineFixState)
const buttonMenu = [
{ id: 1, name: getMessage('eaves'), type: TYPES.EAVES },
{ id: 2, name: getMessage('gable'), type: TYPES.GABLE },
{ id: 3, name: getMessage('wall.merge'), type: TYPES.WALL_MERGE },
{ id: 4, name: getMessage('shed'), type: TYPES.SHED },
]
const settingModalFirstOptions = useRecoilValue(settingModalFirstOptionsState)
useEffect(() => {
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
if (outerLines.length === 0) {
swalFire({ text: getMessage('wall.line.not.found') })
closePopup(id)
}
}, [])
useEffect(() => {
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
wallLines.forEach((wallLine) => {
const id = wallLine.id
wallLine.lines = outerLines.filter((line) => line.attributes?.wallId === id)
})
wallLines.forEach((wallLine) => {
convertPolygonToLines(wallLine)
})
addCanvasMouseEventListener('mouse:over', mouseOverEvent)
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
return () => {
canvas.discardActiveObject()
wallLines.forEach((wallLine) => {
convertLinesToPolygon(wallLine)
})
initEvent()
}
}, [])
useEffect(() => {
typeRef.current = type
}, [type])
const mouseOverEvent = (e) => {
if (e.target && e.target.name === 'outerLine') {
e.target.set({
stroke: 'red',
})
e.target.bringToFront()
canvas.renderAll()
} else {
canvas
?.getObjects()
.filter((obj) => obj.name === 'outerLine')
.forEach((line) => {
line.set({
stroke: 'black',
})
line.bringToFront()
})
}
canvas.renderAll()
}
const mouseDownEvent = (e) => {
if (!e.target || (e.target && e.target.name !== 'outerLine')) {
return
}
const target = e.target
let attributes = target.get('attributes')
switch (typeRef.current) {
case TYPES.EAVES:
if (radioTypeRef.current === '1') {
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.EAVES,
pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset: offsetRef.current.value / 10,
}
} else {
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.HIPANDGABLE,
pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset: offsetRef.current.value / 10,
width: widthRef.current.value / 10,
}
}
break
case TYPES.GABLE:
if (radioTypeRef.current === '1') {
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.GABLE,
offset: offsetRef.current.value / 10,
}
} else {
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.JERKINHEAD,
pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset: offsetRef.current.value / 10,
width: widthRef.current.value / 10,
}
}
break
case TYPES.WALL_MERGE:
if (radioTypeRef.current === '1') {
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.WALL,
offset: 0,
}
} else {
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.WALL,
offset: offsetRef.current.value / 10,
}
}
break
case TYPES.SHED:
attributes = {
...attributes,
type: LINE_TYPE.WALLLINE.SHED,
offset: offsetRef.current.value / 10,
}
break
}
target.set({
attributes,
})
const roofBases = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF && !obj.isFixed)
roofBases.forEach((roof) => {
roof.innerLines.forEach((line) => {
removeLine(line)
})
canvas.remove(roof)
})
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'pitchText' || obj.name === 'lengthText')
removeTargets.forEach((obj) => {
canvas.remove(obj)
})
wallLines.forEach((wallLine) => {
addPitchTextsByOuterLines()
const roof = drawRoofPolygon(wallLine)
canvas?.renderAll()
roof.drawHelpLine(settingModalFirstOptions)
})
wallLines.forEach((wallLine) => {
convertPolygonToLines(wallLine)
})
canvas.renderAll()
addCanvasMouseEventListener('mouse:over', mouseOverEvent)
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
}
// polygon의 lines를 이용해 line으로 변경하기
const convertPolygonToLines = (polygon) => {
polygon.set({ visible: false })
polygon.lines.forEach((line) => {
line.set({ visible: true })
line.set({ selectable: true })
line.set({ strokeWidth: 5 })
line.set({ parent: polygon })
line.bringToFront()
})
// canvas objects에서 polygon.lines를 제외한 다른 line의 selectable을 false로 변경
canvas
.getObjects()
.filter((obj) => obj.name !== 'outerLine' && obj.type === 'QLine')
.forEach((obj) => {
obj.set({ selectable: false })
})
canvas?.renderAll()
}
// 다시 다각형으로 변경하기
const convertLinesToPolygon = (polygon) => {
polygon.set({ visible: true })
polygon.lines.forEach((line) => {
line.set({ visible: false })
// line.set({ selectable: false })
})
canvas?.renderAll()
}
return { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }
}