Merge branch 'dev' into dev-yj
This commit is contained in:
commit
2fea382aca
@ -1,12 +0,0 @@
|
|||||||
import Intro from '@/components/Intro'
|
|
||||||
import { initCheck } from '@/util/session-util'
|
|
||||||
|
|
||||||
export default async function IntroPage() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="container mx-auto p-4 m-4 border">
|
|
||||||
<Intro />
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -159,6 +159,8 @@ export const SAVE_KEY = [
|
|||||||
'groupName',
|
'groupName',
|
||||||
'lineDirection',
|
'lineDirection',
|
||||||
'groupId',
|
'groupId',
|
||||||
|
'planeSize',
|
||||||
|
'actualSize',
|
||||||
]
|
]
|
||||||
|
|
||||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
|
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
|
||||||
|
|||||||
@ -1,142 +0,0 @@
|
|||||||
'use client'
|
|
||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
|
||||||
|
|
||||||
import Link from 'next/link'
|
|
||||||
|
|
||||||
import { useRecoilState } from 'recoil'
|
|
||||||
import { modalContent, modalState } from '@/store/modalAtom'
|
|
||||||
|
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
|
||||||
|
|
||||||
import { Button } from '@nextui-org/react'
|
|
||||||
|
|
||||||
import SingleDatePicker from './common/datepicker/SingleDatePicker'
|
|
||||||
import RangeDatePicker from './common/datepicker/RangeDatePicker'
|
|
||||||
import QGrid from './common/grid/QGrid'
|
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
|
||||||
|
|
||||||
export default function Intro() {
|
|
||||||
const { get } = useAxios()
|
|
||||||
const { swalFire } = useSwal()
|
|
||||||
|
|
||||||
// const [open, setOpen] = useState(false)
|
|
||||||
const [startDate, setStartDate] = useState(new Date())
|
|
||||||
const singleDatePickerProps = {
|
|
||||||
startDate,
|
|
||||||
setStartDate,
|
|
||||||
}
|
|
||||||
|
|
||||||
const [dateRange, setDateRange] = useState([null, null])
|
|
||||||
const [startRangeDate, endRangeDate] = dateRange
|
|
||||||
const rangeDatePickerProps = {
|
|
||||||
startRangeDate,
|
|
||||||
endRangeDate,
|
|
||||||
setDateRange,
|
|
||||||
}
|
|
||||||
|
|
||||||
// const gridProps = {
|
|
||||||
// isPageable: false,
|
|
||||||
// }
|
|
||||||
const [gridProps, setGridProps] = useState({
|
|
||||||
gridData: [],
|
|
||||||
isPageable: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
const [open, setOpen] = useRecoilState(modalState)
|
|
||||||
const [contents, setContent] = useRecoilState(modalContent)
|
|
||||||
|
|
||||||
const modelProps = {
|
|
||||||
open,
|
|
||||||
setOpen,
|
|
||||||
}
|
|
||||||
|
|
||||||
const ipsum = (
|
|
||||||
<>
|
|
||||||
<p className="text-2xl">title</p>
|
|
||||||
<p>
|
|
||||||
저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하여 필요한
|
|
||||||
법률의 제정·개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시행 전에 할 수 있다.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 할 수 있도록 노력하여야 한다. 통신·방송의 시설기준과 신문의 기능을 보장하기
|
|
||||||
위하여 필요한 사항은 법률로 정한다.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는
|
|
||||||
후보자에게 부담시킬 수 없다.
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function fetchData() {
|
|
||||||
// const response = await fetch('https://www.ag-grid.com/example-assets/space-mission-data.json')
|
|
||||||
// const data = await response.json()
|
|
||||||
const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
|
|
||||||
setGridProps({ ...gridProps, gridData: data })
|
|
||||||
}
|
|
||||||
fetchData()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="text-2xl">
|
|
||||||
<Link href={'/login'}>
|
|
||||||
<Button color="primary">로그인 페이지로 이동</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<div className="text-2xl">Single Date Picker</div>
|
|
||||||
<div>
|
|
||||||
<SingleDatePicker {...singleDatePickerProps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<div className="text-2xl">Range Date Picker</div>
|
|
||||||
<div>
|
|
||||||
<RangeDatePicker {...rangeDatePickerProps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<div className="text-2xl">QGrid</div>
|
|
||||||
<div>
|
|
||||||
<QGrid {...gridProps} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<div className="text-2xl">QModal</div>
|
|
||||||
<div>
|
|
||||||
{/* <Button color="primary" onClick={() => setOpen(true)}>
|
|
||||||
Open Modal
|
|
||||||
</Button>
|
|
||||||
<QModal {...modelProps}>{ipsum}</QModal> */}
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setContent(ipsum)
|
|
||||||
setOpen(true)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Open Modal
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="my-2">
|
|
||||||
<div className="text-2xl">QToast</div>
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
onClick={() => {
|
|
||||||
swalFire({
|
|
||||||
text: 'This is a toast message',
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Open Toast
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -39,7 +39,7 @@ export default function Playground() {
|
|||||||
const [color, setColor] = useState('#ff0000')
|
const [color, setColor] = useState('#ff0000')
|
||||||
|
|
||||||
const [textInput, setTextInput] = useState('')
|
const [textInput, setTextInput] = useState('')
|
||||||
const [numberInput, setNumberInput] = useState(null)
|
const [numberInput, setNumberInput] = useState('')
|
||||||
const [radioInput, setRadioInput] = useState('')
|
const [radioInput, setRadioInput] = useState('')
|
||||||
const [checkboxInput, setCheckboxInput] = useState([])
|
const [checkboxInput, setCheckboxInput] = useState([])
|
||||||
const [selectedValue, setSelectedValue] = useState('')
|
const [selectedValue, setSelectedValue] = useState('')
|
||||||
@ -171,7 +171,7 @@ export default function Playground() {
|
|||||||
<button
|
<button
|
||||||
className="btn-frame deepgray"
|
className="btn-frame deepgray"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setNumberInput(null)
|
setNumberInput('')
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
QInput NumberInput DATA RESET
|
QInput NumberInput DATA RESET
|
||||||
|
|||||||
@ -431,7 +431,7 @@ export default function Roof2(props) {
|
|||||||
{ x: 450, y: 850 },
|
{ x: 450, y: 850 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const polygon = new QPolygon(rectangleType2, {
|
const polygon = new QPolygon(type2, {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'green',
|
stroke: 'green',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export default function ColorPickerModal(props) {
|
|||||||
closePopup(id, isConfig)
|
closePopup(id, isConfig)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{getMessage('common.message.save')}
|
{getMessage('modal.common.save')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,16 +1,20 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { contextMenuListState, contextMenuState } from '@/store/contextMenu'
|
import { contextMenuListState, contextMenuState } from '@/store/contextMenu'
|
||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
|
import { useContextMenu } from '@/hooks/useContextMenu'
|
||||||
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
|
||||||
export default function QContextMenu(props) {
|
export default function QContextMenu(props) {
|
||||||
const { contextRef, canvasProps, handleKeyup } = props
|
const { contextRef, canvasProps } = props
|
||||||
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
||||||
const [contextMenuList, setContextMenuList] = useRecoilState(contextMenuListState)
|
const contextMenuList = useRecoilValue(contextMenuListState)
|
||||||
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
||||||
const { tempGridMode, setTempGridMode } = useTempGrid()
|
const { tempGridMode, setTempGridMode } = useTempGrid()
|
||||||
|
const { handleKeyup } = useContextMenu()
|
||||||
|
const { addDocumentEventListener, removeDocumentEvent } = useEvent()
|
||||||
|
|
||||||
let contextType = ''
|
let contextType = ''
|
||||||
|
|
||||||
@ -22,13 +26,13 @@ export default function QContextMenu(props) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const getYPosition = (e) => {
|
const getYPosition = (e) => {
|
||||||
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
||||||
return acc + cur.length
|
return acc + cur.length
|
||||||
}, 0)
|
}, 0)
|
||||||
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!contextRef.current) return
|
if (!contextRef.current) return
|
||||||
|
|
||||||
@ -40,7 +44,7 @@ export default function QContextMenu(props) {
|
|||||||
y: window.innerHeight / 2 < e.pageY ? getYPosition(e) : e.pageY,
|
y: window.innerHeight / 2 < e.pageY ? getYPosition(e) : e.pageY,
|
||||||
}
|
}
|
||||||
setContextMenu({ visible: true, ...position })
|
setContextMenu({ visible: true, ...position })
|
||||||
document.addEventListener('keyup', (e) => handleKeyup(e))
|
addDocumentEventListener('keyup', document, handleKeyup)
|
||||||
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,8 +55,9 @@ export default function QContextMenu(props) {
|
|||||||
|
|
||||||
const handleOutsideClick = (e) => {
|
const handleOutsideClick = (e) => {
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
if (contextMenu.visible && !ref.current.contains(e.target)) {
|
if (contextMenu.visible) {
|
||||||
setContextMenu({ ...contextMenu, visible: false })
|
setContextMenu({ ...contextMenu, visible: false })
|
||||||
|
removeDocumentEvent('keyup')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,10 +66,11 @@ export default function QContextMenu(props) {
|
|||||||
document.addEventListener('click', handleOutsideClick)
|
document.addEventListener('click', handleOutsideClick)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
removeDocumentEvent('keyup')
|
||||||
document.removeEventListener('click', handleClick)
|
document.removeEventListener('click', handleClick)
|
||||||
document.removeEventListener('click', handleOutsideClick)
|
document.removeEventListener('click', handleOutsideClick)
|
||||||
}
|
}
|
||||||
}, [contextRef, contextMenu])
|
}, [contextRef, contextMenuList])
|
||||||
|
|
||||||
const handleObjectMove = () => {
|
const handleObjectMove = () => {
|
||||||
activeObject.set({
|
activeObject.set({
|
||||||
|
|||||||
@ -1,18 +1,18 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useState } from 'react'
|
import { useState } from 'react'
|
||||||
import Draggable from 'react-draggable'
|
import Draggable from 'react-draggable'
|
||||||
|
|
||||||
export default function WithDraggable({ isShow, children, pos, handle = '' }) {
|
export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 }, handle = '' }) {
|
||||||
const [position, setPosition] = useState({ x: 0, y: 0 })
|
const [position, setPosition] = useState(pos)
|
||||||
|
|
||||||
const handleOnDrag = (e, data) => {
|
const handleOnDrag = (e, data) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
setPosition({ x: data.x, y: data.y })
|
setPosition({ x: data.x, y: data.y })
|
||||||
}
|
}
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
setPosition({ ...pos })
|
// setPosition({ ...pos })
|
||||||
}, [])
|
// }, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useCallback } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
|
|
||||||
export default function QInput({ type, className, ref, id, readOnly = false, options = [], placeholder, value, onChange }) {
|
export default function QInput({ type, className, ref, id, readOnly = false, options = [], placeholder, value, onChange }) {
|
||||||
|
const [prevNum, setPrevNum] = useState('')
|
||||||
// options = options || [
|
// options = options || [
|
||||||
// {
|
// {
|
||||||
// id: 'one',
|
// id: 'one',
|
||||||
@ -35,51 +36,59 @@ export default function QInput({ type, className, ref, id, readOnly = false, opt
|
|||||||
|
|
||||||
const handleTextNumberChange = useCallback(
|
const handleTextNumberChange = useCallback(
|
||||||
(e) => {
|
(e) => {
|
||||||
if (type === 'text') {
|
onChange(e.target.value)
|
||||||
onChange(e.target.value)
|
|
||||||
} else if (type === 'number') {
|
|
||||||
onChange(Number(e.target.value))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[type, onChange],
|
[onChange],
|
||||||
)
|
)
|
||||||
|
|
||||||
// type=number 정수 부호, 소수점 검사, 일부 키 허용
|
// type=number 정수 부호, 소수점 검사, 일부 키 허용
|
||||||
|
// const checkInputNumber = (e) => {
|
||||||
|
// const value = e.target.value
|
||||||
|
// const key = e.key
|
||||||
|
// const allowKeys = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'Tab', 'Enter', 'Control'] // 'ArrowUp', 'ArrowDown',
|
||||||
|
// if (key >= '0' && key <= '9') {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// if (key === '.' && !value.includes('.') && value.length > 0 && !isNaN(Number(value))) {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// if (key === '-' && !value.includes('-') && value.length > 0) {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// if (allowKeys.includes(key)) {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// if (key === 'a' || key === 'c' || key === 'v' || key === 'x' || key === 'z') {
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// e.preventDefault()
|
||||||
|
// }
|
||||||
|
// type=number 정수 부호, 소수점 검사
|
||||||
const checkInputNumber = (e) => {
|
const checkInputNumber = (e) => {
|
||||||
const value = e.target.value
|
const value = e.target.defaultValue
|
||||||
const key = e.key
|
if (value === '') return
|
||||||
const allowKeys = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'Tab', 'Enter', 'Control'] // 'ArrowUp', 'ArrowDown',
|
|
||||||
if (key >= '0' && key <= '9') {
|
const regex = /^-?([1-9]\d*|\d)(\.\d*)?$/
|
||||||
return
|
if (regex.test(value)) {
|
||||||
|
setPrevNum(value)
|
||||||
|
} else {
|
||||||
|
onChange(prevNum)
|
||||||
}
|
}
|
||||||
if (key === '.' && !value.includes('.') && value.length > 0 && !isNaN(Number(value))) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (key === '-' && !value.includes('-') && value.length > 0) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (allowKeys.includes(key)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (key === 'a' || key === 'c' || key === 'v' || key === 'x' || key === 'z') {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
e.preventDefault()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// input type : text, number
|
// input type : text, number
|
||||||
const inputTextNumber = () => {
|
const inputTextNumber = () => {
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type={type}
|
type="text"
|
||||||
className={`input-light ${className ? className : ''}`}
|
className={`input-light ${className ? className : ''}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
id={id}
|
id={id}
|
||||||
readOnly={readOnly ? true : false}
|
readOnly={readOnly ? true : false}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
value={value === 0 ? 0 : value || ''}
|
value={value}
|
||||||
onChange={handleTextNumberChange}
|
onChange={handleTextNumberChange}
|
||||||
onKeyDown={type === 'number' ? checkInputNumber : undefined}
|
onKeyUp={type === 'number' ? checkInputNumber : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { popupState } from '@/store/popupAtom'
|
import { popupState } from '@/store/popupAtom'
|
||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
|
|
||||||
export default function PopupManager() {
|
export default function PopupManager() {
|
||||||
const [popup, setPopup] = useRecoilState(popupState)
|
const popup = useRecoilValue(popupState)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...popup?.config.map((child) => <Fragment key={child.id}>{child.component}</Fragment>),
|
...popup?.config.map((child) => <Fragment key={child.id}>{child.component}</Fragment>),
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect, useState, useRef } from 'react'
|
import { useEffect, useState, useContext } from 'react'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
||||||
@ -15,15 +14,15 @@ import dayjs from 'dayjs'
|
|||||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||||
import Select from 'react-select'
|
import Select from 'react-select'
|
||||||
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
||||||
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
|
|
||||||
export default function Estimate({ params }) {
|
export default function Estimate({ params }) {
|
||||||
|
const { session } = useContext(SessionContext)
|
||||||
const [objectNo, setObjectNo] = useState('') //물건번호
|
const [objectNo, setObjectNo] = useState('') //물건번호
|
||||||
const [planNo, setPlanNo] = useState('') //플랜번호
|
const [planNo, setPlanNo] = useState('') //플랜번호
|
||||||
const [files, setFiles] = useState([]) // 보내는 첨부파일
|
|
||||||
|
|
||||||
//체크박스
|
const [files, setFiles] = useState([]) // 보내는 첨부파일
|
||||||
const [checkItems, setCheckItems] = useState(new Set())
|
const [originFiles, setOriginFiles] = useState([]) //기존 첨부파일
|
||||||
const [checkedList, setCheckedList] = useState([])
|
|
||||||
|
|
||||||
const [showContentCode, setShowContentCode] = useState('ATTR001')
|
const [showContentCode, setShowContentCode] = useState('ATTR001')
|
||||||
|
|
||||||
@ -40,7 +39,6 @@ export default function Estimate({ params }) {
|
|||||||
setStartDate,
|
setStartDate,
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
|
||||||
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||||
|
|
||||||
//견적서 상세데이터
|
//견적서 상세데이터
|
||||||
@ -52,16 +50,14 @@ export default function Estimate({ params }) {
|
|||||||
const [specialNoteList, setSpecialNoteList] = useState([])
|
const [specialNoteList, setSpecialNoteList] = useState([])
|
||||||
|
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
const { get, post } = useAxios(globalLocaleState)
|
const { get, promisePost } = useAxios(globalLocaleState)
|
||||||
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const { setMenuNumber } = useCanvasMenu()
|
const { setMenuNumber } = useCanvasMenu()
|
||||||
|
|
||||||
|
//새로 추가한 첨부파일 props
|
||||||
const fileUploadProps = {
|
const fileUploadProps = {
|
||||||
// objectNo: '',
|
|
||||||
// planNo: params.pid,
|
|
||||||
// category: '10',
|
|
||||||
uploadFiles: files,
|
uploadFiles: files,
|
||||||
setUploadFiles: setFiles,
|
setUploadFiles: setFiles,
|
||||||
}
|
}
|
||||||
@ -127,11 +123,42 @@ export default function Estimate({ params }) {
|
|||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 추가한 첨부파일 state에 넣기
|
||||||
|
useEffect(() => {
|
||||||
|
if (isNotEmptyArray(files)) {
|
||||||
|
files.map((row) => {
|
||||||
|
setState({ fileList: row.data })
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
setState({ fileList: [] })
|
||||||
|
}
|
||||||
|
}, [files])
|
||||||
|
|
||||||
|
//상세에서 내려온 첨부파일 set 만들기
|
||||||
|
useEffect(() => {
|
||||||
|
if (isNotEmptyArray(state.fileList)) {
|
||||||
|
setOriginFiles(state.fileList)
|
||||||
|
}
|
||||||
|
}, [state?.fileList])
|
||||||
|
|
||||||
|
// 기존첨부파일 삭제
|
||||||
|
const deleteOriginFile = async (objectNo, no) => {
|
||||||
|
const delParams = {
|
||||||
|
userId: session.userId,
|
||||||
|
objectNo: objectNo,
|
||||||
|
no: no,
|
||||||
|
}
|
||||||
|
await promisePost({ url: 'api/file/fileDelete', data: delParams }).then((res) => {
|
||||||
|
if (res.status === 204) {
|
||||||
|
setOriginFiles(originFiles.filter((file) => file.objectNo === objectNo && file.no !== no))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sub-content estimate">
|
<div className="sub-content estimate">
|
||||||
<div className="sub-content-inner">
|
<div className="sub-content-inner">
|
||||||
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */}
|
{/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */}
|
||||||
{/* <form onSubmit={handleSubmit(onValid)}> */}
|
|
||||||
<div className="sub-content-box">
|
<div className="sub-content-box">
|
||||||
<div className="sub-table-box">
|
<div className="sub-table-box">
|
||||||
<div className="estimate-list-wrap one">
|
<div className="estimate-list-wrap one">
|
||||||
@ -206,7 +233,6 @@ export default function Estimate({ params }) {
|
|||||||
defaultValue={state?.charger}
|
defaultValue={state?.charger}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
//담당자 charger
|
//담당자 charger
|
||||||
// console.log('담당자:::::', e.target.value)
|
|
||||||
setState({ charger: e.target.value })
|
setState({ charger: e.target.value })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -227,7 +253,6 @@ export default function Estimate({ params }) {
|
|||||||
defaultValue={state?.objectName}
|
defaultValue={state?.objectName}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
//안건명 objectName
|
//안건명 objectName
|
||||||
// console.log('안건명::::', e.target.value)
|
|
||||||
setState({ objectName: e.target.value })
|
setState({ objectName: e.target.value })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -244,7 +269,6 @@ export default function Estimate({ params }) {
|
|||||||
if (isObjectNotEmpty(e)) {
|
if (isObjectNotEmpty(e)) {
|
||||||
setState({ objectNameOmit: e.clCodeNm })
|
setState({ objectNameOmit: e.clCodeNm })
|
||||||
} else {
|
} else {
|
||||||
// console.log('XXX')
|
|
||||||
setState({ objectNameOmit: '' })
|
setState({ objectNameOmit: '' })
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -342,7 +366,6 @@ export default function Estimate({ params }) {
|
|||||||
defaultValue={state?.remarks}
|
defaultValue={state?.remarks}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
//비고
|
//비고
|
||||||
// console.log('비고:::::', e.target.value)
|
|
||||||
setState({ remarks: e.target.value })
|
setState({ remarks: e.target.value })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -390,6 +413,23 @@ export default function Estimate({ params }) {
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('estimate.detail.header.fileList2')}</th>
|
<th>{getMessage('estimate.detail.header.fileList2')}</th>
|
||||||
|
<td>
|
||||||
|
<div className="drag-file-box">
|
||||||
|
<ul className="file-list">
|
||||||
|
{isNotEmptyArray(originFiles) &&
|
||||||
|
originFiles.map((originFile) => {
|
||||||
|
return (
|
||||||
|
<li className="file-item">
|
||||||
|
<span>
|
||||||
|
{originFile.faileName}
|
||||||
|
<button className="delete" onClick={() => deleteOriginFile(originFile.objectNo, originFile.no)}></button>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@ -439,7 +479,7 @@ export default function Estimate({ params }) {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
{/* 견적특이사항 선택한 내용?영역시작 */}
|
{/* 견적특이사항 선택한 내용 영역시작 */}
|
||||||
<div className="calculation-estimate">
|
<div className="calculation-estimate">
|
||||||
{specialNoteList.map((row) => {
|
{specialNoteList.map((row) => {
|
||||||
if (row.code === showContentCode) {
|
if (row.code === showContentCode) {
|
||||||
@ -570,7 +610,6 @@ export default function Estimate({ params }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* 기본정보끝 */}
|
{/* 기본정보끝 */}
|
||||||
{/* </form> */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { QLine } from '@/components/fabric/QLine'
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
import {
|
||||||
import { calculateAngle, drawRidgeRoof, drawHippedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils'
|
distanceBetweenPoints,
|
||||||
|
findTopTwoIndexesByDistance,
|
||||||
|
getAllRelatedObjects,
|
||||||
|
getDirectionByPoint,
|
||||||
|
sortedPointLessEightPoint,
|
||||||
|
sortedPoints,
|
||||||
|
} from '@/util/canvas-util'
|
||||||
|
import { calculateAngle, drawRidgeRoof, drawShedRoof, inPolygon, toGeoJSON } from '@/util/qpolygon-utils'
|
||||||
import * as turf from '@turf/turf'
|
import * as turf from '@turf/turf'
|
||||||
import { LINE_TYPE } from '@/common/common'
|
import { LINE_TYPE } from '@/common/common'
|
||||||
|
|
||||||
@ -131,7 +138,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this.on('removed', () => {
|
this.on('removed', () => {
|
||||||
const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id)
|
// const children = getAllRelatedObjects(this.id, this.canvas)
|
||||||
|
const children = this.canvas.getObjects().filter((obj) => obj.parentId === this.id && obj.name === 'lengthText')
|
||||||
children.forEach((child) => {
|
children.forEach((child) => {
|
||||||
this.canvas.remove(child)
|
this.canvas.remove(child)
|
||||||
})
|
})
|
||||||
@ -171,6 +179,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
offset: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
parent: this,
|
parent: this,
|
||||||
|
parentId: this.id,
|
||||||
direction: getDirectionByPoint(point, nextPoint),
|
direction: getDirectionByPoint(point, nextPoint),
|
||||||
idx: i + 1,
|
idx: i + 1,
|
||||||
})
|
})
|
||||||
@ -189,7 +198,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE]
|
const eavesType = [LINE_TYPE.WALLLINE.EAVES, LINE_TYPE.WALLLINE.HIPANDGABLE]
|
||||||
const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD]
|
const gableType = [LINE_TYPE.WALLLINE.GABLE, LINE_TYPE.WALLLINE.JERKINHEAD]
|
||||||
|
|
||||||
const isEaves = types.every((type) => eavesType.includes(type))
|
// const isEaves = types.every((type) => eavesType.includes(type))
|
||||||
const gableOdd = types.filter((type, i) => i % 2 === 0)
|
const gableOdd = types.filter((type, i) => i % 2 === 0)
|
||||||
const gableEven = types.filter((type, i) => i % 2 === 1)
|
const gableEven = types.filter((type, i) => i % 2 === 1)
|
||||||
const hasShed = types.includes(LINE_TYPE.WALLLINE.SHED)
|
const hasShed = types.includes(LINE_TYPE.WALLLINE.SHED)
|
||||||
@ -201,18 +210,40 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
) {
|
) {
|
||||||
console.log('박공 지붕')
|
console.log('박공 지붕')
|
||||||
} else if (hasShed) {
|
} else if (hasShed) {
|
||||||
//편류지붕
|
const sheds = this.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED)
|
||||||
let shedIndex = 0
|
const areLinesParallel = function (line1, line2) {
|
||||||
types.forEach((type, i) => {
|
const angle1 = calculateAngle(line1.startPoint, line1.endPoint)
|
||||||
if (type === LINE_TYPE.WALLLINE.SHED) {
|
const angle2 = calculateAngle(line2.startPoint, line2.endPoint)
|
||||||
shedIndex = i
|
return angle1 === angle2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isShedRoof = true
|
||||||
|
sheds.forEach((shed, i) => {
|
||||||
|
isShedRoof = areLinesParallel(shed, sheds[(i + 1) % sheds.length])
|
||||||
})
|
})
|
||||||
const shedOdd = types.filter((type, i) => i % 2 === shedIndex % 2).filter((type) => type !== LINE_TYPE.WALLLINE.SHED)
|
if (isShedRoof) {
|
||||||
const shedEven = types.filter((type, i) => i % 2 !== shedIndex % 2)
|
const eaves = this.lines
|
||||||
types.forEach((type, i) => console.log(type, i, i % 2, shedIndex % 2, i % 2 === shedIndex % 2))
|
.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||||
if (shedOdd.every((type) => type === LINE_TYPE.WALLLINE.EAVES) && shedEven.every((type) => type === LINE_TYPE.WALLLINE.GABLE)) {
|
.filter((line) => {
|
||||||
console.log('편류지붕')
|
const angle1 = calculateAngle(sheds[0].startPoint, sheds[0].endPoint)
|
||||||
|
const angle2 = calculateAngle(line.startPoint, line.endPoint)
|
||||||
|
if (Math.abs(angle1 - angle2) === 180) {
|
||||||
|
return line
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (eaves.length > 0) {
|
||||||
|
const gables = this.lines.filter((line) => sheds.includes(line) === false && eaves.includes(line) === false)
|
||||||
|
const isGable = gables.every((line) => gableType.includes(line.attributes.type))
|
||||||
|
if (isGable) {
|
||||||
|
drawShedRoof(this.id, this.canvas)
|
||||||
|
} else {
|
||||||
|
drawRidgeRoof(this.id, this.canvas)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
drawRidgeRoof(this.id, this.canvas)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
drawRidgeRoof(this.id, this.canvas)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drawRidgeRoof(this.id, this.canvas)
|
drawRidgeRoof(this.id, this.canvas)
|
||||||
|
|||||||
@ -19,7 +19,7 @@ export default function CanvasFrame() {
|
|||||||
const { canvas } = useCanvas('canvas')
|
const { canvas } = useCanvas('canvas')
|
||||||
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
||||||
const currentMenu = useRecoilValue(currentMenuState)
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
const { contextMenu, handleClick, handleKeyup } = useContextMenu()
|
const { contextMenu, handleClick } = useContextMenu()
|
||||||
const { selectedPlan, modifiedPlanFlag, checkCanvasObjectEvent, resetModifiedPlans } = usePlan()
|
const { selectedPlan, modifiedPlanFlag, checkCanvasObjectEvent, resetModifiedPlans } = usePlan()
|
||||||
useEvent()
|
useEvent()
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ export default function CanvasFrame() {
|
|||||||
<div className="canvas-frame">
|
<div className="canvas-frame">
|
||||||
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
||||||
|
|
||||||
<QContextMenu contextRef={canvasRef} canvasProps={canvas} handleKeyup={handleKeyup}>
|
<QContextMenu contextRef={canvasRef} canvasProps={canvas}>
|
||||||
{contextMenu?.map((menus, index) => (
|
{contextMenu?.map((menus, index) => (
|
||||||
<ul key={index}>
|
<ul key={index}>
|
||||||
{menus.map((menu) => (
|
{menus.map((menu) => (
|
||||||
|
|||||||
@ -240,7 +240,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
<WithDraggable isShow={true} pos={pos}>
|
||||||
<div className={`modal-pop-wrap lr-2`}>
|
<div className={`modal-pop-wrap lr-2`}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('plan.menu.placement.surface.arrangement')} </h1>
|
<h1 className="title">{getMessage('plan.menu.placement.surface.arrangement')} </h1>
|
||||||
|
|||||||
@ -11,12 +11,12 @@ import { useRecoilValue } from 'recoil'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function SettingModal01(props) {
|
export default function SettingModal01(props) {
|
||||||
const { setShowDotLineGridModal, setShowFontSettingModal, id, isConfig } = props
|
const { id } = props
|
||||||
console.log(props)
|
|
||||||
const [buttonAct, setButtonAct] = useState(1)
|
const [buttonAct, setButtonAct] = useState(1)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor)
|
const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor)
|
||||||
const { addPopup, closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const handleBtnClick = (num) => {
|
const handleBtnClick = (num) => {
|
||||||
setButtonAct(num)
|
setButtonAct(num)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,21 +5,19 @@ import { useRouter, usePathname } from 'next/navigation'
|
|||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import StuffQGrid from './StuffQGrid'
|
import StuffQGrid from './StuffQGrid'
|
||||||
import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil'
|
import { useRecoilValue, useRecoilState, useSetRecoilState, useResetRecoilState } from 'recoil'
|
||||||
import { stuffSearchState } from '@/store/stuffAtom'
|
import { stuffSearchState } from '@/store/stuffAtom'
|
||||||
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
|
||||||
import { convertNumberToPriceDecimal } from '@/util/common-utils'
|
import { convertNumberToPriceDecimal } from '@/util/common-utils'
|
||||||
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
|
||||||
import KO from '@/locales/ko.json'
|
import KO from '@/locales/ko.json'
|
||||||
import JA from '@/locales/ja.json'
|
import JA from '@/locales/ja.json'
|
||||||
import QPagination from '../common/pagination/QPagination'
|
import QPagination from '../common/pagination/QPagination'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
|
|
||||||
export default function Stuff() {
|
export default function Stuff() {
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
const setAppMessageState = useSetRecoilState(appMessageStore)
|
const setAppMessageState = useSetRecoilState(appMessageStore)
|
||||||
const stuffSearchParams = useRecoilValue(stuffSearchState)
|
const stuffSearchParams = useRecoilValue(stuffSearchState)
|
||||||
@ -34,9 +32,6 @@ export default function Stuff() {
|
|||||||
const { get } = useAxios(globalLocaleState)
|
const { get } = useAxios(globalLocaleState)
|
||||||
const gridRef = useRef()
|
const gridRef = useRef()
|
||||||
|
|
||||||
// const [selectedRowData, setSelectedRowData] = useState([])
|
|
||||||
// const [selectedRowDataCount, setSelectedRowDataCount] = useState(0)
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
|
|
||||||
@ -67,10 +62,6 @@ export default function Stuff() {
|
|||||||
field: 'lastEditDatetime',
|
field: 'lastEditDatetime',
|
||||||
minWidth: 200,
|
minWidth: 200,
|
||||||
headerName: getMessage('stuff.gridHeader.lastEditDatetime'),
|
headerName: getMessage('stuff.gridHeader.lastEditDatetime'),
|
||||||
// headerCheckboxSelection: true,
|
|
||||||
// headerCheckboxSelectionCurrentPageOnly: true, //페이징시 현재 페이지만 체크되도록
|
|
||||||
// checkboxSelection: true,
|
|
||||||
// showDisabledCheckboxes: true,
|
|
||||||
cellStyle: { justifyContent: 'center' },
|
cellStyle: { justifyContent: 'center' },
|
||||||
valueFormatter: function (params) {
|
valueFormatter: function (params) {
|
||||||
if (params.value) {
|
if (params.value) {
|
||||||
@ -169,77 +160,69 @@ export default function Stuff() {
|
|||||||
|
|
||||||
// 진입시 그리드 데이터 조회
|
// 진입시 그리드 데이터 조회
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isObjectNotEmpty(session)) {
|
if (stuffSearchParams?.code === 'S') {
|
||||||
if (stuffSearchParams?.code === 'S') {
|
const params = {
|
||||||
const params = {
|
saleStoreId: session.storeId,
|
||||||
// saleStoreId: stuffSearchParams.schSelSaleStoreId,
|
schObjectNo: stuffSearchParams?.schObjectNo,
|
||||||
saleStoreId: session.storeId,
|
schAddress: stuffSearchParams?.schAddress,
|
||||||
schObjectNo: stuffSearchParams?.schObjectNo,
|
schObjectName: stuffSearchParams?.schObjectName,
|
||||||
schAddress: stuffSearchParams?.schAddress,
|
schSaleStoreName: stuffSearchParams?.schSaleStoreName,
|
||||||
schObjectName: stuffSearchParams?.schObjectName,
|
schReceiveUser: stuffSearchParams?.schReceiveUser,
|
||||||
schSaleStoreName: stuffSearchParams?.schSaleStoreName,
|
schDispCompanyName: stuffSearchParams?.schDispCompanyName,
|
||||||
schReceiveUser: stuffSearchParams?.schReceiveUser,
|
schDateType: stuffSearchParams.schDateType,
|
||||||
schDispCompanyName: stuffSearchParams?.schDispCompanyName,
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
||||||
schDateType: stuffSearchParams.schDateType,
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
startRow: (pageNo - 1) * pageSize + 1,
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
endRow: pageNo * pageSize,
|
||||||
startRow: (pageNo - 1) * pageSize + 1,
|
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId,
|
||||||
endRow: pageNo * pageSize,
|
schSortType: stuffSearchParams.schSortType,
|
||||||
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId
|
}
|
||||||
? stuffSearchParams.schOtherSelSaleStoreId
|
|
||||||
: stuffSearchParams.schSelSaleStoreId,
|
async function fetchData() {
|
||||||
schSortType: stuffSearchParams.schSortType,
|
const apiUrl = `/api/object/list?${queryStringFormatter(params)}`
|
||||||
}
|
await get({
|
||||||
async function fetchData() {
|
url: apiUrl,
|
||||||
const apiUrl = `/api/object/list?${queryStringFormatter(params)}`
|
}).then((res) => {
|
||||||
await get({
|
if (!isEmptyArray(res)) {
|
||||||
url: apiUrl,
|
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
|
||||||
}).then((res) => {
|
setTotalCount(res[0].totCnt)
|
||||||
if (!isEmptyArray(res)) {
|
}
|
||||||
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
|
|
||||||
setTotalCount(res[0].totCnt)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (stuffSearchParams?.schSelSaleStoreId !== '') {
|
|
||||||
fetchData()
|
|
||||||
}
|
|
||||||
} else if (stuffSearchParams?.code === 'M') {
|
|
||||||
//메인화면에서 진입
|
|
||||||
const params = {
|
|
||||||
saleStoreId: session?.storeId,
|
|
||||||
schObjectNo: stuffSearchParams.schObjectNo,
|
|
||||||
schAddress: '',
|
|
||||||
schObjectName: '',
|
|
||||||
schSaleStoreName: '',
|
|
||||||
schReceiveUser: '',
|
|
||||||
schDispCompanyName: '',
|
|
||||||
schDateType: 'U',
|
|
||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
|
||||||
startRow: (pageNo - 1) * pageSize + 1,
|
|
||||||
endRow: pageNo * pageSize,
|
|
||||||
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId
|
|
||||||
? stuffSearchParams.schOtherSelSaleStoreId
|
|
||||||
: stuffSearchParams.schSelSaleStoreId,
|
|
||||||
schSortType: 'R',
|
|
||||||
}
|
|
||||||
setStuffSearch({
|
|
||||||
...params,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}, [pageNo, session, stuffSearchParams])
|
|
||||||
|
|
||||||
useEffect(() => {
|
if (stuffSearch.schSelSaleStoreId !== '') {
|
||||||
if (stuffSearchParams?.code === 'E') {
|
fetchData()
|
||||||
|
}
|
||||||
|
} else if (stuffSearchParams?.code === 'M') {
|
||||||
|
const params = {
|
||||||
|
saleStoreId: session?.storeId,
|
||||||
|
schObjectNo: stuffSearchParams.schObjectNo,
|
||||||
|
schAddress: '',
|
||||||
|
schObjectName: '',
|
||||||
|
schSaleStoreName: '',
|
||||||
|
schReceiveUser: '',
|
||||||
|
schDispCompanyName: '',
|
||||||
|
schDateType: 'U',
|
||||||
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
||||||
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
||||||
|
startRow: (pageNo - 1) * pageSize + 1,
|
||||||
|
endRow: pageNo * pageSize,
|
||||||
|
schSelSaleStoreId: stuffSearchParams?.schOtherSelSaleStoreId ? stuffSearchParams.schOtherSelSaleStoreId : stuffSearchParams.schSelSaleStoreId,
|
||||||
|
schSortType: 'R',
|
||||||
|
}
|
||||||
|
setStuffSearch({
|
||||||
|
...params,
|
||||||
|
})
|
||||||
|
} else if (stuffSearchParams?.code === 'E') {
|
||||||
stuffSearchParams.startRow = 1
|
stuffSearchParams.startRow = 1
|
||||||
stuffSearchParams.endRow = 1 * pageSize
|
stuffSearchParams.endRow = 1 * pageSize
|
||||||
stuffSearchParams.schSortType = defaultSortType
|
stuffSearchParams.schSortType = defaultSortType
|
||||||
|
|
||||||
setPageNo(1)
|
setPageNo(1)
|
||||||
|
setStuffSearch({
|
||||||
|
...stuffSearch,
|
||||||
|
code: 'FINISH',
|
||||||
|
})
|
||||||
|
|
||||||
//조회를 눌렀을때
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
||||||
await get({ url: apiUrl }).then((res) => {
|
await get({ url: apiUrl }).then((res) => {
|
||||||
@ -252,7 +235,10 @@ export default function Stuff() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData()
|
fetchData()
|
||||||
|
} else if (stuffSearchParams?.code === 'C') {
|
||||||
|
resetStuffRecoil()
|
||||||
}
|
}
|
||||||
}, [stuffSearchParams])
|
}, [stuffSearchParams])
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty } from '@/util/common-u
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useForm } from 'react-hook-form'
|
import { useForm } from 'react-hook-form'
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
import FindAddressPop from './popup/FindAddressPop'
|
import FindAddressPop from './popup/FindAddressPop'
|
||||||
import PlanRequestPop from './popup/PlanRequestPop'
|
import PlanRequestPop from './popup/PlanRequestPop'
|
||||||
@ -28,7 +27,6 @@ export default function StuffDetail() {
|
|||||||
const [selOptions, setSelOptions] = useState('') //선택한 1차점
|
const [selOptions, setSelOptions] = useState('') //선택한 1차점
|
||||||
const [otherSelOptions, setOtherSelOptions] = useState('') //선택한 1차점외
|
const [otherSelOptions, setOtherSelOptions] = useState('') //선택한 1차점외
|
||||||
|
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@ -320,12 +318,11 @@ export default function StuffDetail() {
|
|||||||
let firstList
|
let firstList
|
||||||
let otherList
|
let otherList
|
||||||
let favList
|
let favList
|
||||||
// if (sessionState?.storeId === 'T01') {
|
|
||||||
if (session?.storeId === 'T01') {
|
if (session?.storeId === 'T01') {
|
||||||
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
||||||
} else {
|
} else {
|
||||||
if (session.storeLvl === '1') {
|
if (session.storeLvl === '1') {
|
||||||
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
||||||
} else {
|
} else {
|
||||||
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
||||||
}
|
}
|
||||||
@ -400,7 +397,6 @@ export default function StuffDetail() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// }, [objectNo, sessionState])
|
|
||||||
}, [objectNo, session])
|
}, [objectNo, session])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -1279,9 +1275,7 @@ export default function StuffDetail() {
|
|||||||
|
|
||||||
//1차점 or 2차점 안고르고 임시저장하면
|
//1차점 or 2차점 안고르고 임시저장하면
|
||||||
if (params.saleStoreId == '') {
|
if (params.saleStoreId == '') {
|
||||||
// params.saleStoreId = sessionState.storeId
|
|
||||||
params.saleStoreId = session.storeId
|
params.saleStoreId = session.storeId
|
||||||
// params.saleStoreLevel = sessionState.storeLvl
|
|
||||||
params.saleStoreLevel = session.storeLvl
|
params.saleStoreLevel = session.storeLvl
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,7 +1439,6 @@ export default function StuffDetail() {
|
|||||||
</th>
|
</th>
|
||||||
<td>
|
<td>
|
||||||
<div className="flx-box">
|
<div className="flx-box">
|
||||||
{/* {sessionState?.storeId === 'T01' && ( */}
|
|
||||||
{session?.storeId === 'T01' && (
|
{session?.storeId === 'T01' && (
|
||||||
<>
|
<>
|
||||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||||
@ -1479,7 +1472,6 @@ export default function StuffDetail() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl === '1' && ( */}
|
|
||||||
{session?.storeId !== 'T01' && session?.storeLvl === '1' && (
|
{session?.storeId !== 'T01' && session?.storeLvl === '1' && (
|
||||||
<>
|
<>
|
||||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||||
@ -1511,7 +1503,6 @@ export default function StuffDetail() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl !== '1' && ( */}
|
|
||||||
{session?.storeId !== 'T01' && session?.storeLvl !== '1' && (
|
{session?.storeId !== 'T01' && session?.storeLvl !== '1' && (
|
||||||
<>
|
<>
|
||||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import { isEmptyArray } from '@/util/common-utils'
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
||||||
import { sessionStore } from '@/store/commonAtom'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
|
|
||||||
@ -20,7 +19,6 @@ import { SessionContext } from '@/app/SessionProvider'
|
|||||||
|
|
||||||
export default function StuffSearchCondition() {
|
export default function StuffSearchCondition() {
|
||||||
const { session } = useContext(SessionContext)
|
const { session } = useContext(SessionContext)
|
||||||
const sessionState = useRecoilValue(sessionStore)
|
|
||||||
const setAppMessageState = useSetRecoilState(appMessageStore)
|
const setAppMessageState = useSetRecoilState(appMessageStore)
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
@ -94,13 +92,13 @@ export default function StuffSearchCondition() {
|
|||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
setStuffSearch({
|
setStuffSearch({
|
||||||
schObjectNo: objectNo ? objectNo : '',
|
schObjectNo: objectNo,
|
||||||
schSaleStoreName: saleStoreName ? saleStoreName : '',
|
schSaleStoreName: saleStoreName,
|
||||||
schAddress: address ? address : '',
|
schAddress: address,
|
||||||
schObjectName: objectName ? objectName : '',
|
schObjectName: objectName,
|
||||||
schDispCompanyName: dispCompanyName ? dispCompanyName : '',
|
schDispCompanyName: dispCompanyName,
|
||||||
schSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : stuffSearch.schSelSaleStoreId,
|
schSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : stuffSearch.schSelSaleStoreId,
|
||||||
schReceiveUser: receiveUser ? receiveUser : '',
|
schReceiveUser: receiveUser,
|
||||||
schDateType: dateType,
|
schDateType: dateType,
|
||||||
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
|
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
|
||||||
schToDt: dayjs(endDate).format('YYYY-MM-DD'),
|
schToDt: dayjs(endDate).format('YYYY-MM-DD'),
|
||||||
@ -131,14 +129,12 @@ export default function StuffSearchCondition() {
|
|||||||
setDateType('U')
|
setDateType('U')
|
||||||
setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||||
setEndDate(dayjs(new Date()).format('YYYY-MM-DD'))
|
setEndDate(dayjs(new Date()).format('YYYY-MM-DD'))
|
||||||
// if (sessionState?.storeId === 'T01') {
|
|
||||||
if (session?.storeId === 'T01') {
|
if (session?.storeId === 'T01') {
|
||||||
setSchSelSaleStoreId('')
|
setSchSelSaleStoreId('')
|
||||||
handleClear1() //판매대리점선택 자동완성 클리어
|
handleClear1() //판매대리점선택 자동완성 클리어
|
||||||
resetStuffRecoil()
|
resetStuffRecoil()
|
||||||
setStuffSearch({
|
setStuffSearch({
|
||||||
...stuffSearch,
|
...stuffSearch,
|
||||||
code: 'C',
|
|
||||||
schSelSaleStoreId: '',
|
schSelSaleStoreId: '',
|
||||||
schOtherSelSaleStoreId: '',
|
schOtherSelSaleStoreId: '',
|
||||||
})
|
})
|
||||||
@ -156,23 +152,17 @@ export default function StuffSearchCondition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// if (isObjectNotEmpty(sessionState)) {
|
|
||||||
if (isObjectNotEmpty(session)) {
|
if (isObjectNotEmpty(session)) {
|
||||||
// storeId가 T01 이거나 storeLvl이 1차점일때만 판매대리점 선택 활성화
|
// storeId가 T01 이거나 storeLvl이 1차점일때만 판매대리점 선택 활성화
|
||||||
let url
|
let url
|
||||||
// if (sessionState?.storeId === 'T01') {
|
|
||||||
if (session?.storeId === 'T01') {
|
if (session?.storeId === 'T01') {
|
||||||
//T01일떄
|
//T01일떄
|
||||||
// url = `/api/object/saleStore/${sessionState?.storeId}/firstList?userId=${sessionState?.userId}`
|
|
||||||
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
||||||
} else {
|
} else {
|
||||||
// if (sessionState.storeLvl === '1') {
|
|
||||||
if (session.storeLvl === '1') {
|
if (session.storeLvl === '1') {
|
||||||
//T01아닌 1차점일때
|
//T01아닌 1차점일때
|
||||||
// url = `/api/object/saleStore/${sessionState?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
||||||
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}`
|
|
||||||
} else {
|
} else {
|
||||||
// url = `/api/object/saleStore/${sessionState?.storeId}/list?firstFlg=1&userId=${sessionState?.userId}`
|
|
||||||
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,7 +177,6 @@ export default function StuffSearchCondition() {
|
|||||||
let allList
|
let allList
|
||||||
let favList
|
let favList
|
||||||
let otherList
|
let otherList
|
||||||
// if (sessionState?.storeId === 'T01') {
|
|
||||||
if (session?.storeId === 'T01') {
|
if (session?.storeId === 'T01') {
|
||||||
allList = res
|
allList = res
|
||||||
allList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
|
allList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
|
||||||
@ -195,17 +184,14 @@ export default function StuffSearchCondition() {
|
|||||||
setSchSelSaleStoreList(allList)
|
setSchSelSaleStoreList(allList)
|
||||||
setFavoriteStoreList(favList)
|
setFavoriteStoreList(favList)
|
||||||
setShowSaleStoreList(favList)
|
setShowSaleStoreList(favList)
|
||||||
// setSchSelSaleStoreId(sessionState?.storeId)
|
|
||||||
setSchSelSaleStoreId(session?.storeId)
|
setSchSelSaleStoreId(session?.storeId)
|
||||||
setStuffSearch({
|
setStuffSearch({
|
||||||
...stuffSearch,
|
...stuffSearch,
|
||||||
code: 'S',
|
code: 'S',
|
||||||
// schSelSaleStoreId: sessionState?.storeId,
|
|
||||||
schSelSaleStoreId: session?.storeId,
|
schSelSaleStoreId: session?.storeId,
|
||||||
})
|
})
|
||||||
|
|
||||||
//T01일때 2차 판매점 호출하기 디폴트로 1차점을 본인으로 셋팅해서 세션storeId사용
|
//T01일때 2차 판매점 호출하기 디폴트로 1차점을 본인으로 셋팅해서 세션storeId사용
|
||||||
// url = `/api/object/saleStore/${sessionState?.storeId}/list?firstFlg=0&userId=${sessionState?.userId}`
|
|
||||||
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=0&userId=${session?.userId}`
|
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=0&userId=${session?.userId}`
|
||||||
|
|
||||||
get({ url: url }).then((res) => {
|
get({ url: url }).then((res) => {
|
||||||
@ -222,7 +208,6 @@ export default function StuffSearchCondition() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// if (sessionState?.storeLvl === '1') {
|
|
||||||
if (session?.storeLvl === '1') {
|
if (session?.storeLvl === '1') {
|
||||||
allList = res
|
allList = res
|
||||||
favList = res.filter((row) => row.priority !== 'B')
|
favList = res.filter((row) => row.priority !== 'B')
|
||||||
@ -250,7 +235,6 @@ export default function StuffSearchCondition() {
|
|||||||
setOtherSaleStoreList(otherList)
|
setOtherSaleStoreList(otherList)
|
||||||
|
|
||||||
//선택한 2차점 세션으로 자동셋팅
|
//선택한 2차점 세션으로 자동셋팅
|
||||||
// setOtherSaleStoreId(sessionState?.storeId)
|
|
||||||
setOtherSaleStoreId(session?.storeId)
|
setOtherSaleStoreId(session?.storeId)
|
||||||
setStuffSearch({
|
setStuffSearch({
|
||||||
...stuffSearch,
|
...stuffSearch,
|
||||||
@ -262,7 +246,6 @@ export default function StuffSearchCondition() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// }, [sessionState])
|
|
||||||
}, [session])
|
}, [session])
|
||||||
|
|
||||||
//초기화 눌렀을 때 1차판매점 자동완성도..
|
//초기화 눌렀을 때 1차판매점 자동완성도..
|
||||||
@ -296,7 +279,6 @@ export default function StuffSearchCondition() {
|
|||||||
stuffSearch.schSelSaleStoreId = key.saleStoreId
|
stuffSearch.schSelSaleStoreId = key.saleStoreId
|
||||||
//T01아닌 1차점은 본인으로 디폴트셋팅이고 수정할수없어서 여기안옴
|
//T01아닌 1차점은 본인으로 디폴트셋팅이고 수정할수없어서 여기안옴
|
||||||
//고른 1차점의 saleStoreId로 2차점 API호출하기
|
//고른 1차점의 saleStoreId로 2차점 API호출하기
|
||||||
// let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${sessionState?.userId}`
|
|
||||||
let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${session?.userId}`
|
let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${session?.userId}`
|
||||||
let otherList
|
let otherList
|
||||||
get({ url: url }).then((res) => {
|
get({ url: url }).then((res) => {
|
||||||
@ -339,6 +321,12 @@ export default function StuffSearchCondition() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||||
setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
|
setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
|
||||||
|
setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
|
||||||
|
setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
|
||||||
|
setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
|
||||||
|
setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
|
||||||
|
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
||||||
|
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
||||||
}, [stuffSearch])
|
}, [stuffSearch])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -401,7 +389,7 @@ export default function StuffSearchCondition() {
|
|||||||
ref={objectNoRef}
|
ref={objectNoRef}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
defaultValue={stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo}
|
defaultValue={stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo}
|
||||||
onChange={(e) => {
|
onChange={() => {
|
||||||
setObjectNo(objectNoRef.current.value)
|
setObjectNo(objectNoRef.current.value)
|
||||||
}}
|
}}
|
||||||
onKeyUp={handleByOnKeyUp}
|
onKeyUp={handleByOnKeyUp}
|
||||||
@ -416,7 +404,7 @@ export default function StuffSearchCondition() {
|
|||||||
ref={saleStoreNameRef}
|
ref={saleStoreNameRef}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
defaultValue={stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName}
|
defaultValue={stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName}
|
||||||
onChange={(e) => {
|
onChange={() => {
|
||||||
setSaleStoreName(saleStoreNameRef.current.value)
|
setSaleStoreName(saleStoreNameRef.current.value)
|
||||||
}}
|
}}
|
||||||
onKeyUp={handleByOnKeyUp}
|
onKeyUp={handleByOnKeyUp}
|
||||||
@ -431,7 +419,7 @@ export default function StuffSearchCondition() {
|
|||||||
ref={addressRef}
|
ref={addressRef}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
defaultValue={stuffSearch?.schAddress ? stuffSearch.schAddress : address}
|
defaultValue={stuffSearch?.schAddress ? stuffSearch.schAddress : address}
|
||||||
onChange={(e) => {
|
onChange={() => {
|
||||||
setAddress(addressRef.current.value)
|
setAddress(addressRef.current.value)
|
||||||
}}
|
}}
|
||||||
onKeyUp={handleByOnKeyUp}
|
onKeyUp={handleByOnKeyUp}
|
||||||
@ -446,7 +434,7 @@ export default function StuffSearchCondition() {
|
|||||||
ref={dispCompanyNameRef}
|
ref={dispCompanyNameRef}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
defaultValue={stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName}
|
defaultValue={stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName}
|
||||||
onChange={(e) => {
|
onChange={() => {
|
||||||
setDispCompanyName(dispCompanyNameRef.current.value)
|
setDispCompanyName(dispCompanyNameRef.current.value)
|
||||||
}}
|
}}
|
||||||
onKeyUp={handleByOnKeyUp}
|
onKeyUp={handleByOnKeyUp}
|
||||||
@ -463,7 +451,7 @@ export default function StuffSearchCondition() {
|
|||||||
ref={objectNameRef}
|
ref={objectNameRef}
|
||||||
className="input-light"
|
className="input-light"
|
||||||
defaultValue={stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName}
|
defaultValue={stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName}
|
||||||
onChange={(e) => {
|
onChange={() => {
|
||||||
setobjectName(objectNameRef.current.value)
|
setobjectName(objectNameRef.current.value)
|
||||||
}}
|
}}
|
||||||
onKeyUp={handleByOnKeyUp}
|
onKeyUp={handleByOnKeyUp}
|
||||||
@ -478,7 +466,7 @@ export default function StuffSearchCondition() {
|
|||||||
className="input-light"
|
className="input-light"
|
||||||
ref={receiveUserRef}
|
ref={receiveUserRef}
|
||||||
defaultValue={stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser}
|
defaultValue={stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser}
|
||||||
onChange={(e) => {
|
onChange={() => {
|
||||||
setReceiveUser(receiveUserRef.current.value)
|
setReceiveUser(receiveUserRef.current.value)
|
||||||
}}
|
}}
|
||||||
onKeyUp={handleByOnKeyUp}
|
onKeyUp={handleByOnKeyUp}
|
||||||
@ -620,7 +608,6 @@ export default function StuffSearchCondition() {
|
|||||||
value={'U'}
|
value={'U'}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setDateType(e.target.value)
|
setDateType(e.target.value)
|
||||||
//setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="radio_u">{getMessage('stuff.search.schDateTypeU')}</label>
|
<label htmlFor="radio_u">{getMessage('stuff.search.schDateTypeU')}</label>
|
||||||
@ -634,7 +621,6 @@ export default function StuffSearchCondition() {
|
|||||||
value={'R'}
|
value={'R'}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setDateType(e.target.value)
|
setDateType(e.target.value)
|
||||||
//setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
|
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useEffect, useReducer, useState } from 'react'
|
import { useContext, useEffect, useReducer, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { globalLocaleStore } from '@/store/localeAtom'
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
|
|
||||||
const reducer = (prevState, nextState) => {
|
const reducer = (prevState, nextState) => {
|
||||||
return { ...prevState, ...nextState }
|
return { ...prevState, ...nextState }
|
||||||
}
|
}
|
||||||
@ -41,6 +43,7 @@ const defaultEstimateData = {
|
|||||||
unit: '',
|
unit: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
fileList: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
@ -51,14 +54,14 @@ const updateItemInList = (itemList, itemId, updates) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useEstimateController = (planNo) => {
|
export const useEstimateController = (planNo) => {
|
||||||
|
const { session } = useContext(SessionContext)
|
||||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||||
const [estimateData, setEstimateData] = useRecoilState(estimateState)
|
const [estimateData, setEstimateData] = useRecoilState(estimateState)
|
||||||
|
|
||||||
const { get, post } = useAxios(globalLocaleState)
|
const { get, post, promisePost } = useAxios(globalLocaleState)
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false)
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
const { promisePost } = useAxios()
|
|
||||||
const [state, setState] = useReducer(reducer, defaultEstimateData)
|
const [state, setState] = useReducer(reducer, defaultEstimateData)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -123,12 +126,32 @@ export const useEstimateController = (planNo) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setEstimateData({ ...state })
|
setEstimateData({ ...state, userId: session.userId })
|
||||||
|
//sapSalesStoreCd 추가예정 필수값
|
||||||
|
// setEstimateData({ ...state, userId: session.userId, sapSalesStoreCd : session.sapSalesStoreCd })
|
||||||
}, [state])
|
}, [state])
|
||||||
|
|
||||||
//견적서 저장
|
//견적서 저장
|
||||||
const handleEstimateSubmit = async () => {
|
const handleEstimateSubmit = async () => {
|
||||||
console.log('::담긴 estimateData:::', estimateData)
|
console.log('::담긴 estimateData:::', estimateData)
|
||||||
|
//1. 첨부파일 저장
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('file', estimateData.fileList)
|
||||||
|
formData.append('objectNo', estimateData.objectNo)
|
||||||
|
formData.append('planNo', estimateData.planNo)
|
||||||
|
formData.append('category', '10')
|
||||||
|
formData.append('userId', estimateData.userId)
|
||||||
|
for (const value of formData.values()) {
|
||||||
|
console.log('formData::', value)
|
||||||
|
}
|
||||||
|
|
||||||
|
await promisePost({ url: '/api/file/fileUpload', data: formData }).then((res) => {
|
||||||
|
console.log('파일저장::::::::::', res)
|
||||||
|
})
|
||||||
|
|
||||||
|
//2. 상세데이터 저장
|
||||||
|
|
||||||
|
console.log('상세저장시작!!')
|
||||||
return
|
return
|
||||||
try {
|
try {
|
||||||
const result = await promisePost({
|
const result = await promisePost({
|
||||||
|
|||||||
@ -815,7 +815,7 @@ export function useAuxiliaryDrawing(id) {
|
|||||||
roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 }))
|
roofBase.lines.some((line) => isPointOnLine(line, { x: line.x2, y: line.y2 }))
|
||||||
|
|
||||||
if (inPolygon1 && inPolygon2) {
|
if (inPolygon1 && inPolygon2) {
|
||||||
line.attributes = { ...line.attributes, roofId: roofBase.id }
|
line.attributes = { ...line.attributes, roofId: roofBase.id, actualSize: 0, planeSize: line.getLength() }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { useRecoilValue } from 'recoil'
|
|||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { setSurfaceShapePattern } from '@/util/canvas-util'
|
import { setSurfaceShapePattern } from '@/util/canvas-util'
|
||||||
import { splitPolygonWithLines } from '@/util/qpolygon-utils'
|
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||||
@ -13,7 +12,7 @@ import { POLYGON_TYPE } from '@/common/common'
|
|||||||
export function useRoofAllocationSetting(id) {
|
export function useRoofAllocationSetting(id) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||||
const { drawDirectionArrow } = usePolygon()
|
const { drawDirectionArrow, addLengthText, splitPolygonWithLines } = usePolygon()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
|
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
|
|||||||
@ -170,6 +170,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
//기존 wallLine 삭제
|
//기존 wallLine 삭제
|
||||||
|
|
||||||
let outerLines
|
let outerLines
|
||||||
|
let direction
|
||||||
|
|
||||||
switch (shapeNum) {
|
switch (shapeNum) {
|
||||||
case 1: {
|
case 1: {
|
||||||
@ -196,6 +197,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
// 서쪽
|
// 서쪽
|
||||||
initLineSetting()
|
initLineSetting()
|
||||||
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
|
direction = 'west'
|
||||||
|
|
||||||
outerLines.forEach((line) => {
|
outerLines.forEach((line) => {
|
||||||
setWestAndEastRoof(line)
|
setWestAndEastRoof(line)
|
||||||
@ -240,6 +242,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
case 6: {
|
case 6: {
|
||||||
initLineSetting()
|
initLineSetting()
|
||||||
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
|
direction = 'east'
|
||||||
|
|
||||||
outerLines.forEach((line) => {
|
outerLines.forEach((line) => {
|
||||||
setWestAndEastRoof(line)
|
setWestAndEastRoof(line)
|
||||||
@ -285,6 +288,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
case 7: {
|
case 7: {
|
||||||
initLineSetting()
|
initLineSetting()
|
||||||
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
|
direction = 'south'
|
||||||
|
|
||||||
outerLines.forEach((line) => {
|
outerLines.forEach((line) => {
|
||||||
setSouthAndNorthRoof(line)
|
setSouthAndNorthRoof(line)
|
||||||
@ -329,6 +333,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
case 8: {
|
case 8: {
|
||||||
initLineSetting()
|
initLineSetting()
|
||||||
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
|
direction = 'north'
|
||||||
|
|
||||||
outerLines.forEach((line) => {
|
outerLines.forEach((line) => {
|
||||||
setSouthAndNorthRoof(line)
|
setSouthAndNorthRoof(line)
|
||||||
@ -389,7 +394,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
canvas.remove(obj)
|
canvas.remove(obj)
|
||||||
})
|
})
|
||||||
|
|
||||||
const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL })
|
const polygon = addPolygonByLines(outerLines, { name: POLYGON_TYPE.WALL, direction })
|
||||||
polygon.lines = [...outerLines]
|
polygon.lines = [...outerLines]
|
||||||
|
|
||||||
addPitchTextsByOuterLines()
|
addPitchTextsByOuterLines()
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { canvasSizeState, canvasState, canvasZoomState, currentObjectState, fontFamilyState, fontSizeState } from '@/store/canvasAtom'
|
import { canvasSizeState, canvasState, canvasZoomState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
import { fontSelector } from '@/store/fontAtom'
|
import { fontSelector } from '@/store/fontAtom'
|
||||||
@ -12,8 +12,6 @@ export function useCanvasEvent() {
|
|||||||
const [canvasForEvent, setCanvasForEvent] = useState(null)
|
const [canvasForEvent, setCanvasForEvent] = useState(null)
|
||||||
const [currentObject, setCurrentObject] = useRecoilState(currentObjectState)
|
const [currentObject, setCurrentObject] = useRecoilState(currentObjectState)
|
||||||
const canvasSize = useRecoilValue(canvasSizeState)
|
const canvasSize = useRecoilValue(canvasSizeState)
|
||||||
const fontSize = useRecoilValue(fontSizeState)
|
|
||||||
const fontFamily = useRecoilValue(fontFamilyState)
|
|
||||||
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||||
const lengthTextOption = useRecoilValue(fontSelector('lengthText'))
|
const lengthTextOption = useRecoilValue(fontSelector('lengthText'))
|
||||||
const { modifiedPlanFlag, setModifiedPlanFlag } = usePlan()
|
const { modifiedPlanFlag, setModifiedPlanFlag } = usePlan()
|
||||||
@ -209,13 +207,52 @@ export function useCanvasEvent() {
|
|||||||
created: (e) => {
|
created: (e) => {
|
||||||
const target = e.selected[0]
|
const target = e.selected[0]
|
||||||
setCurrentObject(target)
|
setCurrentObject(target)
|
||||||
|
const { selected } = e
|
||||||
|
|
||||||
|
if (selected?.length > 0) {
|
||||||
|
selected.forEach((obj) => {
|
||||||
|
if (obj.type === 'QPolygon') {
|
||||||
|
obj.set({ stroke: 'red' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
canvas.renderAll()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
cleared: (e) => {
|
cleared: (e) => {
|
||||||
setCurrentObject(null)
|
setCurrentObject(null)
|
||||||
|
const { deselected } = e
|
||||||
|
|
||||||
|
if (deselected?.length > 0) {
|
||||||
|
deselected.forEach((obj) => {
|
||||||
|
if (obj.type === 'QPolygon') {
|
||||||
|
obj.set({ stroke: 'black' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
canvas.renderAll()
|
||||||
},
|
},
|
||||||
updated: (e) => {
|
updated: (e) => {
|
||||||
const target = e.selected[0]
|
const target = e.selected[0]
|
||||||
setCurrentObject(target)
|
setCurrentObject(target)
|
||||||
|
const { selected, deselected } = e
|
||||||
|
|
||||||
|
if (deselected?.length > 0) {
|
||||||
|
deselected.forEach((obj) => {
|
||||||
|
if (obj.type === 'QPolygon') {
|
||||||
|
obj.set({ stroke: 'black' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selected?.length > 0) {
|
||||||
|
selected.forEach((obj) => {
|
||||||
|
if (obj.type === 'QPolygon') {
|
||||||
|
obj.set({ stroke: 'red' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.renderAll()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -231,12 +231,12 @@ export function useContextMenu() {
|
|||||||
y: 180,
|
y: 180,
|
||||||
})
|
})
|
||||||
setCurrentContextMenu(menu)
|
setCurrentContextMenu(menu)
|
||||||
|
currentMenuSetting()
|
||||||
setQContextMenu({ ...qContextMenu, visible: false })
|
setQContextMenu({ ...qContextMenu, visible: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleKeyup = (e) => {
|
const handleKeyup = (e) => {
|
||||||
let menu = null
|
let menu = null
|
||||||
|
|
||||||
for (let i = 0; i < contextMenu.length; i++) {
|
for (let i = 0; i < contextMenu.length; i++) {
|
||||||
const temp = contextMenu[i].filter((menu) => {
|
const temp = contextMenu[i].filter((menu) => {
|
||||||
return menu.shortcut?.includes(e.key)
|
return menu.shortcut?.includes(e.key)
|
||||||
@ -259,7 +259,6 @@ export function useContextMenu() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('currentObject', currentObject)
|
console.log('currentObject', currentObject)
|
||||||
if (currentObject?.name) {
|
if (currentObject?.name) {
|
||||||
console.log(currentObject?.name)
|
|
||||||
switch (currentObject.name) {
|
switch (currentObject.name) {
|
||||||
case 'triangleDormer':
|
case 'triangleDormer':
|
||||||
case 'pentagonDormer':
|
case 'pentagonDormer':
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom'
|
import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint, polygonToTurfPolygon } from '@/util/canvas-util'
|
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
|
||||||
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
||||||
import { useDotLineGrid } from '@/hooks/useDotLineGrid'
|
import { useDotLineGrid } from '@/hooks/useDotLineGrid'
|
||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
|
||||||
|
|
||||||
export function useEvent() {
|
export function useEvent() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -100,7 +99,13 @@ export function useEvent() {
|
|||||||
const distance = calculateDistance(pointer, closestLine)
|
const distance = calculateDistance(pointer, closestLine)
|
||||||
|
|
||||||
if (distance < adsorptionRange) {
|
if (distance < adsorptionRange) {
|
||||||
arrivalPoint = closestLine.direction === 'vertical' ? { x: closestLine.x1, y: pointer.y } : { x: pointer.x, y: closestLine.y1 }
|
arrivalPoint =
|
||||||
|
closestLine.direction === 'vertical'
|
||||||
|
? { x: closestLine.x1, y: pointer.y }
|
||||||
|
: {
|
||||||
|
x: pointer.x,
|
||||||
|
y: closestLine.y1,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -261,6 +266,7 @@ export function useEvent() {
|
|||||||
addCanvasMouseEventListener,
|
addCanvasMouseEventListener,
|
||||||
removeAllMouseEventListeners,
|
removeAllMouseEventListeners,
|
||||||
removeAllDocumentEventListeners,
|
removeAllDocumentEventListeners,
|
||||||
|
removeDocumentEvent,
|
||||||
removeMouseEvent,
|
removeMouseEvent,
|
||||||
removeMouseLine,
|
removeMouseLine,
|
||||||
initEvent,
|
initEvent,
|
||||||
|
|||||||
@ -1515,9 +1515,17 @@ export function useMode() {
|
|||||||
pitch: 4,
|
pitch: 4,
|
||||||
sleeve: true,
|
sleeve: true,
|
||||||
}
|
}
|
||||||
/*if (index === 1 || index === 3) {
|
/*if (index === 1) {
|
||||||
line.attributes = {
|
line.attributes = {
|
||||||
type: LINE_TYPE.WALLLINE.WALL,
|
type: LINE_TYPE.WALLLINE.SHED,
|
||||||
|
offset: 30, //출폭
|
||||||
|
width: 30, //폭
|
||||||
|
pitch: 4, //구배
|
||||||
|
sleeve: true, //소매
|
||||||
|
}
|
||||||
|
} else if (index === 5 || index === 3) {
|
||||||
|
line.attributes = {
|
||||||
|
type: LINE_TYPE.WALLLINE.EAVES,
|
||||||
offset: 50, //출폭
|
offset: 50, //출폭
|
||||||
width: 30, //폭
|
width: 30, //폭
|
||||||
pitch: 4, //구배
|
pitch: 4, //구배
|
||||||
@ -1525,8 +1533,8 @@ export function useMode() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
line.attributes = {
|
line.attributes = {
|
||||||
type: LINE_TYPE.WALLLINE.EAVES,
|
type: LINE_TYPE.WALLLINE.GABLE,
|
||||||
offset: 40,
|
offset: 20,
|
||||||
width: 50,
|
width: 50,
|
||||||
pitch: 4,
|
pitch: 4,
|
||||||
sleeve: true,
|
sleeve: true,
|
||||||
@ -1746,12 +1754,20 @@ export function useMode() {
|
|||||||
return { x1: point.x, y1: point.y }
|
return { x1: point.x, y1: point.y }
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
if (wall.direction) {
|
||||||
|
roof.direction = wall.direction
|
||||||
|
}
|
||||||
roof.name = POLYGON_TYPE.ROOF
|
roof.name = POLYGON_TYPE.ROOF
|
||||||
roof.setWall(wall)
|
roof.setWall(wall)
|
||||||
|
|
||||||
roof.lines.forEach((line, index) => {
|
roof.lines.forEach((line, index) => {
|
||||||
|
const lineLength = Math.sqrt(
|
||||||
|
Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2),
|
||||||
|
)
|
||||||
line.attributes = {
|
line.attributes = {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
|
planeSize: lineLength,
|
||||||
|
actualSize: lineLength,
|
||||||
wallLine: wall.lines[index].id,
|
wallLine: wall.lines[index].id,
|
||||||
type: wall.lines[index].attributes.type,
|
type: wall.lines[index].attributes.type,
|
||||||
offset: wall.lines[index].attributes.offset,
|
offset: wall.lines[index].attributes.offset,
|
||||||
@ -1770,9 +1786,6 @@ export function useMode() {
|
|||||||
line.attributes.currentRoof = roof.lines[index].id
|
line.attributes.currentRoof = roof.lines[index].id
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log('drawRoofPolygon roof : ', roof)
|
|
||||||
console.log('drawRoofPolygon wall : ', wall)
|
|
||||||
|
|
||||||
setRoof(roof)
|
setRoof(roof)
|
||||||
setWall(wall)
|
setWall(wall)
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, fontFamilyState, fontSizeState, pitchTextSelector } 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 { getDegreeByChon, getDirectionByPoint } from '@/util/canvas-util'
|
import { getDegreeByChon, getDirectionByPoint, isPointOnLine } from '@/util/canvas-util'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
import { isSamePoint } from '@/util/qpolygon-utils'
|
import { isSamePoint, removeDuplicatePolygons } from '@/util/qpolygon-utils'
|
||||||
import { flowDisplaySelector } from '@/store/settingAtom'
|
import { flowDisplaySelector } from '@/store/settingAtom'
|
||||||
import { fontSelector } from '@/store/fontAtom'
|
import { fontSelector } from '@/store/fontAtom'
|
||||||
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
export const usePolygon = () => {
|
export const usePolygon = () => {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -25,6 +27,7 @@ export const usePolygon = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
canvas?.add(polygon)
|
canvas?.add(polygon)
|
||||||
|
addLengthText(polygon)
|
||||||
|
|
||||||
return polygon
|
return polygon
|
||||||
}
|
}
|
||||||
@ -40,7 +43,64 @@ export const usePolygon = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const addLengthText = (polygon) => {
|
const addLengthText = (polygon) => {
|
||||||
const points = polygon.get('points')
|
const lengthTexts = canvas.getObjects().filter((obj) => obj.name === 'lengthText' && obj.parentId === polygon.id)
|
||||||
|
lengthTexts.forEach((text) => {
|
||||||
|
canvas.remove(text)
|
||||||
|
})
|
||||||
|
const lines = polygon.lines
|
||||||
|
|
||||||
|
lines.forEach((line, i) => {
|
||||||
|
const length = line.getLength()
|
||||||
|
const { planeSize, actualSize } = line.attributes
|
||||||
|
const scaleX = line.scaleX
|
||||||
|
const scaleY = line.scaleY
|
||||||
|
const x1 = line.left
|
||||||
|
const y1 = line.top
|
||||||
|
const x2 = line.left + line.width * scaleX
|
||||||
|
const y2 = line.top + line.height * scaleY
|
||||||
|
|
||||||
|
let left, top
|
||||||
|
|
||||||
|
if (line.direction === 'left' || line.direction === 'right') {
|
||||||
|
left = (x1 + x2) / 2
|
||||||
|
top = (y1 + y2) / 2 + 10
|
||||||
|
} else if (line.direction === 'top' || line.direction === 'bottom') {
|
||||||
|
left = (x1 + x2) / 2 + 10
|
||||||
|
top = (y1 + y2) / 2
|
||||||
|
}
|
||||||
|
|
||||||
|
const minX = line.left
|
||||||
|
const maxX = line.left + line.width
|
||||||
|
const minY = line.top
|
||||||
|
const maxY = line.top + line.length
|
||||||
|
const degree = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI
|
||||||
|
|
||||||
|
const text = new fabric.Textbox(actualSize ? actualSize.toString() : planeSize ? planeSize.toString() : length.toString(), {
|
||||||
|
left: left,
|
||||||
|
top: top,
|
||||||
|
fontSize: lengthTextFontOptions.fontSize.value,
|
||||||
|
minX,
|
||||||
|
maxX,
|
||||||
|
minY,
|
||||||
|
maxY,
|
||||||
|
parentDirection: line.direction,
|
||||||
|
parentDegree: degree,
|
||||||
|
parentId: polygon.id,
|
||||||
|
planeSize,
|
||||||
|
actualSize,
|
||||||
|
editable: false,
|
||||||
|
selectable: true,
|
||||||
|
lockRotation: true,
|
||||||
|
lockScalingX: true,
|
||||||
|
lockScalingY: true,
|
||||||
|
parent: polygon,
|
||||||
|
name: 'lengthText',
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.add(text)
|
||||||
|
})
|
||||||
|
|
||||||
|
/*const points = polygon.get('points')
|
||||||
points.forEach((start, i) => {
|
points.forEach((start, i) => {
|
||||||
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
|
||||||
@ -71,12 +131,12 @@ export const usePolygon = () => {
|
|||||||
lockScalingY: true,
|
lockScalingY: true,
|
||||||
idx: i,
|
idx: i,
|
||||||
name: 'lengthText',
|
name: 'lengthText',
|
||||||
parent: this,
|
parent: polygon,
|
||||||
})
|
})
|
||||||
|
|
||||||
// this.texts.push(text)
|
// this.texts.push(text)
|
||||||
canvas.add(text)
|
canvas.add(text)
|
||||||
})
|
})*/
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -409,7 +469,8 @@ export const usePolygon = () => {
|
|||||||
|
|
||||||
const addTextByArrows = (arrows, txt, canvas) => {
|
const addTextByArrows = (arrows, txt, canvas) => {
|
||||||
arrows.forEach((arrow, index) => {
|
arrows.forEach((arrow, index) => {
|
||||||
const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`
|
// const textStr = `${txt}${index + 1} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`
|
||||||
|
const textStr = `${txt} (${currentAngleType === ANGLE_TYPE.SLOPE ? arrow.pitch : getDegreeByChon(arrow.pitch)}${pitchText})`
|
||||||
|
|
||||||
const text = new fabric.Text(`${textStr}`, {
|
const text = new fabric.Text(`${textStr}`, {
|
||||||
fontSize: flowFontOptions.fontSize.value,
|
fontSize: flowFontOptions.fontSize.value,
|
||||||
@ -432,10 +493,272 @@ export const usePolygon = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const splitPolygonWithLines = (polygon) => {
|
||||||
|
polygon.set({ visible: false })
|
||||||
|
let innerLines = [...polygon.innerLines]
|
||||||
|
let polygonLines = [...polygon.lines]
|
||||||
|
const roofs = []
|
||||||
|
|
||||||
|
let delIndexs = []
|
||||||
|
let newLines = []
|
||||||
|
|
||||||
|
polygonLines.forEach((line, index) => {
|
||||||
|
line.tempIndex = index
|
||||||
|
innerLines.forEach((innerLine) => {
|
||||||
|
let newLine1, newLine2
|
||||||
|
if (isPointOnLine(line, innerLine.startPoint)) {
|
||||||
|
// 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다.
|
||||||
|
newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 3,
|
||||||
|
})
|
||||||
|
|
||||||
|
newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 3,
|
||||||
|
})
|
||||||
|
delIndexs.push(polygonLines.indexOf(line))
|
||||||
|
canvas.remove(polygonLines[polygonLines.indexOf(line)])
|
||||||
|
if (newLine1.length / 10 > 10) {
|
||||||
|
newLines.push(newLine1)
|
||||||
|
}
|
||||||
|
if (newLine2.length / 10 > 10) {
|
||||||
|
newLines.push(newLine2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isPointOnLine(line, innerLine.endPoint)) {
|
||||||
|
newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 3,
|
||||||
|
})
|
||||||
|
|
||||||
|
newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 3,
|
||||||
|
})
|
||||||
|
delIndexs.push(polygonLines.indexOf(line))
|
||||||
|
canvas.remove(polygonLines[polygonLines.indexOf(line)])
|
||||||
|
if (newLine1.length / 10 > 10) {
|
||||||
|
newLines.push(newLine1)
|
||||||
|
}
|
||||||
|
if (newLine2.length / 10 > 10) {
|
||||||
|
newLines.push(newLine2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex))
|
||||||
|
polygonLines = [...polygonLines, ...newLines]
|
||||||
|
|
||||||
|
const allLines = [...polygonLines, ...innerLines]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 왼쪽 상단을 startPoint로 전부 변경
|
||||||
|
*/
|
||||||
|
allLines.forEach((line) => {
|
||||||
|
let startPoint // 시작점
|
||||||
|
let endPoint // 끝점
|
||||||
|
if (line.x1 < line.x2) {
|
||||||
|
startPoint = { x: line.x1, y: line.y1 }
|
||||||
|
endPoint = { x: line.x2, y: line.y2 }
|
||||||
|
} else if (line.x1 > line.x2) {
|
||||||
|
startPoint = { x: line.x2, y: line.y2 }
|
||||||
|
endPoint = { x: line.x1, y: line.y1 }
|
||||||
|
} else {
|
||||||
|
if (line.y1 < line.y2) {
|
||||||
|
startPoint = { x: line.x1, y: line.y1 }
|
||||||
|
endPoint = { x: line.x2, y: line.y2 }
|
||||||
|
} else {
|
||||||
|
startPoint = { x: line.x2, y: line.y2 }
|
||||||
|
endPoint = { x: line.x1, y: line.y1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line.startPoint = startPoint
|
||||||
|
line.endPoint = endPoint
|
||||||
|
})
|
||||||
|
|
||||||
|
polygonLines.forEach((line) => {
|
||||||
|
const startPoint = line.startPoint // 시작점
|
||||||
|
let arrivalPoint = line.endPoint // 도착점
|
||||||
|
|
||||||
|
let currentPoint = startPoint
|
||||||
|
const roofPoints = [startPoint]
|
||||||
|
|
||||||
|
const startLine = line
|
||||||
|
const visitPoints = [startPoint]
|
||||||
|
const visitLines = [startLine]
|
||||||
|
let cnt = 0
|
||||||
|
|
||||||
|
while (!isSamePoint(currentPoint, arrivalPoint)) {
|
||||||
|
let nextLines = allLines.filter(
|
||||||
|
(line2) =>
|
||||||
|
(isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) &&
|
||||||
|
line !== line2 &&
|
||||||
|
innerLines.includes(line2) &&
|
||||||
|
!visitLines.includes(line2),
|
||||||
|
)
|
||||||
|
|
||||||
|
if (nextLines.length === 0) {
|
||||||
|
nextLines = allLines.filter(
|
||||||
|
(line2) =>
|
||||||
|
(isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) &&
|
||||||
|
line !== line2 &&
|
||||||
|
!visitLines.includes(line2),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nextLines) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
let comparisonPoints = []
|
||||||
|
|
||||||
|
nextLines.forEach((nextLine) => {
|
||||||
|
if (isSamePoint(nextLine.startPoint, currentPoint)) {
|
||||||
|
comparisonPoints.push(nextLine.endPoint)
|
||||||
|
} else {
|
||||||
|
comparisonPoints.push(nextLine.startPoint)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
comparisonPoints = comparisonPoints.filter((point) => !visitPoints.some((visitPoint) => isSamePoint(visitPoint, point)))
|
||||||
|
comparisonPoints = comparisonPoints.filter((point) => !isSamePoint(point, currentPoint))
|
||||||
|
|
||||||
|
const minDistancePoint = comparisonPoints.reduce((prev, current) => {
|
||||||
|
const prevDistance = Math.sqrt(Math.pow(prev.x - arrivalPoint.x, 2) + Math.pow(prev.y - arrivalPoint.y, 2))
|
||||||
|
const currentDistance = Math.sqrt(Math.pow(current.x - arrivalPoint.x, 2) + Math.pow(current.y - arrivalPoint.y, 2))
|
||||||
|
|
||||||
|
return prevDistance < currentDistance ? prev : current
|
||||||
|
}, comparisonPoints[0])
|
||||||
|
|
||||||
|
nextLines.forEach((nextLine) => {
|
||||||
|
if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) {
|
||||||
|
visitLines.push(nextLine)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
currentPoint = { ...minDistancePoint }
|
||||||
|
roofPoints.push(currentPoint)
|
||||||
|
cnt++
|
||||||
|
if (cnt > 100) {
|
||||||
|
throw new Error('무한루프')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roofs.push(roofPoints)
|
||||||
|
})
|
||||||
|
|
||||||
|
const newRoofs = removeDuplicatePolygons(roofs)
|
||||||
|
|
||||||
|
newRoofs.forEach((roofPoint, index) => {
|
||||||
|
let defense, pitch
|
||||||
|
const polygonLines = [...polygon.lines]
|
||||||
|
|
||||||
|
let representLines = []
|
||||||
|
let representLine
|
||||||
|
|
||||||
|
// 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다.
|
||||||
|
polygonLines.forEach((line) => {
|
||||||
|
let startFlag = false
|
||||||
|
let endFlag = false
|
||||||
|
const startPoint = line.startPoint
|
||||||
|
const endPoint = line.endPoint
|
||||||
|
roofPoint.forEach((point, index) => {
|
||||||
|
if (isSamePoint(point, startPoint)) {
|
||||||
|
startFlag = true
|
||||||
|
}
|
||||||
|
if (isSamePoint(point, endPoint)) {
|
||||||
|
endFlag = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (startFlag && endFlag) {
|
||||||
|
if (!representLines.includes(line)) {
|
||||||
|
representLines.push(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// representLines중 가장 긴 line을 찾는다.
|
||||||
|
representLines.forEach((line) => {
|
||||||
|
if (!representLine) {
|
||||||
|
representLine = line
|
||||||
|
} else {
|
||||||
|
if (representLine.length < line.length) {
|
||||||
|
representLine = line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const direction = newRoofs.length === 1 ? polygon.direction : representLine.direction
|
||||||
|
const polygonDirection = polygon.direction
|
||||||
|
|
||||||
|
switch (direction) {
|
||||||
|
case 'top':
|
||||||
|
defense = 'east'
|
||||||
|
break
|
||||||
|
case 'right':
|
||||||
|
defense = 'south'
|
||||||
|
break
|
||||||
|
case 'bottom':
|
||||||
|
defense = 'west'
|
||||||
|
break
|
||||||
|
case 'left':
|
||||||
|
defense = 'north'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
pitch = polygon.lines[index].attributes?.pitch ?? 0
|
||||||
|
|
||||||
|
const roof = new QPolygon(roofPoint, {
|
||||||
|
fontSize: polygon.fontSize,
|
||||||
|
stroke: 'black',
|
||||||
|
fill: 'transparent',
|
||||||
|
strokeWidth: 3,
|
||||||
|
name: POLYGON_TYPE.ROOF,
|
||||||
|
originX: 'center',
|
||||||
|
originY: 'center',
|
||||||
|
selectable: true,
|
||||||
|
defense: defense,
|
||||||
|
direction: newRoofs.length === 1 ? polygonDirection : defense,
|
||||||
|
pitch: pitch,
|
||||||
|
})
|
||||||
|
|
||||||
|
//allLines중 생성된 roof와 관련있는 line을 찾는다.
|
||||||
|
|
||||||
|
roof.lines = [...polygon.lines, ...polygon.innerLines].filter((line) => {
|
||||||
|
let startFlag = false
|
||||||
|
let endFlag = false
|
||||||
|
const startPoint = line.startPoint
|
||||||
|
const endPoint = line.endPoint
|
||||||
|
roofPoint.forEach((point, index) => {
|
||||||
|
if (isSamePoint(point, startPoint)) {
|
||||||
|
startFlag = true
|
||||||
|
}
|
||||||
|
if (isSamePoint(point, endPoint)) {
|
||||||
|
endFlag = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return startFlag && endFlag
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas.add(roof)
|
||||||
|
addLengthText(roof)
|
||||||
|
canvas.remove(polygon)
|
||||||
|
canvas.renderAll()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addPolygon,
|
addPolygon,
|
||||||
addPolygonByLines,
|
addPolygonByLines,
|
||||||
removePolygon,
|
removePolygon,
|
||||||
drawDirectionArrow,
|
drawDirectionArrow,
|
||||||
|
addLengthText,
|
||||||
|
splitPolygonWithLines,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -925,3 +925,32 @@ export function checkLineOrientation(line) {
|
|||||||
return 'diagonal' // 대각선
|
return 'diagonal' // 대각선
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 최상위 parentId를 통해 모든 하위 객체를 찾는 함수
|
||||||
|
export const getAllRelatedObjects = (id, canvas) => {
|
||||||
|
const result = []
|
||||||
|
const map = new Map()
|
||||||
|
|
||||||
|
// Create a map of objects by their id
|
||||||
|
canvas.getObjects().forEach((obj) => {
|
||||||
|
map.set(obj.id, obj)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Helper function to recursively find all related objects
|
||||||
|
function findRelatedObjects(id) {
|
||||||
|
const obj = map.get(id)
|
||||||
|
if (obj) {
|
||||||
|
result.push(obj)
|
||||||
|
canvas.getObjects().forEach((o) => {
|
||||||
|
if (o.parentId === id) {
|
||||||
|
findRelatedObjects(o.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the search with the given parentId
|
||||||
|
findRelatedObjects(id)
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|||||||
@ -1177,244 +1177,6 @@ export default function offsetPolygon(vertices, offset) {
|
|||||||
polygon.canvas.renderAll()
|
polygon.canvas.renderAll()
|
||||||
})
|
})
|
||||||
}*/
|
}*/
|
||||||
export const splitPolygonWithLines = (polygon) => {
|
|
||||||
const canvas = polygon.canvas
|
|
||||||
polygon.set({ visible: false })
|
|
||||||
let innerLines = [...polygon.innerLines]
|
|
||||||
let polygonLines = [...polygon.lines]
|
|
||||||
const roofs = []
|
|
||||||
|
|
||||||
let delIndexs = []
|
|
||||||
let newLines = []
|
|
||||||
|
|
||||||
polygonLines.forEach((line, index) => {
|
|
||||||
line.tempIndex = index
|
|
||||||
innerLines.forEach((innerLine) => {
|
|
||||||
let newLine1, newLine2
|
|
||||||
if (isPointOnLine(line, innerLine.startPoint)) {
|
|
||||||
// 해당 line을 startPoint로 나눈 line2개를 canvas에 추가 하고 기존 line을 제거한다.
|
|
||||||
newLine1 = new QLine([line.x1, line.y1, innerLine.startPoint.x, innerLine.startPoint.y], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 3,
|
|
||||||
})
|
|
||||||
|
|
||||||
newLine2 = new QLine([innerLine.startPoint.x, innerLine.startPoint.y, line.x2, line.y2], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 3,
|
|
||||||
})
|
|
||||||
delIndexs.push(polygonLines.indexOf(line))
|
|
||||||
canvas.remove(polygonLines[polygonLines.indexOf(line)])
|
|
||||||
if (newLine1.length / 10 > 10) {
|
|
||||||
newLines.push(newLine1)
|
|
||||||
}
|
|
||||||
if (newLine2.length / 10 > 10) {
|
|
||||||
newLines.push(newLine2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (isPointOnLine(line, innerLine.endPoint)) {
|
|
||||||
newLine1 = new QLine([line.x1, line.y1, innerLine.endPoint.x, innerLine.endPoint.y], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 3,
|
|
||||||
})
|
|
||||||
|
|
||||||
newLine2 = new QLine([innerLine.endPoint.x, innerLine.endPoint.y, line.x2, line.y2], {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'black',
|
|
||||||
strokeWidth: 3,
|
|
||||||
})
|
|
||||||
delIndexs.push(polygonLines.indexOf(line))
|
|
||||||
canvas.remove(polygonLines[polygonLines.indexOf(line)])
|
|
||||||
if (newLine1.length / 10 > 10) {
|
|
||||||
newLines.push(newLine1)
|
|
||||||
}
|
|
||||||
if (newLine2.length / 10 > 10) {
|
|
||||||
newLines.push(newLine2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
polygonLines = polygonLines.filter((line) => !delIndexs.includes(line.tempIndex))
|
|
||||||
polygonLines = [...polygonLines, ...newLines]
|
|
||||||
|
|
||||||
const allLines = [...polygonLines, ...innerLines]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 왼쪽 상단을 startPoint로 전부 변경
|
|
||||||
*/
|
|
||||||
allLines.forEach((line) => {
|
|
||||||
let startPoint // 시작점
|
|
||||||
let endPoint // 끝점
|
|
||||||
if (line.x1 < line.x2) {
|
|
||||||
startPoint = { x: line.x1, y: line.y1 }
|
|
||||||
endPoint = { x: line.x2, y: line.y2 }
|
|
||||||
} else if (line.x1 > line.x2) {
|
|
||||||
startPoint = { x: line.x2, y: line.y2 }
|
|
||||||
endPoint = { x: line.x1, y: line.y1 }
|
|
||||||
} else {
|
|
||||||
if (line.y1 < line.y2) {
|
|
||||||
startPoint = { x: line.x1, y: line.y1 }
|
|
||||||
endPoint = { x: line.x2, y: line.y2 }
|
|
||||||
} else {
|
|
||||||
startPoint = { x: line.x2, y: line.y2 }
|
|
||||||
endPoint = { x: line.x1, y: line.y1 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
line.startPoint = startPoint
|
|
||||||
line.endPoint = endPoint
|
|
||||||
})
|
|
||||||
|
|
||||||
polygonLines.forEach((line) => {
|
|
||||||
const startPoint = line.startPoint // 시작점
|
|
||||||
let arrivalPoint = line.endPoint // 도착점
|
|
||||||
|
|
||||||
let currentPoint = startPoint
|
|
||||||
const roofPoints = [startPoint]
|
|
||||||
|
|
||||||
const startLine = line
|
|
||||||
const visitPoints = [startPoint]
|
|
||||||
const visitLines = [startLine]
|
|
||||||
let cnt = 0
|
|
||||||
|
|
||||||
while (!isSamePoint(currentPoint, arrivalPoint)) {
|
|
||||||
line.set({ stroke: 'red' })
|
|
||||||
canvas.renderAll()
|
|
||||||
let nextLines = allLines.filter(
|
|
||||||
(line2) =>
|
|
||||||
(isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) &&
|
|
||||||
line !== line2 &&
|
|
||||||
innerLines.includes(line2) &&
|
|
||||||
!visitLines.includes(line2),
|
|
||||||
)
|
|
||||||
|
|
||||||
if (nextLines.length === 0) {
|
|
||||||
nextLines = allLines.filter(
|
|
||||||
(line2) =>
|
|
||||||
(isSamePoint(line2.startPoint, currentPoint) || isSamePoint(line2.endPoint, currentPoint)) &&
|
|
||||||
line !== line2 &&
|
|
||||||
!visitLines.includes(line2),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nextLines) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
let comparisonPoints = []
|
|
||||||
|
|
||||||
nextLines.forEach((nextLine) => {
|
|
||||||
if (isSamePoint(nextLine.startPoint, currentPoint)) {
|
|
||||||
comparisonPoints.push(nextLine.endPoint)
|
|
||||||
} else {
|
|
||||||
comparisonPoints.push(nextLine.startPoint)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
comparisonPoints = comparisonPoints.filter((point) => !visitPoints.some((visitPoint) => isSamePoint(visitPoint, point)))
|
|
||||||
comparisonPoints = comparisonPoints.filter((point) => !isSamePoint(point, currentPoint))
|
|
||||||
|
|
||||||
const minDistancePoint = comparisonPoints.reduce((prev, current) => {
|
|
||||||
const prevDistance = Math.sqrt(Math.pow(prev.x - arrivalPoint.x, 2) + Math.pow(prev.y - arrivalPoint.y, 2))
|
|
||||||
const currentDistance = Math.sqrt(Math.pow(current.x - arrivalPoint.x, 2) + Math.pow(current.y - arrivalPoint.y, 2))
|
|
||||||
|
|
||||||
return prevDistance < currentDistance ? prev : current
|
|
||||||
}, comparisonPoints[0])
|
|
||||||
|
|
||||||
nextLines.forEach((nextLine) => {
|
|
||||||
if (isSamePoint(nextLine.startPoint, minDistancePoint) || isSamePoint(nextLine.endPoint, minDistancePoint)) {
|
|
||||||
visitLines.push(nextLine)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
currentPoint = { ...minDistancePoint }
|
|
||||||
roofPoints.push(currentPoint)
|
|
||||||
cnt++
|
|
||||||
if (cnt > 100) {
|
|
||||||
throw new Error('무한루프')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
roofs.push(roofPoints)
|
|
||||||
})
|
|
||||||
|
|
||||||
const newRoofs = removeDuplicatePolygons(roofs)
|
|
||||||
newRoofs.forEach((roofPoint, index) => {
|
|
||||||
let defense, pitch
|
|
||||||
const polygonLines = [...polygon.lines]
|
|
||||||
|
|
||||||
let representLines = []
|
|
||||||
let representLine
|
|
||||||
|
|
||||||
// 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다.
|
|
||||||
polygonLines.forEach((line) => {
|
|
||||||
let startFlag = false
|
|
||||||
let endFlag = false
|
|
||||||
const startPoint = line.startPoint
|
|
||||||
const endPoint = line.endPoint
|
|
||||||
roofPoint.forEach((point, index) => {
|
|
||||||
if (isSamePoint(point, startPoint)) {
|
|
||||||
startFlag = true
|
|
||||||
}
|
|
||||||
if (isSamePoint(point, endPoint)) {
|
|
||||||
endFlag = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (startFlag && endFlag) {
|
|
||||||
representLines.push(line)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// representLines중 가장 긴 line을 찾는다.
|
|
||||||
representLines.forEach((line) => {
|
|
||||||
if (!representLine) {
|
|
||||||
representLine = line
|
|
||||||
} else {
|
|
||||||
if (representLine.length < line.length) {
|
|
||||||
representLine = line
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const direction = representLine.direction
|
|
||||||
|
|
||||||
switch (direction) {
|
|
||||||
case 'top':
|
|
||||||
defense = 'east'
|
|
||||||
break
|
|
||||||
case 'right':
|
|
||||||
defense = 'south'
|
|
||||||
break
|
|
||||||
case 'bottom':
|
|
||||||
defense = 'west'
|
|
||||||
break
|
|
||||||
case 'left':
|
|
||||||
defense = 'north'
|
|
||||||
break
|
|
||||||
}
|
|
||||||
pitch = polygon.lines[index].attributes?.pitch ?? 0
|
|
||||||
|
|
||||||
const roof = new QPolygon(roofPoint, {
|
|
||||||
fontSize: polygon.fontSize,
|
|
||||||
stroke: 'black',
|
|
||||||
fill: 'transparent',
|
|
||||||
strokeWidth: 3,
|
|
||||||
name: POLYGON_TYPE.ROOF,
|
|
||||||
originX: 'center',
|
|
||||||
originY: 'center',
|
|
||||||
selectable: true,
|
|
||||||
defense: defense,
|
|
||||||
direction: defense,
|
|
||||||
pitch: pitch,
|
|
||||||
})
|
|
||||||
|
|
||||||
polygon.canvas.add(roof)
|
|
||||||
canvas.remove(polygon)
|
|
||||||
polygon.canvas.renderAll()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizePoint(point) {
|
function normalizePoint(point) {
|
||||||
return {
|
return {
|
||||||
@ -1432,7 +1194,7 @@ function arePolygonsEqual(polygon1, polygon2) {
|
|||||||
return normalizedPolygon1.every((point, index) => arePointsEqual(point, normalizedPolygon2[index]))
|
return normalizedPolygon1.every((point, index) => arePointsEqual(point, normalizedPolygon2[index]))
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeDuplicatePolygons(polygons) {
|
export function removeDuplicatePolygons(polygons) {
|
||||||
const uniquePolygons = []
|
const uniquePolygons = []
|
||||||
|
|
||||||
polygons.forEach((polygon) => {
|
polygons.forEach((polygon) => {
|
||||||
@ -1477,6 +1239,42 @@ function calculateAngleBetweenLines(line1, line2) {
|
|||||||
return (angleInRadians * 180) / Math.PI
|
return (angleInRadians * 180) / Math.PI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 한쪽흐름 지붕
|
||||||
|
* @param roofId
|
||||||
|
* @param canvas
|
||||||
|
*/
|
||||||
|
export const drawShedRoof = (roofId, canvas) => {
|
||||||
|
const roof = canvas?.getObjects().find((object) => object.id === roofId)
|
||||||
|
const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
|
||||||
|
if (hasNonParallelLines.length > 0) {
|
||||||
|
alert('대각선이 존재합니다.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const sheds = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.SHED)
|
||||||
|
const eaves = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||||
|
const gables = roof.lines.filter((line) => line.attributes !== undefined && line.attributes.type === LINE_TYPE.WALLLINE.GABLE)
|
||||||
|
|
||||||
|
console.log('gable', gables)
|
||||||
|
|
||||||
|
let shedDegree = sheds[0].attributes.degree || 0
|
||||||
|
const shedChon = sheds[0].attributes.pitch || 0
|
||||||
|
|
||||||
|
if (shedDegree === 0) {
|
||||||
|
shedDegree = getDegreeByChon(shedChon)
|
||||||
|
}
|
||||||
|
const getHeight = function (adjust, degree) {
|
||||||
|
return Math.tan(degree * (Math.PI / 180)) * adjust
|
||||||
|
}
|
||||||
|
|
||||||
|
gables.forEach((gable) => {
|
||||||
|
const adjust = gable.attributes.planeSize
|
||||||
|
const height = getHeight(adjust, shedDegree)
|
||||||
|
gable.attributes.actualSize = Math.round(Math.sqrt(Math.pow(adjust, 2) + Math.pow(height, 2)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const drawRidgeRoof = (roofId, canvas) => {
|
export const drawRidgeRoof = (roofId, canvas) => {
|
||||||
const roof = canvas?.getObjects().find((object) => object.id === roofId)
|
const roof = canvas?.getObjects().find((object) => object.id === roofId)
|
||||||
const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
|
const hasNonParallelLines = roof.lines.filter((line) => line.x1 !== line.x2 && line.y1 !== line.y2)
|
||||||
@ -1769,6 +1567,9 @@ const drawRidge = (roof, canvas) => {
|
|||||||
attributes: { roofId: roof.id },
|
attributes: { roofId: roof.id },
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
|
||||||
canvas.add(ridge)
|
canvas.add(ridge)
|
||||||
roof.ridges.push(ridge)
|
roof.ridges.push(ridge)
|
||||||
roof.innerLines.push(ridge)
|
roof.innerLines.push(ridge)
|
||||||
@ -1809,6 +1610,8 @@ const drawRidge = (roof, canvas) => {
|
|||||||
roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2))
|
roof.ridges = roof.ridges.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2))
|
||||||
roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2))
|
roof.innerLines = roof.innerLines.filter((r) => !(ridge.x1 === r.x1 && ridge.y1 === r.y1 && ridge.x2 === r.x2 && ridge.y2 === r.y2))
|
||||||
roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2))
|
roof.innerLines = roof.innerLines.filter((r) => !(ridge2.x1 === r.x1 && ridge2.y1 === r.y1 && ridge2.x2 === r.x2 && ridge2.y2 === r.y2))
|
||||||
|
newRidge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
newRidge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
canvas.add(newRidge)
|
canvas.add(newRidge)
|
||||||
roof.ridges.push(newRidge)
|
roof.ridges.push(newRidge)
|
||||||
roof.innerLines.push(newRidge)
|
roof.innerLines.push(newRidge)
|
||||||
@ -1884,7 +1687,7 @@ const drawHips = (roof, canvas) => {
|
|||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
name: LINE_TYPE.SUBLINE.HIP,
|
name: LINE_TYPE.SUBLINE.HIP,
|
||||||
attributes: { roofId: roof.id, currentRoof: currentRoof.id },
|
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
|
||||||
})
|
})
|
||||||
canvas.add(hip1)
|
canvas.add(hip1)
|
||||||
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
|
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
|
||||||
@ -1901,12 +1704,7 @@ const drawHips = (roof, canvas) => {
|
|||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
name: LINE_TYPE.SUBLINE.HIP,
|
name: LINE_TYPE.SUBLINE.HIP,
|
||||||
attributes: {
|
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
|
||||||
roofId: roof.id,
|
|
||||||
currentRoof: currentRoof.id,
|
|
||||||
planeSize: currentRoof.length,
|
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
canvas.add(hip2)
|
canvas.add(hip2)
|
||||||
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
|
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
|
||||||
@ -1977,12 +1775,7 @@ const drawHips = (roof, canvas) => {
|
|||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
name: LINE_TYPE.SUBLINE.HIP,
|
name: LINE_TYPE.SUBLINE.HIP,
|
||||||
attributes: {
|
attributes: { roofId: roof.id, currentRoof: currentRoof.id, actualSize: 0 },
|
||||||
roofId: roof.id,
|
|
||||||
currentRoof: currentRoof.id,
|
|
||||||
planeSize: currentRoof.length,
|
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
canvas.add(hip)
|
canvas.add(hip)
|
||||||
const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10
|
const hipBase = ((Math.abs(hip.x1 - hip.x2) + Math.abs(hip.y1 - hip.y2)) / 2) * 10
|
||||||
@ -2040,92 +1833,6 @@ const checkValley = (polygon, line1, line2) => {
|
|||||||
return isValley
|
return isValley
|
||||||
}
|
}
|
||||||
|
|
||||||
const getPointInPolygon = (polygon, point, isInclude = false) => {
|
|
||||||
let inside = false
|
|
||||||
let minX = Math.min(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x),
|
|
||||||
maxX = Math.max(polygon[0].x, polygon[1].x, polygon[2].x, polygon[3].x),
|
|
||||||
minY = Math.min(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y),
|
|
||||||
maxY = Math.max(polygon[0].y, polygon[1].y, polygon[2].y, polygon[3].y)
|
|
||||||
if (!isInclude && minX < point.x && point.x < maxX && minY < point.y && point.y < maxY) {
|
|
||||||
inside = true
|
|
||||||
}
|
|
||||||
if (isInclude && minX <= point.x && point.x <= maxX && minY <= point.y && point.y <= maxY) {
|
|
||||||
inside = true
|
|
||||||
}
|
|
||||||
return inside
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 라인과 마주하는 다른 라인과의 가장 가까운 거리를 구한다.
|
|
||||||
* @param polygon
|
|
||||||
* @param currentLine 현재 라인
|
|
||||||
* @param dVector 현재 라인의 방향
|
|
||||||
* @returns {*[]|null}
|
|
||||||
*/
|
|
||||||
const getAcrossLine = (polygon, currentLine, dVector) => {
|
|
||||||
let acrossLine
|
|
||||||
switch (dVector) {
|
|
||||||
case 45:
|
|
||||||
acrossLine = polygon.lines
|
|
||||||
.filter((line) => line.x1 > currentLine.x1 && line.y1 <= currentLine.y1)
|
|
||||||
.reduce((prev, current) => {
|
|
||||||
if (prev.length > 0) {
|
|
||||||
return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
break
|
|
||||||
case 135:
|
|
||||||
acrossLine = polygon.lines
|
|
||||||
.filter((line) => line.x1 > currentLine.x1 && line.y1 >= currentLine.y1)
|
|
||||||
.reduce((prev, current) => {
|
|
||||||
if (prev.length > 0) {
|
|
||||||
return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
break
|
|
||||||
case 225:
|
|
||||||
acrossLine = polygon.lines
|
|
||||||
.filter((line) => line.x1 < currentLine.x1 && line.y1 >= currentLine.y1)
|
|
||||||
.reduce((prev, current) => {
|
|
||||||
if (prev.length > 0) {
|
|
||||||
return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
break
|
|
||||||
case 315:
|
|
||||||
acrossLine = polygon.lines
|
|
||||||
.filter((line) => line.x1 < currentLine.x1 && line.y1 <= currentLine.y1)
|
|
||||||
.reduce((prev, current) => {
|
|
||||||
if (prev.length > 0) {
|
|
||||||
return Math.abs(currentLine.x1 - current.x1) < Math.abs(currentLine.x1 - prev.x1) ? current : prev
|
|
||||||
} else {
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
return acrossLine
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
추녀마루(hip) 중복방지를 위해 마루와 함께 그려진 추녀마루를 확인한다
|
|
||||||
*/
|
|
||||||
const isAlreadyHip = (polygon, line) => {
|
|
||||||
let isAlreadyHip = false
|
|
||||||
polygon.hips.forEach((hip) => {
|
|
||||||
if (line.x1 === hip.x1 && line.y1 === hip.y1) {
|
|
||||||
isAlreadyHip = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return isAlreadyHip
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
3개 이상 이어지지 않은 라인 포인트 계산
|
3개 이상 이어지지 않은 라인 포인트 계산
|
||||||
모임지붕에서 point는 3개 이상의 라인과 접해야 함.
|
모임지붕에서 point는 3개 이상의 라인과 접해야 함.
|
||||||
@ -2216,6 +1923,8 @@ const connectLinePoint = (polygon) => {
|
|||||||
stroke: 'purple',
|
stroke: 'purple',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
})
|
})
|
||||||
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10
|
||||||
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10) / 10
|
||||||
polygon.canvas.add(line)
|
polygon.canvas.add(line)
|
||||||
polygon.innerLines.push(line)
|
polygon.innerLines.push(line)
|
||||||
})
|
})
|
||||||
@ -2272,6 +1981,8 @@ const connectLinePoint = (polygon) => {
|
|||||||
stroke: 'purple',
|
stroke: 'purple',
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
})
|
})
|
||||||
|
line.attributes.planeSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10)
|
||||||
|
line.attributes.actualSize = Math.round(Math.sqrt(Math.pow(line.x1 - line.x2, 2) + Math.pow(line.y1 - line.y2, 2)) * 10)
|
||||||
polygon.canvas.add(line)
|
polygon.canvas.add(line)
|
||||||
polygon.innerLines.push(line)
|
polygon.innerLines.push(line)
|
||||||
})
|
})
|
||||||
@ -2576,6 +2287,8 @@ const changeEavesRoof = (currentRoof, canvas) => {
|
|||||||
hipX2 = midX - addHipX2
|
hipX2 = midX - addHipX2
|
||||||
hipY2 = midY - addHipY2
|
hipY2 = midY - addHipY2
|
||||||
}
|
}
|
||||||
|
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
hipLines.forEach((hip) => {
|
hipLines.forEach((hip) => {
|
||||||
@ -2753,6 +2466,8 @@ const changeGableRoof = (currentRoof, canvas) => {
|
|||||||
})
|
})
|
||||||
currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
|
currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
|
||||||
}
|
}
|
||||||
|
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
|
||||||
let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], {
|
let hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX, midY], {
|
||||||
fontSize: roof.fontSize,
|
fontSize: roof.fontSize,
|
||||||
@ -2814,6 +2529,14 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
|||||||
if (wallLine.length > 0) {
|
if (wallLine.length > 0) {
|
||||||
wallLine = wallLine[0]
|
wallLine = wallLine[0]
|
||||||
}
|
}
|
||||||
|
let prevRoof, nextRoof
|
||||||
|
roof.lines.forEach((r, index) => {
|
||||||
|
if (r.id === currentRoof.id) {
|
||||||
|
currentRoof = r
|
||||||
|
prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1]
|
||||||
|
nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심
|
const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심
|
||||||
const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심
|
const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심
|
||||||
@ -2927,6 +2650,8 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
|||||||
})
|
})
|
||||||
currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
|
currentRoof.attributes.ridgeCoordinate = { x1: ridge.x2, y1: ridge.y2 }
|
||||||
}
|
}
|
||||||
|
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], {
|
const hip1 = new QLine([currentRoof.x1, currentRoof.y1, midX + hipX2, midY + hipY2], {
|
||||||
@ -2937,10 +2662,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoof: currentRoof.id,
|
currentRoof: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
|
||||||
|
const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
|
||||||
|
|
||||||
|
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
|
||||||
|
const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180))
|
||||||
|
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
|
||||||
|
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
|
||||||
canvas?.add(hip1)
|
canvas?.add(hip1)
|
||||||
roof.innerLines.push(hip1)
|
roof.innerLines.push(hip1)
|
||||||
|
|
||||||
@ -2956,6 +2686,10 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
|||||||
actualSize: currentRoof.length,
|
actualSize: currentRoof.length,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
|
||||||
|
const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180))
|
||||||
|
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
|
||||||
|
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
|
||||||
canvas?.add(hip2)
|
canvas?.add(hip2)
|
||||||
roof.innerLines.push(hip2)
|
roof.innerLines.push(hip2)
|
||||||
|
|
||||||
@ -2974,7 +2708,7 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
hipLines.forEach((hip) => {
|
hipLines.forEach((hip, i) => {
|
||||||
const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], {
|
const gableLine = new QLine([hip.x2, hip.y2, currentRoof.attributes.ridgeCoordinate.x1, currentRoof.attributes.ridgeCoordinate.y1], {
|
||||||
fontSize: roof.fontSize,
|
fontSize: roof.fontSize,
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
@ -2983,10 +2717,15 @@ const changeHipAndGableRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoof: currentRoof.id,
|
currentRoof: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const gableDegree = i === 0 ? prevDegree : nextDegree
|
||||||
|
const gableBase = ((Math.abs(gableLine.x1 - gableLine.x2) + Math.abs(gableLine.y1 - gableLine.y2)) / 2) * 10
|
||||||
|
const gableHeight = Math.round(gableBase / Math.tan(((90 - gableDegree) * Math.PI) / 180))
|
||||||
|
gableLine.attributes.planeSize =
|
||||||
|
Math.round(Math.sqrt(Math.pow(gableLine.x1 - gableLine.x2, 2) + Math.pow(gableLine.y1 - gableLine.y2, 2))) * 10
|
||||||
|
gableLine.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gableLine.attributes.planeSize, 2) + Math.pow(gableHeight, 2)))
|
||||||
canvas?.add(gableLine)
|
canvas?.add(gableLine)
|
||||||
roof.innerLines.push(gableLine)
|
roof.innerLines.push(gableLine)
|
||||||
})
|
})
|
||||||
@ -3016,6 +2755,18 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
wallLine = wallLine[0]
|
wallLine = wallLine[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let prevRoof, nextRoof
|
||||||
|
roof.lines.forEach((r, index) => {
|
||||||
|
if (r.id === currentRoof.id) {
|
||||||
|
currentRoof = r
|
||||||
|
prevRoof = roof.lines[index === 0 ? roof.lines.length - 1 : index - 1]
|
||||||
|
nextRoof = roof.lines[index === roof.lines.length - 1 ? 0 : index + 1]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
|
||||||
|
const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
|
||||||
|
|
||||||
const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심
|
const midX = (currentRoof.x1 + currentRoof.x2) / 2 // 지붕의 X 중심
|
||||||
const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심
|
const midY = (currentRoof.y1 + currentRoof.y2) / 2 // 지붕의 Y 중심
|
||||||
const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심
|
const midWallX = (wallLine.x1 + wallLine.x2) / 2 // 벽의 X 중심
|
||||||
@ -3137,6 +2888,8 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
hipX2 = midX - xWidth
|
hipX2 = midX - xWidth
|
||||||
hipY2 = midY - yWidth
|
hipY2 = midY - yWidth
|
||||||
}
|
}
|
||||||
|
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
}
|
}
|
||||||
|
|
||||||
let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2
|
let hipX1 = (Math.sign(currentRoof.x1 - midX) * currentRoof.attributes.width) / 2
|
||||||
@ -3150,10 +2903,14 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoofId: currentRoof.id,
|
currentRoofId: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const gableDegree = currentRoof.attributes.degree > 0 ? currentRoof.attributes.degree : getDegreeByChon(currentRoof.attributes.pitch)
|
||||||
|
const gable1Base = ((Math.abs(gable1.x1 - gable1.x2) + Math.abs(gable1.y1 - gable1.y2)) / 2) * 10
|
||||||
|
const gable1Height = Math.round(gable1Base / Math.tan(((90 - gableDegree) * Math.PI) / 180))
|
||||||
|
gable1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable1.x1 - gable1.x2, 2) + Math.pow(gable1.y1 - gable1.y2, 2))) * 10
|
||||||
|
gable1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable1.attributes.planeSize, 2) + Math.pow(gable1Height, 2)))
|
||||||
canvas?.add(gable1)
|
canvas?.add(gable1)
|
||||||
roof.innerLines.push(gable1)
|
roof.innerLines.push(gable1)
|
||||||
|
|
||||||
@ -3168,10 +2925,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoofId: currentRoof.id,
|
currentRoofId: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const gable2Base = ((Math.abs(gable2.x1 - gable2.x2) + Math.abs(gable2.y1 - gable2.y2)) / 2) * 10
|
||||||
|
const gable2Height = Math.round(gable2Base / Math.tan(((90 - gableDegree) * Math.PI) / 180))
|
||||||
|
gable2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable2.x1 - gable2.x2, 2) + Math.pow(gable2.y1 - gable2.y2, 2))) * 10
|
||||||
|
gable2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable2.attributes.planeSize, 2) + Math.pow(gable2Height, 2)))
|
||||||
canvas?.add(gable2)
|
canvas?.add(gable2)
|
||||||
roof.innerLines.push(gable2)
|
roof.innerLines.push(gable2)
|
||||||
|
|
||||||
@ -3183,10 +2943,11 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoofId: currentRoof.id,
|
currentRoofId: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
gable3.attributes.planeSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10
|
||||||
|
gable3.attributes.actualSize = Math.round(Math.sqrt(Math.pow(gable3.x1 - gable3.x2, 2) + Math.pow(gable3.y1 - gable3.y2, 2))) * 10
|
||||||
canvas?.add(gable3)
|
canvas?.add(gable3)
|
||||||
roof.innerLines.push(gable3)
|
roof.innerLines.push(gable3)
|
||||||
|
|
||||||
@ -3198,10 +2959,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoofId: currentRoof.id,
|
currentRoofId: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
|
||||||
|
const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180))
|
||||||
|
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
|
||||||
|
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
|
||||||
canvas?.add(hip1)
|
canvas?.add(hip1)
|
||||||
roof.innerLines.push(hip1)
|
roof.innerLines.push(hip1)
|
||||||
|
|
||||||
@ -3213,10 +2977,13 @@ const changeJerkInHeadRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoofId: currentRoof.id,
|
currentRoofId: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
|
||||||
|
const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180))
|
||||||
|
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
|
||||||
|
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
|
||||||
canvas?.add(hip2)
|
canvas?.add(hip2)
|
||||||
roof.innerLines.push(hip2)
|
roof.innerLines.push(hip2)
|
||||||
}
|
}
|
||||||
@ -3312,6 +3079,9 @@ const changeWallRoof = (currentRoof, canvas) => {
|
|||||||
canvas?.remove(line)
|
canvas?.remove(line)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const prevDegree = prevRoof.attributes.pitch > 0 ? getDegreeByChon(prevRoof.attributes.pitch) : prevRoof.attributes.degree
|
||||||
|
const nextDegree = nextRoof.attributes.pitch > 0 ? getDegreeByChon(nextRoof.attributes.pitch) : nextRoof.attributes.degree
|
||||||
|
|
||||||
if (currentRoof.attributes.sleeve && currentRoof.attributes.width > 0 && prevRoof.attributes.offset > 0 && nextRoof.attributes.offset > 0) {
|
if (currentRoof.attributes.sleeve && currentRoof.attributes.width > 0 && prevRoof.attributes.offset > 0 && nextRoof.attributes.offset > 0) {
|
||||||
const prevSignX = Math.sign(prevRoof.x1 - prevRoof.x2)
|
const prevSignX = Math.sign(prevRoof.x1 - prevRoof.x2)
|
||||||
const prevSignY = Math.sign(prevRoof.y1 - prevRoof.y2)
|
const prevSignY = Math.sign(prevRoof.y1 - prevRoof.y2)
|
||||||
@ -3417,6 +3187,8 @@ const changeWallRoof = (currentRoof, canvas) => {
|
|||||||
y2: ridge.y2 - diffY,
|
y2: ridge.y2 - diffY,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
ridge.attributes.planeSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
ridge.attributes.actualSize = Math.round(Math.sqrt(Math.pow(ridge.x1 - ridge.x2, 2) + Math.pow(ridge.y1 - ridge.y2, 2)) * 10)
|
||||||
|
|
||||||
let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], {
|
let hip1 = new QLine([currentRoof.x1, currentRoof.y1, wallMidX, wallMidY], {
|
||||||
fontSize: roof.fontSize,
|
fontSize: roof.fontSize,
|
||||||
@ -3426,10 +3198,14 @@ const changeWallRoof = (currentRoof, canvas) => {
|
|||||||
attributes: {
|
attributes: {
|
||||||
roofId: roof.id,
|
roofId: roof.id,
|
||||||
currentRoofId: currentRoof.id,
|
currentRoofId: currentRoof.id,
|
||||||
planeSize: currentRoof.length,
|
actualSize: 0,
|
||||||
actualSize: currentRoof.length,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const hip1Base = ((Math.abs(hip1.x1 - hip1.x2) + Math.abs(hip1.y1 - hip1.y2)) / 2) * 10
|
||||||
|
const hip1Height = Math.round(hip1Base / Math.tan(((90 - prevDegree) * Math.PI) / 180))
|
||||||
|
hip1.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip1.x1 - hip1.x2, 2) + Math.pow(hip1.y1 - hip1.y2, 2))) * 10
|
||||||
|
hip1.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip1.attributes.planeSize, 2) + Math.pow(hip1Height, 2)))
|
||||||
|
|
||||||
let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX, wallMidY], {
|
let hip2 = new QLine([currentRoof.x2, currentRoof.y2, wallMidX, wallMidY], {
|
||||||
fontSize: roof.fontSize,
|
fontSize: roof.fontSize,
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
@ -3442,6 +3218,10 @@ const changeWallRoof = (currentRoof, canvas) => {
|
|||||||
actualSize: currentRoof.length,
|
actualSize: currentRoof.length,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const hip2Base = ((Math.abs(hip2.x1 - hip2.x2) + Math.abs(hip2.y1 - hip2.y2)) / 2) * 10
|
||||||
|
const hip2Height = Math.round(hip2Base / Math.tan(((90 - nextDegree) * Math.PI) / 180))
|
||||||
|
hip2.attributes.planeSize = Math.round(Math.sqrt(Math.pow(hip2.x1 - hip2.x2, 2) + Math.pow(hip2.y1 - hip2.y2, 2))) * 10
|
||||||
|
hip2.attributes.actualSize = Math.round(Math.sqrt(Math.pow(hip2.attributes.planeSize, 2) + Math.pow(hip2Height, 2)))
|
||||||
canvas?.add(hip1)
|
canvas?.add(hip1)
|
||||||
canvas?.add(hip2)
|
canvas?.add(hip2)
|
||||||
roof.innerLines.push(hip1)
|
roof.innerLines.push(hip1)
|
||||||
@ -3505,8 +3285,13 @@ export const changeCurrentRoof = (currentRoof, canvas) => {
|
|||||||
newRoof.setWall(wall)
|
newRoof.setWall(wall)
|
||||||
|
|
||||||
newRoof.lines.forEach((line, index) => {
|
newRoof.lines.forEach((line, index) => {
|
||||||
|
const lineLength = Math.sqrt(
|
||||||
|
Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2),
|
||||||
|
)
|
||||||
line.attributes = {
|
line.attributes = {
|
||||||
roofId: newRoof.id,
|
roofId: newRoof.id,
|
||||||
|
planeSize: lineLength,
|
||||||
|
actualSize: lineLength,
|
||||||
wallLine: wall.lines[index].id,
|
wallLine: wall.lines[index].id,
|
||||||
type: wall.lines[index].attributes.type,
|
type: wall.lines[index].attributes.type,
|
||||||
offset: wall.lines[index].attributes.offset,
|
offset: wall.lines[index].attributes.offset,
|
||||||
@ -3561,6 +3346,19 @@ const reDrawPolygon = (polygon, canvas) => {
|
|||||||
line.attributes = l.attributes
|
line.attributes = l.attributes
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const lineLength = Math.sqrt(
|
||||||
|
Math.pow(Math.round(Math.abs(line.x1 - line.x2) * 10), 2) + Math.pow(Math.round(Math.abs(line.y1 - line.y2) * 10), 2),
|
||||||
|
)
|
||||||
|
if (line.attributes !== undefined) {
|
||||||
|
line.attributes.planeSize = lineLength
|
||||||
|
line.attributes.actualSize = line
|
||||||
|
} else {
|
||||||
|
line.attributes = {
|
||||||
|
roofId: newPolygon.id,
|
||||||
|
planeSize: lineLength,
|
||||||
|
actualSize: lineLength,
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
canvas?.add(newPolygon)
|
canvas?.add(newPolygon)
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
import { checkSession } from '@/lib/user'
|
|
||||||
import { redirect } from 'next/navigation'
|
|
||||||
|
|
||||||
export const initCheck = async () => {
|
|
||||||
const { session } = await checkSession()
|
|
||||||
|
|
||||||
if (!session.isLoggedIn) {
|
|
||||||
redirect('/login')
|
|
||||||
}
|
|
||||||
|
|
||||||
return session
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user