This commit is contained in:
minsik 2024-10-28 15:08:52 +09:00
commit 293471411e
45 changed files with 405 additions and 165 deletions

View File

@ -0,0 +1,3 @@
export default function EstimatePage() {
return <div>이자리....</div>
}

View File

@ -1,11 +1,17 @@
'use client' 'use client'
import FloorPlan from '@/components/floor-plan/FloorPlan'
import { FloorPlanProvider } from './FloorPlanProvider' import { FloorPlanProvider } from './FloorPlanProvider'
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
export default function FloorPlanLayout({ children }) { export default function FloorPlanLayout({ children }) {
console.log('FloorPlanLayout') console.log('FloorPlanLayout')
return ( return (
<> <>
<FloorPlanProvider>{children}</FloorPlanProvider> <FloorPlanProvider>
<FloorPlan>
<CanvasLayout>{children}</CanvasLayout>
</FloorPlan>
</FloorPlanProvider>
</> </>
) )
} }

View File

@ -1,9 +1,10 @@
import CanvasFrame from '@/components/floor-plan/CanvasFrame'
import FloorPlan from '@/components/floor-plan/FloorPlan' import FloorPlan from '@/components/floor-plan/FloorPlan'
export default function FloorPlanPage() { export default function FloorPlanPage() {
return ( return (
<> <>
<FloorPlan /> <CanvasFrame />
</> </>
) )
} }

View File

@ -12,7 +12,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
idx: 0, idx: 0,
area: 0, area: 0,
children: [], children: [],
initialize: function (points, options, canvas) { initialize: function (points, options, length = 0) {
this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true }) this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true })
if (options.id) { if (options.id) {
this.id = options.id this.id = options.id
@ -27,7 +27,11 @@ export const QLine = fabric.util.createClass(fabric.Line, {
this.idx = options.idx ?? 0 this.idx = options.idx ?? 0
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
this.setLength() if (length !== 0) {
this.length = length
} else {
this.setLength()
}
this.startPoint = { x: this.x1, y: this.y1 } this.startPoint = { x: this.x1, y: this.y1 }
this.endPoint = { x: this.x2, y: this.y2 } this.endPoint = { x: this.x2, y: this.y2 }
@ -148,7 +152,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
getLength() { getLength() {
//10배 곱해진 값 return //10배 곱해진 값 return
return Number(this.length.toFixed(2) * 10) return Number(this.length.toFixed(1)) * 10
}, },
setViewLengthText(bool) { setViewLengthText(bool) {

View File

@ -183,7 +183,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
const end = points[(i + 1) % points.length] const end = points[(i + 1) % points.length]
const dx = end.x - start.x const dx = end.x - start.x
const dy = end.y - start.y const dy = end.y - start.y
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(2)) * 10 const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10
let midPoint let midPoint

View File

@ -15,7 +15,7 @@ import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitial
import { MENU } from '@/common/common' import { MENU } from '@/common/common'
import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics' import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics'
export default function CanvasFrame({ plan }) { export default function CanvasFrame() {
const canvasRef = useRef(null) const canvasRef = useRef(null)
const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState) const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState)
const { canvas } = useCanvas('canvas') const { canvas } = useCanvas('canvas')
@ -24,14 +24,14 @@ export default function CanvasFrame({ plan }) {
const currentObject = useRecoilValue(currentObjectState) const currentObject = useRecoilValue(currentObjectState)
const currentMenu = useRecoilValue(currentMenuState) const currentMenu = useRecoilValue(currentMenuState)
const { contextMenu, handleClick, handleKeyup } = useContextMenu() const { contextMenu, handleClick, handleKeyup } = useContextMenu()
const { checkCanvasObjectEvent, checkUnsavedCanvasPlan, resetModifiedPlans } = usePlan() const { selectedPlan, checkCanvasObjectEvent, checkUnsavedCanvasPlan, resetModifiedPlans } = usePlan()
useEvent() useEvent()
const loadCanvas = () => { const loadCanvas = () => {
if (canvas) { if (canvas) {
canvas?.clear() // . canvas?.clear() // .
if (plan?.canvasStatus) { if (selectedPlan?.canvasStatus) {
canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () { canvas?.loadFromJSON(JSON.parse(selectedPlan.canvasStatus), function () {
canvasLoadInit() //config canvasLoadInit() //config
canvas?.renderAll() // . canvas?.renderAll() // .
}) })
@ -41,15 +41,15 @@ export default function CanvasFrame({ plan }) {
} }
useEffect(() => { useEffect(() => {
if (modifiedPlanFlag && plan?.id) { if (modifiedPlanFlag && selectedPlan?.id) {
checkCanvasObjectEvent(plan.id) checkCanvasObjectEvent(selectedPlan.id)
} }
}, [modifiedPlanFlag]) }, [modifiedPlanFlag])
useEffect(() => { useEffect(() => {
loadCanvas() loadCanvas()
resetModifiedPlans() resetModifiedPlans()
}, [plan, canvas]) }, [selectedPlan, canvas])
return ( return (
<div className="canvas-frame"> <div className="canvas-frame">

View File

@ -9,9 +9,11 @@ import { usePlan } from '@/hooks/usePlan'
import { modifiedPlansState } from '@/store/canvasAtom' import { modifiedPlansState } from '@/store/canvasAtom'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { SessionContext } from '@/app/SessionProvider' import { SessionContext } from '@/app/SessionProvider'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
export default function CanvasLayout(props) { export default function CanvasLayout({ children }) {
const { menuNumber } = props // const { menuNumber } = props
const { menuNumber } = useCanvasMenu()
const { session } = useContext(SessionContext) const { session } = useContext(SessionContext)
const [objectNo, setObjectNo] = useState('test123240822001') // const [objectNo, setObjectNo] = useState('test123240822001') //
const [modifiedPlans, setModifiedPlans] = useRecoilState(modifiedPlansState) // canvas plan const [modifiedPlans, setModifiedPlans] = useRecoilState(modifiedPlansState) // canvas plan
@ -60,7 +62,7 @@ export default function CanvasLayout(props) {
</button> </button>
)} )}
</div> </div>
<CanvasFrame plan={plans.find((plan) => plan.isCurrent === true)} /> {children}
</div> </div>
) )
} }

View File

@ -7,16 +7,18 @@ import { globalLocaleStore } from '@/store/localeAtom'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import CanvasMenu from '@/components/floor-plan/CanvasMenu' import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import CanvasLayout from '@/components/floor-plan/CanvasLayout' import CanvasLayout from '@/components/floor-plan/CanvasLayout'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import '@/styles/contents.scss' import '@/styles/contents.scss'
export default function FloorPlan() { export default function FloorPlan({ children }) {
const globalLocaleState = useRecoilValue(globalLocaleStore) const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get } = useAxios(globalLocaleState) const { get } = useAxios(globalLocaleState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const [objectNo, setObjectNo] = useState('test123240912001') // const [objectNo, setObjectNo] = useState('test123240912001') //
const [menuNumber, setMenuNumber] = useState(null) // const [menuNumber, setMenuNumber] = useState(null)
const { menuNumber, setMenuNumber } = useCanvasMenu()
const modalProps = { const modalProps = {
menuNumber, menuNumber,
@ -57,9 +59,7 @@ export default function FloorPlan() {
<> <>
<div className="canvas-wrap"> <div className="canvas-wrap">
<CanvasMenu {...modalProps} /> <CanvasMenu {...modalProps} />
<div className={`canvas-content ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}> <div className={`canvas-content ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>{children}</div>
<CanvasLayout menuNumber={menuNumber} />
</div>
</div> </div>
</> </>
) )

View File

@ -1,6 +1,6 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import { globalPitchState } from '@/store/canvasAtom' import { globalPitchState, pitchSelector, pitchTextSelector } from '@/store/canvasAtom'
import { useRecoilState } from 'recoil' import { useRecoilState } from 'recoil'
import { useRef } from 'react' import { useRef } from 'react'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
@ -8,7 +8,8 @@ import { usePopup } from '@/hooks/usePopup'
export default function Slope({ id, pos = { x: 50, y: 230 } }) { export default function Slope({ id, pos = { x: 50, y: 230 } }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
const [globalPitch, setGlobalPitch] = useRecoilState(globalPitchState) const [globalPitch, setGlobalPitch] = useRecoilState(pitchSelector)
const pitchText = useRecoilState(pitchTextSelector)
const inputRef = useRef() const inputRef = useRef()
return ( return (
@ -29,7 +30,7 @@ export default function Slope({ id, pos = { x: 50, y: 230 } }) {
<div className="input-grid mr5"> <div className="input-grid mr5">
<input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} /> <input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} />
</div> </div>
<span className="thin">{getMessage('size.angle')}</span> <span className="thin">{pitchText}</span>
</div> </div>
</div> </div>
<div className="grid-btn-wrap"> <div className="grid-btn-wrap">

View File

@ -11,12 +11,13 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } = useEavesGableEdit(id) const { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef, pitchText } = useEavesGableEdit(id)
const eavesProps = { const eavesProps = {
pitchRef, pitchRef,
offsetRef, offsetRef,
widthRef, widthRef,
radioTypeRef, radioTypeRef,
pitchText,
} }
const gableProps = { const gableProps = {
@ -24,6 +25,7 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
offsetRef, offsetRef,
widthRef, widthRef,
radioTypeRef, radioTypeRef,
pitchText,
} }
const wallMergeProps = { const wallMergeProps = {

View File

@ -1,14 +1,17 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import Image from 'next/image' import Image from 'next/image'
import { useState } from 'react' import { useState } from 'react'
import { useRecoilValue } from 'recoil'
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) { export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [type, setType] = useState('1') const [type, setType] = useState('1')
const onChange = (e) => { const onChange = (e) => {
setType(e.target.value) setType(e.target.value)
radioTypeRef.current = e.target.value radioTypeRef.current = e.target.value
} }
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
return ( return (
<> <>
<div className="outline-wrap"> <div className="outline-wrap">
@ -17,9 +20,9 @@ export default function Eaves({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
{getMessage('slope')} {getMessage('slope')}
</span> </span>
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="number" className="input-origin block" defaultValue={4} ref={pitchRef} /> <input type="number" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
</div> </div>
<span className="thin"></span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span className="mr10" style={{ width: '24px' }}> <span className="mr10" style={{ width: '24px' }}>

View File

@ -1,14 +1,18 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import Image from 'next/image' import Image from 'next/image'
import { useState } from 'react' import { useState } from 'react'
import { useRecoilValue } from 'recoil'
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) { export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [type, setType] = useState('1') const [type, setType] = useState('1')
const onChange = (e) => { const onChange = (e) => {
setType(e.target.value) setType(e.target.value)
radioTypeRef.current = e.target.value radioTypeRef.current = e.target.value
} }
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
return ( return (
<> <>
<div className="outline-wrap"> <div className="outline-wrap">
@ -57,9 +61,15 @@ export default function Gable({ pitchRef, offsetRef, widthRef, radioTypeRef }) {
{getMessage('slope')} {getMessage('slope')}
</span> </span>
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={4.5} ref={pitchRef} readOnly={type === '1'} /> <input
type="text"
className="input-origin block"
defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4.5 : 20}
ref={pitchRef}
readOnly={type === '1'}
/>
</div> </div>
<span className="thin"></span> <span className="thin">{pitchText}</span>
</div> </div>
</div> </div>
<div className="eaves-keraba-td"> <div className="eaves-keraba-td">

View File

@ -8,6 +8,7 @@ import { useMessage } from '@/hooks/useMessage'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { basicSettingState } from '@/store/settingAtom'
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
const [objectNo, setObjectNo] = useState('test123241008001') // const [objectNo, setObjectNo] = useState('test123241008001') //
@ -16,22 +17,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(1) const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(1)
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const [basicSetting, setBasicSettings] = useState({ const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
roofSizeSet: 1,
roofAngleSet: 'slope',
roofs: [
{
roofApply: true,
roofSeq: 1,
roofType: 1,
roofWidth: 200,
roofHeight: 200,
roofHajebichi: 200,
roofGap: 0,
roofLayout: 'parallel',
},
],
})
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { get, post } = useAxios() const { get, post } = useAxios()

View File

@ -7,18 +7,21 @@ import { useRoofShapePassivitySetting } from '@/hooks/roofcover/useRoofShapePass
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 } }) { export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 } }) {
const { handleSave, handleConfirm, handleRollback, buttons, type, setType, TYPES, offsetRef, pitchRef } = useRoofShapePassivitySetting(id) const { handleSave, handleConfirm, handleRollback, buttons, type, setType, TYPES, offsetRef, pitchRef, pitchText } =
useRoofShapePassivitySetting(id)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
const eavesProps = { const eavesProps = {
offsetRef, offsetRef,
pitchRef, pitchRef,
pitchText,
} }
const gableProps = { const gableProps = {
offsetRef, offsetRef,
pitchRef, pitchRef,
pitchText,
} }
const shedProps = { const shedProps = {

View File

@ -38,11 +38,12 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
buttonMenu, buttonMenu,
handleConfirm, handleConfirm,
handleRollBack, handleRollBack,
pitchText,
} = useRoofShapeSetting(id) } = useRoofShapeSetting(id)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const ridgeProps = { pitch, setPitch, eavesOffset, setEavesOffset } const ridgeProps = { pitch, setPitch, eavesOffset, setEavesOffset, pitchText }
const patternProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset } const patternProps = { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, pitchText }
const sideProps = { const sideProps = {
pitch, pitch,
setPitch, setPitch,
@ -67,6 +68,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
buttonMenu, buttonMenu,
handleConfirm, handleConfirm,
handleRollBack, handleRollBack,
pitchText,
} }
const directionProps = { const directionProps = {
@ -78,6 +80,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
setGableOffset, setGableOffset,
shedWidth, shedWidth,
setShedWidth, setShedWidth,
pitchText,
} }
return ( return (

View File

@ -1,7 +1,10 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRecoilValue } from 'recoil'
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
export default function Eaves({ offsetRef, pitchRef }) { export default function Eaves({ offsetRef, pitchRef, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
return ( return (
<> <>
<div className="outline-form mb10"> <div className="outline-form mb10">
@ -9,9 +12,9 @@ export default function Eaves({ offsetRef, pitchRef }) {
{getMessage('slope')} {getMessage('slope')}
</span> </span>
<div className="input-grid mr5"> <div className="input-grid mr5">
<input type="text" className="input-origin block" defaultValue={4} ref={pitchRef} /> <input type="text" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
</div> </div>
<span className="thin"></span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form mb10"> <div className="outline-form mb10">
<span className="mr10" style={{ width: '63px' }}> <span className="mr10" style={{ width: '63px' }}>

View File

@ -1,7 +1,10 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRecoilValue } from 'recoil'
import { ANGLE_TYPE, currentAngleTypeSelector } from '@/store/canvasAtom'
export default function Gable({ offsetRef, pitchRef }) { export default function Gable({ offsetRef, pitchRef, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
return ( return (
<> <>
<div className="outline-form mb10"> <div className="outline-form mb10">
@ -9,9 +12,9 @@ export default function Gable({ offsetRef, pitchRef }) {
{getMessage('slope')} {getMessage('slope')}
</span> </span>
<div className="input-grid mr5"> <div className="input-grid mr5">
<input type="text" className="input-origin block" defaultValue={4} ref={pitchRef} /> <input type="text" className="input-origin block" defaultValue={currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8} ref={pitchRef} />
</div> </div>
<span className="thin"></span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form mb10"> <div className="outline-form mb10">
<span className="mr10" style={{ width: '63px' }}> <span className="mr10" style={{ width: '63px' }}>

View File

@ -1,7 +1,7 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth }) { export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, shedWidth, setShedWidth, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
return ( return (
<div className="setting-box"> <div className="setting-box">
@ -12,7 +12,7 @@ export default function Direction({ pitch, setPitch, eavesOffset, setEavesOffset
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} /> <input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
</div> </div>
<span className="thin">{getMessage('size')}</span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form mb10"> <div className="outline-form mb10">
<span className="mr10" style={{ width: '60px' }}> <span className="mr10" style={{ width: '60px' }}>

View File

@ -3,7 +3,7 @@ import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/inpu
export default function Pattern(props) { export default function Pattern(props) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset } = props const { pitch, setPitch, eavesOffset, setEavesOffset, gableOffset, setGableOffset, pitchText } = props
return ( return (
<div className="setting-box"> <div className="setting-box">
<div className="outline-form mb10"> <div className="outline-form mb10">
@ -13,7 +13,7 @@ export default function Pattern(props) {
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} /> <input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
</div> </div>
<span className="thin"> {getMessage('size')}</span> <span className="thin"> {pitchText}</span>
</div> </div>
<div className="outline-form mb10"> <div className="outline-form mb10">
<span className="mr10" style={{ width: '60px' }}> <span className="mr10" style={{ width: '60px' }}>

View File

@ -4,7 +4,7 @@ import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/inpu
export default function Ridge(props) { export default function Ridge(props) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { pitch, setPitch, eavesOffset, setEavesOffset } = props const { pitch, setPitch, eavesOffset, setEavesOffset, pitchText } = props
return ( return (
<div className="setting-box"> <div className="setting-box">
@ -15,7 +15,7 @@ export default function Ridge(props) {
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} /> <input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
</div> </div>
<span className="thin">{getMessage('size')}</span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span className="mr10" style={{ width: '24px' }}> <span className="mr10" style={{ width: '24px' }}>

View File

@ -32,13 +32,14 @@ export default function Side(props) {
buttonMenu, buttonMenu,
handleConfirm, handleConfirm,
handleRollBack, handleRollBack,
pitchText,
} = props } = props
const eavesProps = { pitch, setPitch, eavesOffset, setEavesOffset } const eavesProps = { pitch, setPitch, eavesOffset, setEavesOffset, pitchText }
const gableProps = { gableOffset, setGableOffset } const gableProps = { gableOffset, setGableOffset }
const wallProps = { sleeveOffset, setSleeveOffset, hasSleeve, setHasSleeve } const wallProps = { sleeveOffset, setSleeveOffset, hasSleeve, setHasSleeve }
const hipAndGableProps = { pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth } const hipAndGableProps = { pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth, pitchText }
const jerkinheadProps = { gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch } const jerkinheadProps = { gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch, pitchText }
const shedProps = { shedWidth, setShedWidth } const shedProps = { shedWidth, setShedWidth }
const { getMessage } = useMessage() const { getMessage } = useMessage()

View File

@ -1,7 +1,7 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset }) { export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
return ( return (
<> <>
@ -12,7 +12,7 @@ export default function Eaves({ pitch, setPitch, eavesOffset, setEavesOffset })
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} /> <input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
</div> </div>
<span className="thin">{getMessage('size')}</span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span className="mr10" style={{ width: '24px' }}> <span className="mr10" style={{ width: '24px' }}>

View File

@ -1,7 +1,7 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth }) { export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffset, hipAndGableWidth, setHipAndGableWidth, pitchText }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
return ( return (
<> <>
@ -12,7 +12,7 @@ export default function HipAndGable({ pitch, setPitch, eavesOffset, setEavesOffs
<div className="input-grid mr5" style={{ width: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} /> <input type="text" className="input-origin block" value={pitch} onChange={(e) => onlyNumberWithDotInputChange(e, setPitch)} />
</div> </div>
<span className="thin">{getMessage('size')}</span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form mb10"> <div className="outline-form mb10">
<span className="mr10" style={{ width: '60px' }}> <span className="mr10" style={{ width: '60px' }}>

View File

@ -1,7 +1,15 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
export default function Jerkinhead({ gableOffset, setGableOffset, jerkinHeadWidth, setJerkinHeadWidth, jerkinHeadPitch, setJerkinHeadPitch }) { export default function Jerkinhead({
gableOffset,
setGableOffset,
jerkinHeadWidth,
setJerkinHeadWidth,
jerkinHeadPitch,
setJerkinHeadPitch,
pitchText,
}) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
return ( return (
<> <>
@ -35,7 +43,7 @@ export default function Jerkinhead({ gableOffset, setGableOffset, jerkinHeadWidt
onChange={(e) => onlyNumberWithDotInputChange(e, setJerkinHeadPitch)} onChange={(e) => onlyNumberWithDotInputChange(e, setJerkinHeadPitch)}
/> />
</div> </div>
<span className="thin">{getMessage('size')}</span> <span className="thin">{pitchText}</span>
</div> </div>
</> </>
) )

View File

@ -33,8 +33,8 @@ export default function Stuff() {
const { get } = useAxios(globalLocaleState) const { get } = useAxios(globalLocaleState)
const gridRef = useRef() const gridRef = useRef()
const [selectedRowData, setSelectedRowData] = useState([]) // const [selectedRowData, setSelectedRowData] = useState([])
const [selectedRowDataCount, setSelectedRowDataCount] = useState(0) // const [selectedRowDataCount, setSelectedRowDataCount] = useState(0)
const router = useRouter() const router = useRouter()
const pathname = usePathname() const pathname = usePathname()
@ -165,11 +165,11 @@ export default function Stuff() {
} }
} }
// //
const getSelectedRowdata = (data) => { // const getSelectedRowdata = (data) => {
setSelectedRowData(data) // setSelectedRowData(data)
setSelectedRowDataCount(data.length) // setSelectedRowDataCount(data.length)
} // }
// //
// const fnDeleteRowData = (data) => { // const fnDeleteRowData = (data) => {
@ -405,8 +405,8 @@ export default function Stuff() {
<span>{convertNumberToPriceDecimal(totalCount)}</span> <span>{convertNumberToPriceDecimal(totalCount)}</span>
</li> </li>
<li> <li>
{getMessage('stuff.search.grid.selected')} {/* {getMessage('stuff.search.grid.selected')} */}
<span className="red">{convertNumberToPriceDecimal(selectedRowDataCount)}</span> {/* <span className="red">{convertNumberToPriceDecimal(selectedRowDataCount)}</span> */}
</li> </li>
</ul> </ul>
</div> </div>
@ -428,7 +428,7 @@ export default function Stuff() {
</div> </div>
<div className="grid-table-wrap"> <div className="grid-table-wrap">
<div className="q-grid"> <div className="q-grid">
<StuffQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} getCellDoubleClicked={getCellDoubleClicked} gridRef={gridRef} /> <StuffQGrid {...gridProps} getCellDoubleClicked={getCellDoubleClicked} gridRef={gridRef} />
<div className="pagination-wrap"> <div className="pagination-wrap">
<QPagination pageNo={pageNo} pageSize={pageSize} pagePerBlock={10} totalCount={totalCount} handleChangePage={handleChangePage} /> <QPagination pageNo={pageNo} pageSize={pageSize} pagePerBlock={10} totalCount={totalCount} handleChangePage={handleChangePage} />
</div> </div>

View File

@ -10,15 +10,18 @@ import { globalLocaleStore } from '@/store/localeAtom'
import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty } from '@/util/common-utils' import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty } 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 } from 'recoil' import { useRecoilValue, useSetRecoilState } from 'recoil'
import { sessionStore } from '@/store/commonAtom' import { sessionStore } from '@/store/commonAtom'
import FindAddressPop from './popup/FindAddressPop' import FindAddressPop from './popup/FindAddressPop'
import PlanRequestPop from './popup/PlanRequestPop' import PlanRequestPop from './popup/PlanRequestPop'
import WindSelectPop from './popup/WindSelectPop' import WindSelectPop from './popup/WindSelectPop'
import { useCommonCode } from '@/hooks/common/useCommonCode' import { useCommonCode } from '@/hooks/common/useCommonCode'
import StuffPlanQGrid from './StuffPlanQGrid' import StuffPlanQGrid from './StuffPlanQGrid'
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
export default function StuffDetail() { export default function StuffDetail() {
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //
const inputReceiveUserEl = useRef(null) //ref const inputReceiveUserEl = useRef(null) //ref
const inputObjectNameEl = useRef(null) //ref const inputObjectNameEl = useRef(null) //ref
const inputZipNoEl = useRef(null) //ref const inputZipNoEl = useRef(null) //ref
@ -1077,6 +1080,7 @@ export default function StuffDetail() {
// //
if (res.status === 201) { if (res.status === 201) {
alert(getMessage('stuff.detail.save')) alert(getMessage('stuff.detail.save'))
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`) router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`)
} }
}) })
@ -1085,6 +1089,7 @@ export default function StuffDetail() {
await promisePut({ url: apiUrl, data: params }).then((res) => { await promisePut({ url: apiUrl, data: params }).then((res) => {
if (res.status === 201) { if (res.status === 201) {
alert(getMessage('stuff.detail.save')) alert(getMessage('stuff.detail.save'))
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
router.refresh() router.refresh()
} }
}) })
@ -1153,7 +1158,8 @@ export default function StuffDetail() {
alert(getMessage('stuff.detail.delete.message1')) alert(getMessage('stuff.detail.delete.message1'))
} else { } else {
if (confirm(getMessage('common.message.data.delete'))) { if (confirm(getMessage('common.message.data.delete'))) {
del({ url: `/api/object/${objectNo}` }).then((res) => { del({ url: `/api/object/${objectNo}` }).then(() => {
setFloorPlanObjectNo({ floorPlanObjectNo: '' })
router.push('/management/stuff') router.push('/management/stuff')
}) })
} }

View File

@ -6,7 +6,7 @@ export default function StuffPlanQGrid(props) {
const { planGridData, planGridColumns, isPageable = true } = props const { planGridData, planGridColumns, isPageable = true } = props
const [rowData, setRowData] = useState(null) const [rowData, setRowData] = useState(null)
const [gridApi, setGridApi] = useState(null) // const [gridApi, setGridApi] = useState(null)
const [colDefs, setColDefs] = useState(planGridColumns) const [colDefs, setColDefs] = useState(planGridColumns)
const defaultColDef = useMemo(() => { const defaultColDef = useMemo(() => {
@ -20,24 +20,24 @@ export default function StuffPlanQGrid(props) {
} }
}, []) }, [])
const rowBuffer = 100 const rowBuffer = 10
useEffect(() => { useEffect(() => {
planGridData ? setRowData(planGridData) : '' planGridData ? setRowData(planGridData) : ''
}, [planGridData]) }, [planGridData])
const onGridReady = useCallback( // const onGridReady = useCallback(
(params) => { // (params) => {
setGridApi(params.api) // setGridApi(params.api)
planGridData ? setRowData(planGridData) : '' // planGridData ? setRowData(planGridData) : ''
}, // },
[planGridData], // [planGridData],
) // )
return ( return (
<div className="ag-theme-quartz" style={{ height: '100%' }}> <div className="ag-theme-quartz" style={{ height: '100%' }}>
<AgGridReact <AgGridReact
onGridReady={onGridReady} // onGridReady={onGridReady}
rowBuffer={rowBuffer} rowBuffer={rowBuffer}
rowData={rowData} rowData={rowData}
columnDefs={colDefs} columnDefs={colDefs}

View File

@ -62,10 +62,10 @@ export default function StuffQGrid(props) {
[count], [count],
) )
// //
const onSelectionChanged = useCallback((event) => { // const onSelectionChanged = useCallback((event) => {
props.getSelectedRowdata(event.api.getSelectedRows()) // props.getSelectedRowdata(event.api.getSelectedRows())
}, []) // }, [])
// //
const onCellDoubleClicked = useCallback((event) => { const onCellDoubleClicked = useCallback((event) => {
@ -95,7 +95,7 @@ export default function StuffQGrid(props) {
isRowSelectable={isRowSelectable} isRowSelectable={isRowSelectable}
rowSelection={'multiple'} rowSelection={'multiple'}
suppressRowClickSelection={true} suppressRowClickSelection={true}
onSelectionChanged={onSelectionChanged} // onSelectionChanged={onSelectionChanged}
onCellDoubleClicked={onCellDoubleClicked} onCellDoubleClicked={onCellDoubleClicked}
pagination={isPageable} pagination={isPageable}
overlayNoRowsTemplate={`<span className="ag-overlay-loading-center">${getMessage('stuff.grid.noData')}</span>`} overlayNoRowsTemplate={`<span className="ag-overlay-loading-center">${getMessage('stuff.grid.noData')}</span>`}

View File

@ -5,14 +5,15 @@ import Link from 'next/link'
import Image from 'next/image' import Image from 'next/image'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRouter, useSearchParams } from 'next/navigation' import { useRouter, useSearchParams } from 'next/navigation'
import { stuffSearchState } from '@/store/stuffAtom' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { useSetRecoilState } from 'recoil' import { useSetRecoilState } from 'recoil'
export default function StuffSubHeader({ type }) { export default function StuffSubHeader({ type }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const router = useRouter() const router = useRouter()
const setSchObjectNo = useSetRecoilState(stuffSearchState) const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState)
useEffect(() => { useEffect(() => {
window.scrollTo(0, 0) window.scrollTo(0, 0)
}, []) }, [])
@ -22,7 +23,7 @@ export default function StuffSubHeader({ type }) {
// url // url
const moveFloorPlan = () => { const moveFloorPlan = () => {
setSchObjectNo(objectNo) setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
router.push('/floor-plan') router.push('/floor-plan')
} }

View File

@ -28,7 +28,7 @@ export default function FindAddressPopGrid(props) {
} }
}, []) }, [])
const rowBuffer = 100 const rowBuffer = 10
useEffect(() => { useEffect(() => {
gridData ? setRowData(gridData) : '' gridData ? setRowData(gridData) : ''

View File

@ -28,7 +28,7 @@ export default function PlanRequestPopQGrid(props) {
} }
}, []) }, [])
const rowBuffer = 100 const rowBuffer = 20
useEffect(() => { useEffect(() => {
gridData ? setRowData(gridData) : '' gridData ? setRowData(gridData) : ''

View File

@ -1,8 +1,8 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { roofDisplaySelector, settingModalFirstOptionsState } from '@/store/settingAtom' import { basicSettingState, roofDisplaySelector, settingModalFirstOptionsState } from '@/store/settingAtom'
import { canvasState, dotLineGridSettingState } from '@/store/canvasAtom' import { canvasState, dotLineGridSettingState, pitchText, pitchTextSelector, showAngleUnitSelector } from '@/store/canvasAtom'
import { setSurfaceShapePattern } from '@/util/canvas-util' import { getChonByDegree, getDegreeByChon, setSurfaceShapePattern } from '@/util/canvas-util'
import { useFont } from '@/hooks/common/useFont' import { useFont } from '@/hooks/common/useFont'
import { useGrid } from '@/hooks/common/useGrid' import { useGrid } from '@/hooks/common/useGrid'
import { globalFontAtom } from '@/store/fontAtom' import { globalFontAtom } from '@/store/fontAtom'
@ -11,9 +11,12 @@ import { useRoof } from '@/hooks/common/useRoof'
export function useCanvasConfigInitialize() { export function useCanvasConfigInitialize() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const roofDisplay = useRecoilValue(roofDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector)
const setGlobalFonts = useSetRecoilState(globalFontAtom) const setGlobalFonts = useSetRecoilState(globalFontAtom)
const setDotLineGridSetting = useSetRecoilState(dotLineGridSettingState) const setDotLineGridSetting = useSetRecoilState(dotLineGridSettingState)
const pitchText = useRecoilValue(pitchTextSelector)
const angleUnit = useRecoilValue(showAngleUnitSelector)
const {} = useFont() const {} = useFont()
const {} = useGrid() const {} = useGrid()
const {} = useRoof() const {} = useRoof()
@ -29,6 +32,31 @@ export function useCanvasConfigInitialize() {
canvas.renderAll() canvas.renderAll()
}, [roofDisplay]) }, [roofDisplay])
useEffect(() => {
if (!canvas) return
const offsetTexts = canvas.getObjects().filter((obj) => obj.name === 'pitchText')
const flowTexts = canvas.getObjects().filter((obj) => obj.name === 'flowText')
if (basicSetting.roofAngleSet === 'slope') {
offsetTexts.forEach((obj) => {
obj.set({ text: `${obj.originText}-∠${obj.pitch}${angleUnit}` })
})
flowTexts.forEach((obj) => {
obj.set({ text: `${obj.originText}-∠${obj.pitch}${pitchText}` })
})
}
if (basicSetting.roofAngleSet === 'flat') {
offsetTexts.forEach((obj) => {
obj.set({ text: `${obj.originText}-∠${getDegreeByChon(obj.pitch)}${angleUnit}` })
})
flowTexts.forEach((obj) => {
obj.set({ text: `${obj.originText}-∠${getDegreeByChon(obj.pitch)}${pitchText}` })
})
}
canvas.renderAll()
}, [basicSetting])
const canvasLoadInit = () => { const canvasLoadInit = () => {
roofInit() //화면표시 초기화 roofInit() //화면표시 초기화
} }

View File

@ -0,0 +1,10 @@
import { useState } from 'react'
export const useCanvasMenu = () => {
const [menuNumber, setMenuNumber] = useState(null)
return {
menuNumber,
setMenuNumber,
}
}

View File

@ -33,7 +33,7 @@ export function useFirstOption() {
optionName = ['outerLine', 'wallLine'] optionName = ['outerLine', 'wallLine']
break break
case 'gridDisplay': //그리드 표시 case 'gridDisplay': //그리드 표시
optionName = ['lineGrid', 'dotGrid'] optionName = ['lineGrid', 'dotGrid', 'adsorptionPoint', 'tempGrid']
break break
case 'lineDisplay': //지붕선 표시 case 'lineDisplay': //지붕선 표시
optionName = ['roof', 'roofBase'] optionName = ['roof', 'roofBase']

View File

@ -1,6 +1,6 @@
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { LINE_TYPE } from '@/common/common' import { LINE_TYPE } from '@/common/common'
@ -9,6 +9,7 @@ import { useMode } from '@/hooks/useMode'
import { outerLineFixState } from '@/store/outerLineAtom' import { outerLineFixState } from '@/store/outerLineAtom'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { getChonByDegree } from '@/util/canvas-util'
// 처마.케라바 변경 // 처마.케라바 변경
export function useEavesGableEdit(id) { export function useEavesGableEdit(id) {
@ -28,6 +29,8 @@ export function useEavesGableEdit(id) {
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { drawRoofPolygon } = useMode() const { drawRoofPolygon } = useMode()
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const pitchRef = useRef(null) const pitchRef = useRef(null)
const offsetRef = useRef(null) const offsetRef = useRef(null)
@ -105,13 +108,13 @@ export function useEavesGableEdit(id) {
if (radioTypeRef.current === '1') { if (radioTypeRef.current === '1') {
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
pitch: pitchRef.current.value, pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset: offsetRef.current.value / 10, offset: offsetRef.current.value / 10,
} }
} else { } else {
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.HIPANDGABLE, type: LINE_TYPE.WALLLINE.HIPANDGABLE,
pitch: pitchRef.current.value, pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset: offsetRef.current.value / 10, offset: offsetRef.current.value / 10,
width: widthRef.current.value / 10, width: widthRef.current.value / 10,
} }
@ -126,7 +129,7 @@ export function useEavesGableEdit(id) {
} else { } else {
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.JERKINHEAD, type: LINE_TYPE.WALLLINE.JERKINHEAD,
pitch: pitchRef.current.value, pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset: offsetRef.current.value / 10, offset: offsetRef.current.value / 10,
width: widthRef.current.value / 10, width: widthRef.current.value / 10,
} }
@ -217,5 +220,5 @@ export function useEavesGableEdit(id) {
canvas?.renderAll() canvas?.renderAll()
} }
return { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef } return { type, setType, buttonMenu, TYPES, pitchRef, offsetRef, widthRef, radioTypeRef, pitchText }
} }

View File

@ -1,4 +1,4 @@
import { canvasState, currentObjectState } from '@/store/canvasAtom' import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, currentObjectState, pitchTextSelector } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useLine } from '@/hooks/useLine' import { useLine } from '@/hooks/useLine'
@ -10,6 +10,7 @@ import { usePolygon } from '@/hooks/usePolygon'
import { outerLineFixState } from '@/store/outerLineAtom' import { outerLineFixState } from '@/store/outerLineAtom'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { getChonByDegree } from '@/util/canvas-util'
//지붕형상 수동 설정 //지붕형상 수동 설정
export function useRoofShapePassivitySetting(id) { export function useRoofShapePassivitySetting(id) {
@ -19,6 +20,8 @@ export function useRoofShapePassivitySetting(id) {
SHED: 'shed', SHED: 'shed',
} }
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { showLine, hideLine, addPitchTextsByOuterLines } = useLine() const { showLine, hideLine, addPitchTextsByOuterLines } = useLine()
const { swalFire } = useSwal() const { swalFire } = useSwal()
@ -34,6 +37,7 @@ export function useRoofShapePassivitySetting(id) {
const isFix = useRef(false) const isFix = useRef(false)
const initLines = useRef([]) const initLines = useRef([])
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const buttons = [ const buttons = [
{ id: 1, name: getMessage('eaves'), type: TYPES.EAVES }, { id: 1, name: getMessage('eaves'), type: TYPES.EAVES },
@ -134,12 +138,12 @@ export function useRoofShapePassivitySetting(id) {
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
offset, offset,
pitch: pitchRef.current.value, pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
} }
} else if (type === TYPES.GABLE) { } else if (type === TYPES.GABLE) {
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.GABLE, type: LINE_TYPE.WALLLINE.GABLE,
pitch: pitchRef.current.value, pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value),
offset, offset,
} }
} else if (type === TYPES.SHED) { } else if (type === TYPES.SHED) {
@ -216,5 +220,5 @@ export function useRoofShapePassivitySetting(id) {
canvas.renderAll() canvas.renderAll()
} }
return { handleSave, handleConfirm, buttons, type, setType, TYPES, offsetRef, pitchRef, handleRollback } return { handleSave, handleConfirm, buttons, type, setType, TYPES, offsetRef, pitchRef, handleRollback, pitchText }
} }

View File

@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom' import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, currentMenuState, currentObjectState, pitchTextSelector } from '@/store/canvasAtom'
import { LINE_TYPE } from '@/common/common' import { LINE_TYPE } from '@/common/common'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { useMode } from '@/hooks/useMode' import { useMode } from '@/hooks/useMode'
@ -9,6 +9,7 @@ import { useLine } from '@/hooks/useLine'
import { outerLineFixState } from '@/store/outerLineAtom' import { outerLineFixState } from '@/store/outerLineAtom'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { getChonByDegree } from '@/util/canvas-util'
// 지붕형상 설정 // 지붕형상 설정
export function useRoofShapeSetting(id) { export function useRoofShapeSetting(id) {
@ -17,13 +18,16 @@ export function useRoofShapeSetting(id) {
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { getMessage } = useMessage() const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const { addPolygonByLines } = usePolygon() const { addPolygonByLines } = usePolygon()
const [pitch, setPitch] = useState(4)
const [pitch, setPitch] = useState(currentAngleType === ANGLE_TYPE.SLOPE ? 4 : 21.8) // 경사
const [eavesOffset, setEavesOffset] = useState(500) // 처마출폭 const [eavesOffset, setEavesOffset] = useState(500) // 처마출폭
const [gableOffset, setGableOffset] = useState(300) // 케라바출폭 const [gableOffset, setGableOffset] = useState(300) // 케라바출폭
const [sleeveOffset, setSleeveOffset] = useState(300) // 소매출폭 const [sleeveOffset, setSleeveOffset] = useState(300) // 소매출폭
const [jerkinHeadWidth, setJerkinHeadWidth] = useState(800) // 반절처 폭 const [jerkinHeadWidth, setJerkinHeadWidth] = useState(800) // 반절처 폭
const [jerkinHeadPitch, setJerkinHeadPitch] = useState(4.5) // 반절처 경사 const [jerkinHeadPitch, setJerkinHeadPitch] = useState(currentAngleType === ANGLE_TYPE.SLOPE ? 4.5 : 20) // 반절처 경사
const [hipAndGableWidth, setHipAndGableWidth] = useState(800) // 팔작지붕 폭 const [hipAndGableWidth, setHipAndGableWidth] = useState(800) // 팔작지붕 폭
const [shedWidth, setShedWidth] = useState(300) // 한쪽흐름 폭 const [shedWidth, setShedWidth] = useState(300) // 한쪽흐름 폭
const [hasSleeve, setHasSleeve] = useState('0') const [hasSleeve, setHasSleeve] = useState('0')
@ -34,9 +38,21 @@ export function useRoofShapeSetting(id) {
const setCurrentMenu = useSetRecoilState(currentMenuState) const setCurrentMenu = useSetRecoilState(currentMenuState)
const outerLineFix = useRecoilValue(outerLineFixState) const outerLineFix = useRecoilValue(outerLineFixState)
const isFixRef = useRef(false)
const pitchRef = useRef(null)
const jerkinHeadPitchRef = useRef(null)
const history = useRef([]) const history = useRef([])
const { closePopup } = usePopup() const { closePopup } = usePopup()
useEffect(() => {
pitchRef.current = currentAngleType === ANGLE_TYPE.SLOPE ? pitch : getChonByDegree(pitch)
}, [pitch])
useEffect(() => {
jerkinHeadPitchRef.current = currentAngleType === ANGLE_TYPE.SLOPE ? jerkinHeadPitch : getChonByDegree(jerkinHeadPitch)
}, [jerkinHeadPitch])
useEffect(() => { useEffect(() => {
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
if (!outerLineFix || outerLines.length === 0) { if (!outerLineFix || outerLines.length === 0) {
@ -46,6 +62,10 @@ export function useRoofShapeSetting(id) {
} }
return () => { return () => {
if (!isFixRef.current) {
return
}
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
const pitchTexts = canvas.getObjects().filter((obj) => obj.name === 'pitchText') const pitchTexts = canvas.getObjects().filter((obj) => obj.name === 'pitchText')
canvas.remove(...pitchTexts) canvas.remove(...pitchTexts)
@ -69,7 +89,6 @@ export function useRoofShapeSetting(id) {
}) })
addPitchText(line) addPitchText(line)
line.setViewLengthText(false)
} }
}) })
canvas.renderAll() canvas.renderAll()
@ -114,12 +133,10 @@ export function useRoofShapeSetting(id) {
canvas?.renderAll() canvas?.renderAll()
} }
setPitch(4)
setEavesOffset(500) setEavesOffset(500)
setGableOffset(300) setGableOffset(300)
setSleeveOffset(300) setSleeveOffset(300)
setJerkinHeadWidth(800) setJerkinHeadWidth(800)
setJerkinHeadPitch(4.5)
setHipAndGableWidth(800) setHipAndGableWidth(800)
setShedWidth(300) setShedWidth(300)
}, [shapeNum]) }, [shapeNum])
@ -181,7 +198,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'bottom') { if (line.direction === 'bottom') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -197,7 +214,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'top') { if (line.direction === 'top') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -205,7 +222,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'bottom') { if (line.direction === 'bottom') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -226,7 +243,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'top') { if (line.direction === 'top') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -234,7 +251,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'bottom') { if (line.direction === 'bottom') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -242,7 +259,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'bottom') { if (line.direction === 'bottom') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -250,7 +267,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'top') { if (line.direction === 'top') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -270,7 +287,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'right') { if (line.direction === 'right') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -278,7 +295,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'left') { if (line.direction === 'left') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -286,7 +303,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'left') { if (line.direction === 'left') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -294,7 +311,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'right') { if (line.direction === 'right') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -315,7 +332,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'left') { if (line.direction === 'left') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -323,7 +340,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'right') { if (line.direction === 'right') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -331,7 +348,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'right') { if (line.direction === 'right') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -339,7 +356,7 @@ export function useRoofShapeSetting(id) {
if (line.direction === 'left') { if (line.direction === 'left') {
line.attributes = { line.attributes = {
offset: shedWidth / 10, offset: shedWidth / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.SHED, type: LINE_TYPE.WALLLINE.SHED,
} }
} }
@ -376,6 +393,7 @@ export function useRoofShapeSetting(id) {
canvas?.renderAll() canvas?.renderAll()
roof.drawHelpLine() roof.drawHelpLine()
// setShowRoofShapeSettingModal(false) // setShowRoofShapeSettingModal(false)
isFixRef.current = true
closePopup(id) closePopup(id)
} }
@ -436,7 +454,7 @@ export function useRoofShapeSetting(id) {
outerLines.forEach((line) => { outerLines.forEach((line) => {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
// hideLine(line) // hideLine(line)
@ -458,7 +476,7 @@ export function useRoofShapeSetting(id) {
} else if (line.direction === 'top' || line.direction === 'bottom') { } else if (line.direction === 'top' || line.direction === 'bottom') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -481,7 +499,7 @@ export function useRoofShapeSetting(id) {
} else if (line.direction === 'left' || line.direction === 'right') { } else if (line.direction === 'left' || line.direction === 'right') {
line.attributes = { line.attributes = {
offset: eavesOffset / 10, offset: eavesOffset / 10,
pitch: pitch, pitch: pitchRef.current,
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
} }
} }
@ -504,7 +522,7 @@ export function useRoofShapeSetting(id) {
// 처마 // 처마
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.EAVES, type: LINE_TYPE.WALLLINE.EAVES,
pitch: pitch, pitch: pitchRef.current,
offset: eavesOffset / 10, offset: eavesOffset / 10,
} }
addPitchText(currentObject) addPitchText(currentObject)
@ -535,7 +553,7 @@ export function useRoofShapeSetting(id) {
// 팔작지붕 // 팔작지붕
attributes = { attributes = {
type: LINE_TYPE.WALLLINE.HIPANDGABLE, type: LINE_TYPE.WALLLINE.HIPANDGABLE,
pitch: pitch, pitch: pitchRef.current,
offset: eavesOffset / 10, offset: eavesOffset / 10,
width: hipAndGableWidth / 10, width: hipAndGableWidth / 10,
} }
@ -550,7 +568,7 @@ export function useRoofShapeSetting(id) {
type: LINE_TYPE.WALLLINE.JERKINHEAD, type: LINE_TYPE.WALLLINE.JERKINHEAD,
offset: gableOffset / 10, offset: gableOffset / 10,
width: jerkinHeadWidth / 10, width: jerkinHeadWidth / 10,
pitch: jerkinHeadPitch, pitch: jerkinHeadPitchRef.current,
} }
addPitchText(currentObject) addPitchText(currentObject)
selectedLine.set({ strokeWidth: 4 }) selectedLine.set({ strokeWidth: 4 })
@ -629,5 +647,6 @@ export function useRoofShapeSetting(id) {
setButtonAct, setButtonAct,
handleConfirm, handleConfirm,
handleRollBack, handleRollBack,
pitchText,
} }
} }

View File

@ -11,6 +11,7 @@ import {
modifiedPlanFlagState, modifiedPlanFlagState,
} from '@/store/canvasAtom' } from '@/store/canvasAtom'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { fontSelector } from '@/store/fontAtom'
// 캔버스에 필요한 이벤트 // 캔버스에 필요한 이벤트
export function useCanvasEvent() { export function useCanvasEvent() {
@ -22,6 +23,7 @@ export function useCanvasEvent() {
const fontFamily = useRecoilValue(fontFamilyState) const fontFamily = useRecoilValue(fontFamilyState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState) const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState)
const lengthTextOption = useRecoilValue(fontSelector('lengthText'))
// 기본적인 이벤트 필요시 추가 // 기본적인 이벤트 필요시 추가
const attachDefaultEventOnCanvas = () => { const attachDefaultEventOnCanvas = () => {
@ -108,16 +110,17 @@ export function useCanvasEvent() {
}) })
} }
if (target.type.toLowerCase().includes('text')) { if (target.name === 'lengthText' && target.type.toLowerCase().includes('text') > 0) {
target.set({ fontSize })
target.set({ fontFamily })
}
if (target.name === 'lengthText') {
const x = target.left const x = target.left
const y = target.top const y = target.top
target.lockMovementX = false target.lockMovementX = false
target.lockMovementY = false target.lockMovementY = false
target.fill = lengthTextOption.fontColor.value
target.fontFamily = lengthTextOption.fontFamily.value
target.fontSize = lengthTextOption.fontSize.value
target.fontWeight = lengthTextOption.fontWeight.value
// Add a property to store the previous value // Add a property to store the previous value
const previousValue = target.text const previousValue = target.text
target.on('selected', (e) => { target.on('selected', (e) => {

View File

@ -1,11 +1,23 @@
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' import {
ANGLE_TYPE,
canvasState,
currentAngleTypeSelector,
fontFamilyState,
fontSizeState,
pitchTextSelector,
showAngleUnitSelector,
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
export const useLine = () => { export const useLine = () => {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const fontSize = useRecoilValue(fontSizeState) const fontSize = useRecoilValue(fontSizeState)
const fontFamily = useRecoilValue(fontFamilyState) const fontFamily = useRecoilValue(fontFamilyState)
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const angleUnit = useRecoilValue(showAngleUnitSelector)
const addLine = (points = [], options) => { const addLine = (points = [], options) => {
const line = new QLine(points, { const line = new QLine(points, {
@ -77,6 +89,11 @@ export const useLine = () => {
let left, top let left, top
const textStr =
currentAngleType === ANGLE_TYPE.SLOPE
? `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + attributes.pitch + angleUnit : ''}`
: `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + getDegreeByChon(attributes.pitch) + angleUnit : ''}`
if (direction === 'top') { if (direction === 'top') {
left = (startPoint.x + endPoint.x) / 2 left = (startPoint.x + endPoint.x) / 2
top = (startPoint.y + endPoint.y) / 2 - 50 top = (startPoint.y + endPoint.y) / 2 - 50
@ -91,17 +108,20 @@ export const useLine = () => {
top = (startPoint.y + endPoint.y) / 2 - 30 top = (startPoint.y + endPoint.y) / 2 - 30
} }
const text = new fabric.Text( if (!attributes.pitch) {
`${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + attributes.pitch : ''}`, return
{ }
left,
top, const text = new fabric.Text(`${textStr}`, {
fontSize: 20, left,
fill: 'black', top,
name: 'pitchText', fontSize: 20,
parentId: line.id, originText: `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}`,
}, fill: 'black',
) name: 'pitchText',
parentId: line.id,
pitch: attributes.pitch,
})
canvas.add(text) canvas.add(text)
} }

View File

@ -8,6 +8,7 @@ import { useSwal } from '@/hooks/useSwal'
export function usePlan() { export function usePlan() {
const [planNum, setPlanNum] = useState(0) const [planNum, setPlanNum] = useState(0)
const [selectedPlan, setSelectedPlan] = useState(null)
const [canvas, setCanvas] = useRecoilState(canvasState) const [canvas, setCanvas] = useRecoilState(canvasState)
const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
@ -65,6 +66,7 @@ export function usePlan() {
'text', 'text',
'pitch', 'pitch',
'uuid', 'uuid',
'originText',
]) ])
const str = JSON.stringify(objs) const str = JSON.stringify(objs)
@ -144,7 +146,7 @@ export function usePlan() {
* DB에 저장된 데이터를 canvas에서 사용할 있도록 포맷화 * DB에 저장된 데이터를 canvas에서 사용할 있도록 포맷화
*/ */
const dbToCanvasFormat = (cs) => { const dbToCanvasFormat = (cs) => {
return cs.replace(/##/g, '"').replace(/&ang;/g, '∠') return cs.replace(/##/g, '"').replace(/&ang;/g, '∠').replace(/&deg;/g, '°')
} }
/** /**
@ -278,6 +280,7 @@ export function usePlan() {
} }
useEffect(() => { useEffect(() => {
setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null)
setSelectedPlan(plans.find((plan) => plan.isCurrent))
}, [plans]) }, [plans])
/** /**
@ -365,6 +368,7 @@ export function usePlan() {
return { return {
canvas, canvas,
plans, plans,
selectedPlan,
modifiedPlans, modifiedPlans,
checkCanvasObjectEvent, checkCanvasObjectEvent,
resetModifiedPlans, resetModifiedPlans,

View File

@ -1,7 +1,7 @@
import { canvasState, fontFamilyState, fontSizeState } from '@/store/canvasAtom' import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, fontFamilyState, fontSizeState, pitchTextSelector } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { fabric } from 'fabric' import { fabric } from 'fabric'
import { getDirectionByPoint } from '@/util/canvas-util' import { getDegreeByChon, getDirectionByPoint } from '@/util/canvas-util'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { isSamePoint } from '@/util/qpolygon-utils' import { isSamePoint } from '@/util/qpolygon-utils'
import { flowDisplaySelector } from '@/store/settingAtom' import { flowDisplaySelector } from '@/store/settingAtom'
@ -12,6 +12,8 @@ export const usePolygon = () => {
const isFlowDisplay = useRecoilValue(flowDisplaySelector) const isFlowDisplay = useRecoilValue(flowDisplaySelector)
const flowFontOptions = useRecoilValue(fontSelector('flowText')) const flowFontOptions = useRecoilValue(fontSelector('flowText'))
const lengthTextFontOptions = useRecoilValue(fontSelector('lengthText')) const lengthTextFontOptions = useRecoilValue(fontSelector('lengthText'))
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
const pitchText = useRecoilValue(pitchTextSelector)
const addPolygon = (points, options) => { const addPolygon = (points, options) => {
const polygon = new QPolygon(points, { const polygon = new QPolygon(points, {
@ -401,14 +403,18 @@ export const usePolygon = () => {
const addTextByArrows = (arrows, txt, canvas) => { const addTextByArrows = (arrows, txt, canvas) => {
arrows.forEach((arrow, index) => { arrows.forEach((arrow, index) => {
const text = new fabric.Text(`${txt}${index + 1} (${arrow.pitch}寸)`, { const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`
const text = new fabric.Text(`${textStr}`, {
fontSize: flowFontOptions.fontSize.value, fontSize: flowFontOptions.fontSize.value,
fill: flowFontOptions.fontColor.value, fill: flowFontOptions.fontColor.value,
fontFamily: flowFontOptions.fontFamily.value, fontFamily: flowFontOptions.fontFamily.value,
fontWeight: flowFontOptions.fontWeight.value, fontWeight: flowFontOptions.fontWeight.value,
pitch: arrow.pitch,
originX: 'center', originX: 'center',
originY: 'center', originY: 'center',
name: 'flowText', name: 'flowText',
originText: `${txt}${index + 1}`,
selectable: false, selectable: false,
left: arrow.stickeyPoint.x, left: arrow.stickeyPoint.x,
top: arrow.stickeyPoint.y, top: arrow.stickeyPoint.y,

View File

@ -1,6 +1,8 @@
import { atom, selector } from 'recoil' import { atom, selector } from 'recoil'
import { MENU } from '@/common/common' import { MENU } from '@/common/common'
import { outerLineFixState, outerLinePointsState } from '@/store/outerLineAtom' import { outerLineFixState, outerLinePointsState } from '@/store/outerLineAtom'
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
import { basicSettingState } from '@/store/settingAtom'
export const canvasState = atom({ export const canvasState = atom({
key: 'canvasState', key: 'canvasState',
@ -305,3 +307,60 @@ export const globalPitchState = atom({
key: 'globalPitch', key: 'globalPitch',
default: 4, default: 4,
}) })
export const pitchSelector = selector({
key: 'pitchSelector',
get: ({ get }) => {
const globalPitch = get(globalPitchState)
const basicSettingStateValue = get(basicSettingState)
const roofAngleSet = basicSettingStateValue.roofAngleSet
if (roofAngleSet === 'slope') {
return globalPitch
} else {
return getDegreeByChon(globalPitch)
}
},
set: ({ get, set }, newValue) => {
const basicSettingStateValue = get(basicSettingState)
const roofAngleSet = basicSettingStateValue.roofAngleSet
console.log(newValue)
if (roofAngleSet === 'slope') {
set(globalPitchState, newValue)
} else {
set(globalPitchState, getChonByDegree(newValue))
}
},
})
export const ANGLE_TYPE = {
SLOPE: 'slope',
FLAT: 'flat',
}
export const currentAngleTypeSelector = selector({
key: 'currentAngleTypeSelector',
get: ({ get }) => {
const basicSettingStateValue = get(basicSettingState)
return basicSettingStateValue.roofAngleSet
},
})
export const pitchTextSelector = selector({
key: 'pitchTextSelector',
get: ({ get }) => {
const basicSettingStateValue = get(basicSettingState)
const roofAngleSet = basicSettingStateValue.roofAngleSet
return roofAngleSet === 'slope' ? '寸' : '度'
},
})
//각도 표시, offset 길이에서는 각도가 한자가 아닌 도형으로 표시되어야 한다.
export const showAngleUnitSelector = selector({
key: 'showAngleUnitSelector',
get: ({ get }) => {
const basicSettingStateValue = get(basicSettingState)
const roofAngleSet = basicSettingStateValue.roofAngleSet
return roofAngleSet === 'slope' ? '寸' : '°'
},
})

View File

@ -0,0 +1,9 @@
import { atom } from 'recoil'
import { v1 } from 'uuid'
export const floorPlanObjectState = atom({
key: `floorPlanObjectState/${v1()}`,
default: {
objectNo: '', //물건번호
},
dangerouslyAllowMutability: true,
})

View File

@ -157,3 +157,23 @@ export const roofDisplaySelector = selector({
}, },
dangerouslyAllowMutability: true, dangerouslyAllowMutability: true,
}) })
export const basicSettingState = atom({
key: 'basicSettingState',
default: {
roofSizeSet: 1,
roofAngleSet: 'slope',
roofs: [
{
roofApply: true,
roofSeq: 1,
roofType: 1,
roofWidth: 200,
roofHeight: 200,
roofHajebichi: 200,
roofGap: 0,
roofLayout: 'parallel',
},
],
},
})

View File

@ -262,6 +262,15 @@ export const getDegreeByChon = (chon) => {
return Number((radians * (180 / Math.PI)).toFixed(2)) return Number((radians * (180 / Math.PI)).toFixed(2))
} }
/**
*
*/
export const getChonByDegree = (degree) => {
// tan(theta) = height / base
const radians = (degree * Math.PI) / 180
return Number(Number(Math.tan(radians) * 10).toFixed(1))
}
/** /**
* 사이의 방향을 반환합니다. * 사이의 방향을 반환합니다.
* @param a {fabric.Object} * @param a {fabric.Object}