Merge branch 'dev' into feature/Q-CAST-III-T-22
This commit is contained in:
commit
479c618c83
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@ -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 [textInput, setTextInput] = useState('')
|
||||
const [numberInput, setNumberInput] = useState(null)
|
||||
const [numberInput, setNumberInput] = useState('')
|
||||
const [radioInput, setRadioInput] = useState('')
|
||||
const [checkboxInput, setCheckboxInput] = useState([])
|
||||
const [selectedValue, setSelectedValue] = useState('')
|
||||
@ -171,7 +171,7 @@ export default function Playground() {
|
||||
<button
|
||||
className="btn-frame deepgray"
|
||||
onClick={() => {
|
||||
setNumberInput(null)
|
||||
setNumberInput('')
|
||||
}}
|
||||
>
|
||||
QInput NumberInput DATA RESET
|
||||
|
||||
@ -52,7 +52,7 @@ export default function ColorPickerModal(props) {
|
||||
closePopup(id, isConfig)
|
||||
}}
|
||||
>
|
||||
{getMessage('common.message.save')}
|
||||
{getMessage('modal.common.save')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
'use client'
|
||||
import { useEffect } from 'react'
|
||||
import '@/styles/contents.scss'
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { contextMenuListState, contextMenuState } from '@/store/contextMenu'
|
||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||
import { useContextMenu } from '@/hooks/useContextMenu'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
|
||||
export default function QContextMenu(props) {
|
||||
const { contextRef, canvasProps, handleKeyup } = props
|
||||
const { contextRef, canvasProps } = props
|
||||
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
||||
const [contextMenuList, setContextMenuList] = useRecoilState(contextMenuListState)
|
||||
const contextMenuList = useRecoilValue(contextMenuListState)
|
||||
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
||||
const { tempGridMode, setTempGridMode } = useTempGrid()
|
||||
const { handleKeyup } = useContextMenu()
|
||||
const { addDocumentEventListener, removeDocumentEvent } = useEvent()
|
||||
|
||||
let contextType = ''
|
||||
|
||||
@ -22,13 +26,13 @@ export default function QContextMenu(props) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getYPosition = (e) => {
|
||||
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
||||
return acc + cur.length
|
||||
}, 0)
|
||||
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!contextRef.current) return
|
||||
|
||||
@ -40,7 +44,7 @@ export default function QContextMenu(props) {
|
||||
y: window.innerHeight / 2 < e.pageY ? getYPosition(e) : e.pageY,
|
||||
}
|
||||
setContextMenu({ visible: true, ...position })
|
||||
document.addEventListener('keyup', (e) => handleKeyup(e))
|
||||
addDocumentEventListener('keyup', document, handleKeyup)
|
||||
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
||||
}
|
||||
|
||||
@ -51,8 +55,9 @@ export default function QContextMenu(props) {
|
||||
|
||||
const handleOutsideClick = (e) => {
|
||||
// e.preventDefault()
|
||||
if (contextMenu.visible && !ref.current.contains(e.target)) {
|
||||
if (contextMenu.visible) {
|
||||
setContextMenu({ ...contextMenu, visible: false })
|
||||
removeDocumentEvent('keyup')
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,10 +66,11 @@ export default function QContextMenu(props) {
|
||||
document.addEventListener('click', handleOutsideClick)
|
||||
|
||||
return () => {
|
||||
removeDocumentEvent('keyup')
|
||||
document.removeEventListener('click', handleClick)
|
||||
document.removeEventListener('click', handleOutsideClick)
|
||||
}
|
||||
}, [contextRef, contextMenu])
|
||||
}, [contextRef, contextMenuList])
|
||||
|
||||
const handleObjectMove = () => {
|
||||
activeObject.set({
|
||||
|
||||
@ -1,18 +1,18 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useState } from 'react'
|
||||
import Draggable from 'react-draggable'
|
||||
|
||||
export default function WithDraggable({ isShow, children, pos, handle = '' }) {
|
||||
const [position, setPosition] = useState({ x: 0, y: 0 })
|
||||
export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 }, handle = '' }) {
|
||||
const [position, setPosition] = useState(pos)
|
||||
|
||||
const handleOnDrag = (e, data) => {
|
||||
e.stopPropagation()
|
||||
setPosition({ x: data.x, y: data.y })
|
||||
}
|
||||
useEffect(() => {
|
||||
setPosition({ ...pos })
|
||||
}, [])
|
||||
// useEffect(() => {
|
||||
// setPosition({ ...pos })
|
||||
// }, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
'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 }) {
|
||||
const [prevNum, setPrevNum] = useState('')
|
||||
// options = options || [
|
||||
// {
|
||||
// id: 'one',
|
||||
@ -35,51 +36,59 @@ export default function QInput({ type, className, ref, id, readOnly = false, opt
|
||||
|
||||
const handleTextNumberChange = useCallback(
|
||||
(e) => {
|
||||
if (type === 'text') {
|
||||
onChange(e.target.value)
|
||||
} else if (type === 'number') {
|
||||
onChange(Number(e.target.value))
|
||||
}
|
||||
onChange(e.target.value)
|
||||
},
|
||||
[type, onChange],
|
||||
[onChange],
|
||||
)
|
||||
|
||||
// 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 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
|
||||
const value = e.target.defaultValue
|
||||
if (value === '') return
|
||||
|
||||
const regex = /^-?([1-9]\d*|\d)(\.\d*)?$/
|
||||
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
|
||||
const inputTextNumber = () => {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
type="text"
|
||||
className={`input-light ${className ? className : ''}`}
|
||||
ref={ref}
|
||||
id={id}
|
||||
readOnly={readOnly ? true : false}
|
||||
placeholder={placeholder}
|
||||
value={value === 0 ? 0 : value || ''}
|
||||
value={value}
|
||||
onChange={handleTextNumberChange}
|
||||
onKeyDown={type === 'number' ? checkInputNumber : undefined}
|
||||
onKeyUp={type === 'number' ? checkInputNumber : undefined}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { popupState } from '@/store/popupAtom'
|
||||
import { Fragment } from 'react'
|
||||
|
||||
export default function PopupManager() {
|
||||
const [popup, setPopup] = useRecoilState(popupState)
|
||||
const popup = useRecoilValue(popupState)
|
||||
|
||||
return [
|
||||
...popup?.config.map((child) => <Fragment key={child.id}>{child.component}</Fragment>),
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState, useRef } from 'react'
|
||||
import { useEffect, useState, useContext } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
import { sessionStore } from '@/store/commonAtom'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
||||
import EstimateFileUploader from './EstimateFileUploader'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
import { isNotEmptyArray, isObjectNotEmpty } from '@/util/common-utils'
|
||||
import dayjs from 'dayjs'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import Select from 'react-select'
|
||||
@ -21,6 +21,8 @@ export default function Estimate({ params }) {
|
||||
const [planNo, setPlanNo] = useState('') //플랜번호
|
||||
const [files, setFiles] = useState([]) // 보내는 첨부파일
|
||||
|
||||
const [showContentCode, setShowContentCode] = useState('ATTR001')
|
||||
|
||||
//견적특이사항 접고 펼치기
|
||||
const [hidden, setHidden] = useState(false)
|
||||
|
||||
@ -34,12 +36,17 @@ export default function Estimate({ params }) {
|
||||
setStartDate,
|
||||
}
|
||||
|
||||
const sessionState = useRecoilValue(sessionStore)
|
||||
const { session } = useContext(SessionContext)
|
||||
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||
|
||||
//견적서 상세데이터
|
||||
const { state, setState } = useEstimateController(params.pid)
|
||||
|
||||
//견적특이사항 상세 데이터 LIST
|
||||
|
||||
//견적특이사항 List
|
||||
const [specialNoteList, setSpecialNoteList] = useState([])
|
||||
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
const { get, post } = useAxios(globalLocaleState)
|
||||
|
||||
@ -65,17 +72,70 @@ export default function Estimate({ params }) {
|
||||
if (code1 != null) {
|
||||
setHonorificCodeList(code1)
|
||||
}
|
||||
|
||||
//견적특이사항 API호출
|
||||
//http://localhost:8080/api/estimate/special-note-list
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
//견적특이사항 API호출
|
||||
//여러개 선택하면 구분자로 (、)
|
||||
let url = `/api/estimate/special-note-list`
|
||||
get({ url: url }).then((res) => {
|
||||
if (isNotEmptyArray(res)) {
|
||||
if (state?.estimateOption) {
|
||||
res.map((row) => {
|
||||
let estimateOption = state?.estimateOption?.split('、')
|
||||
row.text = false
|
||||
estimateOption.map((row2) => {
|
||||
if (row2 === row.code) {
|
||||
row.text = true
|
||||
}
|
||||
})
|
||||
})
|
||||
setSpecialNoteList(res)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [state?.estimateOption])
|
||||
|
||||
//견적일 set
|
||||
useEffect(() => {
|
||||
let estimateDatej = dayjs(startDate).format('YYYY-MM-DD')
|
||||
setState({ estimateDate: estimateDatej })
|
||||
let estimateDate = dayjs(startDate).format('YYYY-MM-DD')
|
||||
setState({ estimateDate: estimateDate })
|
||||
}, [startDate])
|
||||
|
||||
useEffect(() => {
|
||||
//선택된 견적특이사항 setState
|
||||
if (isNotEmptyArray(specialNoteList)) {
|
||||
const liveCheckedData = specialNoteList.filter((row) => row.text === true)
|
||||
|
||||
const data = []
|
||||
for (let ele of liveCheckedData) {
|
||||
data.push(ele.code)
|
||||
}
|
||||
|
||||
const newData = data.join('、')
|
||||
setState({ estimateOption: newData })
|
||||
}
|
||||
}, [specialNoteList])
|
||||
|
||||
// 견적특이사항 remark 보여주기
|
||||
const settingShowContent = (code, event) => {
|
||||
setShowContentCode(code)
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
// 첨부파일 state에 넣기
|
||||
useEffect(() => {
|
||||
// console.log(files)
|
||||
if (files.length > 0) {
|
||||
files.map((row) => {
|
||||
setState({ fileList: row.data })
|
||||
})
|
||||
} else {
|
||||
console.log('첨부파일 없음')
|
||||
setState({ fileList: [] })
|
||||
}
|
||||
}, [files])
|
||||
|
||||
return (
|
||||
<div className="sub-content estimate">
|
||||
<div className="sub-content-inner">
|
||||
@ -155,7 +215,6 @@ export default function Estimate({ params }) {
|
||||
defaultValue={state?.charger}
|
||||
onChange={(e) => {
|
||||
//담당자 charger
|
||||
// console.log('담당자:::::', e.target.value)
|
||||
setState({ charger: e.target.value })
|
||||
}}
|
||||
/>
|
||||
@ -176,7 +235,6 @@ export default function Estimate({ params }) {
|
||||
defaultValue={state?.objectName}
|
||||
onChange={(e) => {
|
||||
//안건명 objectName
|
||||
// console.log('안건명::::', e.target.value)
|
||||
setState({ objectName: e.target.value })
|
||||
}}
|
||||
/>
|
||||
@ -193,7 +251,6 @@ export default function Estimate({ params }) {
|
||||
if (isObjectNotEmpty(e)) {
|
||||
setState({ objectNameOmit: e.clCodeNm })
|
||||
} else {
|
||||
// console.log('XXX')
|
||||
setState({ objectNameOmit: '' })
|
||||
}
|
||||
}}
|
||||
@ -291,7 +348,6 @@ export default function Estimate({ params }) {
|
||||
defaultValue={state?.remarks}
|
||||
onChange={(e) => {
|
||||
//비고
|
||||
// console.log('비고:::::', e.target.value)
|
||||
setState({ remarks: e.target.value })
|
||||
}}
|
||||
/>
|
||||
@ -359,17 +415,47 @@ export default function Estimate({ params }) {
|
||||
{/* 견적 특이사항 코드영역시작 */}
|
||||
<div className={`estimate-check-wrap ${hidden ? 'hide' : ''}`}>
|
||||
<div className="estimate-check-inner">
|
||||
<div className="special-note-check-wrap"></div>
|
||||
<div className="special-note-check-wrap">
|
||||
{/* SpecialNoteList반복문 */}
|
||||
{specialNoteList.map((row) => {
|
||||
return (
|
||||
<div
|
||||
className="special-note-check-item"
|
||||
onClick={(event) => {
|
||||
settingShowContent(row.code, event)
|
||||
}}
|
||||
>
|
||||
<div className="d-check-box light">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={row.code}
|
||||
checked={!!row.text}
|
||||
disabled={row.code === 'ATTR001' ? true : false}
|
||||
onChange={(event) => {
|
||||
setSpecialNoteList((specialNote) =>
|
||||
specialNote.map((temp) => (temp.code === row.code ? { ...temp, text: !temp.text } : temp)),
|
||||
)
|
||||
settingShowContent(row.code, event)
|
||||
}}
|
||||
/>
|
||||
<label htmlFor={row.code}>{row.codeNm}</label>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
{/* 견적특이사항 선택한 내용?영역시작 */}
|
||||
<div className="calculation-estimate">
|
||||
<dl>
|
||||
<dt>제목11??</dt>
|
||||
<dd>제목1 비고</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>제목22??</dt>
|
||||
<dd>제목2 비고</dd>
|
||||
</dl>
|
||||
{specialNoteList.map((row) => {
|
||||
if (row.code === showContentCode) {
|
||||
return (
|
||||
<dl>
|
||||
<dt>{row.codeNm}</dt>
|
||||
<dd>{row.remarks}</dd>
|
||||
</dl>
|
||||
)
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
{/* 견적특이사항 선택한 내용?영역끝 */}
|
||||
</div>
|
||||
|
||||
@ -137,6 +137,22 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
})
|
||||
})
|
||||
|
||||
this.on('polygonMoved', () => {
|
||||
//폴리곤일때만 사용
|
||||
let matrix = this.calcTransformMatrix()
|
||||
|
||||
let transformedPoints = this.get('points')
|
||||
.map((p) => {
|
||||
return new fabric.Point(p.x - this.pathOffset.x, p.y - this.pathOffset.y)
|
||||
})
|
||||
.map((p) => {
|
||||
return fabric.util.transformPoint(p, matrix)
|
||||
})
|
||||
this.set('points', transformedPoints)
|
||||
this.set('pathOffset', { x: this.left, y: this.top })
|
||||
this.setCoords()
|
||||
})
|
||||
|
||||
// polygon.fillCell({ width: 50, height: 30, padding: 10 })
|
||||
},
|
||||
|
||||
@ -211,6 +227,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
|
||||
let points = this.getCurrentPoints()
|
||||
|
||||
this.texts = []
|
||||
points.forEach((start, i) => {
|
||||
const end = points[(i + 1) % points.length]
|
||||
const dx = end.x - start.x
|
||||
|
||||
@ -19,7 +19,7 @@ export default function CanvasFrame() {
|
||||
const { canvas } = useCanvas('canvas')
|
||||
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
||||
const currentMenu = useRecoilValue(currentMenuState)
|
||||
const { contextMenu, handleClick, handleKeyup } = useContextMenu()
|
||||
const { contextMenu, handleClick } = useContextMenu()
|
||||
const { selectedPlan, modifiedPlanFlag, checkCanvasObjectEvent, resetModifiedPlans } = usePlan()
|
||||
useEvent()
|
||||
|
||||
@ -57,7 +57,7 @@ export default function CanvasFrame() {
|
||||
<div className="canvas-frame">
|
||||
<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) => (
|
||||
<ul key={index}>
|
||||
{menus.map((menu) => (
|
||||
|
||||
@ -1,22 +1,49 @@
|
||||
import { useState, useEffect, useRef } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { contextPopupPositionState } from '@/store/popupAtom'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { useState } from 'react'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
|
||||
export default function DormerOffset(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
const { id, pos = contextPopupPosition } = props
|
||||
const { id, pos = contextPopupPosition, title } = props
|
||||
const { getMessage } = useMessage()
|
||||
const { closePopup } = usePopup()
|
||||
const [arrow1, setArrow1] = useState(null)
|
||||
const [arrow2, setArrow2] = useState(null)
|
||||
const arrow1LengthRef = useRef()
|
||||
const arrow2LengthRef = useRef()
|
||||
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { dormerOffsetKeyEvent, dormerOffset } = useObjectBatch({})
|
||||
|
||||
useEffect(() => {
|
||||
if (canvas) {
|
||||
dormerOffsetKeyEvent(setArrow1, setArrow2)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleOffsetDormer = () => {
|
||||
const length1 = arrow1LengthRef.current.value
|
||||
const length2 = arrow2LengthRef.current.value
|
||||
|
||||
dormerOffset(arrow1, arrow2, length1, length2)
|
||||
|
||||
setArrow1(null)
|
||||
setArrow2(null)
|
||||
arrow1LengthRef.current.value = ''
|
||||
arrow2LengthRef.current.value = ''
|
||||
|
||||
// closePopup(id)
|
||||
}
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<h1 className="title">{getMessage('contextmenu.dormer.offset')}</h1>
|
||||
<h1 className="title">{title}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
</button>
|
||||
@ -29,44 +56,40 @@ export default function DormerOffset(props) {
|
||||
<p className="mb5">{getMessage('length')}</p>
|
||||
<div className="input-move-wrap mb5">
|
||||
<div className="input-move">
|
||||
<input type="text" className="input-origin" defaultValue={0} />
|
||||
<input type="text" className="input-origin" ref={arrow1LengthRef} placeholder="0" />
|
||||
</div>
|
||||
<span>mm</span>
|
||||
<div className="direction-move-wrap">
|
||||
<button
|
||||
className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
|
||||
className={`direction up ${arrow1 === 'up' ? 'act' : ''}`}
|
||||
onClick={() => {
|
||||
setArrow1('↑')
|
||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
||||
setArrow1('up')
|
||||
}}
|
||||
></button>
|
||||
<button
|
||||
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
|
||||
className={`direction down ${arrow1 === 'down' ? 'act' : ''}`}
|
||||
onClick={() => {
|
||||
setArrow1('↓')
|
||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
||||
setArrow1('down')
|
||||
}}
|
||||
></button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="input-move-wrap">
|
||||
<div className="input-move">
|
||||
<input type="text" className="input-origin" defaultValue={0} />
|
||||
<input type="text" className="input-origin" ref={arrow2LengthRef} placeholder="0" />
|
||||
</div>
|
||||
<span>mm</span>
|
||||
<div className="direction-move-wrap">
|
||||
<button
|
||||
className={`direction left ${arrow2 === '←' ? 'act' : ''}`}
|
||||
className={`direction left ${arrow2 === 'left' ? 'act' : ''}`}
|
||||
onClick={() => {
|
||||
setArrow2('←')
|
||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
||||
setArrow2('left')
|
||||
}}
|
||||
></button>
|
||||
<button
|
||||
className={`direction right ${arrow2 === '→' ? 'act' : ''}`}
|
||||
className={`direction right ${arrow2 === 'right' ? 'act' : ''}`}
|
||||
onClick={() => {
|
||||
setArrow2('→')
|
||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||||
setArrow2('right')
|
||||
}}
|
||||
></button>
|
||||
</div>
|
||||
@ -75,7 +98,9 @@ export default function DormerOffset(props) {
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid-btn-wrap">
|
||||
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||
<button className="btn-frame modal act" onClick={handleOffsetDormer}>
|
||||
{getMessage('modal.common.save')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -8,6 +8,8 @@ import { contextPopupPositionState } from '@/store/popupAtom'
|
||||
import { useRef, useState, useEffect } from 'react'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { BATCH_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
|
||||
export default function SizeSetting(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
@ -15,8 +17,8 @@ export default function SizeSetting(props) {
|
||||
const { id, pos = contextPopupPosition, target } = props
|
||||
const { getMessage } = useMessage()
|
||||
const { closePopup } = usePopup()
|
||||
const { reSizeObjectBatch } = useObjectBatch({})
|
||||
|
||||
const { resizeObjectBatch } = useObjectBatch({})
|
||||
const { reSizePolygon } = useSurfaceShapeBatch()
|
||||
const widthRef = useRef(null)
|
||||
const heightRef = useRef(null)
|
||||
|
||||
@ -30,7 +32,15 @@ export default function SizeSetting(props) {
|
||||
const width = widthRef.current.value
|
||||
const height = heightRef.current.value
|
||||
|
||||
reSizeObjectBatch(settingTarget, target, width, height)
|
||||
if (
|
||||
target.name === BATCH_TYPE.OPENING ||
|
||||
target.name === BATCH_TYPE.SHADOW ||
|
||||
target.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||
target.name === BATCH_TYPE.PENTAGON_DORMER ||
|
||||
target.name === POLYGON_TYPE.ROOF
|
||||
) {
|
||||
resizeObjectBatch(settingTarget, target, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -240,7 +240,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap lr-2`}>
|
||||
<div className="modal-head">
|
||||
<h1 className="title">{getMessage('plan.menu.placement.surface.arrangement')} </h1>
|
||||
|
||||
@ -11,12 +11,12 @@ import { useRecoilValue } from 'recoil'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
|
||||
export default function SettingModal01(props) {
|
||||
const { setShowDotLineGridModal, setShowFontSettingModal, id, isConfig } = props
|
||||
console.log(props)
|
||||
const { id } = props
|
||||
const [buttonAct, setButtonAct] = useState(1)
|
||||
const { getMessage } = useMessage()
|
||||
const canGridOptionSeletorValue = useRecoilValue(canGridOptionSeletor)
|
||||
const { addPopup, closePopup } = usePopup()
|
||||
const { closePopup } = usePopup()
|
||||
|
||||
const handleBtnClick = (num) => {
|
||||
setButtonAct(num)
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import { useRouter, usePathname } from 'next/navigation'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import StuffQGrid from './StuffQGrid'
|
||||
import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil'
|
||||
import { useRecoilValue, useRecoilState, useSetRecoilState, useResetRecoilState } from 'recoil'
|
||||
import { stuffSearchState } from '@/store/stuffAtom'
|
||||
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
||||
import dayjs from 'dayjs'
|
||||
@ -19,7 +19,7 @@ import { sessionStore } from '@/store/commonAtom'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
|
||||
export default function Stuff() {
|
||||
const sessionState = useRecoilValue(sessionStore)
|
||||
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
|
||||
const { session } = useContext(SessionContext)
|
||||
const setAppMessageState = useSetRecoilState(appMessageStore)
|
||||
const stuffSearchParams = useRecoilValue(stuffSearchState)
|
||||
@ -34,9 +34,6 @@ export default function Stuff() {
|
||||
const { get } = useAxios(globalLocaleState)
|
||||
const gridRef = useRef()
|
||||
|
||||
// const [selectedRowData, setSelectedRowData] = useState([])
|
||||
// const [selectedRowDataCount, setSelectedRowDataCount] = useState(0)
|
||||
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
|
||||
@ -67,10 +64,6 @@ export default function Stuff() {
|
||||
field: 'lastEditDatetime',
|
||||
minWidth: 200,
|
||||
headerName: getMessage('stuff.gridHeader.lastEditDatetime'),
|
||||
// headerCheckboxSelection: true,
|
||||
// headerCheckboxSelectionCurrentPageOnly: true, //페이징시 현재 페이지만 체크되도록
|
||||
// checkboxSelection: true,
|
||||
// showDisabledCheckboxes: true,
|
||||
cellStyle: { justifyContent: 'center' },
|
||||
valueFormatter: function (params) {
|
||||
if (params.value) {
|
||||
@ -167,138 +160,70 @@ export default function Stuff() {
|
||||
}
|
||||
}
|
||||
|
||||
//그리드 체크박스 선택시 미사용
|
||||
// const getSelectedRowdata = (data) => {
|
||||
// setSelectedRowData(data)
|
||||
// setSelectedRowDataCount(data.length)
|
||||
// }
|
||||
|
||||
//물건삭제
|
||||
// const fnDeleteRowData = (data) => {
|
||||
// if (data.length === 0) {
|
||||
// return alert('삭제할 데이터를 선택하세요')
|
||||
// }
|
||||
// let errCount = 0
|
||||
// data.forEach((cell) => {
|
||||
// if (!cell.objectNo) {
|
||||
// if (errCount === 0) {
|
||||
// alert('물건정보가 있는 행만 삭제 됩니다')
|
||||
// }
|
||||
// errCount++
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
//행추가
|
||||
// let newCount = 0
|
||||
// const addRowItems = () => {
|
||||
// // console.log('girdRef::::::', gridRef.current.api)
|
||||
// const newItems = [
|
||||
// {
|
||||
// mission: newCount + 1,
|
||||
// successful: true,
|
||||
// },
|
||||
// ]
|
||||
// gridRef.current.api.applyTransaction({
|
||||
// add: newItems,
|
||||
// addIndex: newCount,
|
||||
// })
|
||||
// newCount++
|
||||
// }
|
||||
|
||||
//행삭제
|
||||
// const removeRowItems = () => {
|
||||
// // console.log('selectedRowData::', selectedRowData)
|
||||
// let errCount = 0
|
||||
// selectedRowData.forEach((cell) => {
|
||||
// if (!cell.company) {
|
||||
// let newSelectedRowData = selectedRowData.filter((item) => item.company == null)
|
||||
// gridRef.current.api.applyTransaction({ remove: newSelectedRowData })
|
||||
// } else {
|
||||
// if (errCount === 0) {
|
||||
// alert('행추가로 추가 한 행만 삭제됩니다.')
|
||||
// }
|
||||
// errCount++
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
// 진입시 그리드 데이터 조회
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(session)) {
|
||||
if (stuffSearchParams?.code === 'S') {
|
||||
const params = {
|
||||
// saleStoreId: stuffSearchParams.schSelSaleStoreId,
|
||||
saleStoreId: session.storeId,
|
||||
schObjectNo: stuffSearchParams?.schObjectNo,
|
||||
schAddress: stuffSearchParams?.schAddress,
|
||||
schObjectName: stuffSearchParams?.schObjectName,
|
||||
schSaleStoreName: stuffSearchParams?.schSaleStoreName,
|
||||
schReceiveUser: stuffSearchParams?.schReceiveUser,
|
||||
schDispCompanyName: stuffSearchParams?.schDispCompanyName,
|
||||
schDateType: stuffSearchParams.schDateType,
|
||||
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: stuffSearchParams.schSortType,
|
||||
}
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(params)}`
|
||||
await get({
|
||||
url: apiUrl,
|
||||
}).then((res) => {
|
||||
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,
|
||||
if (stuffSearchParams?.code === 'S') {
|
||||
const params = {
|
||||
saleStoreId: session.storeId,
|
||||
schObjectNo: stuffSearchParams?.schObjectNo,
|
||||
schAddress: stuffSearchParams?.schAddress,
|
||||
schObjectName: stuffSearchParams?.schObjectName,
|
||||
schSaleStoreName: stuffSearchParams?.schSaleStoreName,
|
||||
schReceiveUser: stuffSearchParams?.schReceiveUser,
|
||||
schDispCompanyName: stuffSearchParams?.schDispCompanyName,
|
||||
schDateType: stuffSearchParams.schDateType,
|
||||
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: stuffSearchParams.schSortType,
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(params)}`
|
||||
await get({
|
||||
url: apiUrl,
|
||||
}).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
|
||||
setTotalCount(res[0].totCnt)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [pageNo, session, stuffSearchParams])
|
||||
|
||||
useEffect(() => {
|
||||
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.endRow = 1 * pageSize
|
||||
stuffSearchParams.schSortType = defaultSortType
|
||||
|
||||
setPageNo(1)
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
code: 'FINISH',
|
||||
})
|
||||
|
||||
//조회를 눌렀을때
|
||||
async function fetchData() {
|
||||
let saleStoreId
|
||||
saleStoreId = stuffSearchParams?.schSelSaleStoreId ? stuffSearchParams.schSelSaleStoreId : session?.storeId
|
||||
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
||||
await get({ url: apiUrl }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
@ -310,7 +235,10 @@ export default function Stuff() {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fetchData()
|
||||
} else if (stuffSearchParams?.code === 'C') {
|
||||
resetStuffRecoil()
|
||||
}
|
||||
}, [stuffSearchParams])
|
||||
|
||||
@ -330,8 +258,6 @@ export default function Stuff() {
|
||||
})
|
||||
|
||||
setPageNo(1)
|
||||
let saleStoreId
|
||||
saleStoreId = stuffSearchParams?.schSelSaleStoreId ? stuffSearchParams.schSelSaleStoreId : session?.storeId
|
||||
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
||||
get({ url: apiUrl }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
@ -364,8 +290,6 @@ export default function Stuff() {
|
||||
})
|
||||
|
||||
setPageNo(1)
|
||||
let saleStoreId
|
||||
saleStoreId = stuffSearchParams?.schSelSaleStoreId ? stuffSearchParams.schSelSaleStoreId : session?.storeId
|
||||
const apiUrl = `/api/object/list?saleStoreId=${session?.storeId}&${queryStringFormatter(stuffSearchParams)}`
|
||||
get({ url: apiUrl }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
|
||||
@ -11,7 +11,6 @@ import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty } from '@/util/common-u
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import { sessionStore } from '@/store/commonAtom'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
import FindAddressPop from './popup/FindAddressPop'
|
||||
import PlanRequestPop from './popup/PlanRequestPop'
|
||||
@ -28,7 +27,6 @@ export default function StuffDetail() {
|
||||
const [selOptions, setSelOptions] = useState('') //선택한 1차점
|
||||
const [otherSelOptions, setOtherSelOptions] = useState('') //선택한 1차점외
|
||||
|
||||
const sessionState = useRecoilValue(sessionStore)
|
||||
const { session } = useContext(SessionContext)
|
||||
|
||||
const router = useRouter()
|
||||
@ -320,12 +318,11 @@ export default function StuffDetail() {
|
||||
let firstList
|
||||
let otherList
|
||||
let favList
|
||||
// if (sessionState?.storeId === 'T01') {
|
||||
if (session?.storeId === 'T01') {
|
||||
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
||||
} else {
|
||||
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 {
|
||||
url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=1&userId=${session?.userId}`
|
||||
}
|
||||
@ -400,7 +397,6 @@ export default function StuffDetail() {
|
||||
}
|
||||
})
|
||||
}
|
||||
// }, [objectNo, sessionState])
|
||||
}, [objectNo, session])
|
||||
|
||||
useEffect(() => {
|
||||
@ -420,7 +416,6 @@ export default function StuffDetail() {
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(detailData)) {
|
||||
// console.log('상세데이타세팅:::::', detailData)
|
||||
// 도도부현API
|
||||
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
@ -434,23 +429,18 @@ export default function StuffDetail() {
|
||||
let firstList
|
||||
let otherList
|
||||
let favList
|
||||
// if (sessionState?.storeId === 'T01') {
|
||||
|
||||
if (session?.storeId === 'T01') {
|
||||
// url = `/api/object/saleStore/${sessionState?.storeId}/firstList?userId=${sessionState?.userId}`
|
||||
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
||||
} else {
|
||||
// if (sessionState.storeLvl === '1') {
|
||||
if (session.storeLvl === '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}`
|
||||
} 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}`
|
||||
}
|
||||
}
|
||||
get({ url: url }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
// if (sessionState?.storeId === 'T01') {
|
||||
if (session?.storeId === 'T01') {
|
||||
firstList = res.filter((row) => row.saleStoreLevel === '1')
|
||||
firstList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
|
||||
@ -459,14 +449,19 @@ export default function StuffDetail() {
|
||||
setFavoriteStoreList(favList)
|
||||
setShowSaleStoreList(favList)
|
||||
|
||||
form.setValue('saleStoreId', firstList[0].saleStoreId)
|
||||
form.setValue('saleStoreName', firstList[0].saleStoreName)
|
||||
form.setValue('saleStoreLevel', firstList[0].saleStoreLevel)
|
||||
setSelOptions(firstList[0].saleStoreId)
|
||||
if (detailData.firstAgentId != null) {
|
||||
form.setValue('saleStoreId', detailData.firstAgentId)
|
||||
setSelOptions(detailData.firstAgentId)
|
||||
} else {
|
||||
form.setValue('saleStoreId', detailData.saleStoreId)
|
||||
setSelOptions(detailData.saleStoreId)
|
||||
}
|
||||
|
||||
//상세데이터의 1차점 아이디로 2차점 목록 조회하기
|
||||
// url = `/api/object/saleStore/${detailData?.saleStoreId}/list?firstFlg=0&userId=${sessionState?.userId}`
|
||||
url = `/api/object/saleStore/${detailData?.saleStoreId}/list?firstFlg=0&userId=${session?.userId}`
|
||||
|
||||
let data = detailData?.firstAgentId ? detailData.firstAgentId : detailData.saleStoreId
|
||||
// url = `/api/object/saleStore/${session?.storeId}/list?firstFlg=0&userId=${session?.userId}`
|
||||
url = `/api/object/saleStore/${data}/list?firstFlg=0&userId=${session?.userId}`
|
||||
|
||||
get({ url: url }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
@ -482,7 +477,6 @@ export default function StuffDetail() {
|
||||
})
|
||||
} else {
|
||||
//1차점 셀렉트박스
|
||||
// if (sessionState?.storeLvl === '1') {
|
||||
if (session?.storeLvl === '1') {
|
||||
firstList = res
|
||||
favList = res.filter((row) => row.priority !== 'B')
|
||||
@ -572,7 +566,6 @@ export default function StuffDetail() {
|
||||
form.setValue('remarks', detailData.remarks)
|
||||
})
|
||||
}
|
||||
// }, [detailData, sessionState])
|
||||
}, [detailData, session])
|
||||
|
||||
//경칭선택 변경 이벤트
|
||||
@ -1282,9 +1275,7 @@ export default function StuffDetail() {
|
||||
|
||||
//1차점 or 2차점 안고르고 임시저장하면
|
||||
if (params.saleStoreId == '') {
|
||||
// params.saleStoreId = sessionState.storeId
|
||||
params.saleStoreId = session.storeId
|
||||
// params.saleStoreLevel = sessionState.storeLvl
|
||||
params.saleStoreLevel = session.storeLvl
|
||||
}
|
||||
|
||||
@ -1448,7 +1439,6 @@ export default function StuffDetail() {
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
{/* {sessionState?.storeId === 'T01' && ( */}
|
||||
{session?.storeId === 'T01' && (
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
@ -1482,7 +1472,6 @@ export default function StuffDetail() {
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl === '1' && ( */}
|
||||
{session?.storeId !== 'T01' && session?.storeLvl === '1' && (
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
@ -1514,7 +1503,6 @@ export default function StuffDetail() {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl !== '1' && ( */}
|
||||
{session?.storeId !== 'T01' && session?.storeLvl !== '1' && (
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
@ -1931,7 +1919,6 @@ export default function StuffDetail() {
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
{/* {sessionState?.storeId === 'T01' && ( */}
|
||||
{session?.storeId === 'T01' && (
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
@ -1947,10 +1934,8 @@ export default function StuffDetail() {
|
||||
onChange={onSelectionChange}
|
||||
getOptionLabel={(x) => x.saleStoreName}
|
||||
getOptionValue={(x) => x.saleStoreId}
|
||||
// isClearable={sessionState?.storeLvl === '1' ? true : false}
|
||||
isClearable={session?.storeLvl === '1' ? true : false}
|
||||
// isDisabled={sessionState?.storeLvl !== '1' ? true : false}
|
||||
isDisabled={session?.storeLvl !== '1' ? true : false}
|
||||
isClearable={detailData.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false}
|
||||
isDisabled={detailData.tempFlg === '0' ? true : session?.storeLvl !== '1' ? true : false}
|
||||
value={saleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
@ -1967,7 +1952,6 @@ export default function StuffDetail() {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl === '1' && ( */}
|
||||
{session?.storeId !== 'T01' && session?.storeLvl === '1' && (
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
@ -1983,8 +1967,9 @@ export default function StuffDetail() {
|
||||
getOptionLabel={(x) => x.saleStoreName}
|
||||
getOptionValue={(x) => x.saleStoreId}
|
||||
isClearable={false}
|
||||
// isDisabled={sessionState?.storeLvl !== '1' ? true : sessionState?.storeId !== 'T01' ? true : false}
|
||||
isDisabled={session?.storeLvl !== '1' ? true : session?.storeId !== 'T01' ? true : false}
|
||||
isDisabled={
|
||||
detailData.tempFlg === '0' ? true : session?.storeLvl !== '1' ? true : session?.storeId !== 'T01' ? true : false
|
||||
}
|
||||
value={showSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
@ -2001,7 +1986,6 @@ export default function StuffDetail() {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl !== '1' && ( */}
|
||||
{session?.storeId !== 'T01' && session?.storeLvl !== '1' && (
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
@ -2062,10 +2046,10 @@ export default function StuffDetail() {
|
||||
onChange={onSelectionChange2}
|
||||
getOptionLabel={(x) => x.saleStoreName}
|
||||
getOptionValue={(x) => x.saleStoreId}
|
||||
// isDisabled={sessionState?.storeLvl === '1' && form.watch('saleStoreId') != '' ? false : true}
|
||||
isDisabled={session?.storeLvl === '1' && form.watch('saleStoreId') != '' ? false : true}
|
||||
// isClearable={sessionState?.storeLvl === '1' ? true : false}
|
||||
isClearable={session?.storeLvl === '1' ? true : false}
|
||||
isDisabled={
|
||||
detailData.tempFlg === '0' ? true : session?.storeLvl === '1' && form.watch('saleStoreId') != '' ? false : true
|
||||
}
|
||||
isClearable={detailData.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : false}
|
||||
value={otherSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === otherSelOptions
|
||||
})}
|
||||
|
||||
@ -94,13 +94,13 @@ export default function StuffSearchCondition() {
|
||||
})
|
||||
} else {
|
||||
setStuffSearch({
|
||||
schObjectNo: objectNo ? objectNo : '',
|
||||
schSaleStoreName: saleStoreName ? saleStoreName : '',
|
||||
schAddress: address ? address : '',
|
||||
schObjectName: objectName ? objectName : '',
|
||||
schDispCompanyName: dispCompanyName ? dispCompanyName : '',
|
||||
schObjectNo: objectNo,
|
||||
schSaleStoreName: saleStoreName,
|
||||
schAddress: address,
|
||||
schObjectName: objectName,
|
||||
schDispCompanyName: dispCompanyName,
|
||||
schSelSaleStoreId: stuffSearch?.schOtherSelSaleStoreId ? stuffSearch.schOtherSelSaleStoreId : stuffSearch.schSelSaleStoreId,
|
||||
schReceiveUser: receiveUser ? receiveUser : '',
|
||||
schReceiveUser: receiveUser,
|
||||
schDateType: dateType,
|
||||
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
|
||||
schToDt: dayjs(endDate).format('YYYY-MM-DD'),
|
||||
@ -131,14 +131,12 @@ export default function StuffSearchCondition() {
|
||||
setDateType('U')
|
||||
setStartDate(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||
setEndDate(dayjs(new Date()).format('YYYY-MM-DD'))
|
||||
// if (sessionState?.storeId === 'T01') {
|
||||
if (session?.storeId === 'T01') {
|
||||
setSchSelSaleStoreId('')
|
||||
handleClear1() //판매대리점선택 자동완성 클리어
|
||||
resetStuffRecoil()
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
code: 'C',
|
||||
schSelSaleStoreId: '',
|
||||
schOtherSelSaleStoreId: '',
|
||||
})
|
||||
@ -156,23 +154,17 @@ export default function StuffSearchCondition() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// if (isObjectNotEmpty(sessionState)) {
|
||||
if (isObjectNotEmpty(session)) {
|
||||
// storeId가 T01 이거나 storeLvl이 1차점일때만 판매대리점 선택 활성화
|
||||
let url
|
||||
// if (sessionState?.storeId === 'T01') {
|
||||
if (session?.storeId === 'T01') {
|
||||
//T01일떄
|
||||
// url = `/api/object/saleStore/${sessionState?.storeId}/firstList?userId=${sessionState?.userId}`
|
||||
url = `/api/object/saleStore/${session?.storeId}/firstList?userId=${session?.userId}`
|
||||
} else {
|
||||
// if (sessionState.storeLvl === '1') {
|
||||
if (session.storeLvl === '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=${sessionState?.userId}`
|
||||
} 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}`
|
||||
}
|
||||
}
|
||||
@ -187,7 +179,6 @@ export default function StuffSearchCondition() {
|
||||
let allList
|
||||
let favList
|
||||
let otherList
|
||||
// if (sessionState?.storeId === 'T01') {
|
||||
if (session?.storeId === 'T01') {
|
||||
allList = res
|
||||
allList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
|
||||
@ -195,17 +186,14 @@ export default function StuffSearchCondition() {
|
||||
setSchSelSaleStoreList(allList)
|
||||
setFavoriteStoreList(favList)
|
||||
setShowSaleStoreList(favList)
|
||||
// setSchSelSaleStoreId(sessionState?.storeId)
|
||||
setSchSelSaleStoreId(session?.storeId)
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
code: 'S',
|
||||
// schSelSaleStoreId: sessionState?.storeId,
|
||||
schSelSaleStoreId: session?.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}`
|
||||
|
||||
get({ url: url }).then((res) => {
|
||||
@ -222,7 +210,6 @@ export default function StuffSearchCondition() {
|
||||
}
|
||||
})
|
||||
} else {
|
||||
// if (sessionState?.storeLvl === '1') {
|
||||
if (session?.storeLvl === '1') {
|
||||
allList = res
|
||||
favList = res.filter((row) => row.priority !== 'B')
|
||||
@ -250,7 +237,6 @@ export default function StuffSearchCondition() {
|
||||
setOtherSaleStoreList(otherList)
|
||||
|
||||
//선택한 2차점 세션으로 자동셋팅
|
||||
// setOtherSaleStoreId(sessionState?.storeId)
|
||||
setOtherSaleStoreId(session?.storeId)
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
@ -262,7 +248,6 @@ export default function StuffSearchCondition() {
|
||||
}
|
||||
})
|
||||
}
|
||||
// }, [sessionState])
|
||||
}, [session])
|
||||
|
||||
//초기화 눌렀을 때 1차판매점 자동완성도..
|
||||
@ -296,7 +281,6 @@ export default function StuffSearchCondition() {
|
||||
stuffSearch.schSelSaleStoreId = key.saleStoreId
|
||||
//T01아닌 1차점은 본인으로 디폴트셋팅이고 수정할수없어서 여기안옴
|
||||
//고른 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 otherList
|
||||
get({ url: url }).then((res) => {
|
||||
@ -620,7 +604,6 @@ export default function StuffSearchCondition() {
|
||||
value={'U'}
|
||||
onChange={(e) => {
|
||||
setDateType(e.target.value)
|
||||
//setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="radio_u">{getMessage('stuff.search.schDateTypeU')}</label>
|
||||
@ -634,7 +617,6 @@ export default function StuffSearchCondition() {
|
||||
value={'R'}
|
||||
onChange={(e) => {
|
||||
setDateType(e.target.value)
|
||||
//setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
|
||||
}}
|
||||
/>
|
||||
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
|
||||
|
||||
@ -100,8 +100,6 @@ export function useCanvasConfigInitialize() {
|
||||
const groups = canvas.getObjects().filter((obj) => obj.groupYn && obj.name === 'dimensionGroup')
|
||||
const groupIds = []
|
||||
|
||||
console.log('groupDimensionInit', groups)
|
||||
|
||||
groups.forEach((group) => {
|
||||
if (!groupIds.includes(group.id)) {
|
||||
groupIds.push(group.id)
|
||||
@ -157,6 +155,7 @@ export function useCanvasConfigInitialize() {
|
||||
//그룹아이디로 캔버스의 객체를 조회함
|
||||
const groupObjects = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)
|
||||
const objectsName = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)[0].groupName
|
||||
const objectsParentId = canvas.getObjects().filter((obj) => obj.groupId === id || obj.id === id)[0].parentId
|
||||
|
||||
let objectArray = []
|
||||
|
||||
@ -181,8 +180,14 @@ export function useCanvasConfigInitialize() {
|
||||
lockMovementY: true,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
parentId: objectsParentId,
|
||||
})
|
||||
canvas.add(group)
|
||||
|
||||
//그룹 객체 재그룹 완료
|
||||
group.getObjects().forEach((obj) => {
|
||||
obj.fire('modified')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { useEffect, useReducer, useState } from 'react'
|
||||
import { useContext, useEffect, useReducer, useState } from 'react'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { estimateState, floorPlanObjectState } from '@/store/floorPlanObjectAtom'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
|
||||
const reducer = (prevState, nextState) => {
|
||||
return { ...prevState, ...nextState }
|
||||
}
|
||||
@ -41,6 +43,7 @@ const defaultEstimateData = {
|
||||
unit: '',
|
||||
},
|
||||
],
|
||||
fileList: [],
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
@ -51,14 +54,14 @@ const updateItemInList = (itemList, itemId, updates) => {
|
||||
}
|
||||
|
||||
export const useEstimateController = (planNo) => {
|
||||
const { session } = useContext(SessionContext)
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
const objectRecoil = useRecoilValue(floorPlanObjectState)
|
||||
const [estimateData, setEstimateData] = useRecoilState(estimateState)
|
||||
|
||||
const { get, post } = useAxios(globalLocaleState)
|
||||
const { get, post, promisePost } = useAxios(globalLocaleState)
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
const { promisePost } = useAxios()
|
||||
const [state, setState] = useReducer(reducer, defaultEstimateData)
|
||||
|
||||
useEffect(() => {
|
||||
@ -123,12 +126,32 @@ export const useEstimateController = (planNo) => {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setEstimateData({ ...state })
|
||||
setEstimateData({ ...state, userId: session.userId })
|
||||
//sapSalesStoreCd 추가예정 필수값
|
||||
// setEstimateData({ ...state, userId: session.userId, sapSalesStoreCd : session.sapSalesStoreCd })
|
||||
}, [state])
|
||||
|
||||
//견적서 저장
|
||||
const handleEstimateSubmit = async () => {
|
||||
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
|
||||
try {
|
||||
const result = await promisePost({
|
||||
|
||||
@ -16,7 +16,7 @@ import { fontSelector } from '@/store/fontAtom'
|
||||
export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const { getMessage } = useMessage()
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { addCanvasMouseEventListener, initEvent } = useEvent()
|
||||
const { addCanvasMouseEventListener, initEvent, addDocumentEventListener } = useEvent()
|
||||
const { swalFire } = useSwal()
|
||||
const { drawDirectionArrow } = usePolygon()
|
||||
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
||||
@ -33,10 +33,16 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}, [])
|
||||
|
||||
const dbClickEvent = () => {
|
||||
console.log('dbClickEvent 실행')
|
||||
const dormerObject = canvas.getObjects().filter((obj) => obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER)
|
||||
|
||||
console.log('dormerObject', dormerObject)
|
||||
|
||||
if (dormerObject) {
|
||||
canvas.off('mouse:dblclick')
|
||||
canvas.on('mouse:dblclick', (e) => {
|
||||
console.log('event', e)
|
||||
|
||||
if (e.target && e.target instanceof fabric.Group) {
|
||||
const pointer = canvas.getPointer(e.e)
|
||||
const objects = e.target._objects
|
||||
@ -71,7 +77,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
let rect, isDown, origX, origY
|
||||
let selectedSurface
|
||||
//프리입력
|
||||
console.log('useObjectBatch', isHidden)
|
||||
|
||||
if (selectedType === INPUT_TYPE.FREE) {
|
||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||
isDown = true
|
||||
@ -160,7 +166,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName })
|
||||
rect.set({ name: objName, parentId: selectedSurface.id })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
|
||||
@ -204,6 +210,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
parentId: selectedSurface.id,
|
||||
})
|
||||
|
||||
//개구냐 그림자냐에 따라 변경
|
||||
@ -241,7 +248,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName })
|
||||
rect.set({ name: objName, parentId: selectedSurface.id })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
if (setIsHidden) setIsHidden(false)
|
||||
@ -483,6 +490,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
subTargetCheck: true,
|
||||
name: dormerName,
|
||||
id: id,
|
||||
parentId: selectedSurface.id,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
canvas?.add(objectGroup)
|
||||
|
||||
@ -693,6 +703,10 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
subTargetCheck: true,
|
||||
name: dormerName,
|
||||
id: id,
|
||||
parentId: selectedSurface.id,
|
||||
groupYn: true,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
canvas?.add(objectGroup)
|
||||
|
||||
@ -858,9 +872,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
return [leftPoints, rightPoints]
|
||||
}
|
||||
|
||||
const reSizeObjectBatch = (side, target, width, height) => {
|
||||
const targetObj = canvas.getActiveObject()
|
||||
|
||||
const resizeObjectBatch = (side, target, width, height) => {
|
||||
const objectWidth = target.width
|
||||
const objectHeight = target.height
|
||||
const changeWidth = (width / 10 / objectWidth).toFixed(2)
|
||||
@ -884,7 +896,6 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const newCoords = target.getPointByOrigin(sideX, sideY)
|
||||
|
||||
target.set({
|
||||
...target,
|
||||
originX: sideX,
|
||||
originY: sideY,
|
||||
left: newCoords.x,
|
||||
@ -894,8 +905,8 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
target.setCoords()
|
||||
canvas?.renderAll() //변경 좌표를 한번 적용
|
||||
|
||||
target.scaleX = changeWidth === 0 ? 1 : changeWidth
|
||||
target.scaleY = changeHeight === 0 ? 1 : changeHeight
|
||||
target.scaleX = changeWidth || 1
|
||||
target.scaleY = changeHeight || 1
|
||||
|
||||
//크기 변경후 좌표를 재 적용
|
||||
const changedCoords = target.getPointByOrigin('center', 'center')
|
||||
@ -910,9 +921,12 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
|
||||
if (target.name === 'roof') {
|
||||
//얘는 일단 도머에 적용함
|
||||
target._objects.forEach((obj) => {
|
||||
setSurfaceShapePattern(obj)
|
||||
})
|
||||
if (target.type === 'group') {
|
||||
target._objects.forEach((obj) => setSurfaceShapePattern(obj))
|
||||
} else {
|
||||
setSurfaceShapePattern(target)
|
||||
target.fire('modified')
|
||||
}
|
||||
}
|
||||
// target.setCoords()
|
||||
canvas.renderAll()
|
||||
@ -923,30 +937,34 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const reGroupObject = (groupObj) => {
|
||||
groupObj._restoreObjectsState() //이건 실행만 되도 그룹이 변경됨
|
||||
const reGroupObjects = []
|
||||
|
||||
groupObj._objects.forEach((obj) => {
|
||||
const newObj = new QPolygon(obj.getCurrentPoints(), {
|
||||
...obj,
|
||||
points: obj.getCurrentPoints(),
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
texts: [],
|
||||
})
|
||||
reGroupObjects.push(newObj)
|
||||
canvas.remove(obj)
|
||||
|
||||
if (obj.direction) {
|
||||
drawDirectionArrow(obj)
|
||||
}
|
||||
newObj.fire('modified')
|
||||
})
|
||||
|
||||
const reGroup = new fabric.Group(reGroupObjects, {
|
||||
subTargetCheck: true,
|
||||
name: groupObj.name,
|
||||
id: groupObj.id,
|
||||
groupYn: true,
|
||||
parentId: groupObj.parentId,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
canvas?.add(reGroup)
|
||||
canvas?.remove(groupObj)
|
||||
|
||||
return reGroup
|
||||
}
|
||||
|
||||
const moveObjectBatch = () => {
|
||||
@ -965,17 +983,46 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
})
|
||||
initEvent()
|
||||
obj.setCoords()
|
||||
reGroupObject(obj)
|
||||
if (obj.type === 'group') reGroupObject(obj)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const dormerOffsetKeyEvent = (setArrow1, setArrow2) => {
|
||||
addDocumentEventListener('keydown', document, (e) => {
|
||||
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
|
||||
const keyEvent = e.key === 'ArrowDown' ? 'down' : 'up'
|
||||
setArrow1(keyEvent)
|
||||
} else if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
|
||||
const keyEvent = e.key === 'ArrowLeft' ? 'left' : 'right'
|
||||
setArrow2(keyEvent)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const dormerOffset = (arrow1, arrow2, length1, length2) => {
|
||||
length1 = parseInt(length1) / 10
|
||||
length2 = parseInt(length2) / 10
|
||||
|
||||
const dormer = canvas.getActiveObject()
|
||||
if (length1) dormer.top = arrow1 === 'down' ? dormer.top + length1 : dormer.top - length1
|
||||
if (length2) dormer.left = arrow2 === 'left' ? dormer.left - length2 : dormer.left + length2
|
||||
|
||||
if (dormer.type === 'group') {
|
||||
const newDormer = reGroupObject(dormer)
|
||||
canvas?.setActiveObject(newDormer)
|
||||
}
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
return {
|
||||
applyOpeningAndShadow,
|
||||
applyDormers,
|
||||
splitDormerTriangle,
|
||||
splitDormerPentagon,
|
||||
reSizeObjectBatch,
|
||||
resizeObjectBatch,
|
||||
moveObjectBatch,
|
||||
dormerOffsetKeyEvent,
|
||||
dormerOffset,
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { useEffect, useRef, useState } from 'react'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
|
||||
//동선이동 형 올림 내림
|
||||
export function useMovementSetting(id) {
|
||||
@ -18,6 +19,7 @@ export function useMovementSetting(id) {
|
||||
const { closePopup } = usePopup()
|
||||
const { getMessage } = useMessage()
|
||||
const currentObject = useRecoilValue(currentObjectState)
|
||||
const selectedObject = useRef(null)
|
||||
const buttonType = [
|
||||
{ id: 1, name: getMessage('modal.movement.flow.line.move'), type: TYPE.FLOW_LINE },
|
||||
{ id: 2, name: getMessage('modal.movement.flow.line.updown'), type: TYPE.UP_DOWN },
|
||||
@ -40,6 +42,7 @@ export function useMovementSetting(id) {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
removeFlowLine()
|
||||
typeRef.current = type
|
||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') // 기존 outerLine의 selectable true
|
||||
outerLines.forEach((line) => {
|
||||
@ -85,8 +88,10 @@ export function useMovementSetting(id) {
|
||||
|
||||
canvas.renderAll()
|
||||
addCanvasMouseEventListener('mouse:move', mouseMoveEvent)
|
||||
addCanvasMouseEventListener('mouse:down', mouseDownEvent)
|
||||
return () => {
|
||||
initEvent()
|
||||
removeFlowLine()
|
||||
const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL)
|
||||
wallLines.forEach((line) => {
|
||||
line.set({ visible: true })
|
||||
@ -107,11 +112,14 @@ export function useMovementSetting(id) {
|
||||
outerLines.forEach((line) => {
|
||||
line.set({ stroke: 'black' })
|
||||
})
|
||||
clearRef()
|
||||
selectedObject.current = null
|
||||
|
||||
if (!currentObject) {
|
||||
return
|
||||
}
|
||||
|
||||
clearRef()
|
||||
selectedObject.current = currentObject
|
||||
if (currentObject.name === OUTER_LINE_TYPE.OUTER_LINE) {
|
||||
currentObject.set({ stroke: '#EA10AC' })
|
||||
currentObject.bringToFront()
|
||||
@ -134,14 +142,91 @@ export function useMovementSetting(id) {
|
||||
}
|
||||
}
|
||||
|
||||
const mouseMoveEvent = (e) => {
|
||||
const mouseDownEvent = (e) => {
|
||||
if (typeRef.current === TYPE.FLOW_LINE) {
|
||||
flowLineEvent(e)
|
||||
flowLineDownEvent(e)
|
||||
} else {
|
||||
updownEvent(e)
|
||||
updownDownEvent(e)
|
||||
}
|
||||
}
|
||||
const flowLineEvent = (e) => {
|
||||
|
||||
const removeFlowLine = () => {
|
||||
const flowLine = canvas.getObjects().filter((obj) => obj.name === 'flowLine')
|
||||
flowLine.forEach((line) => {
|
||||
canvas.remove(line)
|
||||
})
|
||||
}
|
||||
|
||||
const mouseMoveEvent = (e) => {
|
||||
if (typeRef.current === TYPE.FLOW_LINE) {
|
||||
flowLineMoveEvent(e)
|
||||
} else {
|
||||
updownMoveEvent(e)
|
||||
}
|
||||
}
|
||||
//동선 이동 마우스 클릭 이벤트
|
||||
const flowLineDownEvent = (e) => {
|
||||
const target = selectedObject.current
|
||||
if (!target) {
|
||||
return
|
||||
}
|
||||
|
||||
const direction = target.direction
|
||||
|
||||
removeFlowLine()
|
||||
|
||||
let newPoint = []
|
||||
if (direction === 'left' || direction === 'right') {
|
||||
if (FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked) {
|
||||
newPoint = [
|
||||
target.x1,
|
||||
target.y1 + Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
|
||||
target.x2,
|
||||
target.y2 + Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
|
||||
]
|
||||
} else {
|
||||
newPoint = [
|
||||
target.x1,
|
||||
target.y1 - Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
|
||||
target.x2,
|
||||
target.y2 - Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
|
||||
]
|
||||
}
|
||||
} else {
|
||||
if (FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked) {
|
||||
newPoint = [
|
||||
target.x1 - Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
|
||||
target.y1,
|
||||
target.x2 - Number(FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value / 10),
|
||||
target.y2,
|
||||
]
|
||||
} else {
|
||||
newPoint = [
|
||||
target.x1 + Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
|
||||
target.y1,
|
||||
target.x2 + Number(FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value / 10),
|
||||
target.y2,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
const cloned = new fabric.Line(newPoint, {
|
||||
stroke: 'red',
|
||||
strokeWidth: 4,
|
||||
name: 'flowLine',
|
||||
currentLine: target,
|
||||
})
|
||||
|
||||
canvas.add(cloned)
|
||||
canvas.renderAll()
|
||||
canvas.discardActiveObject()
|
||||
}
|
||||
|
||||
//형 올림내림 마우스 클릭 이벤트
|
||||
const updownDownEvent = (e) => {
|
||||
console.log('updownDownEvent')
|
||||
}
|
||||
const flowLineMoveEvent = (e) => {
|
||||
const target = canvas.getActiveObject()
|
||||
if (!target) {
|
||||
return
|
||||
@ -181,7 +266,7 @@ export function useMovementSetting(id) {
|
||||
canvas?.renderAll()
|
||||
}
|
||||
|
||||
const updownEvent = (e) => {
|
||||
const updownMoveEvent = (e) => {
|
||||
const target = canvas.getActiveObject()
|
||||
if (!target) {
|
||||
return
|
||||
@ -222,12 +307,24 @@ export function useMovementSetting(id) {
|
||||
|
||||
const handleSave = () => {
|
||||
if (type === TYPE.FLOW_LINE) {
|
||||
// 동선이동
|
||||
if (FLOW_LINE_REF.DOWN_LEFT_RADIO_REF.current.checked) {
|
||||
// 높이 변경: 아래, 왼쪽 체크
|
||||
} else {
|
||||
// 높이 변경: 위, 오른쪽 체크
|
||||
const flowLine = canvas.getObjects().find((obj) => obj.name === 'flowLine')
|
||||
|
||||
const currentLine = flowLine.currentLine
|
||||
if (!flowLine || !currentLine) {
|
||||
return
|
||||
}
|
||||
|
||||
currentLine.set({
|
||||
x1: flowLine.x1,
|
||||
y1: flowLine.y1,
|
||||
x2: flowLine.x2,
|
||||
y2: flowLine.y2,
|
||||
})
|
||||
currentLine.startPoint = { x: flowLine.x1, y: flowLine.y1 }
|
||||
currentLine.endPoint = { x: flowLine.x2, y: flowLine.y2 }
|
||||
|
||||
canvas.remove(flowLine)
|
||||
canvas.renderAll()
|
||||
} else {
|
||||
// 형 올림내림
|
||||
if (UP_DOWN_REF.UP_RADIO_REF.current.checked) {
|
||||
|
||||
@ -12,10 +12,12 @@ import { useEvent } from '@/hooks/useEvent'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||
import { usePolygon } from '@/hooks/usePolygon'
|
||||
import { fontSelector } from '@/store/fontAtom'
|
||||
|
||||
export function useSurfaceShapeBatch() {
|
||||
const { getMessage } = useMessage()
|
||||
const { drawDirectionArrow } = usePolygon()
|
||||
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
||||
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const globalPitch = useRecoilValue(globalPitchState)
|
||||
@ -598,8 +600,214 @@ export function useSurfaceShapeBatch() {
|
||||
})
|
||||
}
|
||||
|
||||
const findAllChildren = (parentId) => {
|
||||
let allChildren = []
|
||||
|
||||
// 직계 자식 객체들 찾기
|
||||
const directChildren = canvas.getObjects().filter((obj) => obj.parentId === parentId)
|
||||
|
||||
directChildren.forEach((child) => {
|
||||
allChildren.push(child) // 현재 자식 추가
|
||||
|
||||
// 자식이 그룹인 경우
|
||||
if (child.type === 'group') {
|
||||
// 그룹 내부의 객체들 추가
|
||||
child.getObjects().forEach((groupItem) => {
|
||||
allChildren.push(groupItem)
|
||||
// 그룹 내부 객체의 자식들도 찾기
|
||||
const nestedChildren = findAllChildren(groupItem.id)
|
||||
allChildren.push(...nestedChildren)
|
||||
})
|
||||
}
|
||||
|
||||
// 현재 자식의 하위 자식들 찾기
|
||||
const childrenOfChild = findAllChildren(child.id)
|
||||
allChildren.push(...childrenOfChild)
|
||||
})
|
||||
|
||||
// 중복 제거하여 반환
|
||||
return [...new Set(allChildren)]
|
||||
}
|
||||
|
||||
const findGroupObjects = (parentId) => {
|
||||
let groupObjectsArray = []
|
||||
|
||||
// 직계 자식 객체들 찾기
|
||||
const directChildren = canvas.getObjects().filter((obj) => obj.parentId === parentId)
|
||||
|
||||
// 각 자식 객체에 대해 처리
|
||||
directChildren.forEach((child) => {
|
||||
groupObjectsArray.push(child) // 현재 자식 추가
|
||||
|
||||
// 자식이 그룹인 경우 그룹 내부 객체들도 처리
|
||||
if (child.type === 'group') {
|
||||
child.getObjects().forEach((groupItem) => {
|
||||
// 그룹 내부 각 아이템의 하위 객체들 찾기
|
||||
const nestedObjects = findGroupObjects(groupItem.id)
|
||||
groupObjectsArray.push(...nestedObjects)
|
||||
})
|
||||
}
|
||||
|
||||
// 일반 자식의 하위 객체들 찾기
|
||||
const childObjects = findGroupObjects(child.id)
|
||||
groupObjectsArray.push(...childObjects)
|
||||
})
|
||||
|
||||
return groupObjectsArray
|
||||
}
|
||||
|
||||
function getAllRelatedObjects(id) {
|
||||
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
|
||||
}
|
||||
|
||||
const moveSurfaceShapeBatch = () => {
|
||||
const roof = canvas.getActiveObject()
|
||||
|
||||
if (roof) {
|
||||
let isDragging = false
|
||||
|
||||
const childrenObjects = canvas.getObjects().filter((obj) => obj.parentId === roof.id)
|
||||
|
||||
console.log('childrenObjects', childrenObjects)
|
||||
|
||||
// const groupObjects = canvas.getObjects().filter((obj) => obj.parentId === roof.id && obj.type === 'group')
|
||||
|
||||
// const ungroupObjects = [] // 그룹 해제된 객체들
|
||||
// const groupChildObjects = []
|
||||
|
||||
// groupObjects.forEach((obj) => {
|
||||
// obj._restoreObjectsState()
|
||||
// obj.getObjects().forEach((o) => {
|
||||
// o.set({
|
||||
// ungroupYn: true,
|
||||
// })
|
||||
// canvas.add(o)
|
||||
// ungroupObjects.push(o)
|
||||
// })
|
||||
// canvas.remove(obj)
|
||||
// })
|
||||
|
||||
// const childObjects = findAllChildren(roof.id)
|
||||
// groupObjects.forEach((obj) => {
|
||||
// groupChildObjects.push(...obj.getObjects())
|
||||
// })
|
||||
|
||||
// console.log('ungroupObjects', ungroupObjects)
|
||||
// console.log('childObjects', childObjects)
|
||||
// console.log('groupChildObjects', groupChildObjects)
|
||||
|
||||
// const children = canvas.getObjects().filter((obj) => obj.parentId === roof.id)
|
||||
// let grandChildren = []
|
||||
|
||||
// children.forEach((child) => {
|
||||
// if (child.type === 'group') {
|
||||
// child.getObjects().forEach((grandChild) => {
|
||||
// const groupObjects = canvas.getObjects().filter((obj) => obj.parentId === grandChild.id)
|
||||
// grandChildren.push(...groupObjects)
|
||||
// })
|
||||
// } else {
|
||||
// grandChildren.push(...canvas.getObjects().filter((obj) => obj.parentId === child.id))
|
||||
// }
|
||||
// })
|
||||
|
||||
const selectionArray = [roof, ...childrenObjects]
|
||||
|
||||
const selection = new fabric.ActiveSelection(selectionArray, {
|
||||
canvas: canvas,
|
||||
draggable: true,
|
||||
lockMovementX: false, // X축 이동 허용
|
||||
lockMovementY: false, // Y축 이동 허용
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
})
|
||||
|
||||
canvas.setActiveObject(selection)
|
||||
|
||||
addCanvasMouseEventListener('mouse:up', (e) => {
|
||||
isDragging = false
|
||||
canvas.selection = true
|
||||
|
||||
canvas.discardActiveObject() // 모든 선택 해제
|
||||
canvas.requestRenderAll() // 화면 업데이트
|
||||
|
||||
selection.getObjects().forEach((obj) => {
|
||||
obj.set({
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
})
|
||||
obj.setCoords()
|
||||
|
||||
if (obj.type === 'group') {
|
||||
reGroupObject(obj)
|
||||
}
|
||||
})
|
||||
|
||||
canvas.renderAll()
|
||||
roof.fire('polygonMoved')
|
||||
if (roof.type === 'group') reGroupObject(obj)
|
||||
drawDirectionArrow(roof)
|
||||
initEvent()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const reGroupObject = (groupObj) => {
|
||||
groupObj._restoreObjectsState() //이건 실행만 되도 그룹이 변경됨
|
||||
const reGroupObjects = []
|
||||
|
||||
groupObj._objects.forEach((obj) => {
|
||||
const newObj = new QPolygon(obj.getCurrentPoints(), {
|
||||
...obj,
|
||||
points: obj.getCurrentPoints(),
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
})
|
||||
reGroupObjects.push(newObj)
|
||||
canvas.remove(obj)
|
||||
|
||||
if (obj.direction) {
|
||||
drawDirectionArrow(obj)
|
||||
}
|
||||
})
|
||||
|
||||
const reGroup = new fabric.Group(reGroupObjects, {
|
||||
subTargetCheck: true,
|
||||
name: groupObj.name,
|
||||
id: groupObj.id,
|
||||
groupYn: true,
|
||||
parentId: groupObj.parentId,
|
||||
})
|
||||
canvas?.add(reGroup)
|
||||
canvas?.remove(groupObj)
|
||||
}
|
||||
|
||||
return {
|
||||
applySurfaceShape,
|
||||
deleteAllSurfacesAndObjects,
|
||||
moveSurfaceShapeBatch,
|
||||
}
|
||||
}
|
||||
|
||||
@ -209,13 +209,52 @@ export function useCanvasEvent() {
|
||||
created: (e) => {
|
||||
const target = e.selected[0]
|
||||
setCurrentObject(target)
|
||||
const { selected } = e
|
||||
|
||||
if (selected.length > 0) {
|
||||
selected.forEach((obj) => {
|
||||
if (obj.type === 'QPolygon') {
|
||||
obj.set({ stroke: 'red' })
|
||||
}
|
||||
})
|
||||
canvas.renderAll()
|
||||
}
|
||||
},
|
||||
cleared: (e) => {
|
||||
setCurrentObject(null)
|
||||
const { deselected } = e
|
||||
|
||||
if (deselected.length > 0) {
|
||||
deselected.forEach((obj) => {
|
||||
if (obj.type === 'QPolygon') {
|
||||
obj.set({ stroke: 'black' })
|
||||
}
|
||||
})
|
||||
}
|
||||
canvas.renderAll()
|
||||
},
|
||||
updated: (e) => {
|
||||
const target = e.selected[0]
|
||||
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()
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@ import RowRemove from '@/components/floor-plan/modal/module/row/RowRemove'
|
||||
import RowInsert from '@/components/floor-plan/modal/module/row/RowInsert'
|
||||
import CircuitNumberEdit from '@/components/floor-plan/modal/module/CircuitNumberEdit'
|
||||
import { useObjectBatch } from '@/hooks/object/useObjectBatch'
|
||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||
|
||||
export function useContextMenu() {
|
||||
const currentMenu = useRecoilValue(currentMenuState) // 현재 메뉴
|
||||
@ -50,7 +51,7 @@ export function useContextMenu() {
|
||||
const [column, setColumn] = useState(null)
|
||||
const { handleZoomClear } = useCanvasEvent()
|
||||
const { moveObjectBatch } = useObjectBatch({})
|
||||
|
||||
const { moveSurfaceShapeBatch } = useSurfaceShapeBatch()
|
||||
const currentMenuSetting = () => {
|
||||
switch (currentMenu) {
|
||||
case MENU.PLAN_DRAWING:
|
||||
@ -230,18 +231,18 @@ export function useContextMenu() {
|
||||
y: 180,
|
||||
})
|
||||
setCurrentContextMenu(menu)
|
||||
currentMenuSetting()
|
||||
setQContextMenu({ ...qContextMenu, visible: false })
|
||||
}
|
||||
|
||||
const handleKeyup = (e) => {
|
||||
let menu = null
|
||||
|
||||
for (let i = 0; i < contextMenu.length; i++) {
|
||||
const temp = contextMenu[i].filter((menu) => {
|
||||
return menu.shortcut?.includes(e.key)
|
||||
})
|
||||
|
||||
if (temp.length > 0) menu = temp
|
||||
if (temp.length > 0) menu = temp[0]
|
||||
}
|
||||
|
||||
if (menu) handleClick(null, menu)
|
||||
@ -256,8 +257,8 @@ export function useContextMenu() {
|
||||
}, [currentContextMenu])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('currentObject', currentObject)
|
||||
if (currentObject?.name) {
|
||||
console.log(currentObject?.name)
|
||||
switch (currentObject.name) {
|
||||
case 'triangleDormer':
|
||||
case 'pentagonDormer':
|
||||
@ -294,7 +295,7 @@ export function useContextMenu() {
|
||||
{
|
||||
id: 'dormerOffset',
|
||||
name: getMessage('contextmenu.dormer.offset'),
|
||||
component: <DormerOffset id={popupId} />,
|
||||
component: <DormerOffset id={popupId} title={getMessage('contextmenu.dormer.offset')} />,
|
||||
},
|
||||
],
|
||||
])
|
||||
@ -305,22 +306,25 @@ export function useContextMenu() {
|
||||
{
|
||||
id: 'sizeEdit',
|
||||
name: '사이즈 변경',
|
||||
component: <SizeSetting id={popupId} />,
|
||||
component: <SizeSetting id={popupId} target={currentObject} />,
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialRemove',
|
||||
shortcut: ['d', 'D'],
|
||||
name: `${getMessage('contextmenu.remove')}(D)`,
|
||||
fn: () => deleteObject(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialMove',
|
||||
shortcut: ['m', 'M'],
|
||||
name: `${getMessage('contextmenu.move')}(M)`,
|
||||
fn: () => moveSurfaceShapeBatch(),
|
||||
},
|
||||
{
|
||||
id: 'roofMaterialCopy',
|
||||
shortcut: ['c', 'C'],
|
||||
name: `${getMessage('contextmenu.copy')}(C)`,
|
||||
fn: () => copyObject(),
|
||||
},
|
||||
],
|
||||
[
|
||||
@ -371,6 +375,7 @@ export function useContextMenu() {
|
||||
{
|
||||
id: 'openingOffset',
|
||||
name: getMessage('contextmenu.opening.offset'),
|
||||
component: <DormerOffset id={popupId} title={getMessage('contextmenu.opening.offset')} />,
|
||||
},
|
||||
],
|
||||
])
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
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 { 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 { useDotLineGrid } from '@/hooks/useDotLineGrid'
|
||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||
import { gridDisplaySelector } from '@/store/settingAtom'
|
||||
|
||||
export function useEvent() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
@ -100,7 +99,13 @@ export function useEvent() {
|
||||
const distance = calculateDistance(pointer, closestLine)
|
||||
|
||||
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,
|
||||
removeAllMouseEventListeners,
|
||||
removeAllDocumentEventListeners,
|
||||
removeDocumentEvent,
|
||||
removeMouseEvent,
|
||||
removeMouseLine,
|
||||
initEvent,
|
||||
|
||||
@ -77,11 +77,9 @@ export function usePlan() {
|
||||
})
|
||||
|
||||
//디렉션이 있는 경우에만
|
||||
if (group.lineDirection) {
|
||||
obj.set({
|
||||
lineDirection: group.lineDirection,
|
||||
})
|
||||
}
|
||||
if (group.lineDirection) obj.set({ lineDirection: group.lineDirection })
|
||||
//부모객체가 있으면 (면형상 위에 도머등..)
|
||||
if (group.parentId) obj.set({ parentId: group.parentId })
|
||||
|
||||
canvas?.add(obj)
|
||||
obj.setCoords()
|
||||
|
||||
@ -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