diff --git a/src/app/intro/page.jsx b/src/app/intro/page.jsx deleted file mode 100644 index ebf1081b..00000000 --- a/src/app/intro/page.jsx +++ /dev/null @@ -1,12 +0,0 @@ -import Intro from '@/components/Intro' -import { initCheck } from '@/util/session-util' - -export default async function IntroPage() { - return ( - <> -
- -
- - ) -} diff --git a/src/components/Intro.jsx b/src/components/Intro.jsx deleted file mode 100644 index a6825af7..00000000 --- a/src/components/Intro.jsx +++ /dev/null @@ -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 = ( - <> -

title

-

- 저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 이 헌법은 1988년 2월 25일부터 시행한다. 다만, 이 헌법을 시행하기 위하여 필요한 - 법률의 제정·개정과 이 헌법에 의한 대통령 및 국회의원의 선거 기타 이 헌법시행에 관한 준비는 이 헌법시행 전에 할 수 있다. -

-

- 국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 할 수 있도록 노력하여야 한다. 통신·방송의 시설기준과 신문의 기능을 보장하기 - 위하여 필요한 사항은 법률로 정한다. -

-

- 국회에서 의결된 법률안은 정부에 이송되어 15일 이내에 대통령이 공포한다. 선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는 - 후보자에게 부담시킬 수 없다. -

- - ) - - 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 ( - <> -
- - - -
-
-
Single Date Picker
-
- -
-
-
-
Range Date Picker
-
- -
-
-
-
QGrid
-
- -
-
-
-
QModal
-
- {/* - {ipsum} */} - -
-
-
-
QToast
-
- -
-
- - ) -} diff --git a/src/components/Playground.jsx b/src/components/Playground.jsx index 5cd4588c..a908ba0f 100644 --- a/src/components/Playground.jsx +++ b/src/components/Playground.jsx @@ -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() { diff --git a/src/components/common/context-menu/QContextMenu.jsx b/src/components/common/context-menu/QContextMenu.jsx index 9d3eb4f3..f6665930 100644 --- a/src/components/common/context-menu/QContextMenu.jsx +++ b/src/components/common/context-menu/QContextMenu.jsx @@ -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({ diff --git a/src/components/common/draggable/WithDraggable.jsx b/src/components/common/draggable/WithDraggable.jsx index 29952981..76656837 100644 --- a/src/components/common/draggable/WithDraggable.jsx +++ b/src/components/common/draggable/WithDraggable.jsx @@ -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 ( <> diff --git a/src/components/common/input/QInput.jsx b/src/components/common/input/QInput.jsx index 3c1046af..83e16657 100644 --- a/src/components/common/input/QInput.jsx +++ b/src/components/common/input/QInput.jsx @@ -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 ( ) } diff --git a/src/components/common/popupManager/PopupManager.jsx b/src/components/common/popupManager/PopupManager.jsx index f24a8526..e84ee610 100644 --- a/src/components/common/popupManager/PopupManager.jsx +++ b/src/components/common/popupManager/PopupManager.jsx @@ -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) => {child.component}), diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 47f99c3d..f12d7c69 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -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 (
@@ -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 }) { {/* 견적 특이사항 코드영역시작 */}
-
+
+ {/* SpecialNoteList반복문 */} + {specialNoteList.map((row) => { + return ( +
{ + settingShowContent(row.code, event) + }} + > +
+ { + setSpecialNoteList((specialNote) => + specialNote.map((temp) => (temp.code === row.code ? { ...temp, text: !temp.text } : temp)), + ) + settingShowContent(row.code, event) + }} + /> + +
+
+ ) + })} +
{/* 견적특이사항 선택한 내용?영역시작 */}
-
-
제목11??
-
제목1 비고
-
-
-
제목22??
-
제목2 비고
-
+ {specialNoteList.map((row) => { + if (row.code === showContentCode) { + return ( +
+
{row.codeNm}
+
{row.remarks}
+
+ ) + } + })}
{/* 견적특이사항 선택한 내용?영역끝 */}
diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 5d1bad29..44cbfb37 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -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 diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index b0881b6e..ad10485c 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -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() {
- + {contextMenu?.map((menus, index) => (
    {menus.map((menu) => ( diff --git a/src/components/floor-plan/modal/object/DormerOffset.jsx b/src/components/floor-plan/modal/object/DormerOffset.jsx index bc56e4b7..191a94ea 100644 --- a/src/components/floor-plan/modal/object/DormerOffset.jsx +++ b/src/components/floor-plan/modal/object/DormerOffset.jsx @@ -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 (
    -

    {getMessage('contextmenu.dormer.offset')}

    +

    {title}

    @@ -29,44 +56,40 @@ export default function DormerOffset(props) {

    {getMessage('length')}

    - +
    mm
    - +
    mm
    @@ -75,7 +98,9 @@ export default function DormerOffset(props) {
    - +
diff --git a/src/components/floor-plan/modal/object/SizeSetting.jsx b/src/components/floor-plan/modal/object/SizeSetting.jsx index 1b20b853..333150ea 100644 --- a/src/components/floor-plan/modal/object/SizeSetting.jsx +++ b/src/components/floor-plan/modal/object/SizeSetting.jsx @@ -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 ( diff --git a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx index c22d2248..431e0f85 100644 --- a/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx +++ b/src/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting.jsx @@ -240,7 +240,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } }) }, []) return ( - +

{getMessage('plan.menu.placement.surface.arrangement')}

diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index e1bef1f0..222226c1 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -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) } diff --git a/src/components/management/Stuff.jsx b/src/components/management/Stuff.jsx index b369defe..8c97347d 100644 --- a/src/components/management/Stuff.jsx +++ b/src/components/management/Stuff.jsx @@ -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)) { diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 49fc92f8..61cdc1df 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -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() {
- {/* {sessionState?.storeId === 'T01' && ( */} {session?.storeId === 'T01' && ( <>
@@ -1482,7 +1472,6 @@ export default function StuffDetail() { )} - {/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl === '1' && ( */} {session?.storeId !== 'T01' && session?.storeLvl === '1' && ( <>
@@ -1514,7 +1503,6 @@ export default function StuffDetail() {
)} - {/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl !== '1' && ( */} {session?.storeId !== 'T01' && session?.storeLvl !== '1' && ( <>
@@ -1931,7 +1919,6 @@ export default function StuffDetail() {
- {/* {sessionState?.storeId === 'T01' && ( */} {session?.storeId === 'T01' && ( <>
@@ -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() {
)} - {/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl === '1' && ( */} {session?.storeId !== 'T01' && session?.storeLvl === '1' && ( <>
@@ -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() {
)} - {/* {sessionState?.storeId !== 'T01' && sessionState?.storeLvl !== '1' && ( */} {session?.storeId !== 'T01' && session?.storeLvl !== '1' && ( <>
@@ -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 })} diff --git a/src/components/management/StuffSearchCondition.jsx b/src/components/management/StuffSearchCondition.jsx index 659ab696..1d40b61a 100644 --- a/src/components/management/StuffSearchCondition.jsx +++ b/src/components/management/StuffSearchCondition.jsx @@ -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 }) }} /> @@ -634,7 +617,6 @@ export default function StuffSearchCondition() { value={'R'} onChange={(e) => { setDateType(e.target.value) - //setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) }} /> diff --git a/src/hooks/common/useCanvasConfigInitialize.js b/src/hooks/common/useCanvasConfigInitialize.js index 8d8eb38b..c4f137b0 100644 --- a/src/hooks/common/useCanvasConfigInitialize.js +++ b/src/hooks/common/useCanvasConfigInitialize.js @@ -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') + }) }) } diff --git a/src/hooks/floorPlan/estimate/useEstimateController.js b/src/hooks/floorPlan/estimate/useEstimateController.js index 87fa15ca..2b92a14a 100644 --- a/src/hooks/floorPlan/estimate/useEstimateController.js +++ b/src/hooks/floorPlan/estimate/useEstimateController.js @@ -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({ diff --git a/src/hooks/object/useObjectBatch.js b/src/hooks/object/useObjectBatch.js index 19cbadec..a16ce0f9 100644 --- a/src/hooks/object/useObjectBatch.js +++ b/src/hooks/object/useObjectBatch.js @@ -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, } } diff --git a/src/hooks/roofcover/useMovementSetting.js b/src/hooks/roofcover/useMovementSetting.js index f872fc17..34961ea0 100644 --- a/src/hooks/roofcover/useMovementSetting.js +++ b/src/hooks/roofcover/useMovementSetting.js @@ -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) { diff --git a/src/hooks/surface/useSurfaceShapeBatch.js b/src/hooks/surface/useSurfaceShapeBatch.js index 2bfefb98..9457169c 100644 --- a/src/hooks/surface/useSurfaceShapeBatch.js +++ b/src/hooks/surface/useSurfaceShapeBatch.js @@ -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, } } diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 4bab1fd6..9b25eedd 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -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() }, } diff --git a/src/hooks/useContextMenu.js b/src/hooks/useContextMenu.js index 9099752e..64892dce 100644 --- a/src/hooks/useContextMenu.js +++ b/src/hooks/useContextMenu.js @@ -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: , + component: , }, ], ]) @@ -305,22 +306,25 @@ export function useContextMenu() { { id: 'sizeEdit', name: '사이즈 변경', - component: , + component: , }, { 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: , }, ], ]) diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index a84dea38..891ad101 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -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, diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 5b78fd7c..ab67452e 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -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() diff --git a/src/util/session-util.js b/src/util/session-util.js deleted file mode 100644 index 6f818e43..00000000 --- a/src/util/session-util.js +++ /dev/null @@ -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 -}