Merge branch 'dev' of https://git.jetbrains.space/nalpari/q-cast-iii/qcast-front into dev
This commit is contained in:
commit
bccca5f817
@ -1,11 +1,15 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Hero from '@/components/Hero'
|
import Hero from '@/components/Hero'
|
||||||
import StuffDetail from '@/components/management/StuffDetail'
|
import StuffDetail from '@/components/management/StuffDetail'
|
||||||
|
import Link from 'next/link'
|
||||||
export default function ManagementStuffDetailPage() {
|
export default function ManagementStuffDetailPage() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="pt-48 flex justify-left">
|
<div className="pt-48 flex justify-left">
|
||||||
<h1 className="text-4xl archivo-black-regular">물건정보</h1>
|
<h1 className="text-4xl archivo-black-regular">물건정보</h1>
|
||||||
|
<Link href="/management/plan">
|
||||||
|
<h1 className="text-4xl archivo-black-regular">도면작성</h1>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="m2">
|
<div className="m2">
|
||||||
<StuffDetail />
|
<StuffDetail />
|
||||||
|
|||||||
15
src/app/[locale]/management/stuff/tempdetail/page.jsx
Normal file
15
src/app/[locale]/management/stuff/tempdetail/page.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import Hero from '@/components/Hero'
|
||||||
|
import StuffDetail from '@/components/management/StuffDetail'
|
||||||
|
export default function ManagementStuffDetailPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="pt-48 flex justify-left">
|
||||||
|
<h1 className="text-4xl archivo-black-regular">물건정보</h1>
|
||||||
|
</div>
|
||||||
|
<div className="m2">
|
||||||
|
<StuffDetail />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,19 +1,22 @@
|
|||||||
export const STEP = {
|
export const MENU = {
|
||||||
INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정
|
INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정
|
||||||
ROOF_COVERING: {
|
ROOF_COVERING: {
|
||||||
EXTERIOR_WALL_LINE: 'exteriorWallLine', // 외벽선 그리기
|
EXTERIOR_WALL_LINE: 'exteriorWallLine', // 외벽선 그리기
|
||||||
ROOF_SHAPE_SETTINGS: 'roofShapeSettings', // 지붕형상 설정
|
ROOF_SHAPE_SETTINGS: 'roofShapeSettings', // 지붕형상 설정
|
||||||
ROOF_SHAPE_EDITING: 'roofShapeEditing', // 지붕형상 편집
|
ROOF_SHAPE_EDITING: 'roofShapeEditing', // 지붕형상 편집
|
||||||
HELP_LINE_DRAWING: 'helpLineDrawing', // 보조선 그리기
|
HELP_LINE_DRAWING: 'helpLineDrawing', // 보조선 그리기
|
||||||
|
DEFAULT: 'roofCoveringDefault', // 아무것도 선택 안할 경우
|
||||||
}, // 지붕덮개
|
}, // 지붕덮개
|
||||||
BATCH_CANVAS: {
|
BATCH_CANVAS: {
|
||||||
BATCH_DRAWING: 'batchDrawing', // 배치면 그리기
|
BATCH_DRAWING: 'batchDrawing', // 배치면 그리기
|
||||||
SURFACE_SHAPE_BATCH: 'surfaceShapeBatch', // 면형상 배치
|
SURFACE_SHAPE_BATCH: 'surfaceShapeBatch', // 면형상 배치
|
||||||
OBJECT_BATCH: 'objectBatch', // 오브젝트 배치
|
OBJECT_BATCH: 'objectBatch', // 오브젝트 배치
|
||||||
|
DEFAULT: 'batchCanvasDefault', // default
|
||||||
}, // 배치면
|
}, // 배치면
|
||||||
MODULE_CIRCUIT_SETTING: {
|
MODULE_CIRCUIT_SETTING: {
|
||||||
BASIC_SETTING: 'basicSetting', // 기본설정
|
BASIC_SETTING: 'basicSetting', // 기본설정
|
||||||
CIRCUIT_TRESTLE_SETTING: 'circuitTrestleSetting', // 회로가대설정
|
CIRCUIT_TRESTLE_SETTING: 'circuitTrestleSetting', // 회로가대설정
|
||||||
|
DEFAULT: 'moduleCircuitSettingDefault',
|
||||||
}, // 모듈회로구성
|
}, // 모듈회로구성
|
||||||
ESTIMATE: 'estimate', // todo 견적서
|
ESTIMATE: 'estimate', // todo 견적서
|
||||||
POWER_GENERATION_SIMULATION: 'powerGenerationSimulation', // todo 발전 시뮬레이션
|
POWER_GENERATION_SIMULATION: 'powerGenerationSimulation', // todo 발전 시뮬레이션
|
||||||
|
|||||||
@ -1,23 +1,29 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState } from "react"
|
import { useState } from 'react'
|
||||||
import CanvasFrame from "./CanvasFrame";
|
import CanvasFrame from './CanvasFrame'
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
import { currentMenuState, stepState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function CanvasLayout() {
|
export default function CanvasLayout() {
|
||||||
const [plans, setPlans] = useState([{ id: 0, name: 'Plan 1' }, { id: 1, name: 'Plan 2' }, { id: 2, name: 'Plan 3' }]);
|
const [plans, setPlans] = useState([
|
||||||
const [idxNum, setIdxNum] = useState(null);
|
{ id: 0, name: 'Plan 1' },
|
||||||
|
{ id: 1, name: 'Plan 2' },
|
||||||
|
{ id: 2, name: 'Plan 3' },
|
||||||
|
])
|
||||||
|
const [idxNum, setIdxNum] = useState(null)
|
||||||
|
|
||||||
const onClickPlane = (num) => {
|
const onClickPlane = (num) => {
|
||||||
setIdxNum(num);
|
setIdxNum(num)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleDeletePlan = (e, id) => {
|
const handleDeletePlan = (e, id) => {
|
||||||
e.stopPropagation(); // 이벤트 버블링 방지
|
e.stopPropagation() // 이벤트 버블링 방지
|
||||||
setPlans(plans.filter(plan => plan.id !== id)); // 삭제할 아이디와 다른 아이템만 남김
|
setPlans(plans.filter((plan) => plan.id !== id)) // 삭제할 아이디와 다른 아이템만 남김
|
||||||
}
|
}
|
||||||
|
|
||||||
const addNewPlan = () => {
|
const addNewPlan = () => {
|
||||||
setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }]);
|
setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }])
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -25,11 +31,7 @@ export default function CanvasLayout () {
|
|||||||
<div className="canvas-page-list">
|
<div className="canvas-page-list">
|
||||||
<div className="canvas-plane-wrap">
|
<div className="canvas-plane-wrap">
|
||||||
{plans.map((plan, idx) => (
|
{plans.map((plan, idx) => (
|
||||||
<button
|
<button key={plan.id} className={`canvas-page-box ${idx === idxNum ? 'on' : ''}`} onClick={() => onClickPlane(idx)}>
|
||||||
key={plan.id}
|
|
||||||
className={`canvas-page-box ${idx === idxNum ? 'on' : ''}`}
|
|
||||||
onClick={() => onClickPlane(idx)}
|
|
||||||
>
|
|
||||||
<span>{plan.name}</span>
|
<span>{plan.name}</span>
|
||||||
<i className="close" onClick={(e) => handleDeletePlan(e, plan.id)}></i>
|
<i className="close" onClick={(e) => handleDeletePlan(e, plan.id)}></i>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import MenuDepth01 from './MenuDepth01'
|
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState } from 'recoil'
|
||||||
import { modalState } from '@/store/modalAtom'
|
import { modalState } from '@/store/modalAtom'
|
||||||
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
import { settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { post } from '@/lib/Axios'
|
import { post } from '@/lib/Axios'
|
||||||
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
|
import { MENU } from '@/common/common'
|
||||||
|
import RoofCoveringMenu from '@/components/floor-plan/RoofCoveringMenu'
|
||||||
|
|
||||||
export default function CanvasMenu() {
|
export default function CanvasMenu() {
|
||||||
const [objectNo, setObjectNo] = useState('test123240912001')
|
const [objectNo, setObjectNo] = useState('test123240912001')
|
||||||
@ -15,11 +17,10 @@ export default function CanvasMenu() {
|
|||||||
const [vertical, setVertical] = useState(true)
|
const [vertical, setVertical] = useState(true)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
|
||||||
const onClickNav = (number) => {
|
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
||||||
setMenuNumber(number)
|
|
||||||
if (menuNumber === number) {
|
const onClickNav = (menu) => {
|
||||||
setMenuNumber(null)
|
setCurrentMenu(menu)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
|
||||||
@ -70,27 +71,31 @@ export default function CanvasMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div
|
||||||
|
className={`canvas-menu-wrap ${Object.values(MENU.ROOF_COVERING).includes(currentMenu) || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}
|
||||||
|
>
|
||||||
<div className="canvas-menu-inner">
|
<div className="canvas-menu-inner">
|
||||||
<ul className="canvas-menu-list">
|
<ul className="canvas-menu-list">
|
||||||
<li className={`canvas-menu-item ${menuNumber === 0 ? 'active' : ''}`} onClick={() => onClickNav(0)}>
|
<li className={`canvas-menu-item `} onClick={() => onClickNav(1)}>
|
||||||
<button>
|
<button>
|
||||||
<span className="menu-icon con00"></span>
|
<span className="menu-icon con00"></span>
|
||||||
{getMessage('plan.menu.plan.drawing')}
|
{getMessage('plan.menu.plan.drawing')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
<li className={`canvas-menu-item ${menuNumber === 1 ? 'active' : ''}`} onClick={() => onClickNav(1)}>
|
{
|
||||||
|
<li
|
||||||
|
className={`canvas-menu-item ${currentMenu === MENU.INITIAL_CANVAS_SETTING ? 'active' : ''}`}
|
||||||
|
onClick={() => onClickNav(MENU.INITIAL_CANVAS_SETTING)}
|
||||||
|
>
|
||||||
<button>
|
<button>
|
||||||
<span className="menu-icon con01"></span>
|
<span className="menu-icon con01"></span>
|
||||||
{getMessage('plan.menu.placement.surface.initial.setting')}
|
{getMessage('plan.menu.placement.surface.initial.setting')}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
|
}
|
||||||
<li
|
<li
|
||||||
className={`canvas-menu-item ${menuNumber === 2 ? 'active' : ''}`}
|
className={`canvas-menu-item ${Object.values(MENU.ROOF_COVERING).includes(currentMenu) ? 'active' : ''}`}
|
||||||
onClick={() => {
|
onClick={() => onClickNav(MENU.ROOF_COVERING.DEFAULT)}
|
||||||
setModalOption({ ...modalOption, outerwall: true })
|
|
||||||
onClickNav(2)
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<button>
|
<button>
|
||||||
<span className="menu-icon con02"></span>
|
<span className="menu-icon con02"></span>
|
||||||
@ -193,10 +198,13 @@ export default function CanvasMenu() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
<div
|
||||||
{menuNumber === 2 && <MenuDepth01 />}
|
className={`canvas-depth2-wrap ${Object.values(MENU.ROOF_COVERING).includes(currentMenu) || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}
|
||||||
|
>
|
||||||
|
{Object.values(MENU.ROOF_COVERING).includes(currentMenu) && <RoofCoveringMenu />}
|
||||||
|
{/*{menuNumber === 2 && <MenuDepth01 />}
|
||||||
{menuNumber === 3 && <MenuDepth01 />}
|
{menuNumber === 3 && <MenuDepth01 />}
|
||||||
{menuNumber === 4 && <MenuDepth01 />}
|
{menuNumber === 4 && <MenuDepth01 />}*/}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
54
src/components/floor-plan/RoofCoveringMenu.jsx
Normal file
54
src/components/floor-plan/RoofCoveringMenu.jsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useRecoilState, useSetRecoilState } from 'recoil'
|
||||||
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
|
import { MENU } from '@/common/common'
|
||||||
|
import { modalState } from '@/store/modalAtom'
|
||||||
|
import { ToggleonMouse } from '@/components/header/Header'
|
||||||
|
|
||||||
|
export default function RoofCoveringMenu() {
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
|
||||||
|
|
||||||
|
const setModalState = useSetRecoilState(modalState)
|
||||||
|
|
||||||
|
const onClickNav = (menu) => {
|
||||||
|
setCurrentMenu(menu)
|
||||||
|
if (menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE) {
|
||||||
|
setModalState((prev) => ({ ...prev, outerwall: true }))
|
||||||
|
} else {
|
||||||
|
setModalState((prev) => ({ ...prev, outerwall: false }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="canvas-depth2-inner">
|
||||||
|
<ul className="canvas-depth2-list">
|
||||||
|
<li className={`canvas-depth2-item ${currentMenu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE ? 'active' : ''}`}>
|
||||||
|
<button onClick={(e) => onClickNav(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)}>{getMessage('plan.menu.root.cover.outline.drawing')}</button>
|
||||||
|
</li>
|
||||||
|
<li className={`canvas-depth2-item ${currentMenu === MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS ? 'active' : ''}`}>
|
||||||
|
<button onClick={(e) => onClickNav(MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS)}>{getMessage('plan.menu.root.cover.roof.setting')}</button>
|
||||||
|
</li>
|
||||||
|
<li className={`canvas-depth2-item ${currentMenu === MENU.ROOF_COVERING.ROOF_SHAPE_EDITING ? 'active' : ''}`}>
|
||||||
|
<button onClick={(e) => onClickNav(MENU.ROOF_COVERING.ROOF_SHAPE_EDITING)}>{getMessage('plan.menu.root.cover.roof.edit')}</button>
|
||||||
|
</li>
|
||||||
|
<li className={`canvas-depth2-item ${currentMenu === MENU.ROOF_COVERING.HELP_LINE_DRAWING ? 'active' : ''}`}>
|
||||||
|
<button onClick={(e) => onClickNav(MENU.ROOF_COVERING.HELP_LINE_DRAWING)}>{getMessage('plan.menu.root.cover.sub.line')}</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<ul className="canvas-depth2-btn-list">
|
||||||
|
<li className="depth2-btn-box" onMouseEnter={(e) => ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
|
||||||
|
<button>{getMessage('plan.menu.estimate.roof.alloc')}</button>
|
||||||
|
</li>
|
||||||
|
<li className="depth2-btn-box" onMouseEnter={(e) => ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
|
||||||
|
<button>屋根材の設定と変更</button>
|
||||||
|
</li>
|
||||||
|
<li className="depth2-btn-box" onMouseEnter={(e) => ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
|
||||||
|
<button>屋根面全体削除</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@ -1,68 +1,443 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useState } from 'react'
|
import { useCallback, useEffect, useRef } from 'react'
|
||||||
import WithDraggable from '@/components/common/draggable/withDraggable'
|
import WithDraggable from '@/components/common/draggable/withDraggable'
|
||||||
import { modalState } from '@/store/modalAtom'
|
import { modalState } from '@/store/modalAtom'
|
||||||
import { useRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
|
import {
|
||||||
|
OUTER_LINE_TYPE,
|
||||||
|
outerLineArrow1State,
|
||||||
|
outerLineArrow2State,
|
||||||
|
outerLineLength1State,
|
||||||
|
outerLineLength2State,
|
||||||
|
outerLinePointsState,
|
||||||
|
outerLineTypeState,
|
||||||
|
} from '@/store/outerLineAtom'
|
||||||
|
import { QLine } from '@/components/fabric/QLine'
|
||||||
|
import { useLine } from '@/hooks/useLine'
|
||||||
|
|
||||||
export default function OuterLineWall() {
|
export default function OuterLineWall() {
|
||||||
const [modalOption, setModalOption] = useRecoilState(modalState) //modal 열림닫힘 state
|
const [modalOption, setModalOption] = useRecoilState(modalState) //modal 열림닫힘 state
|
||||||
const [buttonAct, setButtonAct] = useState(1)
|
|
||||||
const [close, setClose] = useState(false)
|
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const HandleClickClose = () => {
|
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllDocumentEventListeners } = useEvent()
|
||||||
setClose(true)
|
const { addLineText, removeLineText } = useLine()
|
||||||
setTimeout(() => {
|
const length1Ref = useRef(null)
|
||||||
setModalOption({ ...modalOption, outerwall: false })
|
const length2Ref = useRef(null)
|
||||||
setClose(false)
|
const [length1, setLength1] = useRecoilState(outerLineLength1State)
|
||||||
}, 180)
|
const [length2, setLength2] = useRecoilState(outerLineLength2State)
|
||||||
|
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
|
||||||
|
const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
|
||||||
|
const [points, setPoints] = useRecoilState(outerLinePointsState)
|
||||||
|
const [type, setType] = useRecoilState(outerLineTypeState)
|
||||||
|
const arrow1Ref = useRef(arrow1)
|
||||||
|
const arrow2Ref = useRef(arrow2)
|
||||||
|
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
addCanvasMouseEventListener('mouse:down', mouseDown)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
arrow1Ref.current = arrow1
|
||||||
|
}, [arrow1])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
arrow2Ref.current = arrow2
|
||||||
|
}, [arrow2])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
removeAllDocumentEventListeners()
|
||||||
|
addDocumentEventListener('keydown', document, keydown[type])
|
||||||
|
clear()
|
||||||
|
}, [type])
|
||||||
|
|
||||||
|
const clear = () => {
|
||||||
|
setLength1(0)
|
||||||
|
setLength2(0)
|
||||||
|
|
||||||
|
setArrow1('')
|
||||||
|
setArrow2('')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mouseDown = (e) => {
|
||||||
|
const pointer = canvas.getPointer(e.e)
|
||||||
|
|
||||||
|
setPoints((prev) => [...prev, pointer])
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
canvas
|
||||||
|
?.getObjects()
|
||||||
|
.filter((obj) => obj.name === 'outerLine')
|
||||||
|
.forEach((obj) => {
|
||||||
|
canvas?.remove(obj)
|
||||||
|
removeLineText(obj)
|
||||||
|
})
|
||||||
|
canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint'))
|
||||||
|
if (points.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (points.length === 1) {
|
||||||
|
const point = new fabric.Circle({
|
||||||
|
radius: 5,
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: 'red',
|
||||||
|
left: points[0].x - 5,
|
||||||
|
top: points[0].y - 5,
|
||||||
|
selectable: false,
|
||||||
|
name: 'startPoint',
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas?.add(point)
|
||||||
|
} else {
|
||||||
|
points.forEach((point, idx) => {
|
||||||
|
if (idx === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
drawLine(points[idx - 1], point)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [points])
|
||||||
|
|
||||||
|
const drawLine = (point1, point2) => {
|
||||||
|
const line = new QLine([point1.x, point1.y, point2.x, point2.y], {
|
||||||
|
stroke: 'black',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'outerLine',
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas?.add(line)
|
||||||
|
addLineText(line)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 직각 완료될 경우 확인
|
||||||
|
const checkRightAngle = () => {
|
||||||
|
const length1Num = Number(length1Ref.current.value) / 10
|
||||||
|
const length2Num = Number(length2Ref.current.value) / 10
|
||||||
|
console.log(length1Num, length2Num, arrow1Ref.current, arrow2Ref.current)
|
||||||
|
|
||||||
|
if (points.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (length1Num === 0 || length2Num === 0 || arrow1Ref.current === '' || arrow2Ref.current === '') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arrow1Ref.current === '↓' && arrow2Ref.current === '→') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y + length1Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '↓' && arrow2Ref.current === '←') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y + length1Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '↑' && arrow2Ref.current === '→') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y - length1Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '↑' && arrow2Ref.current === '←') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y - length1Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '→' && arrow2Ref.current === '↓') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y + length2Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '→' && arrow2Ref.current === '↑') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y - length2Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '←' && arrow2Ref.current === '↓') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y + length2Num }]
|
||||||
|
})
|
||||||
|
} else if (arrow1Ref.current === '←' && arrow2Ref.current === '↑') {
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y - length2Num }]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const keydown = {
|
||||||
|
outerLine: (e) => {
|
||||||
|
const key = e.key
|
||||||
|
|
||||||
|
if (!length1Ref.current) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const lengthNum = Number(length1Ref.current.value) / 10
|
||||||
|
if (lengthNum === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch (key) {
|
||||||
|
case 'Down': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowDown': {
|
||||||
|
setArrow1('↓')
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y + lengthNum }]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'Up': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowUp':
|
||||||
|
setArrow1('↑')
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y - lengthNum }]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'Left': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowLeft':
|
||||||
|
setArrow1('←')
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x - lengthNum, y: prev[prev.length - 1].y }]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'Right': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowRight':
|
||||||
|
setArrow1('→')
|
||||||
|
setPoints((prev) => {
|
||||||
|
if (prev.length === 0) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return [...prev, { x: prev[prev.length - 1].x + lengthNum, y: prev[prev.length - 1].y }]
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rightAngle: (e) => {
|
||||||
|
const key = e.key
|
||||||
|
|
||||||
|
const activeElem = document.activeElement
|
||||||
|
const length1Num = Number(length1Ref.current.value) / 10
|
||||||
|
const length2Num = Number(length2Ref.current.value) / 10
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
case 'Down': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowDown': {
|
||||||
|
if (activeElem === length1Ref.current) {
|
||||||
|
setArrow1('↓')
|
||||||
|
arrow1Ref.current = '↓'
|
||||||
|
} else if (activeElem === length2Ref.current) {
|
||||||
|
if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
setArrow2('↓')
|
||||||
|
arrow2Ref.current = '↓'
|
||||||
|
checkRightAngle()
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case 'Up': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowUp':
|
||||||
|
if (activeElem === length1Ref.current) {
|
||||||
|
setArrow1('↑')
|
||||||
|
arrow1Ref.current = '↑'
|
||||||
|
} else if (activeElem === length2Ref.current) {
|
||||||
|
if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
setArrow2('↑')
|
||||||
|
arrow2Ref.current = '↑'
|
||||||
|
checkRightAngle()
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
case 'Left': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowLeft':
|
||||||
|
if (activeElem === length1Ref.current) {
|
||||||
|
setArrow1('←')
|
||||||
|
arrow1Ref.current = '←'
|
||||||
|
} else if (activeElem === length2Ref.current) {
|
||||||
|
if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
setArrow2('←')
|
||||||
|
arrow2Ref.current = '←'
|
||||||
|
checkRightAngle()
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
case 'Right': // IE/Edge에서 사용되는 값
|
||||||
|
case 'ArrowRight':
|
||||||
|
if (activeElem === length1Ref.current) {
|
||||||
|
setArrow1('→')
|
||||||
|
arrow1Ref.current = '→'
|
||||||
|
} else if (activeElem === length2Ref.current) {
|
||||||
|
if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
setArrow2('→')
|
||||||
|
arrow2Ref.current = '→'
|
||||||
|
checkRightAngle()
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 일변전으로 돌아가기
|
||||||
|
*/
|
||||||
|
const handleRollback = () => {
|
||||||
|
//points의 마지막 요소를 제거
|
||||||
|
setPoints((prev) => prev.slice(0, prev.length - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClickClose = () => {
|
||||||
|
setModalOption({ ...modalOption, outerwall: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleFix = () => {}
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true}>
|
<WithDraggable isShow={true}>
|
||||||
<div className={`modal-pop-wrap ssm ${modalOption.outerwall ? 'mount' : ''} ${close ? 'unmount' : ''} `}>
|
<div className={`modal-pop-wrap ssm ${modalOption.outerwall ? 'mount' : ''} `}>
|
||||||
<div className="modal-head">
|
<div className="modal-head">
|
||||||
<h1 className="title">{getMessage('modal.cover.outline.drawing')}</h1>
|
<h1 className="title">{getMessage('modal.cover.outline.drawing')}</h1>
|
||||||
<button className="modal-close" onClick={HandleClickClose}>
|
<button className="modal-close" onClick={handleClickClose}>
|
||||||
닫기
|
닫기
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-body">
|
<div className="modal-body">
|
||||||
<div className="modal-btn-wrap">
|
<div className="modal-btn-wrap">
|
||||||
<button className={`btn-frame modal ${buttonAct === 1 ? 'act' : ''}`} onClick={() => setButtonAct(1)}>
|
<button
|
||||||
|
className={`btn-frame modal ${type === OUTER_LINE_TYPE.OUTER_LINE ? 'act' : ''}`}
|
||||||
|
onClick={() => setType(OUTER_LINE_TYPE.OUTER_LINE)}
|
||||||
|
>
|
||||||
{getMessage('modal.cover.outline')}
|
{getMessage('modal.cover.outline')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button className={`btn-frame modal ${buttonAct === 2 ? 'act' : ''}`} onClick={() => setButtonAct(2)}>
|
<button
|
||||||
|
className={`btn-frame modal ${type === OUTER_LINE_TYPE.RIGHT_ANGLE ? 'act' : ''}`}
|
||||||
|
onClick={() => setType(OUTER_LINE_TYPE.RIGHT_ANGLE)}
|
||||||
|
>
|
||||||
{getMessage('modal.cover.outline.right.angle')}
|
{getMessage('modal.cover.outline.right.angle')}
|
||||||
</button>
|
</button>
|
||||||
<button className={`btn-frame modal ${buttonAct === 3 ? 'act' : ''}`} onClick={() => setButtonAct(3)}>
|
<button
|
||||||
|
className={`btn-frame modal ${type === OUTER_LINE_TYPE.LEE_GUBAE ? 'act' : ''}`}
|
||||||
|
onClick={() => setType(OUTER_LINE_TYPE.LEE_GUBAE)}
|
||||||
|
>
|
||||||
{getMessage('modal.cover.outline2')}
|
{getMessage('modal.cover.outline2')}
|
||||||
</button>
|
</button>
|
||||||
<button className={`btn-frame modal ${buttonAct === 4 ? 'act' : ''}`} onClick={() => setButtonAct(4)}>
|
<button className={`btn-frame modal ${type === OUTER_LINE_TYPE.ANGLE ? 'act' : ''}`} onClick={() => setType(OUTER_LINE_TYPE.ANGLE)}>
|
||||||
{getMessage('modal.cover.outline.angle')}
|
{getMessage('modal.cover.outline.angle')}
|
||||||
</button>
|
</button>
|
||||||
<button className={`btn-frame modal ${buttonAct === 5 ? 'act' : ''}`} onClick={() => setButtonAct(5)}>
|
<button
|
||||||
|
className={`btn-frame modal ${type === OUTER_LINE_TYPE.DIAGONAL_LINE ? 'act' : ''}`}
|
||||||
|
onClick={() => setType(OUTER_LINE_TYPE.DIAGONAL_LINE)}
|
||||||
|
>
|
||||||
{getMessage('modal.cover.outline.diagonal')}
|
{getMessage('modal.cover.outline.diagonal')}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="modal-check-btn-wrap">
|
<div className="modal-check-btn-wrap">
|
||||||
<h3 className="check-wrap-title">{getMessage('modal.cover.outline.setting')}</h3>
|
<h3 className="check-wrap-title">{getMessage('modal.cover.outline.setting')}</h3>
|
||||||
|
{type === OUTER_LINE_TYPE.OUTER_LINE ? (
|
||||||
<div className="outer-line-wrap">
|
<div className="outer-line-wrap">
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
|
<label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
|
||||||
<input type="text" className="input-origin block" placeholder="320mm" />
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
value={length1}
|
||||||
|
ref={length1Ref}
|
||||||
|
onChange={(e) => {
|
||||||
|
setLength1(e.target.value.replace(/[^-0-9]/g, ''))
|
||||||
|
}}
|
||||||
|
placeholder="3000"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
|
<label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
|
||||||
<input type="text" className="input-origin block" placeholder="320mm" />
|
<input type="text" value={arrow1} className="input-origin block" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
|
||||||
|
<div className="outer-line-wrap">
|
||||||
|
<div className="form-input">
|
||||||
|
<label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
value={length1}
|
||||||
|
ref={length1Ref}
|
||||||
|
onChange={(e) => {
|
||||||
|
setLength1(e.target.value.replace(/[^-0-9]/g, ''))
|
||||||
|
}}
|
||||||
|
placeholder="3000"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-input">
|
||||||
|
<label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
|
||||||
|
<input type="text" value={arrow1} className="input-origin block" />
|
||||||
|
</div>
|
||||||
|
<div className="form-input">
|
||||||
|
<label htmlFor="">{getMessage('modal.cover.outline.length')}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
value={length2}
|
||||||
|
ref={length2Ref}
|
||||||
|
onChange={(e) => {
|
||||||
|
setLength2(e.target.value.replace(/[^-0-9]/g, ''))
|
||||||
|
}}
|
||||||
|
placeholder="3000"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="form-input">
|
||||||
|
<label htmlFor="">{getMessage('modal.cover.outline.arrow')}</label>
|
||||||
|
<input type="text" value={arrow2} className="input-origin block" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
<div className="flex-check-box for2 btn">
|
<div className="flex-check-box for2 btn">
|
||||||
<button className="arr-btn dark">
|
<button className="arr-btn dark" onClick={handleFix}>
|
||||||
<span>{getMessage('modal.cover.outline.fix')}</span>
|
<span>{getMessage('modal.cover.outline.fix')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="arr-btn dark act">
|
<button className="arr-btn dark act" onClick={handleRollback}>
|
||||||
<span>{getMessage('modal.cover.outline.rollback')}</span>
|
<span>{getMessage('modal.cover.outline.rollback')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button className="arr-btn dark">
|
<button className="arr-btn dark">
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { Button } from '@nextui-org/react'
|
|||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import StuffQGrid from './StuffQGrid'
|
import StuffQGrid from './StuffQGrid'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue, useRecoilState } from 'recoil'
|
||||||
import { stuffSearchState } from '@/store/stuffAtom'
|
import { stuffSearchState } from '@/store/stuffAtom'
|
||||||
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
@ -15,10 +15,12 @@ dayjs.extend(isLeapYear)
|
|||||||
|
|
||||||
export default function Stuff() {
|
export default function Stuff() {
|
||||||
const stuffSearchParams = useRecoilValue(stuffSearchState)
|
const stuffSearchParams = useRecoilValue(stuffSearchState)
|
||||||
|
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [curPage, setCurPage] = useState(1) //현재 페이지 번호
|
const [curPage, setCurPage] = useState(1) //현재 페이지 번호
|
||||||
const [size, setSize] = useState(100) //페이지 당 게시물 수
|
const [defaultSize, setDefaultSize] = useState(100) //페이지 당 게시물 수
|
||||||
const { get, del } = useAxios()
|
const [defaultSortType, setDefaultSortType] = useState('R')
|
||||||
|
const { get } = useAxios()
|
||||||
const gridRef = useRef()
|
const gridRef = useRef()
|
||||||
|
|
||||||
const [gridCount, setGridCount] = useState(0)
|
const [gridCount, setGridCount] = useState(0)
|
||||||
@ -38,13 +40,26 @@ export default function Stuff() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//물건번호 복사버튼 옆에 영역
|
||||||
|
const onDoubleClick = (e) => {
|
||||||
|
let objectNo = e.target.innerText
|
||||||
|
console.log(objectNo)
|
||||||
|
if (objectNo.substring(0, 1) === 'R') {
|
||||||
|
console.log('진짜')
|
||||||
|
router.push(`${pathname}/detail?objectNo=${objectNo.toString()}`)
|
||||||
|
} else {
|
||||||
|
console.log('임시')
|
||||||
|
router.push(`${pathname}/tempdetail?objectNo=${objectNo.toString()}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const [gridProps, setGridProps] = useState({
|
const [gridProps, setGridProps] = useState({
|
||||||
gridData: [],
|
gridData: [],
|
||||||
isPageable: false,
|
isPageable: false,
|
||||||
// sets 10 rows per page (default is 100)
|
// sets 10 rows per page (default is 100)
|
||||||
paginationPageSize: 100,
|
// paginationPageSize: 100,
|
||||||
// allows the user to select the page size from a predefined list of page sizes
|
// allows the user to select the page size from a predefined list of page sizes
|
||||||
paginationPageSizeSelector: [100, 200, 300, 400],
|
// paginationPageSizeSelector: [100, 200, 300, 400],
|
||||||
gridColumns: [
|
gridColumns: [
|
||||||
{
|
{
|
||||||
field: 'lastEditDatetime',
|
field: 'lastEditDatetime',
|
||||||
@ -82,7 +97,6 @@ export default function Stuff() {
|
|||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
// isDisabled={params.data.successful ? false : true}
|
|
||||||
color="default"
|
color="default"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
copyNo(params.value)
|
copyNo(params.value)
|
||||||
@ -90,7 +104,7 @@ export default function Stuff() {
|
|||||||
>
|
>
|
||||||
복사
|
복사
|
||||||
</Button>
|
</Button>
|
||||||
<span>{params.value}</span>
|
<span onDoubleClick={onDoubleClick}>{params.value}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -148,8 +162,15 @@ export default function Stuff() {
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
console.log(' 상세이동::::::::', event.data)
|
console.log(' 상세이동::::::::', event.data)
|
||||||
|
//T 면 임시 R은 진짜
|
||||||
if (event.data.objectNo) {
|
if (event.data.objectNo) {
|
||||||
|
if (event.data.objectNo.substring(0, 1) === 'R') {
|
||||||
|
console.log('진짜:::::::::')
|
||||||
router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`)
|
router.push(`${pathname}/detail?objectNo=${event.data.objectNo.toString()}`)
|
||||||
|
} else {
|
||||||
|
console.log('임시:::::::::::::::::')
|
||||||
|
router.push(`${pathname}/tempdetail?objectNo=${event.data.objectNo.toString()}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -175,45 +196,6 @@ export default function Stuff() {
|
|||||||
errCount++
|
errCount++
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
async function fetchDelete(data) {
|
|
||||||
console.log('물건삭제API호출!!!!!!!!!', data)
|
|
||||||
//행추가말고 api데이터만 보냄
|
|
||||||
// let newData = data.filter((item) => item.company != null)
|
|
||||||
// console.log('삭제에 전송되는 데이타::', newData)
|
|
||||||
// await del({ url: '', data:newData })
|
|
||||||
await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
|
|
||||||
// try {
|
|
||||||
// const res = await del({url:'', data:newData})
|
|
||||||
|
|
||||||
// if(!res || res.length === 0) {
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
fetchData()
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('Data Delete error:', error);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
// 삭제API 완료 후 fetchData Api호출
|
|
||||||
async function fetchData() {
|
|
||||||
console.log('물건삭제후 조회API호출!!!!!!!!!!!!!', stuffSearchParams)
|
|
||||||
const data = await get({ url: 'https://www.ag-grid.com/example-assets/space-mission-data.json' })
|
|
||||||
setGridProps({ ...gridProps, gridData: data, count: data.length })
|
|
||||||
setGridCount(data.length)
|
|
||||||
//data.length = 10
|
|
||||||
//setGridProps({ ...gridProps, gridData: data, count: data.length-1})
|
|
||||||
//setGridCount(data.length - 1 )
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errCount === 0) {
|
|
||||||
// console.log('errCount::::::::', errCount)
|
|
||||||
fetchDelete(data)
|
|
||||||
// fetchData()
|
|
||||||
} else {
|
|
||||||
alert('물건정보가 있는 행만 선택해주세요')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//행추가
|
//행추가
|
||||||
@ -265,15 +247,14 @@ export default function Stuff() {
|
|||||||
schDateType: 'U',
|
schDateType: 'U',
|
||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
|
||||||
startRow: (curPage - 1) * size + 1,
|
startRow: (curPage - 1) * defaultSize + 1,
|
||||||
endRow: curPage * size,
|
endRow: curPage * defaultSize,
|
||||||
|
schSelSaleStoreId: '',
|
||||||
|
schSortType: 'R',
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
console.log('화면진입:::::::::::::', params)
|
console.log('화면진입:::::::::::::', params)
|
||||||
console.log('현재페이지::::::', curPage)
|
|
||||||
console.log('페이지당 게시물수::::::', size)
|
|
||||||
|
|
||||||
//api에 넘길값 startRow, endRow
|
//api에 넘길값 startRow, endRow
|
||||||
// let startRow
|
// let startRow
|
||||||
// let endRow
|
// let endRow
|
||||||
@ -306,6 +287,9 @@ export default function Stuff() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (stuffSearchParams?.code === 'E') {
|
if (stuffSearchParams?.code === 'E') {
|
||||||
|
stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1
|
||||||
|
stuffSearchParams.endRow = curPage * defaultSize
|
||||||
|
stuffSearchParams.schSortType = defaultSortType
|
||||||
console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams)
|
console.log('조회 눌럿을때 ::::::::::::::', stuffSearchParams)
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
|
const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
|
||||||
@ -314,6 +298,9 @@ export default function Stuff() {
|
|||||||
if (!isEmptyArray(res)) {
|
if (!isEmptyArray(res)) {
|
||||||
setGridProps({ ...gridProps, gridData: res, count: res.length })
|
setGridProps({ ...gridProps, gridData: res, count: res.length })
|
||||||
setGridCount(res.length)
|
setGridCount(res.length)
|
||||||
|
} else {
|
||||||
|
setGridProps({ ...gridProps, gridData: [], count: 0 })
|
||||||
|
setGridCount(0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -321,6 +308,56 @@ export default function Stuff() {
|
|||||||
}
|
}
|
||||||
}, [stuffSearchParams])
|
}, [stuffSearchParams])
|
||||||
|
|
||||||
|
//페이지 갯수 변경 이벤트
|
||||||
|
const onChangePerPage = (e) => {
|
||||||
|
let startRow = (curPage - 1) * e.target.value + 1
|
||||||
|
stuffSearchParams.startRow = startRow
|
||||||
|
stuffSearchParams.endRow = curPage * e.target.value
|
||||||
|
setDefaultSize(e.target.value)
|
||||||
|
setStuffSearch({
|
||||||
|
...stuffSearch,
|
||||||
|
code: 'S',
|
||||||
|
startRow: startRow,
|
||||||
|
endRow: curPage * e.target.value,
|
||||||
|
})
|
||||||
|
console.log('셋팅된 검색조건:::', stuffSearchParams)
|
||||||
|
//조회API호출
|
||||||
|
const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
|
||||||
|
get({ url: apiUrl }).then((res) => {
|
||||||
|
console.log('보여줄개수바꿨을때 조회 ::::::::::', res)
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
setGridProps({ ...gridProps, gridData: res, count: res.length })
|
||||||
|
setGridCount(res.length)
|
||||||
|
} else {
|
||||||
|
setGridProps({ ...gridProps, gridData: [], count: 0 })
|
||||||
|
setGridCount(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//최근 등록일 수정일 정렬 이벤트
|
||||||
|
const onChangeSortType = (e) => {
|
||||||
|
stuffSearchParams.schSortType = e.target.value
|
||||||
|
console.log('셋팅된 검색조건:::', stuffSearchParams)
|
||||||
|
setDefaultSortType(e.target.value)
|
||||||
|
setStuffSearch({
|
||||||
|
...stuffSearch,
|
||||||
|
code: 'S',
|
||||||
|
schSortType: e.target.value,
|
||||||
|
})
|
||||||
|
const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
|
||||||
|
// console.log('apiUrl::', apiUrl)
|
||||||
|
get({ url: apiUrl }).then((res) => {
|
||||||
|
console.log('정렬바꿨을때 조회 ::::::::::', res)
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
setGridProps({ ...gridProps, gridData: res, count: res.length })
|
||||||
|
setGridCount(res.length)
|
||||||
|
} else {
|
||||||
|
setGridProps({ ...gridProps, gridData: [], count: 0 })
|
||||||
|
setGridCount(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="text-2xl">
|
<div className="text-2xl">
|
||||||
@ -328,6 +365,15 @@ export default function Stuff() {
|
|||||||
<span>
|
<span>
|
||||||
전체 : {gridCount} // 선택 : {selectedRowDataCount}
|
전체 : {gridCount} // 선택 : {selectedRowDataCount}
|
||||||
</span>
|
</span>
|
||||||
|
<select className="select" onChange={onChangePerPage}>
|
||||||
|
<option value="100">100</option>
|
||||||
|
<option value="200">200</option>
|
||||||
|
<option value="300">300</option>
|
||||||
|
</select>
|
||||||
|
<select className="select" onChange={onChangeSortType}>
|
||||||
|
<option value="R">최근 등록일</option>
|
||||||
|
<option value="U">최근 수정일</option>
|
||||||
|
</select>
|
||||||
<div align="right">
|
<div align="right">
|
||||||
{/* <Button
|
{/* <Button
|
||||||
color="primary"
|
color="primary"
|
||||||
|
|||||||
@ -4,13 +4,15 @@ import React, { useState, useEffect } from 'react'
|
|||||||
import { useRouter, useSearchParams } from 'next/navigation'
|
import { useRouter, useSearchParams } from 'next/navigation'
|
||||||
import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem, Select, SelectItem, Checkbox, Textarea, button } from '@nextui-org/react'
|
import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem, Select, SelectItem, Checkbox, Textarea, button } from '@nextui-org/react'
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { get } from '@/lib/Axios'
|
import { del, get } from '@/lib/Axios'
|
||||||
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
import { queryStringFormatter, isEmptyArray } from '@/util/common-utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useForm } from 'react-hook-form'
|
import { useForm } from 'react-hook-form'
|
||||||
export default function StuffDetail() {
|
export default function StuffDetail() {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
//form
|
//form
|
||||||
const formInitValue = {
|
const formInitValue = {
|
||||||
@ -44,66 +46,95 @@ export default function StuffDetail() {
|
|||||||
|
|
||||||
const [prefCodeList, setPrefCodeList] = useState([]) //도도부현 코트 리스트
|
const [prefCodeList, setPrefCodeList] = useState([]) //도도부현 코트 리스트
|
||||||
const [prefValue, setPrefValue] = useState('')
|
const [prefValue, setPrefValue] = useState('')
|
||||||
|
const [saleStoreList, setSaleStoreList] = useState([]) // 판매점 리스트
|
||||||
|
|
||||||
const [receiveUser, setReceiveUser] = useState('') //담당자
|
const [powerSimAreaList, setPowerSimAreaList] = useState([]) //발전시뮬레이션 리스트
|
||||||
const [name2, setName2] = useState('') //물건명
|
|
||||||
const [name3, setName3] = useState('') //물건명후리가나
|
|
||||||
const [zipCode, setZipCode] = useState('') //우편번호
|
|
||||||
const [name5, setName5] = useState('') //수직적설량
|
|
||||||
const [gubun, setGubun] = useState('NEW') //신축 기축
|
|
||||||
const [sel, setSel] = useState('') //경칭선택
|
|
||||||
const [sel2, setSel2] = useState('') //발전량시뮬레이션지역
|
|
||||||
const [sel3, setSel3] = useState('') //기준풍속
|
|
||||||
const [sel4, setSel4] = useState('') //설치높이
|
|
||||||
|
|
||||||
const [errors, setErrors] = useState({})
|
|
||||||
const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤
|
const [isFormValid, setIsFormValid] = useState(false) //임시저장, 진짜저장 버튼 컨트롤
|
||||||
const [testSelOption, setTestSelOption] = useState([]) // 테스트용
|
|
||||||
const [autoSelectValue, setAutoSelectValue] = useState('') //판매점명 자동완성
|
|
||||||
const [buttonValid, setButtonValid] = useState(false) //주소검색 활성화 컨트롤
|
const [buttonValid, setButtonValid] = useState(false) //주소검색 활성화 컨트롤
|
||||||
const [isSelected, setIsSelected] = useState(false) //한랭지대첵 체크박스
|
|
||||||
const [isSelected2, setIsSelected2] = useState(false) //염해지역용아이템사용 체크박스
|
|
||||||
const [gubun2, setGubun2] = useState('1') //면조도구분 라디오
|
|
||||||
const [gubun3, setGubun3] = useState('A') //계약조건 라디오
|
|
||||||
const [memo, setMemo] = useState('') //메모
|
|
||||||
const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set
|
const objectNo = searchParams.get('objectNo') //url에서 물건번호 꺼내서 바로 set
|
||||||
|
|
||||||
// const [address1, setAddress1] = useState('') //우편API리턴 도도부현명
|
|
||||||
// const [address2, setAddress2] = useState('') //우편API리턴 시구정촌명
|
|
||||||
// const [address3, setAddress3] = useState('') //우편API리턴 마을 지역명
|
|
||||||
// const [prefCode, setPrefCode] = useState(1) //우편API prefcode
|
|
||||||
|
|
||||||
const [editMode, setEditMode] = useState('NEW')
|
const [editMode, setEditMode] = useState('NEW')
|
||||||
const [detailData, setDetailData] = useState({})
|
const [detailData, setDetailData] = useState({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
|
||||||
if (!isEmptyArray(res)) {
|
|
||||||
console.log('도도부현API 결과:::', res)
|
|
||||||
setPrefCodeList(res)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// console.log('상세화면진입:::::::::', searchParams.get('objectNo'))
|
|
||||||
// console.log('물건번호::::', objectNo)
|
|
||||||
|
|
||||||
if (objectNo) {
|
if (objectNo) {
|
||||||
setEditMode('EDIT')
|
setEditMode('EDIT')
|
||||||
|
|
||||||
if (objectNo.substring(0, 1) === 'R') {
|
if (objectNo.substring(0, 1) === 'R') {
|
||||||
|
//진짜
|
||||||
setIsFormValid(true)
|
setIsFormValid(true)
|
||||||
}
|
}
|
||||||
get({ url: `/api/object/${objectNo}/detail` }).then((res) => {
|
get({ url: `/api/object/${objectNo}/detail` }).then((res) => {
|
||||||
|
console.log('물건번호로 상세 API 호출')
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
// console.log('res:::::::', res)
|
console.log('상세res:::::::', res)
|
||||||
setDetailData(res)
|
setDetailData(res)
|
||||||
|
|
||||||
|
// 신규 상세 공통APi
|
||||||
|
// 도도부현API
|
||||||
|
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
//console.log('도도부현API 결과:::', res)
|
||||||
|
setPrefCodeList(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 판매점목록 API /api/object/saleStore/판매점코드/list - 판매점 목록 조회
|
||||||
|
// 임시 1차점 판매점코드 saleStoreId=201TES01
|
||||||
|
// T01
|
||||||
|
//1차점 : X167
|
||||||
|
get({ url: `/api/object/saleStore/201TES01/list` }).then((res) => {
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
console.log('판매점 결과:::::', res)
|
||||||
|
setSaleStoreList(res)
|
||||||
|
//1차 판매점 자동완성 값 셋팅
|
||||||
|
form.setValue('saleStoreId', res[0].saleStoreId)
|
||||||
|
//1차 판매점 번호 셋팅
|
||||||
|
form.setValue('saleStoreName', res[0].saleStoreId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
alert('삭제된 물건입니다')
|
||||||
|
router.push('/management/stuff')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('신규일떄 공통코드세팅')
|
||||||
|
// 신규 상세 공통APi
|
||||||
|
// 도도부현API
|
||||||
|
get({ url: '/api/object/prefecture/list' }).then((res) => {
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
//console.log('도도부현API 결과:::', res)
|
||||||
|
setPrefCodeList(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 판매점목록 API /api/object/saleStore/판매점코드/list - 판매점 목록 조회
|
||||||
|
// 임시 1차점 판매점코드 saleStoreId=201TES01
|
||||||
|
// T01
|
||||||
|
//1차점 : X167
|
||||||
|
get({ url: `/api/object/saleStore/201TES01/list` }).then((res) => {
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
console.log('판매점 결과:::::', res)
|
||||||
|
setSaleStoreList(res)
|
||||||
|
//1차 판매점 자동완성 값 셋팅
|
||||||
|
form.setValue('saleStoreId', res[0].saleStoreId)
|
||||||
|
//1차 판매점 번호 셋팅
|
||||||
|
form.setValue('saleStoreName', res[0].saleStoreId)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}, [objectNo])
|
}, [objectNo])
|
||||||
|
|
||||||
useEffect(() => {
|
//1차점 변경 이벤트
|
||||||
// validateForm()
|
const onSelectionChange = (key) => {
|
||||||
}, [receiveUser, name2, name3, gubun, sel, autoSelectValue, zipCode, sel2, sel3, name5, sel4])
|
if (key == null) {
|
||||||
|
form.setValue('saleStoreId', '')
|
||||||
|
form.setValue('saleStoreName', '')
|
||||||
|
} else {
|
||||||
|
form.setValue('saleStoreId', key)
|
||||||
|
form.setValue('saleStoreName', key)
|
||||||
|
}
|
||||||
|
}
|
||||||
// 우편번호 숫자만 체크
|
// 우편번호 숫자만 체크
|
||||||
const _zipNo = watch('zipNo')
|
const _zipNo = watch('zipNo')
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -114,62 +145,87 @@ export default function StuffDetail() {
|
|||||||
}
|
}
|
||||||
}, [_zipNo])
|
}, [_zipNo])
|
||||||
|
|
||||||
// 수직적설량 숫자만
|
//임시저장 저장 버튼 컨트롤
|
||||||
const textTypeHandler2 = (e) => {
|
// dispCompanyName: '', //담당자
|
||||||
if (!e.target.value.match(/[^0-9]/g)) {
|
// objectName: '', //물건명
|
||||||
setName5(e.target.value)
|
// objectNameOmit: '', //경칭선택
|
||||||
}
|
// saleStoreId: '', //판매점ID
|
||||||
}
|
// zipNo: '', //우편번호
|
||||||
const validateForm = () => {
|
// prefId: '', //도도부현
|
||||||
|
// address: '', //주소
|
||||||
|
// powerSimArea: '', //발전량시뮬레이션지역
|
||||||
|
// windSpeed: '', //기준풍속
|
||||||
|
// snowCover: '', //수직적설량
|
||||||
|
// coldAreaChk: false, //한랭지대책시행
|
||||||
|
// surfaceType: 'Ⅲ・Ⅳ', //면조도구분(Ⅲ・Ⅳ / Ⅱ)
|
||||||
|
// saltAreaChk: false, //염해지역용아이템사용
|
||||||
|
// installHeight: '', //설치높이
|
||||||
|
// powerConTerms: '0', //계약조건(잉여 / 전량)
|
||||||
|
// remark: '', //메모
|
||||||
|
// tempFlag: 'T', //임시저장(1) 저장(0)
|
||||||
|
const _dispCompanyName = watch('dispCompanyName')
|
||||||
|
const _objectName = watch('objectName')
|
||||||
|
const _objectNameOmit = watch('objectNameOmit')
|
||||||
|
const _saleStoreId = watch('saleStoreId')
|
||||||
|
const _prefId = watch('prefId')
|
||||||
|
const _address = watch('address')
|
||||||
|
const _powerSimArea = watch('powerSimArea')
|
||||||
|
const _windSpeed = watch('windSpeed')
|
||||||
|
const _snowCover = watch('snowCover')
|
||||||
|
const _installHeight = watch('installHeight')
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('mode:::::', editMode)
|
||||||
|
if (editMode === 'NEW') {
|
||||||
|
const formData = form.getValues()
|
||||||
|
console.log('폼::::::::::::', formData)
|
||||||
let errors = {}
|
let errors = {}
|
||||||
|
if (!_dispCompanyName || _dispCompanyName.trim().length === 0) {
|
||||||
if (!receiveUser || receiveUser.trim().length === 0) {
|
errors.dispCompanyName = true
|
||||||
errors.receiveUser = '담당자 is required.'
|
}
|
||||||
|
if (!_objectName || _objectName.trim().length === 0) {
|
||||||
|
errors.objectName = true
|
||||||
|
}
|
||||||
|
if (!_objectNameOmit) {
|
||||||
|
errors.objectNameOmit = true
|
||||||
|
}
|
||||||
|
if (!_saleStoreId) {
|
||||||
|
errors.saleStoreId = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name2 || name2.trim().length === 0) {
|
if (!_zipNo || _zipNo.length != 7) {
|
||||||
errors.name2 = '물건명 is required.'
|
errors.zipCode = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!name3 || name3.trim().length === 0) {
|
if (!_prefId) {
|
||||||
errors.name3 = '물건명후리가나 is required.'
|
errors.prefId = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sel) {
|
if (!_address.trim().length === 0) {
|
||||||
errors.sel = '경칭선택 is required'
|
errors.address = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sel2) {
|
if (!_powerSimArea) {
|
||||||
errors.sel2 = '발전량시뮬레이션지역 is required'
|
errors.powerSimArea = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sel3) {
|
if (!_windSpeed) {
|
||||||
errors.sel3 = '기준풍속 is required'
|
errors.windSpeed = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sel4) {
|
if (!_snowCover) {
|
||||||
errors.sel4 = '설치높이 is required'
|
errors.snowCover = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!autoSelectValue) {
|
if (!_installHeight) {
|
||||||
errors.autoSelectValue = '판매점ID자동완성 is required'
|
errors.installHeight = true
|
||||||
}
|
|
||||||
|
|
||||||
if (!zipCode || zipCode.length != 7) {
|
|
||||||
errors.zipCode = '우편번호 is required.'
|
|
||||||
setButtonValid(true)
|
|
||||||
} else {
|
|
||||||
setButtonValid(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!name5) {
|
|
||||||
errors.name5 = '수직적설량 is required.'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('errors::', errors)
|
console.log('errors::', errors)
|
||||||
setErrors(errors)
|
|
||||||
setIsFormValid(Object.keys(errors).length === 0)
|
setIsFormValid(Object.keys(errors).length === 0)
|
||||||
|
} else {
|
||||||
|
console.log('상세일때 폼체크')
|
||||||
}
|
}
|
||||||
|
}, [_dispCompanyName, _objectName, _objectNameOmit, _saleStoreId, _zipNo, _prefId, _address, _powerSimArea, _windSpeed, _snowCover, _installHeight])
|
||||||
|
|
||||||
// 주소검색 API
|
// 주소검색 API
|
||||||
const onSearchPostNumber = () => {
|
const onSearchPostNumber = () => {
|
||||||
@ -178,10 +234,10 @@ export default function StuffDetail() {
|
|||||||
}
|
}
|
||||||
get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => {
|
get({ url: `https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter(params)}` }).then((res) => {
|
||||||
//7830060
|
//7830060
|
||||||
|
//9302226
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
console.log('res.results::', res.results)
|
|
||||||
if (res.results != null) {
|
if (res.results != null) {
|
||||||
console.log('res.results::', res.results)
|
console.log('주소검색::', res.results)
|
||||||
// prefId: '', //도도부현
|
// prefId: '', //도도부현
|
||||||
// address: '', //주소
|
// address: '', //주소
|
||||||
console.log('prefcode::', res.results[0].prefcode)
|
console.log('prefcode::', res.results[0].prefcode)
|
||||||
@ -193,7 +249,10 @@ export default function StuffDetail() {
|
|||||||
alert('등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.')
|
alert('등록된 우편번호에서 주소를 찾을 수 없습니다. 다시 입력해주세요.')
|
||||||
form.setValue('prefId', '')
|
form.setValue('prefId', '')
|
||||||
form.setValue('address', '')
|
form.setValue('address', '')
|
||||||
|
form.setValue('zipNo', '')
|
||||||
setPrefValue('')
|
setPrefValue('')
|
||||||
|
setPowerSimAreaList([])
|
||||||
|
form.setValue('powerSimArea', '')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
alert(res.message)
|
alert(res.message)
|
||||||
@ -201,47 +260,69 @@ export default function StuffDetail() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const onTempSave = () => {
|
useEffect(() => {
|
||||||
console.log('임시저장::', isFormValid)
|
if (prefValue !== '') {
|
||||||
|
console.log('우편번호 검색해서 도도부현골랐을때::::', prefValue)
|
||||||
|
// 발전량시뮬레이션 지역 목록
|
||||||
|
// /api/object/prefecture/도도부현코드/list
|
||||||
|
get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => {
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
console.log('발전시뮬레이션::::::::', res)
|
||||||
|
setPowerSimAreaList(res)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
const onSave = () => {
|
|
||||||
console.log('진짜저장isFormValid:::', isFormValid)
|
|
||||||
}
|
|
||||||
|
|
||||||
const moveList = () => {
|
|
||||||
router.push('/management/stuff')
|
|
||||||
}
|
|
||||||
|
|
||||||
const changeAddress2 = (e) => {
|
|
||||||
console.log('e:::::::', e.target.value)
|
|
||||||
}
|
}
|
||||||
|
}, [prefValue])
|
||||||
|
|
||||||
//필수값 다 입력했을때
|
//필수값 다 입력했을때
|
||||||
const onValid = (data) => {
|
const onValid = (data) => {
|
||||||
|
console.log('필수값 다 있고 저장')
|
||||||
console.log('data::::::', data)
|
console.log('data::::::', data)
|
||||||
const formData = form.getValues()
|
const formData = form.getValues()
|
||||||
//console.log('formData::::', formData)
|
console.log('formData::::', formData)
|
||||||
const _dispCompanyName = watch('dispCompanyName')
|
// const _dispCompanyName = watch('dispCompanyName')
|
||||||
const _objectStatusId = watch('objectStatusId')
|
// const _objectStatusId = watch('objectStatusId')
|
||||||
const _objectNameOmit = watch('objectNameOmit')
|
// const _objectNameOmit = watch('objectNameOmit')
|
||||||
const _zipNo = watch('zipNo')
|
// const _zipNo = watch('zipNo')
|
||||||
const _prefId = watch('prefId')
|
// const _prefId = watch('prefId')
|
||||||
const _address = watch('address')
|
// const _address = watch('address')
|
||||||
const _coldAreaChk = watch('coldAreaChk')
|
// const _coldAreaChk = watch('coldAreaChk')
|
||||||
console.log(_dispCompanyName)
|
// console.log(_dispCompanyName)
|
||||||
console.log(_objectStatusId)
|
// console.log(_objectStatusId)
|
||||||
console.log(_objectNameOmit)
|
// console.log(_objectNameOmit)
|
||||||
console.log(_zipNo)
|
// console.log(_zipNo)
|
||||||
console.log(_prefId)
|
// console.log(_prefId)
|
||||||
console.log('prefValue::', prefValue)
|
// console.log('prefValue::', prefValue)
|
||||||
console.log(_address)
|
// console.log(_address)
|
||||||
console.log('_coldAreaChk::', _coldAreaChk)
|
// console.log('_coldAreaChk::', _coldAreaChk)
|
||||||
}
|
}
|
||||||
|
|
||||||
//필수값 안넣었을때
|
//필수값 안넣었을때 임시저장
|
||||||
const onInvalid = (errors) => {
|
const onInvalid = (errors) => {
|
||||||
console.log('실패', errors)
|
const formData = form.getValues()
|
||||||
|
console.log('임시저장formData::::', formData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 발전량 시뮬레이션 변경
|
||||||
|
const handlePowerSimAreaOnChange = (e) => {
|
||||||
|
console.log('가지고있는 도도부현코드:::::::::', prefValue)
|
||||||
|
// console.log('발전량시뮬레이션변경:::::::::', e.target.value)
|
||||||
|
//값 set해주고 그거 useEffect로 api호출
|
||||||
|
}
|
||||||
|
|
||||||
|
// 물건삭제
|
||||||
|
const onDelete = () => {
|
||||||
|
//http://localhost:8080/api/object/R201TES01240910023
|
||||||
|
console.log('물건번호::::::::', objectNo)
|
||||||
|
alert('사양확정일이 있으면 삭제 불가')
|
||||||
|
if (confirm(getMessage('common.message.data.delete'))) {
|
||||||
|
let testobj = '10'
|
||||||
|
|
||||||
|
del({ url: `/api/object/${testobj}` }).then((res) => {
|
||||||
|
console.log('삭제 결과:::', res)
|
||||||
|
router.push('/management/stuff')
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -276,6 +357,22 @@ export default function StuffDetail() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>1차 판매점명 / ID</label>
|
<label>1차 판매점명 / ID</label>
|
||||||
|
<div className="flex w-full max-w-xs flex-col gap2">
|
||||||
|
{saleStoreList?.length > 0 && (
|
||||||
|
<Autocomplete
|
||||||
|
className="max-w-xs"
|
||||||
|
defaultItems={saleStoreList}
|
||||||
|
label="판매점ID자동완성"
|
||||||
|
// selectedKey={saleStoreValue}
|
||||||
|
selectedKey={form.watch('saleStoreId')}
|
||||||
|
{...form.register('saleStoreId', { required: true })}
|
||||||
|
onSelectionChange={onSelectionChange}
|
||||||
|
>
|
||||||
|
{(option) => <AutocompleteItem key={option.saleStoreId}>{option.saleStoreName}</AutocompleteItem>}
|
||||||
|
</Autocomplete>
|
||||||
|
)}
|
||||||
|
<input type="text" className="input-origin" value={form.watch('saleStoreName')} {...form.register('saleStoreName')} disabled />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>2차 판매점명 / ID</label>
|
<label>2차 판매점명 / ID</label>
|
||||||
@ -313,9 +410,34 @@ export default function StuffDetail() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>발전량시뮬레이션지역</label>
|
<label>발전량시뮬레이션지역</label>
|
||||||
|
{powerSimAreaList?.length > 0 && (
|
||||||
|
<Select
|
||||||
|
className="max-w-xs"
|
||||||
|
selectedKeys={form.watch('powerSimArea')}
|
||||||
|
{...form.register('powerSimArea', { required: true })}
|
||||||
|
onChange={handlePowerSimAreaOnChange}
|
||||||
|
>
|
||||||
|
{powerSimAreaList.map((row) => {
|
||||||
|
// console.log('row::', row)
|
||||||
|
return (
|
||||||
|
<SelectItem key={row.prefName} value={row.prefId}>
|
||||||
|
{row.prefName}
|
||||||
|
</SelectItem>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>기준풍속</label>
|
<label>기준풍속</label>
|
||||||
|
<div className="flex w-full max-w-xs flex-col gap-2">
|
||||||
|
<select name="windSpeed" {...register('windSpeed', { required: true })}>
|
||||||
|
<option value="">기준풍속</option>
|
||||||
|
<option value="30">30</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
<option value="60">60</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>수직적설량</label>
|
<label>수직적설량</label>
|
||||||
@ -354,7 +476,15 @@ export default function StuffDetail() {
|
|||||||
</Checkbox>
|
</Checkbox>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>설치높이 installHeight</label>
|
<label>설치높이</label>
|
||||||
|
<div className="flex w-full max-w-xs flex-col gap-2">
|
||||||
|
<select name="installHeight" {...register('installHeight', { required: true })}>
|
||||||
|
<option value="">설치높이</option>
|
||||||
|
<option value="11">111</option>
|
||||||
|
<option value="22">222</option>
|
||||||
|
<option value="33">333</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="form-input">
|
<div className="form-input">
|
||||||
<label>계약조건</label>
|
<label>계약조건</label>
|
||||||
@ -379,9 +509,51 @@ export default function StuffDetail() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit">신규화면임시저장!!!!!!!!!</button>
|
{!isFormValid ? (
|
||||||
|
<>
|
||||||
|
<Button type="submit">NEW화면임시저장</Button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<button type="submit">NEW화면 저장</button>
|
||||||
|
)}
|
||||||
|
<Link href="/management/stuff">
|
||||||
|
<button type="button">NEW화면 물건목록이동</button>
|
||||||
|
</Link>
|
||||||
</form>
|
</form>
|
||||||
)) || <div>상세:::::::::::</div>}
|
)) || (
|
||||||
|
<>
|
||||||
|
{objectNo.substring(0, 1) === 'R' ? (
|
||||||
|
<>
|
||||||
|
<Link href="/management/stuff">
|
||||||
|
<button type="button">R상세:물건목록</button>
|
||||||
|
</Link>
|
||||||
|
<button type="submit">R상세:저장</button>
|
||||||
|
<button type="submit" onClick={onDelete}>
|
||||||
|
R상세:물건삭제
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Link href="/management/stuff">
|
||||||
|
<button type="button">T상세:물건목록</button>
|
||||||
|
</Link>
|
||||||
|
<button type="submit">T상세:저장</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
// <div>
|
||||||
|
// EDIT모드
|
||||||
|
|
||||||
|
// {/* {objectNo.substring(0,1) ? 'R' ? <><Link>RRRRRRR</Link></> : <><Link>TTTTTTTT</Link></>} */}
|
||||||
|
// {/* <Link href="/management/stuff">
|
||||||
|
// <button type="button">상세:물건목록</button>
|
||||||
|
// </Link>
|
||||||
|
// <button type="submit">상세:저장</button>
|
||||||
|
// <button type="submit" onClick={onDelete}>
|
||||||
|
// 상세:물건삭제
|
||||||
|
// </button> */}
|
||||||
|
// </div>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* <div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
{/* <div className="flex w-full flex-wrap md:flex-nowrap gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Input, RadioGroup, Radio, Button } from '@nextui-org/react'
|
import { Input, RadioGroup, Radio, Button, Autocomplete, AutocompleteItem } from '@nextui-org/react'
|
||||||
import RangeDatePicker from '@/components/common/datepicker/RangeDatePicker'
|
import RangeDatePicker from '@/components/common/datepicker/RangeDatePicker'
|
||||||
import { useRecoilState, useResetRecoilState } from 'recoil'
|
import { useRecoilState, useResetRecoilState } from 'recoil'
|
||||||
import { stuffSearchState } from '@/store/stuffAtom'
|
import { stuffSearchState } from '@/store/stuffAtom'
|
||||||
|
import { isEmptyArray } from '@/util/common-utils'
|
||||||
|
import { get } from '@/lib/Axios'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인
|
import isLeapYear from 'dayjs/plugin/isLeapYear' // 윤년 판단 플러그인
|
||||||
dayjs.extend(isLeapYear)
|
dayjs.extend(isLeapYear)
|
||||||
@ -33,13 +35,16 @@ export default function StuffSearchCondition() {
|
|||||||
const [receiveUser, setReceiveUser] = useState('') //담당자
|
const [receiveUser, setReceiveUser] = useState('') //담당자
|
||||||
const [dispCompanyName, setDispCompanyName] = useState('') //견적처
|
const [dispCompanyName, setDispCompanyName] = useState('') //견적처
|
||||||
const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R)
|
const [dateType, setDateType] = useState('U') //갱신일(U)/등록일(R)
|
||||||
|
const [schSelSaleStoreId, setSchSelSaleStoreId] = useState('') //판매대리점 선택
|
||||||
|
|
||||||
|
const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) //판매대리점 자동완성 SELECT
|
||||||
// 조회
|
// 조회
|
||||||
const onSubmit = () => {
|
const onSubmit = () => {
|
||||||
let diff = dayjs(endRangeDate).diff(startRangeDate, 'day')
|
let diff = dayjs(endRangeDate).diff(startRangeDate, 'day')
|
||||||
if (diff > 366) {
|
if (diff > 366) {
|
||||||
return alert('최대1년 조회 가능합니다.')
|
return alert('최대1년 조회 가능합니다.')
|
||||||
}
|
}
|
||||||
|
|
||||||
setStuffSearch({
|
setStuffSearch({
|
||||||
schObjectNo: stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo,
|
schObjectNo: stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo,
|
||||||
schSaleStoreId: stuffSearch?.schSaleStoreId ? stuffSearch.schSaleStoreId : saleStoreId,
|
schSaleStoreId: stuffSearch?.schSaleStoreId ? stuffSearch.schSaleStoreId : saleStoreId,
|
||||||
@ -53,6 +58,10 @@ export default function StuffSearchCondition() {
|
|||||||
schFromDt: dayjs(startRangeDate).format('YYYY-MM-DD'),
|
schFromDt: dayjs(startRangeDate).format('YYYY-MM-DD'),
|
||||||
schToDt: dayjs(endRangeDate).format('YYYY-MM-DD'),
|
schToDt: dayjs(endRangeDate).format('YYYY-MM-DD'),
|
||||||
code: 'E',
|
code: 'E',
|
||||||
|
schSelSaleStoreId: stuffSearch?.schSelSaleStoreId ? stuffSearch.schSelSaleStoreId : schSelSaleStoreId,
|
||||||
|
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
|
||||||
|
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
|
||||||
|
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,9 +77,31 @@ export default function StuffSearchCondition() {
|
|||||||
setDispCompanyName('')
|
setDispCompanyName('')
|
||||||
setDateType('U')
|
setDateType('U')
|
||||||
setDateRange([dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), dayjs(new Date()).format('YYYY-MM-DD')])
|
setDateRange([dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), dayjs(new Date()).format('YYYY-MM-DD')])
|
||||||
|
setSchSelSaleStoreId('')
|
||||||
resetStuffRecoil()
|
resetStuffRecoil()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
get({ url: `/api/object/saleStore/201TES01/list` }).then((res) => {
|
||||||
|
if (!isEmptyArray(res)) {
|
||||||
|
// console.log('판매점 결과:::::', res)
|
||||||
|
setSchSelSaleStoreList(res)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
//판매대리점 자동완성 변경
|
||||||
|
const onSelectionChange = (key) => {
|
||||||
|
// console.log('자동완성값변경', key)
|
||||||
|
if (key == null) {
|
||||||
|
setSchSelSaleStoreId('')
|
||||||
|
setStuffSearch({ ...stuffSearch, schSelSaleStoreId: '' })
|
||||||
|
} else {
|
||||||
|
setSchSelSaleStoreId(key)
|
||||||
|
setStuffSearch({ ...stuffSearch, schSelSaleStoreId: key })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//x로 날짜 비웠을때 기본값으로 셋팅
|
//x로 날짜 비웠을때 기본값으로 셋팅
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!startRangeDate && !endRangeDate) {
|
if (!startRangeDate && !endRangeDate) {
|
||||||
@ -88,7 +119,7 @@ export default function StuffSearchCondition() {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div align="right">
|
<div align="right">
|
||||||
<Link href="/management/stuff/detail">
|
<Link href="/management/stuff/tempdetail">
|
||||||
<button type="button">물건신규등록</button>
|
<button type="button">물건신규등록</button>
|
||||||
</Link>
|
</Link>
|
||||||
<Button size="sm" onClick={onSubmit}>
|
<Button size="sm" onClick={onSubmit}>
|
||||||
@ -126,10 +157,10 @@ export default function StuffSearchCondition() {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="물건주소 입력"
|
placeholder="물건주소 입력"
|
||||||
value={stuffSearch?.address ? stuffSearch.address : address}
|
value={stuffSearch?.schAddress ? stuffSearch.schAddress : address}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setAddress(e.target.value)
|
setAddress(e.target.value)
|
||||||
setStuffSearch({ ...stuffSearch, code: 'S', address: e.target.value })
|
setStuffSearch({ ...stuffSearch, code: 'S', schAddress: e.target.value })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -220,6 +251,17 @@ export default function StuffSearchCondition() {
|
|||||||
setStuffSearch({ ...stuffSearch, code: 'S', schDispCompanyName: e.target.value })
|
setStuffSearch({ ...stuffSearch, code: 'S', schDispCompanyName: e.target.value })
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
{schSelSaleStoreList?.length > 0 && (
|
||||||
|
<Autocomplete
|
||||||
|
className="max-w-xs"
|
||||||
|
label="판매대리점선택"
|
||||||
|
defaultItems={schSelSaleStoreList}
|
||||||
|
selectedKey={stuffSearch?.schSelSaleStoreId ? stuffSearch.schSelSaleStoreId : schSelSaleStoreId}
|
||||||
|
onSelectionChange={onSelectionChange}
|
||||||
|
>
|
||||||
|
{(option) => <AutocompleteItem key={option.saleStoreId}>{option.saleStoreName}</AutocompleteItem>}
|
||||||
|
</Autocomplete>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilValue } from 'recoil'
|
||||||
import { canvasState, stepState } from '@/store/canvasAtom'
|
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
||||||
|
import { fabric } from 'fabric'
|
||||||
|
|
||||||
export function useEvent() {
|
export function useEvent() {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const step = useRecoilValue(stepState)
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
const keyboardEventListeners = useRef([])
|
const keyboardEventListeners = useRef([])
|
||||||
|
const mouseEventListeners = useRef([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canvas) {
|
if (!canvas) {
|
||||||
@ -16,47 +18,56 @@ export function useEvent() {
|
|||||||
canvas.off(key)
|
canvas.off(key)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
removeAllKeyboardEventListeners()
|
removeAllMouseEventListeners()
|
||||||
addEvent(step)
|
removeAllDocumentEventListeners()
|
||||||
}, [step])
|
addDefaultEvent()
|
||||||
|
}, [currentMenu, canvas])
|
||||||
|
|
||||||
const addEvent = (step) => {
|
const addDefaultEvent = () => {
|
||||||
//default Event 추가
|
//default Event 추가
|
||||||
canvas?.on('mouse:move', defaultMouseMoveEvent)
|
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
|
||||||
addKeyboardEventListener('keydown', document, defaultKeyboardEvent)
|
addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent)
|
||||||
|
addDocumentEventListener('keydown', document, defaultKeyboardEvent)
|
||||||
|
}
|
||||||
|
|
||||||
if (step === 1) {
|
const defaultMouseOutEvent = (e) => {
|
||||||
canvas?.on('mouse:down', (e) => {
|
removeMouseLine()
|
||||||
canvas?.add(new fabric.Rect({ width: 100, height: 100, fill: 'red', left: e.pointer.x, top: e.pointer.y }))
|
|
||||||
})
|
|
||||||
addKeyboardEventListener('keydown', document, (e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
console.log(1111)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else if (step === 2) {
|
|
||||||
canvas?.on('mouse:down', (e) => {
|
|
||||||
canvas?.add(new fabric.Circle({ radius: 50, fill: 'blue', left: e.pointer.x, top: e.pointer.y }))
|
|
||||||
})
|
|
||||||
addKeyboardEventListener('keydown', document, (e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
console.log(2222)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
canvas?.on('mouse:down', (e) => {
|
|
||||||
canvas?.add(new fabric.Triangle({ width: 100, height: 100, fill: 'green', left: e.pointer.x, top: e.pointer.y }))
|
|
||||||
})
|
|
||||||
addKeyboardEventListener('keydown', document, (e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
console.log(333)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultMouseMoveEvent = (e) => {
|
const defaultMouseMoveEvent = (e) => {
|
||||||
console.log('defaultMouseMoveEvent')
|
removeMouseLine()
|
||||||
|
// 가로선
|
||||||
|
const pointer = canvas.getPointer(e.e)
|
||||||
|
const horizontalLine = new fabric.Line([0, pointer.y, 2 * canvas.width, pointer.y], {
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'mouseLine',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 세로선
|
||||||
|
const verticalLine = new fabric.Line([pointer.x, 0, pointer.x, 2 * canvas.height], {
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'mouseLine',
|
||||||
|
})
|
||||||
|
|
||||||
|
// 선들을 캔버스에 추가합니다.
|
||||||
|
canvas?.add(horizontalLine, verticalLine)
|
||||||
|
|
||||||
|
// 캔버스를 다시 그립니다.
|
||||||
|
canvas?.renderAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeMouseLine = () => {
|
||||||
|
// 캔버스에서 마우스 선을 찾아 제거합니다.
|
||||||
|
canvas
|
||||||
|
?.getObjects()
|
||||||
|
.filter((obj) => obj.name === 'mouseLine')
|
||||||
|
.forEach((line) => {
|
||||||
|
canvas?.remove(line)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultKeyboardEvent = (e) => {
|
const defaultKeyboardEvent = (e) => {
|
||||||
@ -65,21 +76,42 @@ export function useEvent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addCanvasMouseEventListener = (eventType, handler) => {
|
||||||
|
canvas.on(eventType, handler)
|
||||||
|
mouseEventListeners.current.push({ eventType, handler })
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeAllMouseEventListeners = () => {
|
||||||
|
mouseEventListeners.current.forEach(({ eventType, handler }) => {
|
||||||
|
canvas.off(eventType, handler)
|
||||||
|
})
|
||||||
|
mouseEventListeners.current.length = 0 // 배열 초기화
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* document 키보드 이벤트 임의로 직접 등록한 이벤트의 경우 remove가 안되기 때문에 이 함수를 통해서만 등록해야 함.
|
* document 이벤트의 경우 이 함수를 통해서만 등록
|
||||||
* @param eventType
|
* @param eventType
|
||||||
* @param element
|
* @param element
|
||||||
* @param handler
|
* @param handler
|
||||||
*/
|
*/
|
||||||
function addKeyboardEventListener(eventType, element, handler) {
|
const addDocumentEventListener = (eventType, element, handler) => {
|
||||||
element.addEventListener(eventType, handler)
|
element.addEventListener(eventType, handler)
|
||||||
keyboardEventListeners.current.push({ eventType, element, handler })
|
keyboardEventListeners.current.push({ eventType, element, handler })
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeAllKeyboardEventListeners() {
|
/**
|
||||||
|
* document에 등록되는 event 제거
|
||||||
|
*/
|
||||||
|
const removeAllDocumentEventListeners = () => {
|
||||||
keyboardEventListeners.current.forEach(({ eventType, element, handler }) => {
|
keyboardEventListeners.current.forEach(({ eventType, element, handler }) => {
|
||||||
element.removeEventListener(eventType, handler)
|
element.removeEventListener(eventType, handler)
|
||||||
})
|
})
|
||||||
keyboardEventListeners.current.length = 0 // 배열 초기화
|
keyboardEventListeners.current.length = 0 // 배열 초기화
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
addDocumentEventListener,
|
||||||
|
addCanvasMouseEventListener,
|
||||||
|
removeAllDocumentEventListeners,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
43
src/hooks/useLine.js
Normal file
43
src/hooks/useLine.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
import { canvasState, fontSizeState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
|
export const useLine = () => {
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
const fontSize = useRecoilValue(fontSizeState)
|
||||||
|
|
||||||
|
const addLineText = (line) => {
|
||||||
|
removeLineText(line)
|
||||||
|
|
||||||
|
const text = new fabric.Text(getLengthByLine(line).toFixed(0), {
|
||||||
|
left: (line.x2 + line.x1) / 2,
|
||||||
|
top: (line.y2 + line.y1) / 2,
|
||||||
|
parent: line,
|
||||||
|
name: 'lengthTxt',
|
||||||
|
fontSize: fontSize,
|
||||||
|
})
|
||||||
|
|
||||||
|
canvas?.add(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeLineText = (line) => {
|
||||||
|
canvas?.remove(canvas?.getObjects().find((obj) => obj.parent === line))
|
||||||
|
}
|
||||||
|
|
||||||
|
const getLengthByLine = (line) => {
|
||||||
|
const scaleX = line.scaleX
|
||||||
|
const scaleY = line.scaleY
|
||||||
|
const x1 = line.left
|
||||||
|
const y1 = line.top
|
||||||
|
const x2 = line.left + line.width * scaleX
|
||||||
|
const y2 = line.top + line.height * scaleY
|
||||||
|
const dx = x2 - x1
|
||||||
|
const dy = y2 - y1
|
||||||
|
|
||||||
|
return Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) * 10
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
addLineText,
|
||||||
|
removeLineText,
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/hooks/usePolygon.js
Normal file
8
src/hooks/usePolygon.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
|
import { useRecoilValue } from 'recoil'
|
||||||
|
|
||||||
|
export const usePolygon = () => {
|
||||||
|
const canvas = useRecoilValue(canvasState)
|
||||||
|
|
||||||
|
return {}
|
||||||
|
}
|
||||||
@ -118,7 +118,7 @@
|
|||||||
"common.message.multi.insert": "Total {0} cases ({1} successes, {2} failures {3})",
|
"common.message.multi.insert": "Total {0} cases ({1} successes, {2} failures {3})",
|
||||||
"common.message.error": "Error occurred, please contact site administrator.",
|
"common.message.error": "Error occurred, please contact site administrator.",
|
||||||
"common.message.data.save": "Do you want to save it?",
|
"common.message.data.save": "Do you want to save it?",
|
||||||
"common.message.data.delete": "Do you want to delete it?",
|
"common.message.data.delete": "정말로 삭제하시겠습니까?",
|
||||||
"common.message.data.exists": "{0} is data that already exists.",
|
"common.message.data.exists": "{0} is data that already exists.",
|
||||||
"common.message.data.no.exists": "{0} is data that does not exist.",
|
"common.message.data.no.exists": "{0} is data that does not exist.",
|
||||||
"common.message.all": "All",
|
"common.message.all": "All",
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { atom } from 'recoil'
|
import { atom } from 'recoil'
|
||||||
|
import { MENU } from '@/common/common'
|
||||||
|
|
||||||
export const canvasState = atom({
|
export const canvasState = atom({
|
||||||
key: 'canvasState',
|
key: 'canvasState',
|
||||||
@ -180,7 +181,7 @@ export const objectPlacementModeState = atom({
|
|||||||
default: { width: 0, height: 0, areaBoundary: false, inputType: 'free', batchType: 'opening' },
|
default: { width: 0, height: 0, areaBoundary: false, inputType: 'free', batchType: 'opening' },
|
||||||
})
|
})
|
||||||
|
|
||||||
export const stepState = atom({
|
export const currentMenuState = atom({
|
||||||
key: 'step',
|
key: 'currentMenu',
|
||||||
default: 0,
|
default: MENU.INITIAL_CANVAS_SETTING,
|
||||||
})
|
})
|
||||||
|
|||||||
65
src/store/outerLineAtom.js
Normal file
65
src/store/outerLineAtom.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import { atom, selector } from 'recoil'
|
||||||
|
|
||||||
|
export const OUTER_LINE_TYPE = {
|
||||||
|
OUTER_LINE: 'outerLine', // 외벽선
|
||||||
|
RIGHT_ANGLE: 'rightAngle', // 직각
|
||||||
|
LEE_GUBAE: 'leeGubae', // 이구배
|
||||||
|
ANGLE: 'angle', // 각도
|
||||||
|
DIAGONAL_LINE: 'diagonalLine', // 대각선
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 외벽선 작성에서 사용하는 recoilState
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const outerLineLength1State = atom({
|
||||||
|
//길이1
|
||||||
|
key: 'outerLineLength1State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineLength2State = atom({
|
||||||
|
// 길이2
|
||||||
|
key: 'outerLineLength2State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineArrow1State = atom({
|
||||||
|
// 방향1
|
||||||
|
key: 'outerLineArrow1State',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineArrow2State = atom({
|
||||||
|
// 방향2
|
||||||
|
key: 'outerLineArrow2State',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineAngle1State = atom({
|
||||||
|
// 각도1
|
||||||
|
key: 'outerLineAngle1State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineAngle2State = atom({
|
||||||
|
// 각도2
|
||||||
|
key: 'outerLineAngle2State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineDiagonalState = atom({
|
||||||
|
// 대각선
|
||||||
|
key: 'outerLineDiagonalState',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLineTypeState = atom({
|
||||||
|
key: 'outerLineTypeState',
|
||||||
|
default: OUTER_LINE_TYPE.OUTER_LINE,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const outerLinePointsState = atom({
|
||||||
|
key: 'outerLinePointsState',
|
||||||
|
default: [],
|
||||||
|
})
|
||||||
@ -17,6 +17,10 @@ export const stuffSearchState = atom({
|
|||||||
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), //시작일
|
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), //시작일
|
||||||
schToDt: dayjs(new Date()).format('YYYY-MM-DD'), //종료일
|
schToDt: dayjs(new Date()).format('YYYY-MM-DD'), //종료일
|
||||||
code: 'S',
|
code: 'S',
|
||||||
|
schSelSaleStoreId: '', //판매대리점 선택
|
||||||
|
startRow: 1,
|
||||||
|
endRow: 100,
|
||||||
|
schSortType: 'R', //정렬조건 (R:최근등록일 U:최근수정일)
|
||||||
},
|
},
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -992,7 +992,7 @@ export const splitPolygonWithLines = (polygon) => {
|
|||||||
/**
|
/**
|
||||||
* 좌표 테스트용
|
* 좌표 테스트용
|
||||||
*/
|
*/
|
||||||
allLines.forEach((line) => {
|
/*allLines.forEach((line) => {
|
||||||
const text = new fabric.Text(`(${line.startPoint.x},${line.startPoint.y})`, {
|
const text = new fabric.Text(`(${line.startPoint.x},${line.startPoint.y})`, {
|
||||||
left: line.startPoint.x,
|
left: line.startPoint.x,
|
||||||
top: line.startPoint.y,
|
top: line.startPoint.y,
|
||||||
@ -1021,7 +1021,7 @@ export const splitPolygonWithLines = (polygon) => {
|
|||||||
|
|
||||||
polygon.canvas.add(text)
|
polygon.canvas.add(text)
|
||||||
polygon.canvas.renderAll()
|
polygon.canvas.renderAll()
|
||||||
})
|
})*/
|
||||||
/**
|
/**
|
||||||
* 좌표 테스트용 끝
|
* 좌표 테스트용 끝
|
||||||
*/
|
*/
|
||||||
@ -2732,6 +2732,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
if (ridge.direction === 'top') {
|
if (ridge.direction === 'top') {
|
||||||
if (ridge.y1 > y1 && ridge.y2 > y1) {
|
if (ridge.y1 > y1 && ridge.y2 > y1) {
|
||||||
offset = Math.abs(ridge.y1 - y1) - offset
|
offset = Math.abs(ridge.y1 - y1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1,
|
x1: ridge.x1,
|
||||||
y1: ridge.y1,
|
y1: ridge.y1,
|
||||||
@ -2763,6 +2764,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
}
|
}
|
||||||
if (ridge.y1 < y1 && ridge.y2 < y1) {
|
if (ridge.y1 < y1 && ridge.y2 < y1) {
|
||||||
offset = Math.abs(ridge.y2 - y1) - offset
|
offset = Math.abs(ridge.y2 - y1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1,
|
x1: ridge.x1,
|
||||||
y1: ridge.y1 - offset,
|
y1: ridge.y1 - offset,
|
||||||
@ -2795,6 +2797,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
if (ridge.direction === 'bottom') {
|
if (ridge.direction === 'bottom') {
|
||||||
if (ridge.y1 > y1 && ridge.y2 > y1) {
|
if (ridge.y1 > y1 && ridge.y2 > y1) {
|
||||||
offset = Math.abs(ridge.y1 - y1) - offset
|
offset = Math.abs(ridge.y1 - y1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1,
|
x1: ridge.x1,
|
||||||
y1: ridge.y1 - offset,
|
y1: ridge.y1 - offset,
|
||||||
@ -2825,6 +2828,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
}
|
}
|
||||||
if (ridge.y1 < y1 && ridge.y2 < y1) {
|
if (ridge.y1 < y1 && ridge.y2 < y1) {
|
||||||
offset = Math.abs(ridge.y2 - y1) - offset
|
offset = Math.abs(ridge.y2 - y1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1,
|
x1: ridge.x1,
|
||||||
y1: ridge.y1,
|
y1: ridge.y1,
|
||||||
@ -2858,6 +2862,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
if (ridge.direction === 'right') {
|
if (ridge.direction === 'right') {
|
||||||
if (ridge.x1 > x1 && ridge.x2 > x1) {
|
if (ridge.x1 > x1 && ridge.x2 > x1) {
|
||||||
offset = Math.abs(ridge.x1 - x1) - offset
|
offset = Math.abs(ridge.x1 - x1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1 - offset,
|
x1: ridge.x1 - offset,
|
||||||
y1: ridge.y1,
|
y1: ridge.y1,
|
||||||
@ -2888,6 +2893,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
}
|
}
|
||||||
if (ridge.x1 < x1 && ridge.x2 < x1) {
|
if (ridge.x1 < x1 && ridge.x2 < x1) {
|
||||||
offset = Math.abs(ridge.x2 - x1) - offset
|
offset = Math.abs(ridge.x2 - x1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1,
|
x1: ridge.x1,
|
||||||
y1: ridge.y1,
|
y1: ridge.y1,
|
||||||
@ -2920,6 +2926,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
if (ridge.direction === 'left') {
|
if (ridge.direction === 'left') {
|
||||||
if (ridge.x1 > x1 && ridge.x2 > x1) {
|
if (ridge.x1 > x1 && ridge.x2 > x1) {
|
||||||
offset = Math.abs(ridge.x1 - x1) - offset
|
offset = Math.abs(ridge.x1 - x1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1,
|
x1: ridge.x1,
|
||||||
y1: ridge.y1,
|
y1: ridge.y1,
|
||||||
@ -2950,6 +2957,7 @@ const setGableRoof = (polygon, ridge, hip1, hip2, offset, canvas) => {
|
|||||||
}
|
}
|
||||||
if (ridge.x1 < x1 && ridge.x2 < x1) {
|
if (ridge.x1 < x1 && ridge.x2 < x1) {
|
||||||
offset = Math.abs(ridge.x2 - x1) - offset
|
offset = Math.abs(ridge.x2 - x1) - offset
|
||||||
|
offset = offset < 0 ? 0 : offset
|
||||||
ridge.set({
|
ridge.set({
|
||||||
x1: ridge.x1 - offset,
|
x1: ridge.x1 - offset,
|
||||||
y1: ridge.y1,
|
y1: ridge.y1,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user