# Conflicts:
#	src/app/layout.js
#	src/components/floor-plan/CanvasFrame.jsx
#	src/components/floor-plan/CanvasMenu.jsx
#	src/components/floor-plan/FloorPlan.jsx
#	src/locales/ja.json
#	src/locales/ko.json
#	src/styles/_modal.scss
This commit is contained in:
minsik 2024-10-21 15:37:42 +09:00
commit f26429ef99
68 changed files with 1715 additions and 1094 deletions

View File

@ -4,5 +4,5 @@ SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-local.q-cells.jp:8120/eos/login/autoLogin"
NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-local.q-cells.jp:8120/qm/login/autoLogin"
NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-qa.q-cells.jp:8120/eos/login/autoLogin"
NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-qa.q-cells.jp:8120/qm/login/autoLogin"

View File

@ -4,5 +4,5 @@ SESSION_SECRET="i3iHH1yp2/2SpQSIySQ4bpyc4g0D+zCF9FAn5xUG0+Y="
NEXT_PUBLIC_CONVERTER_API_URL="https://v2.convertapi.com/convert/dwg/to/png?Secret=secret_bV5zuYMyyIYFlOb3"
NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="http://q-order-local.q-cells.jp:8120/eos/login/autoLogin"
NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="http://q-musubi-local.q-cells.jp:8120/qm/login/autoLogin"
NEXT_PUBLIC_Q_ORDER_AUTO_LOGIN_URL="https://q-order.q-cells.jp/eos/login/autoLogin"
NEXT_PUBLIC_Q_MUSUBI_AUTO_LOGIN_URL="https://q-musubi.q-cells.jp/qm/login/autoLogin"

View File

@ -44,7 +44,6 @@
"prettier": "^3.3.3",
"prisma": "^5.18.0",
"react-color-palette": "^7.2.2",
"react-dropdown-select": "^4.11.3",
"react-select": "^5.8.1",
"sass": "^1.77.8",
"tailwindcss": "^3.4.1"

View File

@ -1,27 +1,24 @@
'use client'
import { useEffect } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import { ErrorBoundary } from 'next/dist/client/components/error-boundary'
import ServerError from './error'
import '@/styles/common.scss'
import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json'
// import KO from '@/locales/ko.json'
// import JA from '@/locales/ja.json'
export const QcastProvider = ({ children }) => {
const globalLocale = useRecoilValue(globalLocaleStore)
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
// const globalLocale = useRecoilValue(globalLocaleStore)
// const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
useEffect(() => {
if (globalLocale === 'ko') {
setAppMessageState(KO)
} else {
setAppMessageState(JA)
}
}, [globalLocale])
// useEffect(() => {
// if (globalLocale === 'ko') {
// setAppMessageState(KO)
// } else {
// setAppMessageState(JA)
// }
// }, [globalLocale])
return (
<>

View File

@ -0,0 +1,12 @@
'use client'
import { createContext, useState } from 'react'
export const SessionContext = createContext({
session: {},
})
export default function SessionProvider({ useSession, children }) {
const [session, setSession] = useState(useSession)
return <SessionContext.Provider value={{ session }}>{children}</SessionContext.Provider>
}

View File

@ -15,6 +15,8 @@ import './globals.css'
import '../styles/style.scss'
import '../styles/contents.scss'
import Dimmed from '@/components/ui/Dimmed'
import SessionProvider from './SessionProvider'
import LocaleSwitch from '@/components/LocaleSwitch'
import PopupManager from '@/components/common/popupManager/PopupManager'
// const inter = Inter({ subsets: ['latin'] })
@ -71,11 +73,14 @@ export default async function RootLayout({ children }) {
<Header userSession={sessionProps} />
<div className="content">
<Dimmed />
<QcastProvider>{children}</QcastProvider>
<QcastProvider>
<SessionProvider useSession={sessionProps}>{children}</SessionProvider>
</QcastProvider>
</div>
<footer>
<div className="footer-inner">
<div className="footer-inner flex justify-center">
<span>COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</span>
<LocaleSwitch />
</div>
</footer>
</div>

View File

@ -66,8 +66,13 @@ export const LINE_TYPE = {
},
SUBLINE: {
/**
*
* 추녀 / 마루 / 박공 / 지붕골 / 박공단
*/
HIP: 'hip',
RIDGE: 'ridge',
GABLE: 'gable',
VALLEY: 'valley',
VERGE: 'verge',
},
}

View File

@ -0,0 +1,23 @@
'use client'
import { globalLocaleStore } from '@/store/localeAtom'
import { useRecoilState } from 'recoil'
export default function LocaleSwitch() {
const [globalLocale, setGlobalLocale] = useRecoilState(globalLocaleStore)
return (
<span
className="locale-switch"
onClick={() => {
if (globalLocale === 'ko') {
setGlobalLocale('ja')
} else {
setGlobalLocale('ko')
}
}}
>
{globalLocale.toUpperCase()}
</span>
)
}

View File

@ -30,7 +30,7 @@ export default function Playground() {
const fileRef = useRef(null)
const queryRef = useRef(null)
const [zoom, setZoom] = useState(20)
const { get, promisePost } = useAxios()
const { get, promiseGet, promisePost } = useAxios()
const testVar = process.env.NEXT_PUBLIC_TEST
const converterUrl = process.env.NEXT_PUBLIC_CONVERTER_API_URL
const { getMessage } = useMessage()
@ -43,6 +43,8 @@ export default function Playground() {
const [checkboxInput, setCheckboxInput] = useState([])
const [selectedValue, setSelectedValue] = useState('')
const [users, setUsers] = useState([])
useEffect(() => {
console.log('textInput:', textInput)
}, [textInput])
@ -142,6 +144,10 @@ export default function Playground() {
},
}
useEffect(() => {
console.log('users:', users)
}, [users])
return (
<>
<div className="container mx-auto p-4 m-4 border">
@ -305,6 +311,32 @@ export default function Playground() {
<div className="my-2">
<QPagination {...paginationProps} />
</div>
<div className="my-2">
<Button
onClick={() => {
promiseGet({ url: 'http://localhost:8080/api/user' }).then((res) => setUsers(res.data))
}}
>
axios get test
</Button>
</div>
<div className="my-2">
<Button
onClick={() => {
const result = promisePost({
url: 'http://localhost:8080/api/user',
data: {
firstName: 'Yoo',
lastName: 'Sangwook',
email: 'yoo1757@naver.com',
age: 46,
},
}).then((res) => console.log('res', res))
}}
>
axios post test
</Button>
</div>
</div>
</>
)

View File

@ -3,7 +3,8 @@
import React, { useEffect, useState } from 'react'
import { Button } from '@nextui-org/react'
import { get, post } from '@/lib/Axios'
import { useAxios } from '@/hooks/useAxios'
import { useRecoilState } from 'recoil'
import { customSettingsState } from '@/store/canvasAtom'
import { modalContent, modalState } from '@/store/modalAtom'
@ -20,6 +21,8 @@ export default function Settings() {
const [open, setOpen] = useRecoilState(modalState)
const [contents, setContent] = useRecoilState(modalContent)
const { get, post } = useAxios()
const handleSavePopup = () => {
console.log('color ', color)
}

View File

@ -0,0 +1,21 @@
'use client'
import { useMessage } from '@/hooks/useMessage'
export default function AutoLoginPage() {
const { getMessage } = useMessage()
return (
<div className="login-input-frame">
<div className="login-frame-tit ">
<span>{getMessage('site.name')}</span>
{getMessage('site.sub_name')}
</div>
<div className="login-input-wrap">
<div className="login-area id" style={{ fontWeight: 'bolder' }}>
{getMessage('login.auto.page.text')}
</div>
</div>
</div>
)
}

View File

@ -15,6 +15,8 @@ import Cookies from 'js-cookie'
import { useSearchParams } from 'next/navigation'
import AutoLogin from './AutoLogin'
export default function Login() {
//
const initParams = useSearchParams()
@ -180,8 +182,7 @@ export default function Login() {
<Link href={'/login'} className="login-logo">
<Image src="/static/images/main/login-logo.svg" alt="react" width={236} height={43} styles={{ width: '236px', height: '43px' }} priority />
</Link>
{passwordReset === 1 && (
{!autoLoginParam && passwordReset === 1 && (
<>
<div className="login-input-frame">
<form onSubmit={loginProcess} className="space-y-6">
@ -266,7 +267,7 @@ export default function Login() {
</div>
</>
)}
{passwordReset === 2 && (
{!autoLoginParam && passwordReset === 2 && (
<>
<div className="login-input-frame">
<div className="login-frame-tit pw-reset">
@ -328,6 +329,7 @@ export default function Login() {
</div>
</>
)}
{autoLoginParam && <AutoLogin />}
</div>
<div className="login-copyright">COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</div>
</div>

View File

@ -27,7 +27,7 @@ export default function QContextMenu(props) {
const handleContextMenu = (e) => {
// e.preventDefault() // contextmenu
setContextMenu({ visible: true, x: e.pageX, y: e.pageY })
console.log(111, canvasProps)
// console.log(111, canvasProps)
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //
}

View File

@ -61,7 +61,7 @@ export default function Archive() {
<div className="sub-content">
<div className="sub-content-inner">
<div className="sub-table-box">
<Search title={boardType.boardTitle} subTitle={boardType.subTitle} isSelectUse={true} />
<Search title={boardType.boardTitle} subTitle={boardType.subTitle} isSelectUse={false} />
<ArchiveTable clsCode={boardType.clsCode} />
</div>
</div>

View File

@ -45,7 +45,7 @@ export default function ArchiveTable({ clsCode }) {
}
fetchData()
}, [search.searchValue])
}, [search.searchValue, search.searchFlag])
//
const handleDetailFileListDown = async (noticeNo) => {
@ -74,30 +74,34 @@ export default function ArchiveTable({ clsCode }) {
return (
<>
<div className="file-down-list">
{boardList?.map((board) => (
<div key={board.noticeNo} className="file-down-item">
<div className="file-item-info">
<div className="item-num">
{/* 번호 */}
{board.rowNumber}
{boardList.length > 0 ? (
<div className="file-down-list">
{boardList?.map((board) => (
<div key={board.noticeNo} className="file-down-item">
<div className="file-item-info">
<div className="item-num">
{/* 번호 */}
{board.rowNumber}
</div>
<div className="item-name">
{/* 제목 */}
{board.title}
</div>
<div className="item-date">
{/* 등록일 */}
{getMessage('board.sub.updDt')} : {board.uptDt ? board.uptDt : board.regDt}
</div>
</div>
<div className="item-name">
{/* 제목 */}
{board.title}
</div>
<div className="item-date">
{/* 등록일 */}
{getMessage('board.sub.updDt')} : {board.uptDt ? board.uptDt : board.regDt}
<div className="file-down-box">
{/* 첨부파일 */}
<button type="button" className="file-down-btn" onClick={() => handleDetailFileListDown(board.noticeNo)}></button>
</div>
</div>
<div className="file-down-box">
{/* 첨부파일 */}
<button type="button" className="file-down-btn" onClick={() => handleDetailFileListDown(board.noticeNo)}></button>
</div>
</div>
))}
</div>
))}
</div>
) : (
<div className="file-down-nodata">{getMessage('common.message.no.data')}</div>
)}
</>
)
}

View File

@ -75,7 +75,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
const y2 = this.top + this.height * scaleY
const dx = x2 - x1
const dy = y2 - y1
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0))
this.length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1))
},
addLengthText() {
@ -150,7 +150,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
getLength() {
//10배 곱해진 값 return
return Number(this.length.toFixed(1) * 10)
return Number(this.length.toFixed(0) * 10)
},
setViewLengthText(bool) {

View File

@ -199,32 +199,16 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
const end = points[(i + 1) % points.length]
const dx = end.x - start.x
const dy = end.y - start.y
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10
const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(0)) * 10
let midPoint
switch (this.direction) {
case 'north':
midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2 - 30)
break
case 'west':
midPoint = new fabric.Point((start.x + end.x) / 2 - 30, (start.y + end.y) / 2)
break
case 'south':
midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2 + 30)
break
case 'east':
midPoint = new fabric.Point((start.x + end.x) / 2 + 30, (start.y + end.y) / 2)
break
default:
midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2)
break
}
midPoint = new fabric.Point((start.x + end.x) / 2, (start.y + end.y) / 2)
const degree = (Math.atan2(dy, dx) * 180) / Math.PI
// Create new text object if it doesn't exist
const text = new fabric.Text(length.toFixed(0), {
const text = new fabric.Text(length.toString(), {
left: midPoint.x,
top: midPoint.y,
fontSize: this.fontSize,

View File

@ -22,9 +22,6 @@ export default function CanvasFrame({ plan }) {
const currentObject = useRecoilValue(currentObjectState)
useEffect(() => {
console.log(currentObject)
}, [currentObject])
useEvent()
const loadCanvas = () => {
@ -46,7 +43,10 @@ export default function CanvasFrame({ plan }) {
return (
<div className="canvas-frame flex justify-center">
<canvas ref={canvasRef} id={'canvas'}></canvas>
<div className="canvas-container" style={{ position: 'relative' }}>
<canvas ref={canvasRef} id={'canvas'}></canvas>
</div>
<QContextMenu contextRef={canvasRef} canvasProps={canvas}>
{contextMenu.map((menus, index) => (
<ul key={index}>
@ -62,7 +62,7 @@ export default function CanvasFrame({ plan }) {
>
{menu.name}
</li>
))}
))}
</ul>
))}
</QContextMenu>

View File

@ -1,140 +1,44 @@
'use client'
import { useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { useContext, useEffect, useState } from 'react'
import { useRecoilValue } from 'recoil'
import CanvasFrame from './CanvasFrame'
import { useMessage } from '@/hooks/useMessage'
import { useSwal } from '@/hooks/useSwal'
import { usePlan } from '@/hooks/usePlan'
import { globalLocaleStore } from '@/store/localeAtom'
import { currentCanvasPlanState, initCanvasPlansState, plansState } from '@/store/canvasAtom'
import { sessionStore } from '@/store/commonAtom'
import { SessionContext } from '@/app/SessionProvider'
export default function CanvasLayout() {
export default function CanvasLayout(props) {
const { menuNumber } = props
const { session } = useContext(SessionContext)
const [objectNo, setObjectNo] = useState('test123240822001') //
const [planNum, setPlanNum] = useState(0)
const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState)
const [plans, setPlans] = useRecoilState(plansState)
const globalLocaleState = useRecoilValue(globalLocaleStore)
const sessionState = useRecoilValue(sessionStore)
const { getMessage } = useMessage()
const { swalFire } = useSwal()
const { getCanvasByObjectNo, delCanvasById, checkModifiedCanvasPlan, saveCanvas, currentCanvasData } = usePlan()
const handleCurrentPlan = (newCurrentId) => {
// console.log('currentPlan newCurrentId: ', newCurrentId)
if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) {
swalFire({
html: getMessage('common.message.confirm.save') + `</br>${currentCanvasPlan.name}`,
type: 'confirm',
confirmFn: async () => {
await saveCanvas(sessionState.userId)
updateCurrentPlan(newCurrentId)
},
denyFn: () => {
updateCurrentPlan(newCurrentId)
},
})
} else {
updateCurrentPlan(newCurrentId)
}
}
}
const updateCurrentPlan = (newCurrentId) => {
setPlans((plans) =>
plans.map((plan) => {
return { ...plan, isCurrent: plan.id === newCurrentId }
}),
)
}
useEffect(() => {
setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null)
}, [plans])
const handleDeletePlan = (e, id) => {
e.stopPropagation() //
if (initCanvasPlans.some((plan) => plan.id === id)) {
delCanvasById(id)
.then((res) => {
swalFire({ text: getMessage('common.message.delete') })
// console.log('[DELETE] canvas-statuses res :::::::: %o', res)
setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id))
setPlans((plans) => plans.filter((plan) => plan.id !== id))
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
// console.error('[DELETE] canvas-statuses res error :::::::: %o', error)
})
} else {
setPlans((plans) => plans.filter((plan) => plan.id !== id))
swalFire({ text: getMessage('common.message.delete') })
}
// last
const lastPlan = plans.filter((plan) => plan.id !== id).at(-1)
if (!lastPlan) {
setPlanNum(0)
setCurrentCanvasPlan(null)
} else if (id !== lastPlan.id) {
handleCurrentPlan(lastPlan.id)
}
}
const addEmptyPlan = () => {
setPlans([...plans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }])
handleCurrentPlan(planNum)
setPlanNum(planNum + 1)
}
const addCopyPlan = () => {
const copyPlan = {
id: planNum,
name: `Plan ${planNum + 1}`,
objectNo: `${objectNo}`,
userId: sessionState.userId,
canvasStatus: currentCanvasData(),
}
setPlans((plans) => [...plans, copyPlan])
handleCurrentPlan(planNum)
setPlanNum(planNum + 1)
}
const { plans, loadCanvasPlanData, handleCurrentPlan, handleAddPlan, handleDeletePlan } = usePlan()
useEffect(() => {
if (!currentCanvasPlan) {
getCanvasByObjectNo(sessionState.userId, objectNo).then((res) => {
// console.log('canvas ', res)
if (res.length > 0) {
setInitCanvasPlans(res)
setPlans(res)
handleCurrentPlan(res.at(-1).id) // last
setPlanNum(res.length)
} else {
addEmptyPlan()
}
})
}
loadCanvasPlanData(session.userId, objectNo)
}, [])
return (
<div className="canvas-layout">
<div className="canvas-page-list">
<div className={`canvas-page-list ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
<div className="canvas-plane-wrap">
{plans.map((plan) => (
<button
key={`plan-${plan.id}`}
className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`}
onClick={() => handleCurrentPlan(plan.id)}
onClick={() => handleCurrentPlan(session.userId, plan.id)}
>
<span>{plan.name}</span>
<i
className="close"
onClick={(e) =>
swalFire({
html: getMessage('common.message.confirm.delete') + `</br>${plan.name}`,
text: `${plan.name} ` + getMessage('plan.message.confirm.delete'),
type: 'confirm',
confirmFn: () => {
handleDeletePlan(e, plan.id)
@ -146,23 +50,7 @@ export default function CanvasLayout() {
))}
</div>
{plans.length < 10 && (
<button
className="plane-add"
onClick={() =>
JSON.parse(currentCanvasData()).objects.length > 0
? swalFire({
html: `${currentCanvasPlan.name} 을 복제하시겠습니까?`,
type: 'confirm',
confirmFn: () => {
addCopyPlan()
},
denyFn: () => {
addEmptyPlan()
},
})
: addEmptyPlan()
}
>
<button className="plane-add" onClick={() => handleAddPlan(session.userId, objectNo)}>
<span></span>
</button>
)}

View File

@ -36,6 +36,8 @@ const canvasMenus = [
export default function CanvasMenu(props) {
const {
menuNumber,
setMenuNumber,
setShowCanvasSettingModal,
showOutlineModal,
setShowOutlineModal,
@ -57,13 +59,13 @@ export default function CanvasMenu(props) {
} = props
const { addPopup, closePopup } = usePopup()
const [menuNumber, setMenuNumber] = useState(null)
const [type, setType] = useState('')
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
const setCurrentMenu = useSetRecoilState(currentMenuState)
const setPoints = useSetRecoilState(outerLinePointsState)
const setOuterLinePoints = useSetRecoilState(outerLinePointsState)
const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const { handleZoomClear } = useCanvasEvent()
@ -127,14 +129,14 @@ export default function CanvasMenu(props) {
}, [menuNumber, type])
// (btn08)
const handleSaveCanvas = () => {
swalFire({
html: getMessage('common.message.confirm.save') + `</br>${currentCanvasPlan.name}`,
type: 'confirm',
confirmFn: () => {
saveCanvas(sessionState.userId)
},
})
const handleSaveCanvas = async () => {
// swalFire({
// text: `${currentCanvasPlan.name} ` + getMessage('plan.message.confirm.save'),
// type: 'confirm',
// confirmFn: async () => {
await saveCanvas(sessionState.userId)
// },
// })
}
const onClickPlacementInitialMenu = () => {
@ -146,7 +148,8 @@ export default function CanvasMenu(props) {
}
const handleClear = () => {
setPoints([])
setOuterLinePoints([])
setPlacementPoints([])
canvas?.clear()
}
//

View File

@ -52,6 +52,8 @@ export default function FloorPlan() {
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const [objectNo, setObjectNo] = useState('test123240912001') //
const [menuNumber, setMenuNumber] = useState(null)
const [showDotLineGridModal, setShowDotLineGridModal] = useState(false)
const [showGridCopyModal, setShowGridCopyModal] = useState(false)
const [showGridMoveModal, setShowGridMoveModal] = useState(false)
const [color, setColor] = useRecoilState(gridColorState)
@ -63,6 +65,8 @@ export default function FloorPlan() {
}
const modalProps = {
menuNumber,
setMenuNumber,
setShowCanvasSettingModal,
showOutlineModal,
setShowOutlineModal,

View File

@ -1,8 +1,13 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { globalPitchState } from '@/store/canvasAtom'
import { useRecoilState } from 'recoil'
import { useRef } from 'react'
export default function Slope({ setShowSlopeSettingModal }) {
const { getMessage } = useMessage()
const [globalPitch, setGlobalPitch] = useRecoilState(globalPitchState)
const inputRef = useRef()
return (
<WithDraggable isShow={true} pos={{ x: 50, y: -950 }}>
<div className={`modal-pop-wrap xxxm`}>
@ -19,13 +24,21 @@ export default function Slope({ setShowSlopeSettingModal }) {
{getMessage('slope')}
</span>
<div className="input-grid mr5">
<input type="text" className="input-origin block" defaultValue={300} />
<input type="text" className="input-origin block" defaultValue={globalPitch} ref={inputRef} />
</div>
<span className="thin">{getMessage('size.angle')}</span>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
<button
className="btn-frame modal act"
onClick={() => {
setGlobalPitch(inputRef.current.value)
setShowSlopeSettingModal(false)
}}
>
{getMessage('modal.common.save')}
</button>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@ import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState
import { onlyNumberInputChange } from '@/util/input-utils'
import { fabric } from 'fabric'
import { gridColorState } from '@/store/gridAtom'
import { settingModalGridOptionsState } from '@/store/settingAtom'
import { gridDisplaySelector, settingModalGridOptionsState } from '@/store/settingAtom'
import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal'
import { usePopup } from '@/hooks/usePopup'
@ -25,6 +25,7 @@ export default function DotLineGrid(props) {
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
const gridColor = useRecoilValue(gridColorState)
const canvas = useRecoilValue(canvasState)
const isGridDisplay = useRecoilValue(gridDisplaySelector)
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState)
@ -181,6 +182,7 @@ export default function DotLineGrid(props) {
fill: pattern,
selectable: false,
name: 'dotGrid',
visible: isGridDisplay,
},
)
@ -211,6 +213,7 @@ export default function DotLineGrid(props) {
strokeDashArray: [5, 2],
opacity: 0.3,
direction: 'horizontal',
visible: isGridDisplay,
},
)
canvas.add(horizontalLine)
@ -237,6 +240,7 @@ export default function DotLineGrid(props) {
strokeDashArray: [5, 2],
opacity: 0.3,
direction: 'vertical',
visible: isGridDisplay,
},
)
canvas.add(verticalLine)

View File

@ -46,6 +46,7 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
heightRef: useRef(null),
pitchRef: useRef(null),
offsetRef: useRef(null),
offsetWidthRef: useRef(null),
directionRef: useRef(null),
}

View File

@ -1,8 +1,17 @@
import Image from 'next/image'
import { useMessage } from '@/hooks/useMessage'
import { forwardRef, useState } from 'react'
export default function PentagonDormer() {
const PentagonDormer = forwardRef((props, refs) => {
const { getMessage } = useMessage()
const [direction, setDirection] = useState('down')
refs.directionRef.current = direction
const getDirection = (e) => {
setDirection(e.target.value)
refs.directionRef.current = e.target.value
}
return (
<>
<div className="discrimination-box mb10">
@ -18,7 +27,7 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={2000} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.heightRef} defaultValue={2000} />
</div>
<span className="thin">mm</span>
</div>
@ -29,7 +38,7 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={1000} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetRef} />
</div>
<span className="thin">mm</span>
</div>
@ -40,18 +49,18 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={4000} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.widthRef} defaultValue={2000} />
</div>
<span className="thin">mm</span>
</div>
</div>
</div>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">{getMessage('modal.object.setting.offset.depth')}</div>
<div className="eaves-keraba-th">{getMessage('modal.object.setting.offset.width')}</div>
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={500} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.offsetWidthRef} />
</div>
<span className="thin">mm</span>
</div>
@ -62,7 +71,7 @@ export default function PentagonDormer() {
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}>
<input type="text" className="input-origin block" defaultValue={4} />
<input type="text" className="input-origin block" placeholder={0} ref={refs.pitchRef} defaultValue={4} />
</div>
<span className="thin"></span>
</div>
@ -80,13 +89,15 @@ export default function PentagonDormer() {
<span className="right">{getMessage('commons.east')}</span>
<span className="bottom">{getMessage('commons.south')}</span>
<span className="left">{getMessage('commons.west')}</span>
<button className="plane-btn up"></button>
<button className="plane-btn right"></button>
<button className="plane-btn down act"></button>
<button className="plane-btn left"></button>
<button className={`plane-btn up ${direction === 'up' ? ' act' : ''}`} value="up" onClick={getDirection}></button>
<button className={`plane-btn right ${direction === 'right' ? ' act' : ''}`} value="right" onClick={getDirection}></button>
<button className={`plane-btn down ${direction === 'down' ? ' act' : ''}`} value="down" onClick={getDirection}></button>
<button className={`plane-btn left ${direction === 'left' ? ' act' : ''}`} value="left" onClick={getDirection}></button>
</div>
</div>
</div>
</>
)
}
})
export default PentagonDormer

View File

@ -5,7 +5,6 @@ import { forwardRef, useState } from 'react'
const TriangleDormer = forwardRef((props, refs) => {
const { getMessage } = useMessage()
const [direction, setDirection] = useState('down')
refs.directionRef.current = direction
const getDirection = (e) => {

View File

@ -1,14 +1,14 @@
import { useRecoilState } from 'recoil'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import { settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react'
import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal'
import { adsorptionPointAddModeState } from '@/store/canvasAtom'
import { useFirstOption } from '@/hooks/option/useFirstOption'
export default function FirstOption() {
const [objectNo, setObjectNo] = useState('test123240912001') //
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const { settingModalFirstOptions, setSettingModalFirstOptions } = useFirstOption()
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { option3, option4 } = settingModalSecondOptions

View File

@ -34,7 +34,6 @@ export default function MainContents({ objectList, businessCharger, businessChar
startRow: 1,
endRow: 1,
}
// const noticeApiUrl = `api/board/list?schNoticeTpCd=QC&schNoticeClsCd=NOTICE&schTitle=&startRow=1&endRow=1`
const noticeApiUrl = `api/board/list?${queryStringFormatter(param)}`
const res = await get({ url: noticeApiUrl })
//console.log('res::', res)
@ -57,7 +56,6 @@ export default function MainContents({ objectList, businessCharger, businessChar
startRow: 1,
endRow: 3,
}
// const faqApiUrl = `api/board/list?schNoticeTpCd=QC&schNoticeClsCd=FAQ&schTitle=&startRow=1&endRow=1`
const faqApiUrl = `api/board/list?${queryStringFormatter(param)}`
const res = await get({ url: faqApiUrl })
//console.log('FAQres::', res)

View File

@ -15,6 +15,7 @@ import { convertNumberToPriceDecimal } from '@/util/common-utils'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json'
import QPagination from '../common/pagination/QPagination'
import '@/styles/grid.scss'
import { sessionStore } from '@/store/commonAtom'
@ -24,9 +25,9 @@ export default function Stuff() {
const stuffSearchParams = useRecoilValue(stuffSearchState)
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
const { getMessage } = useMessage()
const [curPage, setCurPage] = useState(1) //
const [defaultSize, setDefaultSize] = useState(100) //
const [gridCount, setGridCount] = useState(0) //
const [pageNo, setPageNo] = useState(1) //
const [pageSize, setPageSize] = useState(100) //
const [totalCount, setTotalCount] = useState(0) //
const [defaultSortType, setDefaultSortType] = useState('R')
const globalLocaleState = useRecoilValue(globalLocaleStore)
@ -62,13 +63,10 @@ export default function Stuff() {
const [gridProps, setGridProps] = useState({
gridData: [],
isPageable: false,
// sets 10 rows per page (default is 100)
// paginationPageSize: 100,
// allows the user to select the page size from a predefined list of page sizes
// paginationPageSizeSelector: [100, 200, 300, 400],
gridColumns: [
{
field: 'lastEditDatetime',
minWidth: 200,
headerName: getMessage('stuff.gridHeader.lastEditDatetime'),
headerCheckboxSelection: true,
headerCheckboxSelectionCurrentPageOnly: true, //
@ -228,56 +226,40 @@ export default function Stuff() {
//
useEffect(() => {
if (isObjectNotEmpty(sessionState)) {
// sessionState
if (stuffSearchParams?.code === 'S') {
const params = {
schObjectNo: '',
schAddress: '',
schObjectName: '',
schSaleStoreName: '',
schReceiveUser: '',
schDispCompanyName: '',
schDateType: 'U',
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: (curPage - 1) * defaultSize + 1,
endRow: curPage * defaultSize,
startRow: (pageNo - 1) * pageSize + 1,
endRow: pageNo * pageSize,
schSelSaleStoreId: '',
schSortType: 'R',
schSortType: stuffSearchParams.schSortType,
}
async function fetchData() {
//api startRow, endRow
// let startRow
// let endRow
// startRow = (curPage - 1) * size + 1
// endRow = curPage * size
// console.log('startrow::', startRow)
// console.log('endRow::', endRow)
// let curPage
// let totalpage
// let totalCount
// let size
// let pageCount
// console.log(' ::::::::::', sessionState)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}`
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}`
await get({
url: apiUrl,
}).then((res) => {
if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt)
setTotalCount(res[0].totCnt)
}
})
}
fetchData()
} else {
//
const params = {
schObjectNo: '',
schObjectNo: stuffSearchParams.schObjectNo,
schAddress: '',
schObjectName: '',
schSaleStoreName: '',
@ -286,30 +268,13 @@ export default function Stuff() {
schDateType: 'U',
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
startRow: (curPage - 1) * defaultSize + 1,
endRow: curPage * defaultSize,
startRow: (pageNo - 1) * pageSize + 1,
endRow: pageNo * pageSize,
schSelSaleStoreId: '',
schSortType: 'R',
}
async function fetchData() {
//api startRow, endRow
// let startRow
// let endRow
// startRow = (curPage - 1) * size + 1
// endRow = curPage * size
// console.log('startrow::', startRow)
// console.log('endRow::', endRow)
// let curPage
// let totalpage
// let totalCount
// let size
// let pageCount
// console.log(' ::::::::::', sessionState)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(params)}`
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(params)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}`
await get({
@ -317,34 +282,33 @@ export default function Stuff() {
}).then((res) => {
if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt)
setTotalCount(res[0].totCnt)
}
})
}
fetchData()
}
}
}, [sessionState])
}, [pageNo, sessionState])
useEffect(() => {
if (stuffSearchParams?.code === 'E') {
//console.log('::::::::', stuffSearchParams)
stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1
stuffSearchParams.endRow = curPage * defaultSize
stuffSearchParams.startRow = 1
stuffSearchParams.endRow = 1 * pageSize
stuffSearchParams.schSortType = defaultSortType
setPageNo(1)
async function fetchData() {
// console.log(' :::::::::::::', sessionState)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}`
await get({ url: apiUrl }).then((res) => {
// console.log(' API:::::::', res)
if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt)
setTotalCount(res[0].totCnt)
} else {
setGridProps({ ...gridProps, gridData: [], count: 0 })
setGridCount(0)
setTotalCount(0)
}
})
}
@ -354,53 +318,58 @@ export default function Stuff() {
//
const onChangePerPage = (e) => {
let startRow = (curPage - 1) * e.target.value + 1
let startRow = (1 - 1) * e.target.value + 1
stuffSearchParams.startRow = startRow
stuffSearchParams.endRow = curPage * e.target.value
setDefaultSize(e.target.value)
stuffSearchParams.endRow = 1 * e.target.value
setPageSize(e.target.value)
setStuffSearch({
...stuffSearch,
code: 'S',
startRow: startRow,
endRow: curPage * e.target.value,
endRow: 1 * e.target.value,
})
// console.log(' :::', stuffSearchParams)
// console.log(' sessionState:::', sessionState)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
setPageNo(1)
// const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}`
get({ url: apiUrl }).then((res) => {
if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt)
setTotalCount(res[0].totCnt)
} else {
setGridProps({ ...gridProps, gridData: [], count: 0 })
setGridCount(0)
setTotalCount(0)
}
})
}
//
const onChangeSortType = (e) => {
let startRow = (1 - 1) * pageSize + 1
stuffSearchParams.startRow = startRow
stuffSearchParams.endRow = 1 * pageSize
stuffSearchParams.schSortType = e.target.value
// console.log(' :::', stuffSearchParams)
setDefaultSortType(e.target.value)
setStuffSearch({
...stuffSearch,
code: 'S',
startRow: startRow,
endRow: 1 * pageSize,
schSortType: e.target.value,
})
// console.log(' ::::::::::::', sessionState)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
setPageNo(1)
// const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}`
get({ url: apiUrl }).then((res) => {
if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt)
setTotalCount(res[0].totCnt)
} else {
setGridProps({ ...gridProps, gridData: [], count: 0 })
setGridCount(0)
setTotalCount(0)
}
})
}
@ -413,20 +382,34 @@ export default function Stuff() {
}
}, [globalLocaleState])
//
const handleChangePage = (page) => {
stuffSearchParams.code = 'S'
setStuffSearch({
...stuffSearch,
code: 'S',
startRow: (page - 1) * pageSize + 1,
endRow: page * pageSize,
})
setPageNo(page)
}
return (
<>
{/* 퍼블시작 */}
<div className="sub-table-box">
<div className="table-box-title-wrap">
<div className="title-wrap">
<h3>물건목록</h3>
<h3>{getMessage('stuff.search.grid.title')}</h3>
<ul className="info-wrap">
<li>
전체
<span>{convertNumberToPriceDecimal(gridCount)}</span>
{getMessage('stuff.search.grid.all')}
<span>{convertNumberToPriceDecimal(totalCount)}</span>
</li>
<li>
선택
{getMessage('stuff.search.grid.selected')}
<span className="red">{convertNumberToPriceDecimal(selectedRowDataCount)}</span>
</li>
</ul>
@ -434,8 +417,8 @@ export default function Stuff() {
<div className="left-unit-box">
<div className="select-box mr5" style={{ width: '110px' }}>
<select className="select-light black" name="" id="" onChange={onChangeSortType}>
<option value="R">최근 등록일</option>
<option value="U">최근 수정일</option>
<option value="R">{getMessage('stuff.search.grid.schSortTypeR')}</option>
<option value="U">{getMessage('stuff.search.grid.schSortTypeU')}</option>
</select>
</div>
<div className="select-box" style={{ width: '80px' }}>
@ -450,7 +433,9 @@ export default function Stuff() {
<div className="grid-table-wrap">
<div className="q-grid">
<StuffQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} getCellDoubleClicked={getCellDoubleClicked} gridRef={gridRef} />
<div className="pagination-wrap">페이징 컴포넌트예정</div>
<div className="pagination-wrap">
<QPagination pageNo={pageNo} pageSize={pageSize} pagePerBlock={10} totalCount={totalCount} handleChangePage={handleChangePage} />
</div>
</div>
</div>
</div>

View File

@ -16,6 +16,8 @@ import FindAddressPop from './popup/FindAddressPop'
import PlanRequestPop from './popup/PlanRequestPop'
import WindSelectPop from './popup/WindSelectPop'
export default function StuffDetail() {
const [selOptions, setSelOptions] = useState('')
const sessionState = useRecoilValue(sessionStore)
const router = useRouter()
@ -79,7 +81,7 @@ export default function StuffDetail() {
const [detailData, setDetailData] = useState({})
useEffect(() => {
console.log('objectNo::', objectNo)
// console.log('objectNo::', objectNo)
if (objectNo) {
console.log('수정화면')
@ -100,33 +102,34 @@ export default function StuffDetail() {
// API
get({ url: '/api/object/prefecture/list' }).then((res) => {
if (!isEmptyArray(res)) {
// console.log(' API :::', res)
setPrefCodeList(res)
}
})
// 1 saleStoreId=201TES01
// T01
//1 : X167
get({ url: `/api/object/saleStore/T01/list` }).then((res) => {
// get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => {
//1 : X167 T01
// get({ url: `/api/object/saleStore/TEMP02/list` }).then((res) => {
get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => {
if (!isEmptyArray(res)) {
const firstList = res.filter((row) => row.saleStoreLevel === '1')
const otherList = res.filter((row) => row.saleStoreLevel !== '1')
//1
setSaleStoreList(firstList)
setSelOptions(sessionState?.storeId)
form.setValue('saleStoreId', sessionState?.storeId)
form.setValue('saleStoreLevel', sessionState?.storeLvl)
//1
setOriginOtherSaleStoreList(otherList)
setOtherSaleStoreList(otherList)
}
})
}
}, [objectNo])
}, [objectNo, sessionState])
useEffect(() => {
if (isObjectNotEmpty(detailData)) {
console.log('상세데이타:::::::', detailData)
// API
get({ url: '/api/object/prefecture/list' }).then((res) => {
if (!isEmptyArray(res)) {
@ -151,6 +154,8 @@ export default function StuffDetail() {
setOtherSaleStoreList(otherList)
}
})
console.log('상세데이타::세팅:::::', detailData)
}
}, [detailData])
@ -161,12 +166,14 @@ export default function StuffDetail() {
form.setValue('saleStoreId', key.saleStoreId)
form.setValue('saleStoreName', key.saleStoreName)
form.setValue('saleStoreLevel', key.saleStoreLevel)
setSelOptions(key.saleStoreId)
// 1 2 list
// 
let newOtherSaleStoreList = originOtherSaleStoreList.filter((row) => row.firstAgentId === key.saleStoreId)
setOtherSaleStoreList(newOtherSaleStoreList)
} else {
//X
setSelOptions('')
form.setValue('saleStoreId', '')
form.setValue('saleStoreName', '')
form.setValue('saleStoreLevel', '')
@ -209,8 +216,17 @@ export default function StuffDetail() {
form.setValue('zipNo', info.zipNo)
}
//
const setPlanReqInfo = (info) => {}
//
const setPlanReqInfo = (info) => {
console.log('팝업에서 넘어온 설계의뢰 정보::: ', info)
//building :
//planReqName :
//zipNo :
// :address1 : address2
// setPrefValue(info.prefId)
// :
// form.setValue('dispCompanyName', info.planReqName)
}
//
const setWindSppedInfo = (info) => {
@ -286,7 +302,7 @@ export default function StuffDetail() {
}
// console.log('::', errors)
setIsFormValid(Object.keys(errors).length === 0)
setIsFormValid(Object.keys(errors).length === 0 ? true : false)
} else {
console.log('상세일때 폼체크')
}
@ -331,9 +347,8 @@ export default function StuffDetail() {
//
get({ url: `/api/object/prefecture/${prefValue}/list` }).then((res) => {
if (!isEmptyArray(res)) {
// console.log(' ::::::::', res)
form.setValue('areaId', res[0].areaId)
form.setValue('areaName', res[0].prefName)
// form.setValue('areaId', res[0].areaId)
// form.setValue('areaName', res[0].prefName)
setAreaIdList(res)
}
})
@ -342,28 +357,18 @@ export default function StuffDetail() {
//
const handleAreaIdOnChange = (e) => {
form.setValue('areaId', e.target.value)
form.setValue('areaId', e.areaId)
form.setValue('areaName', e.prefName)
}
// useEffect(() => {
// if (!isEmptyArray(areaIdList)) {
// let _prefName = form.watch('prefName')
// // console.log(' API', _prefName)
// get({ url: `/api/object/windSpeed/${_prefName}/list` }).then((res) => {
// // console.log('res::', res)
// if (!isEmptyArray(res)) {
// setWindSpeedList(res)
// }
// })
// }
// }, [areaIdList])
//
const onValid = (data) => {
const onValid = (data, e) => {
const formData = form.getValues()
console.log('필수값 통과:::', data, formData)
// console.log(' formData:::', formData)
// PUT
// console.log(' ')
// console.log('data::::::', data)
const formData = form.getValues()
// console.log('formData::::', formData)
// const _dispCompanyName = watch('dispCompanyName')
// const _objectStatusId = watch('objectStatusId')
@ -391,6 +396,8 @@ export default function StuffDetail() {
//
const onTempSave = async () => {
console.log('임시저장:::::')
return
const formData = form.getValues()
// console.log('formData::', formData)
const params = {
@ -441,7 +448,7 @@ export default function StuffDetail() {
let testobj = '10'
del({ url: `/api/object/${testobj}` }).then((res) => {
// console.log(' :::', res)
console.log('삭제 결과:::', res)
router.push('/management/stuff')
})
}
@ -470,9 +477,9 @@ export default function StuffDetail() {
<div className="input-wrap mr5" style={{ width: '200px' }}>
<input type="text" className="input-light" readOnly />
</div>
<button className="btn-origin grey" onClick={onSearchDesignRequestPopOpen}>
<Button className="btn-origin grey" onClick={onSearchDesignRequestPopOpen}>
{getMessage('stuff.planReqPopup.title')}
</button>
</Button>
</div>
</td>
</tr>
@ -536,13 +543,21 @@ export default function StuffDetail() {
</th>
<td>
<div className="flx-box">
<div style={{ width: '567px', marginRight: '5px' }}>
<div className="select-wrap mr5" style={{ width: '567px' }}>
<Select
id="long-value-select1"
instanceId="long-value-select1"
className="react-select-custom"
classNamePrefix="custom"
placeholder="Select"
options={saleStoreList}
onChange={onSelectionChange}
getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId}
isClearable={true}
value={saleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
@ -562,8 +577,13 @@ export default function StuffDetail() {
</th>
<td>
<div className="flx-box">
<div style={{ width: '567px', marginRight: '5px' }}>
<div className="select-wrap mr5" style={{ width: '567px' }}>
<Select
id="long-value-select2"
instanceId="long-value-select2"
className="react-select-custom"
classNamePrefix="custom"
placeholder="Select"
ref={ref}
options={otherSaleStoreList}
onChange={onSelectionChange2}
@ -610,13 +630,28 @@ export default function StuffDetail() {
<div className="flx-box">
<div className="select-wrap" style={{ width: '200px' }}>
{prefCodeList?.length > 0 && (
<select className="select-light" name="prefName" {...register('prefId')} disabled>
{prefCodeList.map((row) => (
<option key={row.prefId} value={row.prefId}>
{row.prefName}
</option>
))}
</select>
// <select className="select-light" name="prefName" {...register('prefId')} disabled>
// {prefCodeList.map((row) => (
// <option key={row.prefId} value={row.prefId}>
// {row.prefName}
// </option>
// ))}
// </select>
<Select
id="long-value-select3"
instanceId="long-value-select3"
className="react-select-custom"
classNamePrefix="custom"
placeholder="Select"
options={prefCodeList}
getOptionLabel={(x) => x.prefName}
getOptionValue={(x) => x.prefId}
isSearchable={false}
value={prefCodeList.filter(function (option) {
return option.prefId === prefValue
})}
isDisabled={true}
/>
)}
</div>
<div className="input-wrap mr5" style={{ width: '580px' }}>
@ -631,7 +666,7 @@ export default function StuffDetail() {
</th>
<td>
<div className="select-wrap" style={{ width: '200px' }}>
<select
{/* <select
className="select-light"
name="areaId"
disabled={areaIdList?.length > 0 ? false : true}
@ -643,8 +678,25 @@ export default function StuffDetail() {
{row.prefName}
</option>
)
})}
</select>
*/}
<Select
id="long-value-select4"
instanceId="long-value-select4"
className="react-select-custom"
classNamePrefix="custom"
options={areaIdList}
placeholder="Select"
getOptionLabel={(x) => x.prefName}
getOptionValue={(x) => x.areaId}
isSearchable={false}
onChange={handleAreaIdOnChange}
value={areaIdList.filter(function (option) {
return option.areaId === form.watch('areaId')
})}
</select>
isDisabled={areaIdList.length > 0 ? false : true}
/>
</div>
</td>
</tr>
@ -669,9 +721,9 @@ export default function StuffDetail() {
</select>
</div> */}
<span className="mr10">{getMessage('stuff.detail.windSpeedSpan')}</span>
<button className="btn-origin grey" onClick={onSearchWindSpeedPopOpen}>
<Button className="btn-origin grey" onClick={onSearchWindSpeedPopOpen}>
{getMessage('stuff.detail.btn.windSpeedPop')}
</button>
</Button>
</div>
</td>
</tr>
@ -764,13 +816,13 @@ export default function StuffDetail() {
</div>
<div className="sub-table-footer">
{!isFormValid ? (
<button className="btn-origin grey mr5" onClick={onTempSave}>
<Button className="btn-origin grey mr5" onClick={onTempSave}>
New화면 임시저장
</button>
</Button>
) : (
<button type="submit" className="btn-origin navy mr5">
<Button type="submit" className="btn-origin navy mr5">
NEW 화면 저장
</button>
</Button>
)}
<Link href="/management/stuff">
<button type="button" className="btn-origin grey">
@ -801,9 +853,9 @@ export default function StuffDetail() {
<div className="input-wrap mr5" style={{ width: '200px' }}>
<input type="text" className="input-light" readOnly />
</div>
<button className="btn-origin grey" onClick={onSearchDesignRequestPopOpen}>
<Button className="btn-origin grey" onClick={onSearchDesignRequestPopOpen}>
{getMessage('stuff.planReqPopup.title')}
</button>
</Button>
</div>
</td>
</tr>
@ -813,7 +865,7 @@ export default function StuffDetail() {
</th>
<td>
<div className="input-wrap" style={{ width: '500px' }}>
{/* <input type="text" className="input-light" {...form.register('dispCompanyName')} value={form.watch('dispCompanyName')} /> */}
<input type="text" className="input-light" {...form.register('dispCompanyName')} value={form.watch('dispCompanyName')} />
</div>
</td>
</tr>
@ -865,7 +917,7 @@ export default function StuffDetail() {
</th>
<td>
<div className="flx-box">
<div style={{ width: '567px', marginRight: '5px' }}>
<div className="select-wrap mr5" style={{ width: '567px' }}>
{/* <Select
options={saleStoreList}
value={form.watch('saleStoreId')}
@ -890,27 +942,27 @@ export default function StuffDetail() {
{objectNo.substring(0, 1) === 'R' ? (
<>
<Link href="/management/stuff">
<button type="button" className="btn-origin grey">
<button type="button" className="btn-origin grey mr5">
R상세:물건목록
</button>
</Link>
<button type="submit" className="btn-origin navy mr5">
<Button type="submit" className="btn-origin navy mr5">
R상세:저장
</button>
<button type="submit" className="btn-origin navy mr5" onClick={onDelete}>
</Button>
<Button type="submit" className="btn-origin navy" onClick={onDelete}>
R상세:물건삭제
</button>
</Button>
</>
) : (
<>
{!isFormValid ? (
<button type="submit" className="btn-origin navy mr5" onClick={onTempSave}>
<Button type="submit" className="btn-origin navy mr5" onClick={onTempSave}>
TEMP상세:임시저장
</button>
</Button>
) : (
<button type="submit" className="btn-origin navy mr5">
<Button type="submit" className="btn-origin navy mr5">
TEMP상세:저장
</button>
</Button>
)}
<Link href="/management/stuff">
<button type="button" className="btn-origin grey">
@ -923,7 +975,14 @@ export default function StuffDetail() {
)}
{showAddressButtonValid && <FindAddressPop setShowAddressButtonValid={setShowAddressButtonValid} zipInfo={setZipInfo} />}
{showDesignRequestButtonValid && (
<PlanRequestPop setShowDesignRequestButtonValid={setShowDesignRequestButtonValid} planReqInfo={setPlanReqInfo} />
<PlanRequestPop
setShowDesignRequestButtonValid={setShowDesignRequestButtonValid}
saleStoreId={form.watch('saleStoreId')}
saleStoreLevel={form.watch('saleStoreLevel')}
otherSaleStoreId={form.watch('otherSaleStoreId')}
otherSaleStoreLevel={form.watch('otherSaleStoreLevel')}
planReqInfo={setPlanReqInfo}
/>
)}
{showWindSpeedButtonValid && (
<WindSelectPop setShowWindSpeedButtonValid={setShowWindSpeedButtonValid} prefName={form.watch('prefName')} windSpeedInfo={setWindSppedInfo} />

View File

@ -69,12 +69,6 @@ export default function StuffQGrid(props) {
props.getCellDoubleClicked(event)
}, [])
const autoSizeStrategy = useMemo(() => {
return {
type: 'fitCellContents',
}
}, [])
// Fetch data & update rowData state
useEffect(() => {
gridData ? setRowData(gridData) : ''

View File

@ -18,13 +18,19 @@ import { useMessage } from '@/hooks/useMessage'
import { isObjectNotEmpty } from '@/util/common-utils'
export default function StuffSearchCondition() {
const sessionState = useRecoilValue(sessionStore)
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { getMessage } = useMessage()
const ref = useRef()
const { get } = useAxios(globalLocaleState)
const objectNoRef = useRef(null)
const saleStoreNameRef = useRef(null)
const addressRef = useRef(null)
const objectNameRef = useRef(null)
const dispCompanyNameRef = useRef(null)
const receiveUserRef = useRef(null)
// props
const [startDate, setStartDate] = useState(dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
const [endDate, setEndDate] = useState(dayjs(new Date()).format('YYYY-MM-DD'))
@ -43,13 +49,13 @@ export default function StuffSearchCondition() {
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
const [objectNo, setObjectNo] = useState('') //
const [saleStoreName, setSaleStoreName] = useState('') //
const [address, setAddress] = useState('') //
const [objectName, setobjectName] = useState('') //
const [saleStoreName, setSaleStoreName] = useState('') //
const [receiveUser, setReceiveUser] = useState('') //
const [dispCompanyName, setDispCompanyName] = useState('') //
const [dateType, setDateType] = useState('U') //(U)/(R)
const [schSelSaleStoreId, setSchSelSaleStoreId] = useState('') //
const [receiveUser, setReceiveUser] = useState('') //
const [dateType, setDateType] = useState('U') //(U)/(R)
const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) // SELECT
//
@ -59,30 +65,52 @@ export default function StuffSearchCondition() {
return alert(getMessage('stuff.message.periodError'))
}
setStuffSearch({
schObjectNo: stuffSearch?.schObjectNo ? stuffSearch.schObjectNo : objectNo,
schAddress: stuffSearch?.schAddress ? stuffSearch.schAddress : address,
schObjectName: stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName,
schSaleStoreName: stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName,
schReceiveUser: stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser,
schDispCompanyName: stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName,
schDateType: stuffSearch?.schDateType ? stuffSearch.schDateType : dateType,
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
schToDt: dayjs(endDate).format('YYYY-MM-DD'),
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',
selObject: {
label: stuffSearch.selObject.label,
value: stuffSearch.selObject.value,
},
})
if (stuffSearch.code === 'S') {
setStuffSearch({
schObjectNo: objectNo ? objectNo : stuffSearch?.schObjectNo,
schSaleStoreName: stuffSearch?.schSaleStoreName ? stuffSearch?.schSaleStoreName : saleStoreName,
schAddress: address ? address : stuffSearch?.schAddress,
schObjectName: objectName ? objectName : stuffSearch?.schObjectName,
schDispCompanyName: dispCompanyName ? dispCompanyName : stuffSearch?.schDispCompanyName,
schSelSaleStoreId: stuffSearch?.schSelSaleStoreId ? stuffSearch.schSelSaleStoreId : schSelSaleStoreId,
schReceiveUser: receiveUser ? receiveUser : stuffSearch?.schReceiveUser,
schDateType: stuffSearch?.schDateType ? stuffSearch.schDateType : dateType,
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
schToDt: dayjs(endDate).format('YYYY-MM-DD'),
code: 'E',
startRow: stuffSearch?.startRow ? stuffSearch.startRow : 1,
endRow: stuffSearch?.endRow ? stuffSearch.endRow : 100,
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
})
} else {
setStuffSearch({
schObjectNo: objectNo ? objectNo : '',
schSaleStoreName: saleStoreName ? saleStoreName : '',
schAddress: address ? address : '',
schObjectName: objectName ? objectName : '',
schDispCompanyName: dispCompanyName ? dispCompanyName : '',
schSelSaleStoreId: schSelSaleStoreId ? schSelSaleStoreId : '',
schReceiveUser: receiveUser ? receiveUser : '',
schDateType: dateType,
schFromDt: dayjs(startDate).format('YYYY-MM-DD'),
schToDt: dayjs(endDate).format('YYYY-MM-DD'),
code: 'E',
startRow: 1,
endRow: 100,
schSortType: stuffSearch?.schSortType ? stuffSearch.schSortType : 'R',
})
}
}
//
const resetRecoil = () => {
objectNoRef.current.value = ''
saleStoreNameRef.current.value = ''
addressRef.current.value = ''
objectNameRef.current.value = ''
dispCompanyNameRef.current.value = ''
receiveUserRef.current.value = ''
setObjectNo('')
setAddress('')
setobjectName('')
@ -99,9 +127,8 @@ export default function StuffSearchCondition() {
useEffect(() => {
if (isObjectNotEmpty(sessionState)) {
// console.log(' ::::::::', sessionState)
// storeId T01 1
// get({ url: `/api/object/saleStore/201TES01/list` }).then((res) => {
// get({ url: `/api/object/saleStore/TEMP02/list` }).then((res) => {
get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => {
if (!isEmptyArray(res)) {
res.map((row) => {
@ -129,7 +156,6 @@ export default function StuffSearchCondition() {
...stuffSearch,
code: 'S',
schSelSaleStoreId: key.saleStoreId,
selObject: { value: key.saleStoreId, label: key.saleStoreName },
})
} else {
setSchSelSaleStoreId('')
@ -150,6 +176,13 @@ export default function StuffSearchCondition() {
}
}, [globalLocaleState])
//
const handleByOnKeyUp = (e) => {
if (e.key === 'Enter') {
onSubmit()
}
}
return (
<>
{/* 퍼블적용시작 */}
@ -159,7 +192,7 @@ export default function StuffSearchCondition() {
<h3>{getMessage('stuff.search.title')}</h3>
</div>
<div className="left-unit-box">
<Link href="/management/stuff/tempdetail">
<Link href="/management/stuff/tempdetail" scroll={false}>
<button type="button" className="btn-origin navy mr5">
{getMessage('stuff.search.btn1')}
</button>
@ -189,13 +222,13 @@ export default function StuffSearchCondition() {
<div className="input-wrap">
<input
type="text"
ref={objectNoRef}
className="input-light"
// placeholder=" "
value={stuffSearch?.code === 'E' || stuffSearch?.code === 'M' ? stuffSearch.schObjectNo : objectNo}
defaultValue={stuffSearch.code === 'E' || stuffSearch.code === 'M' ? stuffSearch?.schObjectNo : objectNo}
onChange={(e) => {
setObjectNo(e.target.value)
setStuffSearch({ ...stuffSearch, code: 'S', schObjectNo: e.target.value })
setObjectNo(objectNoRef.current.value)
}}
onKeyUp={handleByOnKeyUp}
/>
</div>
</td>
@ -204,12 +237,11 @@ export default function StuffSearchCondition() {
<div className="input-wrap">
<input
type="text"
ref={saleStoreNameRef}
className="input-light"
// placeholder=" "
value={stuffSearch?.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName}
defaultValue={stuffSearch.code === 'E' ? stuffSearch?.schSaleStoreName : saleStoreName}
onChange={(e) => {
setSaleStoreName(e.target.value)
setStuffSearch({ ...stuffSearch, code: 'S', schSaleStoreName: e.target.value })
setSaleStoreName(saleStoreNameRef.current.value)
}}
/>
</div>
@ -219,12 +251,11 @@ export default function StuffSearchCondition() {
<div className="input-wrap">
<input
type="text"
ref={addressRef}
className="input-light"
// placeholder=" "
value={stuffSearch?.schAddress ? stuffSearch.schAddress : address}
defaultValue={stuffSearch.code === 'E' ? stuffSearch?.schAddress : address}
onChange={(e) => {
setAddress(e.target.value)
setStuffSearch({ ...stuffSearch, code: 'S', schAddress: e.target.value })
setAddress(addressRef.current.value)
}}
/>
</div>
@ -236,12 +267,11 @@ export default function StuffSearchCondition() {
<div className="input-wrap">
<input
type="text"
ref={objectNameRef}
className="input-light"
// placeholder=" "
value={stuffSearch?.schObjectName ? stuffSearch.schObjectName : objectName}
defaultValue={stuffSearch.code === 'E' ? stuffSearch?.schObjectName : objectName}
onChange={(e) => {
setobjectName(e.target.value)
setStuffSearch({ ...stuffSearch, code: 'S', schObjectName: e.target.value })
setobjectName(objectNameRef.current.value)
}}
/>
</div>
@ -251,30 +281,50 @@ export default function StuffSearchCondition() {
<div className="input-wrap">
<input
type="text"
ref={dispCompanyNameRef}
className="input-light"
// placeholder=" "
value={stuffSearch?.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName}
defaultValue={stuffSearch.code === 'E' ? stuffSearch?.schDispCompanyName : dispCompanyName}
onChange={(e) => {
setDispCompanyName(e.target.value)
setStuffSearch({ ...stuffSearch, code: 'S', schDispCompanyName: e.target.value })
setDispCompanyName(dispCompanyNameRef.current.value)
}}
/>
</div>
</td>
<th>{getMessage('stuff.search.schSelSaleStoreId')}</th>
<td>
{schSelSaleStoreList?.length > 0 && (
<Select
ref={ref}
options={schSelSaleStoreList}
onChange={onSelectionChange}
getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId}
defaultValue={stuffSearch?.selObject?.value ? stuffSearch?.selObject : null}
isDisabled={sessionState?.storeLvl === '1' ? false : true}
isClearable={true}
/>
)}
<div className="select-wrap">
{schSelSaleStoreList?.length > 0 && (
<Select
id="long-value-select1"
instanceId="long-value-select1"
className="react-select-custom"
classNamePrefix="custom"
placeholder="Select"
ref={ref}
options={schSelSaleStoreList}
onChange={onSelectionChange}
getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId}
value={schSelSaleStoreList.filter(function (option) {
if (stuffSearch?.code === 'S' && schSelSaleStoreId === '') {
return false
} else if (stuffSearch?.code === 'S' && schSelSaleStoreId !== '') {
return option.saleStoreId === schSelSaleStoreId
} else if (stuffSearch?.code === 'E' && schSelSaleStoreId !== '') {
return option.saleStoreId === schSelSaleStoreId
} else {
if (stuffSearch?.schSelSaleStoreId !== '') {
return option.saleStoreId === stuffSearch.schSelSaleStoreId
} else {
return false
}
}
})}
isDisabled={sessionState?.storeLvl === '1' ? false : true}
isClearable={true}
/>
)}
</div>
</td>
</tr>
<tr>
@ -284,11 +334,10 @@ export default function StuffSearchCondition() {
<input
type="text"
className="input-light"
// placeholder=" "
value={stuffSearch?.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser}
ref={receiveUserRef}
defaultValue={stuffSearch.code === 'E' ? stuffSearch?.schReceiveUser : receiveUser}
onChange={(e) => {
setReceiveUser(e.target.value)
setStuffSearch({ ...stuffSearch, code: 'S', schReceiveUser: e.target.value })
setReceiveUser(receiveUserRef.current.value)
}}
/>
</div>
@ -323,7 +372,7 @@ export default function StuffSearchCondition() {
setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
}}
/>
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}등록일</label>
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
</div>
</div>
<div className="date-picker-wrap">

View File

@ -79,7 +79,6 @@ export default function FindAddressPop(props) {
}
//
const applyAddress = () => {
// console.log(' :::::::::', prefId, address1, address2, address3, zipNo)
if (prefId == null) {
alert(getMessage('stuff.addressPopup.error.message2'))
} else {

View File

@ -1,6 +1,5 @@
import React, { useState, useRef, useEffect } from 'react'
import { useForm } from 'react-hook-form'
import { queryStringFormatter } from '@/util/common-utils'
import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom'
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
@ -12,14 +11,24 @@ import dayjs from 'dayjs'
import PlanRequestPopQGrid from './PlanRequestPopQGrid'
import { sessionStore } from '@/store/commonAtom'
import { planReqSearchState } from '@/store/planReqAtom'
import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
import Select from 'react-select'
import QPagination from '@/components/common/pagination/QPagination'
export default function PlanRequestPop(props) {
const sessionState = useRecoilValue(sessionStore)
const [pageNo, setPageNo] = useState(1) //
const [pageSize, setPageSize] = useState(20) //
const [totalCount, setTotalCount] = useState(0) //
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get } = useAxios(globalLocaleState)
const [planReqObject, setPlanReqObject] = useState({})
const { get, promiseGet } = useAxios(globalLocaleState)
const { getMessage } = useMessage()
//Select ref
const ref = useRef()
//
const [startDate, setStartDate] = useState(dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD'))
const [endDate, setEndDate] = useState(dayjs(new Date()).format('YYYY-MM-DD'))
@ -34,7 +43,6 @@ export default function PlanRequestPop(props) {
setStartDate: setEndDate,
}
const ref = useRef()
const resetPlanReqRecoil = useResetRecoilState(planReqSearchState)
const [planReqSearch, setPlanReqSearch] = useRecoilState(planReqSearchState)
@ -47,14 +55,41 @@ export default function PlanRequestPop(props) {
const [schDateGbn, setSchDateGbn] = useState('S') //(S/R)
//
const resetRecoil = () => {}
const resetRecoil = () => {
setSchPlanReqNo('')
setSchTitle('')
setSchAddress('')
setSchSaleStoreName('')
setSchPlanReqName('')
setSchDateGbn('S')
setStartDate(dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD'))
setEndDate(dayjs(new Date()).format('YYYY-MM-DD'))
setSchPlanStatCd('')
handleClear() //
resetPlanReqRecoil()
}
// ..
//
const handleClear = () => {
if (ref.current.state.dropDown) {
ref.current.methods.dropDown()
if (ref.current) {
ref.current.clearValue()
}
}
//
const onSelectionChange = (key) => {
//
// console.log('E::::::::', key)
if (isObjectNotEmpty(key)) {
setSchPlanStatCd(key.value)
setPlanReqSearch({
...planReqSearch,
schPlanStatCd: key.value,
})
} else {
ref.current.state.values = []
//X
setSchPlanStatCd('')
setPlanReqSearch({ ...planReqSearch, schPlanStatCd: '' })
}
}
@ -63,6 +98,60 @@ export default function PlanRequestPop(props) {
setEndDate(planReqSearch?.schEndDt ? planReqSearch.schEndDt : dayjs(new Date()).format('YYYY-MM-DD'))
}, [planReqSearch])
//
const onSubmit = (page, type) => {
const params = {
// saleStoreId: 'T100',
// saleStoreLevel: '1',
saleStoreId: props?.otherSaleStoreId ? props.otherSaleStoreId : props.saleStoreId,
saleStoreLevel: props?.otherSaleStoreLevel ? props.otherSaleStoreLevel : props.saleStoreLevel,
schPlanReqNo: planReqSearch?.schPlanReqNo ? planReqSearch.schPlanReqNo : schPlanReqNo,
schTitle: planReqSearch?.schTitle ? planReqSearch.schTitle : schTitle,
schAddress: planReqSearch?.schAddress ? planReqSearch.schAddress : schAddress,
schSaleStoreName: planReqSearch?.schSaleStoreName ? planReqSearch.schSaleStoreName : schSaleStoreName,
schPlanReqName: planReqSearch?.schPlanReqName ? planReqSearch.schPlanReqName : schPlanReqName,
schPlanStatCd: planReqSearch?.schPlanStatCd ? planReqSearch.schPlanStatCd : schPlanStatCd,
schDateGbn: planReqSearch?.schDateGbn ? planReqSearch.schDateGbn : schDateGbn,
schStartDt: dayjs(startDate).format('YYYY-MM-DD'),
schEndDt: dayjs(endDate).format('YYYY-MM-DD'),
startRow: type === 'S' ? (1 - 1) * pageSize + 1 : (page - 1) * pageSize + 1,
endRow: type === 'S' ? 1 * pageSize : page * pageSize,
}
if (type === 'S') {
setPageNo(1)
} else {
setPageNo(page)
}
// console.log(params)
const apiUrl = `/api/object/planReq/list?${queryStringFormatter(params)}`
promiseGet({ url: apiUrl }).then((res) => {
if (res.status === 200) {
if (isNotEmptyArray(res.data.data)) {
setGridProps({ ...gridProps, gridData: res.data.data, gridCount: res.data.data[0].totCnt })
setTotalCount(res.data.data[0].totCnt)
} else {
setGridProps({ ...gridProps, gridData: [], gridCount: 0 })
setTotalCount(0)
}
} else {
setGridProps({ ...gridProps, gridData: [], gridCount: 0 })
setTotalCount(0)
}
})
}
//
const handleChangePage = (page) => {
setPlanReqSearch({
...planReqSearch,
startRow: (page - 1) * pageSize + 1,
endRow: page * pageSize,
})
setPageNo(page)
onSubmit(page, 'P')
}
const [gridProps, setGridProps] = useState({
gridData: [],
isPageable: false,
@ -117,6 +206,45 @@ export default function PlanRequestPop(props) {
],
})
//
const getSelectedRowdata = (data) => {
if (isNotEmptyArray(data)) {
setPlanReqObject(data[0])
} else {
setPlanReqObject({})
}
}
//
const applyPlanReq = () => {
if (isObjectNotEmpty(planReqObject)) {
props.planReqInfo(planReqObject)
//
props.setShowDesignRequestButtonValid(false)
} else {
alert(getMessage('stuff.planReqPopup.error.message1'))
}
}
const tempList = [
{
label: '완료',
value: 'C',
},
{
label: '저장',
value: 'I',
},
{
label: '접수',
value: 'R',
},
{
label: '제출',
value: 'S',
},
]
return (
<div className="modal-popup">
<div className="modal-dialog big">
@ -132,8 +260,17 @@ export default function PlanRequestPop(props) {
<div className="design-tit-wrap">
<h3>{getMessage('stuff.planReqPopup.popTitle')}</h3>
<div className="design-search-wrap">
<button className="btn-origin grey mr5">{getMessage('stuff.planReqPopup.btn1')}</button>
<button className="btn-origin navy ">{getMessage('stuff.planReqPopup.btn2')}</button>
<button
className="btn-origin navy mr5"
onClick={() => {
onSubmit(pageNo, 'S')
}}
>
{getMessage('stuff.planReqPopup.btn1')}
</button>
<button className="btn-origin grey" onClick={resetRecoil}>
{getMessage('stuff.planReqPopup.btn2')}
</button>
</div>
</div>
<div className="design-request-table">
@ -224,12 +361,18 @@ export default function PlanRequestPop(props) {
<th>{getMessage('stuff.planReqPopup.search.planStatName')}</th>
<td>
<div className="select-wrap">
<select className="select-light" name="" id="">
<option value={''}>All</option>
<option value={'SAVE'}>저장</option>
<option value={'SUBMIT'}>제출</option>
<option value={'RECEIPT'}>접수</option>
</select>
<Select
id="long-value-select1"
instanceId="long-value-select1"
className="react-select-custom"
classNamePrefix="custom"
ref={ref}
options={tempList}
onChange={onSelectionChange}
isSearchable={false}
placeholder="Select"
isClearable={true}
/>
</div>
</td>
</tr>
@ -285,14 +428,19 @@ export default function PlanRequestPop(props) {
</div>
<div className="design-request-grid">
<div className="design-request-grid-tit">Plan List</div>
<PlanRequestPopQGrid {...gridProps} />
<PlanRequestPopQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} />
<div className="pagination-wrap">
<QPagination pageNo={pageNo} pageSize={pageSize} pagePerBlock={10} totalCount={totalCount} handleChangePage={handleChangePage} />
</div>
</div>
</div>
<div className="footer-btn-wrap">
<button className="btn-origin grey mr5" onClick={() => props.setShowDesignRequestButtonValid(false)}>
{getMessage('stuff.planReqPopup.btn3')}
</button>
<button className="btn-origin navy ">{getMessage('stuff.planReqPopup.btn4')}</button>
<button className="btn-origin navy" onClick={applyPlanReq}>
{getMessage('stuff.planReqPopup.btn4')}
</button>
</div>
</div>
</div>

View File

@ -39,8 +39,14 @@ export default function PlanRequestPopQGrid(props) {
[gridData],
)
//
const onSelectionChanged = () => {
const selectedData = gridApi.getSelectedRows()
props.getSelectedRowdata(selectedData)
}
return (
<div className="ag-theme-quartz" style={{ height: 500 }}>
<div className="ag-theme-quartz" style={{ height: 350 }}>
<AgGridReact
onGridReady={onGridReady}
rowBuffer={rowBuffer}
@ -49,7 +55,7 @@ export default function PlanRequestPopQGrid(props) {
defaultColDef={defaultColDef}
rowSelection={'singleRow'}
pagination={isPageable}
// onSelectionChanged={onSelectionChanged}
onSelectionChanged={onSelectionChanged}
/>
</div>
)

View File

@ -150,7 +150,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.userId')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={userId} readOnly />
<input type="text" className="input-light" value={userId || ''} readOnly />
</div>
</td>
</tr>
@ -158,7 +158,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.nameKana')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={info?.nameKana} readOnly />
<input type="text" className="input-light" value={info?.nameKana || ''} readOnly />
</div>
</td>
</tr>
@ -166,7 +166,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.name')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={info?.name} readOnly />
<input type="text" className="input-light" value={info?.name || ''} readOnly />
</div>
</td>
</tr>
@ -235,7 +235,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.category')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={info?.groupName} readOnly />
<input type="text" className="input-light" value={info?.groupName || ''} readOnly />
</div>
</td>
</tr>
@ -243,7 +243,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.tel')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={info?.tel} readOnly />
<input type="text" className="input-light" value={info?.tel || ''} readOnly />
</div>
</td>
</tr>
@ -251,7 +251,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.fax')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={info?.fax} readOnly />
<input type="text" className="input-light" value={info?.fax || ''} readOnly />
</div>
</td>
</tr>
@ -259,7 +259,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<th>{getMessage('myinfo.info.mail')}</th>
<td>
<div className="input-wrap">
<input type="text" className="input-light" value={info?.mail} readOnly />
<input type="text" className="input-light" value={info?.mail || ''} readOnly />
</div>
</td>
</tr>

View File

@ -4,14 +4,7 @@ import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { INPUT_TYPE, BATCH_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent'
import {
polygonToTurfPolygon,
rectToPolygon,
triangleToPolygon,
pointsToTurfPolygon,
splitDormerTriangle,
setSurfaceShapePattern,
} from '@/util/canvas-util'
import { polygonToTurfPolygon, rectToPolygon, triangleToPolygon, pointsToTurfPolygon, setSurfaceShapePattern } from '@/util/canvas-util'
import { useSwal } from '@/hooks/useSwal'
import * as turf from '@turf/turf'
import { QPolygon } from '@/components/fabric/QPolygon'
@ -211,11 +204,13 @@ export function useObjectBatch() {
const dormerName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER : BATCH_TYPE.PENTAGON_DORMER
const dormerTempName = buttonAct === 3 ? BATCH_TYPE.TRIANGLE_DORMER_TEMP : BATCH_TYPE.PENTAGON_DORMER_TEMP
const height = dormerPlacement.heightRef.current.value / 10
const width = dormerPlacement.widthRef.current.value / 10
const pitch = dormerPlacement.pitchRef.current.value
const directionRef = dormerPlacement.directionRef.current
const offsetRef = dormerPlacement.offsetRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetRef.current.value) / 10
const offsetWidthRef = dormerPlacement.offsetWidthRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetWidthRef.current.value) / 10
const directionRef = dormerPlacement.directionRef.current
let dormer, dormerOffset, isDown, selectedSurface
let dormer, dormerOffset, isDown, selectedSurface, pentagonPoints, pentagonOffsetPoints
console.log('dormerPlacement', dormerPlacement)
@ -229,8 +224,6 @@ export function useObjectBatch() {
const bottomLength = height / (pitch * 0.25)
const bottomOffsetLength = (height + offsetRef) / (pitch * 0.25)
console.log(bottomOffsetLength)
addCanvasMouseEventListener('mouse:move', (e) => {
isDown = true
if (!isDown) return
@ -305,16 +298,16 @@ export function useObjectBatch() {
addCanvasMouseEventListener('mouse:up', (e) => {
if (dormer) {
// const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer))
// const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer))
const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
// //지붕 밖으로 그렸을때
// if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) {
// swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
// //일단 지워
// deleteTempObjects()
// return
// }
//지붕 밖으로 그렸을때
if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) {
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
//일단 지워
deleteTempObjects()
return
}
//각도 추가
let originAngle = 0 //기본 남쪽
@ -387,6 +380,183 @@ export function useObjectBatch() {
drawDirectionArrow(leftTriangle)
drawDirectionArrow(rightTriangle)
isDown = false
initEvent()
}
})
} else if (buttonAct === 4) {
const heightLength = height - (width / 2) * (pitch * 0.25)
//(동의길이 깊이)+출폭(깊이)-[(입력한 폭값)/2+출폭(폭)]*(0.25*입력한 寸)
const heightOffsetLength = height + offsetRef - (width / 2 + offsetWidthRef) * (pitch * 0.25)
addCanvasMouseEventListener('mouse:move', (e) => {
isDown = true
if (!isDown) return
canvas?.remove(...canvas?.getObjects().filter((obj) => obj.name === dormerTempName)) //움직일때 일단 지워가면서 움직임
const pointer = canvas.getPointer(e.e)
surfaceShapePolygons.forEach((surface) => {
if (surface.inPolygon({ x: pointer.x, y: pointer.y })) {
selectedSurface = surface
}
})
let angle = 0
if (directionRef === 'left') {
//서
angle = 90
} else if (directionRef === 'right') {
//동
angle = 270
} else if (directionRef === 'up') {
//북
angle = 180
}
pentagonPoints = [
{ x: pointer.x, y: pointer.y },
{ x: pointer.x - width / 2, y: pointer.y + (height - heightLength) },
{ x: pointer.x - width / 2, y: pointer.y + height },
{ x: pointer.x + width / 2, y: pointer.y + height },
{ x: pointer.x + width / 2, y: pointer.y + (height - heightLength) },
]
pentagonOffsetPoints = [
{ x: pointer.x, y: pointer.y },
{ x: pointer.x - width / 2 - offsetWidthRef, y: pointer.y + height + offsetRef - heightOffsetLength },
{ x: pointer.x - width / 2 - offsetWidthRef, y: pointer.y + height + offsetRef },
{ x: pointer.x + width / 2 + offsetWidthRef, y: pointer.y + height + offsetRef },
{ x: pointer.x + width / 2 + offsetWidthRef, y: pointer.y + height + offsetRef - heightOffsetLength },
]
dormer = new QPolygon(pentagonPoints, {
fill: 'white',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
selectable: true,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: dormerTempName,
originX: 'center',
originY: 'top',
angle: angle,
})
canvas?.add(dormer)
if (offsetRef > 0 || offsetWidthRef > 0) {
dormerOffset = new QPolygon(pentagonOffsetPoints, {
fill: 'gray',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
selectable: true,
lockMovementX: true,
lockMovementY: true,
lockRotation: true,
lockScalingX: true,
lockScalingY: true,
name: dormerTempName,
originX: 'center',
originY: 'top',
angle: angle,
})
canvas?.add(dormerOffset)
}
})
addCanvasMouseEventListener('mouse:up', (e) => {
if (dormer) {
// const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer))
// const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
// //지붕 밖으로 그렸을때
// if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) {
// swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
// //일단 지워
// deleteTempObjects()
// return
// }
//각도 추가
let originAngle = 0 //기본 남쪽
let direction = 'south'
if (directionRef === 'left') {
//서
originAngle = 90
direction = 'west'
} else if (directionRef === 'right') {
//동
originAngle = 270
direction = 'east'
} else if (directionRef === 'up') {
//북
originAngle = 180
direction = 'north'
}
const offsetMode = offsetRef > 0 || offsetWidthRef > 0 ? 'offset' : 'normal'
let splitedPentagon =
offsetRef > 0 || offsetWidthRef > 0
? splitDormerPentagon(dormerOffset, directionRef, offsetMode)
: splitDormerPentagon(dormer, directionRef, offsetMode)
canvas?.remove(offsetRef > 0 || offsetWidthRef > 0 ? dormerOffset : dormer)
if (offsetRef > 0)
dormer.set({
name: dormerName,
stroke: 'black',
strokeWidth: 1,
strokeDashArray: [0],
}) //오프셋이 있을땐 같이 도머로 만든다
const leftPentagon = new QPolygon(splitedPentagon[0], {
fill: 'transparent',
stroke: 'red',
strokeWidth: 1,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
fontSize: 14,
direction: direction,
originX: 'center',
originY: 'center',
name: dormerName,
})
const rightPentagon = new QPolygon(splitedPentagon[1], {
fill: 'transparent',
stroke: 'red',
strokeWidth: 1,
selectable: true,
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
viewLengthText: true,
fontSize: 14,
direction: direction,
originX: 'center',
originY: 'center',
name: dormerName,
})
canvas?.add(leftPentagon)
canvas?.add(rightPentagon)
//패턴
setSurfaceShapePattern(leftPentagon)
setSurfaceShapePattern(rightPentagon)
//방향
drawDirectionArrow(leftPentagon)
drawDirectionArrow(rightPentagon)
isDown = false
initEvent()
}
@ -408,8 +578,140 @@ export function useObjectBatch() {
initEvent() //이벤트 초기화
}
const splitDormerTriangle = (triangle, direction) => {
const halfWidth = triangle.width / 2
let leftPoints = []
let rightPoints = []
if (direction === 'down') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - halfWidth, y: triangle.top + triangle.height },
{ x: triangle.left, y: triangle.top + triangle.height },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left, y: triangle.top + triangle.height },
{ x: triangle.left + halfWidth, y: triangle.top + triangle.height },
]
} else if (direction === 'up') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - halfWidth, y: triangle.top - triangle.height },
{ x: triangle.left, y: triangle.top - triangle.height },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left, y: triangle.top - triangle.height },
{ x: triangle.left + halfWidth, y: triangle.top - triangle.height },
]
} else if (direction === 'left') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - triangle.height, y: triangle.top - halfWidth },
{ x: triangle.left - triangle.height, y: triangle.top },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - triangle.height, y: triangle.top },
{ x: triangle.left - triangle.height, y: triangle.top + halfWidth },
]
} else if (direction === 'right') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top + triangle.height },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top - triangle.height },
]
}
return [leftPoints, rightPoints]
}
const splitDormerPentagon = (pentagon, direction, offsetMode) => {
const points = pentagon.points
console.log(pentagon.points)
let leftPoints = []
let rightPoints = []
if (direction === 'down') {
leftPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[1].x, y: points[1].y },
{ x: points[2].x, y: points[2].y },
{ x: points[0].x, y: points[3].y },
]
rightPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[0].x, y: points[2].y },
{ x: points[3].x, y: points[3].y },
{ x: points[4].x, y: points[4].y },
]
} else if (direction === 'up') {
leftPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[1].x, y: points[0].y - (points[1].y - points[0].y) },
{ x: points[2].x, y: points[0].y - (points[2].y - points[0].y) },
{ x: points[0].x, y: points[0].y - (points[2].y - points[0].y) },
]
rightPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[3].x, y: points[0].y - (points[1].y - points[0].y) },
{ x: points[3].x, y: points[0].y - (points[2].y - points[0].y) },
{ x: points[0].x, y: points[0].y - (points[2].y - points[0].y) },
]
} else if (direction === 'left') {
leftPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[0].x - (points[1].y - points[0].y), y: points[0].y - (points[0].x - points[1].x) },
{ x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y - (points[0].x - points[1].x) },
{ x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y },
]
rightPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[0].x - (points[1].y - points[0].y), y: points[0].y + (points[0].x - points[1].x) },
{ x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y + (points[0].x - points[1].x) },
{ x: points[0].x - (points[1].y - points[0].y) - (points[2].y - points[1].y), y: points[0].y },
]
} else if (direction === 'right') {
leftPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[0].x + (points[1].y - points[0].y), y: points[0].y + (points[0].x - points[1].x) },
{ x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y + (points[0].x - points[1].x) },
{ x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y },
]
rightPoints = [
{ x: points[0].x, y: points[0].y },
{ x: points[0].x + (points[1].y - points[0].y), y: points[0].y - (points[0].x - points[1].x) },
{ x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y - (points[0].x - points[1].x) },
{ x: points[0].x + (points[1].y - points[0].y) + (points[2].y - points[1].y), y: points[0].y },
]
}
console.log(leftPoints, rightPoints)
return [leftPoints, rightPoints]
}
return {
applyOpeningAndShadow,
applyDormers,
splitDormerTriangle,
splitDormerPentagon,
}
}

View File

@ -0,0 +1,23 @@
import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { useEffect } from 'react'
import { settingModalFirstOptionsState } from '@/store/settingAtom'
export function useFirstOption() {
const canvas = useRecoilValue(canvasState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
useEffect(() => {
const option1 = settingModalFirstOptions.option1
canvas
.getObjects()
.filter((obj) => obj.name === '')
.forEach((obj) => {
obj.set({ visible: !obj.visible })
})
}, [settingModalFirstOptions])
return { settingModalFirstOptions, setSettingModalFirstOptions }
}

View File

@ -23,10 +23,11 @@ import {
outerLineLength2State,
outerLineTypeState,
} from '@/store/outerLineAtom'
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint, polygonToTurfPolygon } from '@/util/canvas-util'
import { fabric } from 'fabric'
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
import { useSwal } from '@/hooks/useSwal'
import { booleanPointInPolygon } from '@turf/turf'
// 보조선 작성
export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
@ -76,6 +77,8 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
useEffect(() => {
typeRef.current = type
clear()
addDocumentEventListener('keydown', document, keydown[type])
}, [type])
useEffect(() => {
@ -103,12 +106,8 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
}
}, [])
useEffect(() => {
clear()
addDocumentEventListener('keydown', document, keydown[type])
}, [type])
const clear = () => {
addCanvasMouseEventListener('mouse:move', mouseMove)
setLength1(0)
setLength2(0)
@ -459,8 +458,9 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
}
const mouseDown = (e) => {
addCanvasMouseEventListener('mouse:move', mouseMove)
canvas.renderAll()
const pointer = getIntersectMousePoint(e)
console.log(pointer)
mousePointerArr.current.push(pointer)
if (mousePointerArr.current.length === 2) {
@ -538,59 +538,66 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
// 보조선 절삭
const cutAuxiliary = (e) => {
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isFixed)
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine')
if (auxiliaryLines.length === 0) {
return
}
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
const allLines = [...auxiliaryLines]
roofBases.forEach((roofBase) => {
roofBase.lines.forEach((line) => {
allLines.push(line)
})
})
auxiliaryLines.forEach((line1) => {
auxiliaryLines.forEach((line2) => {
const lines = [line1, line2]
allLines.forEach((line2) => {
if (line1 === line2) {
return
}
const intersectionPoint = calculateIntersection(line1, line2)
if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) {
if (!intersectionPoint) {
return
}
roofAdsorptionPoints.current.push(intersectionPoint)
intersectionPoints.current.push(intersectionPoint)
lines.forEach((line) => {
const distance1 = distanceBetweenPoints({ x: line.x1, y: line.y1 }, intersectionPoint)
const distance2 = distanceBetweenPoints({ x: line.x2, y: line.y2 }, intersectionPoint)
if (distance1 === 0 || distance2 === 0) {
return
}
//historyLine에서 기존 line을 제거한다.
lineHistory.current = lineHistory.current.filter((history) => history !== line)
const distance1 = distanceBetweenPoints({ x: line1.x1, y: line1.y1 }, intersectionPoint)
const distance2 = distanceBetweenPoints({ x: line1.x2, y: line1.y2 }, intersectionPoint)
let newLine
if (distance1 === 0 || distance2 === 0) {
return
}
//historyLine에서 기존 line을 제거한다.
lineHistory.current = lineHistory.current.filter((history) => history !== line1)
if (distance1 >= distance2) {
newLine = addLine([line.x1, line.y1, intersectionPoint.x, intersectionPoint.y], {
stroke: 'black',
strokeWidth: 1,
selectable: false,
name: 'auxiliaryLine',
isFixed: true,
intersectionPoint,
})
} else {
newLine = addLine([line.x2, line.y2, intersectionPoint.x, intersectionPoint.y], {
stroke: 'black',
strokeWidth: 1,
selectable: false,
name: 'auxiliaryLine',
isFixed: true,
intersectionPoint,
})
}
lineHistory.current.push(newLine)
removeLine(line)
})
let newLine
if (distance1 >= distance2) {
newLine = addLine([line1.x1, line1.y1, intersectionPoint.x, intersectionPoint.y], {
stroke: 'black',
strokeWidth: 1,
selectable: false,
name: 'auxiliaryLine',
isFixed: true,
intersectionPoint,
})
} else {
newLine = addLine([line1.x2, line1.y2, intersectionPoint.x, intersectionPoint.y], {
stroke: 'black',
strokeWidth: 1,
selectable: false,
name: 'auxiliaryLine',
isFixed: true,
intersectionPoint,
})
}
lineHistory.current.push(newLine)
removeLine(line1)
})
})
addCanvasMouseEventListener('mouse:move', mouseMove)
@ -600,10 +607,15 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
* 일변전으로 돌아가기
*/
const handleRollback = () => {
const lastLine = lineHistory.current.pop()
mousePointerArr.current = []
canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'innerPoint'))
const innerPoint = canvas.getObjects().find((obj) => obj.name === 'innerPoint')
if (innerPoint) {
mousePointerArr.current = []
canvas.remove(innerPoint)
canvas.renderAll()
return
}
const lastLine = lineHistory.current.pop()
if (lastLine) {
roofAdsorptionPoints.current = roofAdsorptionPoints.current.filter(
(point) => point.x !== lastLine.intersectionPoint?.x && point.y !== lastLine.intersectionPoint?.y,
@ -621,10 +633,25 @@ export function useAuxiliaryDrawing(setShowAuxiliaryModal) {
return
}
const roofBases = canvas.getObjects().find((obj) => obj.name === 'roofBase')
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
const innerLines = [...lineHistory.current]
roofBases.innerLines = [...innerLines]
roofBases.forEach((roofBase) => {
const roofInnerLines = innerLines.filter((line) => {
const turfPolygon = polygonToTurfPolygon(roofBase)
// innerLines의 두 점이 모두 polygon 안에 있는지 확인
const inPolygon1 = booleanPointInPolygon([line.x1, line.y1], turfPolygon)
const inPolygon2 = booleanPointInPolygon([line.x2, line.y2], turfPolygon)
if (inPolygon1 && inPolygon2) {
line.attributes = { ...line.attributes, roofId: roofBase.id }
return true
}
})
roofBase.innerLines = [...roofInnerLines]
})
setShowAuxiliaryModal(false)
}

View File

@ -29,12 +29,20 @@ import {
} from '@/store/outerLineAtom'
import { calculateAngle } from '@/util/qpolygon-utils'
import { fabric } from 'fabric'
import { QLine } from '@/components/fabric/QLine'
import { outlineDisplaySelector } from '@/store/settingAtom'
//외벽선 그리기
export function useOuterLineWall(setShowOutlineModal) {
const canvas = useRecoilValue(canvasState)
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
useEvent()
const {
initEvent,
addCanvasMouseEventListener,
addDocumentEventListener,
removeAllMouseEventListeners,
removeAllDocumentEventListeners,
removeMouseEvent,
} = useEvent()
const { getIntersectMousePoint } = useMouse()
const { addLine, removeLine } = useLine()
const { tempGridMode } = useTempGrid()
@ -46,6 +54,8 @@ export function useOuterLineWall(setShowOutlineModal) {
const adsorptionRange = useRecoilValue(adsorptionRangeState)
const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격
const isOutlineDisplay = useRecoilValue(outlineDisplaySelector)
const length1Ref = useRef(null)
const length2Ref = useRef(null)
const angle1Ref = useRef(null)
@ -75,6 +85,9 @@ export function useOuterLineWall(setShowOutlineModal) {
addCanvasMouseEventListener('mouse:down', mouseDown)
clear()
return () => {
initEvent()
}
}, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval, tempGridMode])
useEffect(() => {
@ -215,11 +228,11 @@ export function useOuterLineWall(setShowOutlineModal) {
return
}
/*if (lastPoint.x === firstPoint.x && lastPoint.y === firstPoint.y) {
if (Math.abs(lastPoint.x - firstPoint.x) < 1 && Math.abs(lastPoint.y - firstPoint.y) < 1) {
return
}
if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
if (Math.abs(lastPoint.x - firstPoint.x) < 1 || Math.abs(lastPoint.y - firstPoint.y) < 1) {
let isAllRightAngle = true
const firstPoint = points[0]
@ -238,38 +251,30 @@ export function useOuterLineWall(setShowOutlineModal) {
if (isAllRightAngle) {
return
}
const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
const line = addLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
selectable: false,
name: 'helpGuideLine',
visible: isOutlineDisplay,
})
canvas?.add(line)
addLineText(line)
} else {
const guideLine1 = new QLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], {
const guideLine1 = addLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
strokeDashArray: [1, 1, 1],
name: 'helpGuideLine',
visible: isOutlineDisplay,
})
const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], {
const guideLine2 = addLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
strokeDashArray: [1, 1, 1],
name: 'helpGuideLine',
visible: isOutlineDisplay,
})
if (guideLine1.length > 0) {
canvas?.add(guideLine1)
addLineText(guideLine1)
}
canvas?.add(guideLine2)
addLineText(guideLine2)
}*/
}
}
}, [points])
@ -284,6 +289,7 @@ export function useOuterLineWall(setShowOutlineModal) {
y1: point1.y,
x2: point2.x,
y2: point2.y,
visible: isOutlineDisplay,
})
}

View File

@ -95,7 +95,11 @@ export function useRoofAllocationSetting(setShowRoofAllocationSettingModal) {
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
roofBases.forEach((roofBase) => {
splitPolygonWithLines(roofBase)
try {
splitPolygonWithLines(roofBase)
} catch (e) {
return
}
roofBase.innerLines.forEach((line) => {
canvas.remove(line)

View File

@ -33,6 +33,11 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod
const [type, setType] = useState(TYPES.EAVES)
const isFix = useRef(false)
const initLines = useRef([])
const [isLoading, setIsLoading] = useState(false)
const buttons = [
{ id: 1, name: getMessage('eaves'), type: TYPES.EAVES },
{ id: 2, name: getMessage('gable'), type: TYPES.GABLE },
@ -46,15 +51,20 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod
if (!outerLineFix || outerLines.length === 0) {
swalFire({ text: '외벽선이 없습니다.' })
setShowRoofShapePassivitySettingModal(false)
return
}
setIsLoading(true)
}, [])
useEffect(() => {
if (!isLoading) return
addCanvasMouseEventListener('mouse:down', mouseDown)
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
canvas.remove(wallLines)
canvas?.remove(...wallLines)
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
initLines.current = outerLines.map((line) => ({ ...line }))
outerLines.forEach((outerLine, idx) => {
if (idx === 0) {
currentLineRef.current = outerLine
@ -66,10 +76,11 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod
canvas?.renderAll()
return () => {
handleLineToPolygon()
canvas?.discardActiveObject()
initEvent()
}
}, [])
}, [isLoading])
useEffect(() => {
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
@ -166,6 +177,14 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod
}
const handleSave = () => {
isFix.current = true
handleLineToPolygon()
setShowRoofShapePassivitySettingModal(false)
}
const handleLineToPolygon = () => {
const roofBases = canvas.getObjects().filter((obj) => obj.name === 'roofBase')
const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine')
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
exceptObjs.forEach((obj) => {
@ -176,13 +195,28 @@ export function useRoofShapePassivitySetting(setShowRoofShapePassivitySettingMod
hideLine(line)
})
const wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' })
let wall
if (isFix.current) {
wall = addPolygonByLines(lines, { name: 'wallLine', fill: 'transparent', stroke: 'black' })
} else {
// 그냥 닫을 경우 처리
wall = addPolygonByLines([...initLines.current], { name: 'wallLine', fill: 'transparent', stroke: 'black' })
lines.forEach((line, idx) => {
line.attributes = initLines.current[idx].attributes
})
}
wall.lines = [...lines]
// 기존 그려진 지붕이 없다면
if (isFix.current) {
// 완료 한 경우에는 지붕까지 그려줌
const roof = drawRoofPolygon(wall)
}
const roof = drawRoofPolygon(wall)
canvas.renderAll()
setShowRoofShapePassivitySettingModal(false)
}
return { handleSave, handleConfirm, buttons, type, setType, TYPES, offsetRef, pitchRef, handleRollback }
}

View File

@ -244,8 +244,13 @@ export function useRoofShapeSetting(setShowRoofShapeSettingModal) {
}
}
// 기존 wallLine 제거
canvas?.remove(canvas.getObjects().filter((obj) => obj.name === 'wallLine'))
// 기존 wallLine, roofBase 제거
canvas
.getObjects()
.filter((obj) => obj.name === 'wallLine' || obj.name === 'roofBase')
.forEach((line) => {
canvas.remove(line)
})
const polygon = addPolygonByLines(outerLines, { name: 'wallLine' })
polygon.lines = [...outerLines]

View File

@ -1,4 +1,4 @@
import { canvasState } from '@/store/canvasAtom'
import { canvasState, currentObjectState } from '@/store/canvasAtom'
import { useRecoilValue } from 'recoil'
import { useEffect, useRef, useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
@ -21,6 +21,8 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) {
const arrow1Ref = useRef(null)
const arrow2Ref = useRef(null)
const currentObject = useRecoilValue(currentObjectState)
const [isLoading, setIsLoading] = useState(false)
const drawLine = (point1, point2, idx, direction = currentWallLineRef.current.direction) => {
@ -87,6 +89,7 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) {
if (!isLoading) {
return
}
canvas?.discardActiveObject()
removeOuterLineEditCircle()
addCanvasMouseEventListener('mouse:down', mouseDown)
if (type === TYPES.WALL_LINE_EDIT) {
@ -94,6 +97,20 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) {
}
}, [type])
useEffect(() => {
canvas
.getObjects()
.filter((obj) => obj.name === 'outerLine')
.forEach((line) => {
line.set({ stroke: 'black' })
})
if (currentObject?.name === 'outerLine') {
currentObject.set({ stroke: '#EA10AC' })
canvas.renderAll()
}
}, [currentObject])
const removeOuterLineEditCircle = () => {
canvas.remove(...canvas.getObjects().filter((obj) => obj.name === 'outerLineEditCircleStart' || obj.name === 'outerLineEditCircleEnd'))
}
@ -106,7 +123,6 @@ export function useWallLineOffsetSetting(setShowWallLineOffsetSettingModal) {
}
currentWallLineRef.current = e.target
console.log(currentWallLineRef.current.idx, currentWallLineRef.current.direction)
if (type === TYPES.WALL_LINE_EDIT) {
addCircleByLine(currentWallLineRef.current)
}

View File

@ -232,11 +232,11 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) {
return
}
/*if (lastPoint.x === firstPoint.x && lastPoint.y === firstPoint.y) {
if (Math.abs(lastPoint.x - firstPoint.x) < 1 && Math.abs(lastPoint.y - firstPoint.y) < 1) {
return
}
if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
if (Math.abs(lastPoint.x - firstPoint.x) < 1 || Math.abs(lastPoint.y - firstPoint.y) < 1) {
let isAllRightAngle = true
const firstPoint = points[0]
@ -255,38 +255,27 @@ export function usePlacementShapeDrawing(setShowPlaceShapeDrawingModal) {
if (isAllRightAngle) {
return
}
const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
const line = addLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
selectable: false,
name: 'helpGuideLine',
})
canvas?.add(line)
addLineText(line)
} else {
const guideLine1 = new QLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], {
const guideLine1 = addLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
strokeDashArray: [1, 1, 1],
name: 'helpGuideLine',
})
const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], {
const guideLine2 = addLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], {
stroke: 'grey',
strokeWidth: 1,
strokeDashArray: [1, 1, 1],
name: 'helpGuideLine',
})
if (guideLine1.length > 0) {
canvas?.add(guideLine1)
addLineText(guideLine1)
}
canvas?.add(guideLine2)
addLineText(guideLine2)
}*/
}
}
}, [points])

View File

@ -2,13 +2,14 @@ import { useRecoilState, useRecoilValue } from 'recoil'
import { adsorptionPointAddModeState, adsorptionPointModeState, adsorptionRangeState, canvasState } from '@/store/canvasAtom'
import { fabric } from 'fabric'
import { useMouse } from '@/hooks/useMouse'
import { gridDisplaySelector } from '@/store/settingAtom'
export function useAdsorptionPoint() {
const canvas = useRecoilValue(canvasState)
const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState)
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState)
const isGridDisplay = useRecoilValue(gridDisplaySelector)
const { getIntersectMousePoint } = useMouse()
const getAdsorptionPoints = () => {
@ -28,6 +29,7 @@ export function useAdsorptionPoint() {
y: pointer.y,
selectable: true,
name: 'adsorptionPoint',
visible: isGridDisplay,
})
canvas.add(adsorptionPoint)

View File

@ -40,59 +40,59 @@ export function useAxios(lang = '') {
// response 추가 로직
axios.interceptors.request.use(undefined, (error) => {})
const get = async ({ url }) => {
const get = async ({ url, option = {} }) => {
return await getInstances(url)
.get(url)
.get(url, option)
.then((res) => res.data)
.catch(console.error)
}
const promiseGet = async ({ url }) => {
return await getInstances(url).get(url)
const promiseGet = async ({ url, option = {} }) => {
return await getInstances(url).get(url, option)
}
const post = async ({ url, data }) => {
const post = async ({ url, data, option = {} }) => {
return await getInstances(url)
.post(url, data)
.post(url, data, option)
.then((res) => res.data)
.catch(console.error)
}
const promisePost = async ({ url, data }) => {
return await getInstances(url).post(url, data)
const promisePost = async ({ url, data, option = {} }) => {
return await getInstances(url).post(url, data, option)
}
const put = async ({ url, data }) => {
const put = async ({ url, data, option = {} }) => {
return await getInstances(url)
.put(url, data)
.put(url, data, option)
.then((res) => res.data)
.catch(console.error)
}
const promisePut = async ({ url, data }) => {
return await getInstances(url).put(url, data)
const promisePut = async ({ url, data, option = {} }) => {
return await getInstances(url).put(url, data, option)
}
const patch = async ({ url, data }) => {
const patch = async ({ url, data, option = {} }) => {
return await getInstances(url)
.patch(url, data)
.patch(url, data, option)
.then((res) => res.data)
.catch(console.error)
}
const promisePatch = async ({ url, data }) => {
return await getInstances(url).patch(url, data)
const promisePatch = async ({ url, data, option = {} }) => {
return await getInstances(url).patch(url, data, option)
}
const del = async ({ url }) => {
const del = async ({ url, option = {} }) => {
return await getInstances(url)
.delete(url)
.delete(url, option)
.then((res) => res.data)
.catch(console.error)
}
const promiseDel = async ({ url }) => {
return await getInstances(url).delete(url)
const promiseDel = async ({ url, option = {} }) => {
return await getInstances(url).delete(url, option)
}
return { get, promiseGet, post, promisePost, put, promisePut, patch, promisePatch, del, promiseDel }

View File

@ -2,10 +2,11 @@ import { useEffect, useRef } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState, canvasZoomState, currentMenuState, textModeState } from '@/store/canvasAtom'
import { fabric } from 'fabric'
import { calculateDistance, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint, polygonToTurfPolygon } 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)
@ -43,7 +44,6 @@ export function useEvent() {
//default Event 추가
addCanvasMouseEventListener('mouse:move', defaultMouseMoveEvent)
addCanvasMouseEventListener('mouse:out', defaultMouseOutEvent)
addDocumentEventListener('keydown', document, defaultKeyboardEvent)
addDocumentEventListener('contextmenu', document, defaultContextMenuEvent)
if (adsorptionPointAddMode) {
addCanvasMouseEventListener('mouse:down', adsorptionPointAddModeStateEvent)
@ -152,6 +152,17 @@ export function useEvent() {
}
}
try {
const helpGuideLines = canvas.getObjects().filter((obj) => obj.name === 'helpGuideLine')
if (helpGuideLines.length === 2) {
const guideIntersectionPoint = calculateIntersection(helpGuideLines[0], helpGuideLines[1])
if (guideIntersectionPoint && distanceBetweenPoints(guideIntersectionPoint, pointer) <= adsorptionRange) {
arrivalPoint = guideIntersectionPoint
}
}
} catch (e) {}
const horizontalLine = new fabric.Line([-1 * canvas.width, arrivalPoint.y, 2 * canvas.width, arrivalPoint.y], {
stroke: 'red',
strokeWidth: 1,

View File

@ -14,7 +14,7 @@ export const useLine = () => {
fontFamily: fontFamily,
})
if (line.length === 0) {
if (line.length < 1) {
return null
}

View File

@ -1,14 +1,17 @@
import { useEffect } from 'react'
import { useRecoilValue } from 'recoil'
import { appMessageStore } from '@/store/localeAtom'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
// import KO from '@/locales/ko.json'
// import JA from '@/locales/ja.json'
import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json'
const SESSION_STORAGE_MESSAGE_KEY = 'QCAST_MESSAGE_STORAGE'
export const useMessage = () => {
// const globalLocale = useRecoilValue(globalLocaleState)
const appMessageState = useRecoilValue(appMessageStore)
// const appMessageState = useRecoilValue(appMessageStore)
const globalLocale = useRecoilValue(globalLocaleStore)
const appMessageState = globalLocale === 'ko' ? KO : JA
const getMessage = (key, args = []) => {
// if (sessionStorage.getItem(SESSION_STORAGE_MESSAGE_KEY) === null) {

View File

@ -1,4 +1,4 @@
import { useState } from 'react'
import { useEffect, useState } from 'react'
/**
* 페이지네이션
@ -14,6 +14,10 @@ const usePagination = ({ pageNo = 1, pageSize = 10, pagePerBlock = 10, totalCoun
setCurrentPage(page)
}
useEffect(() => {
setCurrentPage(pageNo)
}, [pageNo])
const pageGroup = Math.floor((currentPage - 1) / pagePerBlock) + 1
const totalPages = Math.ceil(totalCount / pageSize)
const pages = Array.from({ length: totalPages }, (_, i) => i + 1)

View File

@ -1,14 +1,19 @@
import { useEffect, useState } from 'react'
import { useRecoilState } from 'recoil'
import { v4 as uuidv4 } from 'uuid'
import { canvasState, currentCanvasPlanState, initCanvasPlansState, plansState } from '@/store/canvasAtom'
import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage'
import { useSwal } from '@/hooks/useSwal'
export function usePlan() {
const [planNum, setPlanNum] = useState(0)
const [canvas, setCanvas] = useRecoilState(canvasState)
const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState)
const [plans, setPlans] = useRecoilState(plansState)
const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) // DB에 저장된 plan
const [plans, setPlans] = useRecoilState(plansState) // 전체 plan (DB에 저장된 plan + 저장 안된 새로운 plan)
const { swalFire } = useSwal()
const { getMessage } = useMessage()
const { get, promisePost, promisePut, promiseDel } = useAxios()
@ -72,6 +77,9 @@ export function usePlan() {
// }, 1000)
}
/**
* 현재 캔버스에 그려진 데이터를 추출
*/
const currentCanvasData = () => {
removeMouseLines()
return addCanvas()
@ -81,8 +89,7 @@ export function usePlan() {
* 실시간 캔버스 상태와 DB에 저장된 캔버스 상태를 비교하여 수정 여부를 판단
*/
const checkModifiedCanvasPlan = () => {
removeMouseLines()
const canvasStatus = addCanvas()
const canvasStatus = currentCanvasData()
const initPlanData = initCanvasPlans.find((plan) => plan.id === currentCanvasPlan.id)
if (!initPlanData) {
@ -90,15 +97,10 @@ export function usePlan() {
return JSON.parse(canvasStatus).objects.length > 0
} else {
// 저장된 캔버스
if (canvasStatus === initPlanData.canvasStatus) {
return false
} else {
// 각각 object들의 id 목록을 추출하여 비교
const canvasObjsIds = getObjectIds(JSON.parse(canvasStatus).objects)
const dbObjsIds = getObjectIds(JSON.parse(initPlanData.canvasStatus).objects)
return canvasObjsIds.length !== dbObjsIds.length || !canvasObjsIds.every((id, index) => id === dbObjsIds[index])
}
// 각각 object들의 id 목록을 추출하여 비교
const canvasObjsIds = getObjectIds(JSON.parse(canvasStatus).objects)
const dbObjsIds = getObjectIds(JSON.parse(initPlanData.canvasStatus).objects)
return canvasObjsIds.length !== dbObjsIds.length || !canvasObjsIds.every((id, index) => id === dbObjsIds[index])
}
}
const getObjectIds = (objects) => {
@ -112,9 +114,6 @@ export function usePlan() {
* DB에 저장된 데이터를 canvas에서 사용할 있도록 포맷화
*/
const dbToCanvasFormat = (cs) => {
// return JSON.stringify(cs.replace(/##/g, '"')) //.replace(/\\/g, ''))//.slice(1, -1))
// JSON.stringify()를 사용하면 "가 \"로 바뀐다. 따라서, JSON.stringify를 제거
// canvasToDbFormat()에서 \\의 상황을 없앴으므로 replace(/\\/g, '')를 제거
return cs.replace(/##/g, '"')
}
@ -122,92 +121,24 @@ export function usePlan() {
* canvas의 데이터를 DB에 저장할 있도록 포맷화
*/
const canvasToDbFormat = (cs) => {
// return JSON.stringify(cs).replace(/"/g, '##')
// addCanvas()에서 JSON.stringify()를 거쳐서 나오는데, 또 감싸버려서 \가 \\로 된다. 따라서, JSON.stringify를 제거
return cs.replace(/"/g, '##')
}
/**
* 페이지 캔버스를 저장하는 함수
*
* 1. 신규 저장 : POST
* param(body) : userId, objectNo, canvasStatus
* 2. 수정 저장 : PUT
* param(body) : id, canvasStatus
* 페이지 캔버스를 저장
*/
const saveCanvas = async (userId) => {
removeMouseLines()
const canvasStatus = addCanvas()
if (initCanvasPlans.some((plan) => plan.id === currentCanvasPlan.id)) {
// canvas 수정
const planData = {
id: currentCanvasPlan.id,
canvasStatus: canvasToDbFormat(canvasStatus),
}
return await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
swalFire({ text: getMessage('common.message.save') })
// console.log('[PUT] canvas-statuses res :::::::: %o', res)
setInitCanvasPlans((initCanvasPlans) =>
initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)),
)
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
// console.error('[PUT] canvas-statuses error :::::::: %o', error)
})
} else {
// canvas 신규 등록
const planData = {
userId: userId,
imageName: 'image_name', // api 필수항목이여서 임시로 넣음, 이후 삭제 필요
objectNo: currentCanvasPlan.objectNo,
canvasStatus: canvasToDbFormat(canvasStatus),
}
return await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
swalFire({ text: getMessage('common.message.save') })
// console.log('[POST] canvas-statuses response :::::::: %o', res)
setInitCanvasPlans((initCanvasPlans) => [
...initCanvasPlans,
{
id: res.data,
name: currentCanvasPlan.objectNo + '-' + res.data,
userId: userId,
canvasStatus: canvasStatus,
isNew: currentCanvasPlan.id,
},
])
setPlans((plans) =>
plans.map((plan) =>
plan.id === currentCanvasPlan.id
? {
...plan,
id: res.data,
name: currentCanvasPlan.objectNo + '-' + res.data,
userId: userId,
canvasStatus: canvasStatus,
isNew: currentCanvasPlan.id,
}
: plan,
),
)
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
// console.error('[POST] canvas-statuses res error :::::::: %o', error)
})
}
const canvasStatus = currentCanvasData()
initCanvasPlans.some((plan) => plan.id === currentCanvasPlan.id)
? await putCanvasStatus(canvasStatus)
: await postCanvasStatus(userId, canvasStatus)
}
/**
* objectNo에 해당하는 canvas 목록을 조회하는 함수
* objectNo에 해당하는 canvas 목록을 조회
*/
const getCanvasByObjectNo = async (userId, objectNo) => {
// console.log(`[GET] objectNo: ${objectNo} / userId: ${userId}`)
return get({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}/${userId}` }).then((res) =>
res.map((item) => ({
id: item.id,
@ -220,27 +151,193 @@ export function usePlan() {
}
/**
* id에 해당하는 canvas 데이터를 삭제하는 함수
* canvas 데이터를 추가
*/
const postCanvasStatus = async (userId, canvasStatus) => {
const planData = {
userId: userId,
imageName: 'image_name', // api 필수항목이여서 임시로 넣음, 이후 삭제 필요
objectNo: currentCanvasPlan.objectNo,
canvasStatus: canvasToDbFormat(canvasStatus),
}
await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
swalFire({ text: getMessage('plan.message.save') })
setInitCanvasPlans((initCanvasPlans) => [...initCanvasPlans, { id: res.data, canvasStatus: canvasStatus }])
setPlans((plans) =>
plans.map((plan) =>
plan.id === currentCanvasPlan.id
? {
...plan,
id: res.data,
name: currentCanvasPlan.objectNo + '-' + res.data,
canvasStatus: canvasStatus,
}
: plan,
),
)
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
})
}
/**
* id에 해당하는 canvas 데이터를 수정
*/
const putCanvasStatus = async (canvasStatus) => {
const planData = {
id: currentCanvasPlan.id,
canvasStatus: canvasToDbFormat(canvasStatus),
}
await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => {
swalFire({ text: getMessage('plan.message.save') })
setInitCanvasPlans((initCanvasPlans) =>
initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)),
)
setPlans((plans) => plans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)))
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
})
}
/**
* id에 해당하는 canvas 데이터를 삭제
*/
const delCanvasById = (id) => {
return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-id/${id}` })
}
/**
* objectNo에 해당하는 canvas 데이터들을 삭제하는 함수
* objectNo에 해당하는 canvas 데이터들을 삭제
*/
const delCanvasByObjectNo = (objectNo) => {
return promiseDel({ url: `/api/canvas-management/canvas-statuses/by-object/${objectNo}` })
}
/**
* plan 이동
* 현재 plan의 작업상태를 확인, 저장 이동
*/
const handleCurrentPlan = (userId, newCurrentId) => {
if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) {
swalFire({
text: `${currentCanvasPlan.name} ` + getMessage('plan.message.confirm.save'),
type: 'confirm',
confirmFn: async () => {
await saveCanvas(userId)
updateCurrentPlan(newCurrentId)
},
denyFn: () => {
updateCurrentPlan(newCurrentId)
},
})
} else {
updateCurrentPlan(newCurrentId)
}
}
}
const updateCurrentPlan = (newCurrentId) => {
setPlans((plans) =>
plans.map((plan) => {
return { ...plan, isCurrent: plan.id === newCurrentId }
}),
)
}
useEffect(() => {
setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null)
}, [plans])
/**
* 새로운 plan 생성
* 현재 plan의 데이터가 있을 경우 복제 여부를 확인
*/
const handleAddPlan = (userId, objectNo) => {
JSON.parse(currentCanvasData()).objects.length > 0
? swalFire({
text: `${currentCanvasPlan.name} ` + getMessage('plan.message.confirm.copy'),
type: 'confirm',
confirmFn: () => {
addPlan(userId, objectNo, currentCanvasData())
},
denyFn: () => {
addPlan(userId, objectNo)
},
})
: addPlan(userId, objectNo)
}
const addPlan = (userId, objectNo, canvasStatus = '') => {
const id = uuidv4()
const newPlan = {
id: id,
name: `Plan ${planNum + 1}`,
objectNo: objectNo,
userId: userId,
canvasStatus: canvasStatus,
}
setPlans([...plans, newPlan])
handleCurrentPlan(userId, id)
setPlanNum(planNum + 1)
}
/**
* plan 삭제
*/
const handleDeletePlan = (e, id) => {
e.stopPropagation() // 이벤트 버블링 방지
if (initCanvasPlans.some((plan) => plan.id === id)) {
delCanvasById(id)
.then((res) => {
swalFire({ text: getMessage('plan.message.delete') })
setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id))
setPlans((plans) => plans.filter((plan) => plan.id !== id))
})
.catch((error) => {
swalFire({ text: error.message, icon: 'error' })
})
} else {
setPlans((plans) => plans.filter((plan) => plan.id !== id))
swalFire({ text: getMessage('plan.message.delete') })
}
// 삭제 후 last 데이터에 포커싱
const lastPlan = plans.filter((plan) => plan.id !== id).at(-1)
if (!lastPlan) {
setPlanNum(0)
setCurrentCanvasPlan(null)
} else if (id !== lastPlan.id) {
updateCurrentPlan(lastPlan.id)
}
}
/**
* plan 조회
*/
const loadCanvasPlanData = (userId, objectNo) => {
getCanvasByObjectNo(userId, objectNo).then((res) => {
// console.log('canvas 목록 ', res)
if (res.length > 0) {
setInitCanvasPlans(res)
setPlans(res)
updateCurrentPlan(res.at(-1).id) // last 데이터에 포커싱
setPlanNum(res.length)
} else {
addPlan(userId, objectNo)
}
})
}
return {
canvas,
removeMouseLines,
currentCanvasData,
plans,
saveCanvas,
addCanvas,
checkModifiedCanvasPlan,
getCanvasByObjectNo,
delCanvasById,
handleCurrentPlan,
handleAddPlan,
handleDeletePlan,
loadCanvasPlanData,
}
}

View File

@ -1,11 +1,13 @@
import { canvasState, tempGridModeState } from '@/store/canvasAtom'
import { useRecoilState, useRecoilValue } from 'recoil'
import { gridColorState } from '@/store/gridAtom'
import { gridDisplaySelector } from '@/store/settingAtom'
export function useTempGrid() {
const canvas = useRecoilValue(canvasState)
const gridColor = useRecoilValue(gridColorState)
const [tempGridMode, setTempGridMode] = useRecoilState(tempGridModeState)
const isGridDisplay = useRecoilValue(gridDisplaySelector)
const tempGridModeStateLeftClickEvent = (e) => {
//임의 그리드 모드일 경우
let pointer = canvas.getPointer(e.e)
@ -22,6 +24,7 @@ export function useTempGrid() {
strokeDashArray: [5, 2],
opacity: 0.3,
direction: 'vertical',
visible: isGridDisplay,
name: 'tempGrid',
})
@ -48,6 +51,7 @@ export function useTempGrid() {
strokeDashArray: [5, 2],
opacity: 0.3,
name: 'tempGrid',
visible: isGridDisplay,
direction: 'horizontal',
})

View File

@ -1,18 +0,0 @@
'use client'
import { createI18nClient } from 'next-international/client'
export const { useI18n, useScopedI18n, I18nProviderClient, useChangeLocale, defineLocale, useCurrentLocale } = createI18nClient(
{
ko: () => import('./ko'),
ja: () => import('./ja'),
},
{
// Uncomment to set base path
// basePath: '/base',
// Uncomment to use custom segment name
// segmentName: 'locale',
// Uncomment to set fallback locale
// fallbackLocale: en,
},
)

View File

@ -1,90 +0,0 @@
console.log('Loaded JA')
export default {
hello: 'こんにちは',
welcome: 'こんにちは {name}!',
locale: '現在のロケールは {locale} です。',
common: {
require: '필수',
},
site: {
name: 'Q.CAST III',
sub_name: '태양광 발전 시스템 도면관리 사이트',
},
login: {
login: 'Login',
init_password: {
btn: '비밀번호 초기화',
title: '비밀번호 초기화',
sub_title: '비밀번호를 초기화할 아이디와 이메일 주소를 입력해 주세요.',
},
},
join: {
title: 'Q.CAST3 로그인ID 발행 신청',
sub1: {
title: '판매대리점 정보',
comment: '※ 등록되는 리셀러의 회사 이름을 입력하십시오. (2차점은 「○○판매주식회사(2차점××설비주식회사)」로 기입해 주세요.)',
storeQcastNm: '판매대리점명',
storeQcastNm_placeholder: '株式会社エネルギア・ソリューション・アンド・サービス2次店山口住機販売有限会社',
storeQcastNmKana: '판매대리점명 후리가나',
storeQcastNmKana_placeholder: 'カブシキガイシャエネルギア・ソリューション・アン',
postCd: '우편번호',
postCd_placeholder: '숫자 7자리',
addr: '주소',
addr_placeholder: '전각50자이내',
telNo: '전화번호',
telNo_placeholder: '00-0000-0000',
fax: 'FAX 번호',
fax_placeholder: '00-0000-0000',
},
sub2: {
title: '담당자 정보',
userNm: '담당자명',
userNmKana: '담당자명 후리가나',
userId: '신청 ID',
email: '이메일 주소',
telNo: '전화번호',
telNo_placeholder: '00-0000-0000',
fax: 'FAX 번호',
fax_placeholder: '00-0000-0000',
category: '부서명',
},
sub3: {
title: '견적서 제출용 회사정보',
qtCompNm: '회사명',
qtPostCd: '우편번호',
qtPostCd_placeholder: '숫자 7자리',
qtAddr: '주소',
qtAddr_placeholder: '전각50자이내',
qtEmail: '이메일 주소',
qtTelNo: '전화번호',
qtTelNo_placeholder: '00-0000-0000',
qtFax: 'FAX 번호',
qtFax_placeholder: '00-0000-0000',
},
btn: {
approval_request: 'ID 승인요청',
},
complete: {
title: 'Q.CAST3 로그인ID 발행신청 완료',
contents: '※ 신청한 ID가 승인되면, 담당자 정보에 입력한 이메일 주소로 로그인 관련 안내 메일이 전송됩니다.',
email_comment: '담당자 이메일 주소',
email: 'test@naver.com',
},
},
stuff: {
gridHeader: {
lastEditDatetime: '갱신일시',
objectNo: '물건번호',
planTotCnt: '플랜 수',
objectName: '물건명',
saleStoreId: '대리점ID',
saleStoreName: '대리점명',
address: '물건주소',
dispCompanyName: '견적처',
receiveUser: '담당자',
specDate: '사양확인',
createDatetime: '등록일',
},
},
}

View File

@ -253,6 +253,11 @@
"modal.placement.surface.setting.diagonal.length": "斜めの長さ",
"modal.color.picker.title": "色の設定",
"modal.color.picker.default.color": "基本色",
"plan.message.confirm.save": "PLAN을 저장하시겠습니까?",
"plan.message.confirm.copy": "PLAN을 복사하시겠습니까?",
"plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?",
"plan.message.save": "저장되었습니다.",
"plan.message.delete": "삭제되었습니다.",
"setting": "設定",
"common.message.no.data": "No data",
"common.message.no.dataDown": "ダウンロードするデータがありません",
@ -341,7 +346,7 @@
"common.message.writeToConfirm": "作成解除を実行しますか?",
"common.message.password.init.success": "パスワード [{0}] に初期化されました。",
"common.message.no.edit.save": "この文書は変更できません。",
"common.require": "필수",
"common.require": "必須",
"commons.west": "立つ",
"commons.east": "ドン",
"commons.south": "立つ",
@ -386,6 +391,7 @@
"myinfo.message.save": "パスワードが変更されました。",
"myinfo.message.password.error": "パスワードが間違っています。",
"login": "ログイン",
"login.auto.page.text": "自動ログイン中です。",
"login.id.save": "ID保存",
"login.id.placeholder": "IDを入力してください。",
"login.password.placeholder": "パスワードを入力してください。",
@ -503,6 +509,7 @@
"stuff.planReqPopup.search.period": "期間検索",
"stuff.planReqPopup.search.schDateGbnS": "提出日",
"stuff.planReqPopup.search.schDateGbnR": "受付日",
"stuff.planReqPopup.error.message1": "設計依頼を選択してください。",
"stuff.search.title": "物件状況",
"stuff.search.btn1": "物件登録",
"stuff.search.btn2": "照会",
@ -517,6 +524,11 @@
"stuff.search.period": "期間検索",
"stuff.search.schDateTypeU": "更新日",
"stuff.search.schDateTypeR": "登録日",
"stuff.search.grid.title": "商品リスト",
"stuff.search.grid.all": "全体",
"stuff.search.grid.selected": "選択",
"stuff.search.grid.schSortTypeR": "最近の登録日",
"stuff.search.grid.schSortTypeU": "最近の更新日",
"stuff.windSelectPopup.title": "風速選択",
"stuff.windSelectPopup.table.selected": "選択",
"stuff.windSelectPopup.table.windspeed": "風速",

View File

@ -1,91 +0,0 @@
console.log('Loaded KO')
export default {
hello: '안녕',
welcome: '안녕 {name}!',
locale: '현재 로케일은 {locale}입니다.',
common: {
require: '필수',
},
site: {
name: 'Q.CAST III',
sub_name: '태양광 발전 시스템 도면관리 사이트',
},
login: {
login: '로그인',
init_password: {
btn: '비밀번호 초기화',
title: '비밀번호 초기화',
sub_title: '비밀번호를 초기화할 아이디와 이메일 주소를 입력해 주세요.',
complete_message: '비밀번호가 초기화 되었습니다. 초기화된 비밀번호는 아이디와 같습니다.',
},
},
join: {
title: 'Q.CAST3 로그인ID 발행 신청',
sub1: {
title: '판매대리점 정보',
comment: '※ 등록되는 리셀러의 회사 이름을 입력하십시오. (2차점은 「○○판매주식회사(2차점××설비주식회사)」로 기입해 주세요.)',
storeQcastNm: '판매대리점명',
storeQcastNm_placeholder: '주식회사 에너지 기어 솔루션 앤 서비스 (2차점: 야마구치 주기 판매 유한회사)',
storeQcastNmKana: '판매대리점명 후리가나',
storeQcastNmKana_placeholder: '주식회사 에너지 기어 솔루션',
postCd: '우편번호',
postCd_placeholder: '숫자 7자리',
addr: '주소',
addr_placeholder: '전각50자이내',
telNo: '전화번호',
telNo_placeholder: '00-0000-0000',
fax: 'FAX 번호',
fax_placeholder: '00-0000-0000',
},
sub2: {
title: '담당자 정보',
userNm: '담당자명',
userNmKana: '담당자명 후리가나',
userId: '신청 ID',
email: '이메일 주소',
telNo: '전화번호',
telNo_placeholder: '00-0000-0000',
fax: 'FAX 번호',
fax_placeholder: '00-0000-0000',
category: '부서명',
},
sub3: {
title: '견적서 제출용 회사정보',
qtCompNm: '회사명',
qtPostCd: '우편번호',
qtPostCd_placeholder: '숫자 7자리',
qtAddr: '주소',
qtAddr_placeholder: '전각50자이내',
qtEmail: '이메일 주소',
qtTelNo: '전화번호',
qtTelNo_placeholder: '00-0000-0000',
qtFax: 'FAX 번호',
qtFax_placeholder: '00-0000-0000',
},
btn: {
approval_request: 'ID 승인요청',
},
complete: {
title: 'Q.CAST3 로그인ID 발행신청 완료',
contents: '※ 신청한 ID가 승인되면, 담당자 정보에 입력한 이메일 주소로 로그인 관련 안내 메일이 전송됩니다.',
email_comment: '담당자 이메일 주소',
email: 'test@naver.com',
},
},
stuff: {
gridHeader: {
lastEditDatetime: '갱신일시',
objectNo: '물건번호',
planTotCnt: '플랜 수',
objectName: '물건명',
saleStoreId: '대리점ID',
saleStoreName: '대리점명',
address: '물건주소',
dispCompanyName: '견적처',
receiveUser: '담당자',
specDate: '사양확인',
createDatetime: '등록일',
},
},
}

View File

@ -258,6 +258,11 @@
"modal.placement.surface.setting.diagonal.length": "대각선 길이",
"modal.color.picker.title": "색 설정",
"modal.color.picker.default.color": "기본색상",
"plan.message.confirm.save": "PLAN을 저장하시겠습니까?",
"plan.message.confirm.copy": "PLAN을 복사하시겠습니까?",
"plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?",
"plan.message.save": "저장되었습니다.",
"plan.message.delete": "삭제되었습니다.",
"setting": "설정",
"common.message.no.data": "No data",
"common.message.no.dataDown": "No data to download",
@ -391,6 +396,7 @@
"myinfo.message.save": "비밀번호가 변경되었습니다.",
"myinfo.message.password.error": "비밀번호가 틀렸습니다.",
"login": "로그인",
"login.auto.page.text": "자동로그인 중 입니다.",
"login.id.save": "ID Save",
"login.id.placeholder": "아이디를 입력해주세요.",
"login.password.placeholder": "비밀번호를 입력해주세요.",
@ -508,6 +514,7 @@
"stuff.planReqPopup.search.period": "기간검색",
"stuff.planReqPopup.search.schDateGbnS": "제출일",
"stuff.planReqPopup.search.schDateGbnR": "접수일",
"stuff.planReqPopup.error.message1": "설계의뢰를 선택해주세요.",
"stuff.search.title": "물건현황",
"stuff.search.btn1": "신규등록",
"stuff.search.btn2": "조회",
@ -522,6 +529,11 @@
"stuff.search.period": "기간검색",
"stuff.search.schDateTypeU": "갱신일",
"stuff.search.schDateTypeR": "등록일",
"stuff.search.grid.title": "물건목록",
"stuff.search.grid.all": "전체",
"stuff.search.grid.selected": "선택",
"stuff.search.grid.schSortTypeR": "최근 등록일",
"stuff.search.grid.schSortTypeU": "최근 갱신일",
"stuff.windSelectPopup.title": "풍속선택",
"stuff.windSelectPopup.table.selected": "선택",
"stuff.windSelectPopup.table.windspeed": "풍속",

View File

@ -1,14 +0,0 @@
import { createI18nServer } from 'next-international/server'
export const { getI18n, getScopedI18n, getCurrentLocale, getStaticParams } = createI18nServer(
{
ko: () => import('./ko'),
ja: () => import('./ja'),
},
{
// Uncomment to use custom segment name
// segmentName: 'locale',
// Uncomment to set fallback locale
// fallbackLocale: en,
},
)

View File

@ -289,3 +289,8 @@ export const canGridOptionSeletor = selector({
return points.length === 0 || outerLineFix
},
})
export const globalPitchState = atom({
key: 'globalPitch',
default: 4,
})

View File

@ -16,7 +16,7 @@ export const planReqSearchState = atom({
schStartDt: dayjs(new Date()).add(-3, 'month').format('YYYY-MM-DD'), //시작일
schEndDt: dayjs(new Date()).format('YYYY-MM-DD'), //종료일
startRow: 1,
endRow: 100,
endRow: 20,
},
dangerouslyAllowMutability: true,
})

View File

@ -15,12 +15,12 @@ export const settingModalFirstOptionsState = atom({
{ id: 9, column: 'totalDisplay', name: 'modal.canvas.setting.first.option.total', selected: false },
],
dimensionDisplay: [
{ id: 1, column: 'corridorDimension', name: 'modal.canvas.setting.first.option.corridor.dimension', selected: false },
{ id: 1, column: 'corridorDimension', name: 'modal.canvas.setting.first.option.corridor.dimension', selected: true },
{ id: 2, column: 'realDimension', name: 'modal.canvas.setting.first.option.real.dimension', selected: false },
{ id: 3, column: 'noneDimension', name: 'modal.canvas.setting.first.option.none.dimension', selected: false },
],
option2: [
{ id: 1, column: 'onlyBorder', name: 'modal.canvas.setting.first.option.border', selected: false },
{ id: 1, column: 'onlyBorder', name: 'modal.canvas.setting.first.option.border', selected: true },
{ id: 2, column: 'lineHatch', name: 'modal.canvas.setting.first.option.line', selected: false },
{ id: 3, column: 'allPainted', name: 'modal.canvas.setting.first.option.all', selected: false },
],
@ -57,3 +57,102 @@ export const settingModalGridOptionsState = atom({
],
dangerouslyAllowMutability: true,
})
// 디스플레이 설정 - 할당 표시
export const allocDisplaySelector = selector({
key: 'allocDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'allocDisplay').selected
},
})
// 디스플레이 설정 - 외벽선 표시
export const outlineDisplaySelector = selector({
key: 'outlineDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'outlineDisplay').selected
},
})
// 디스플레이 설정 - 그리드 표시
export const gridDisplaySelector = selector({
key: 'gridDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'gridDisplay').selected
},
})
// 디스플레이 설정 - 지붕선 표시
export const roofLineDisplaySelector = selector({
key: 'lineDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'lineDisplay').selected
},
})
// 디스플레이 설정 - 문자 표시
export const wordDisplaySelector = selector({
key: 'wordDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'wordDisplay').selected
},
})
// 디스플레이 설정 - 회로번호 표시
export const circuitNumDisplaySelector = selector({
key: 'circuitNumDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'circuitNumDisplay').selected
},
})
// 디스플레이 설정 - 흐름 방향 표시
export const flowDisplaySelector = selector({
key: 'flowDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'flowDisplay').selected
},
})
// 디스플레이 설정 - 가대 표시
export const trestleDisplaySelector = selector({
key: 'trestleDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'trestleDisplay').selected
},
})
// 디스플레이 설정 - 집계표 표시
export const totalDisplaySelector = selector({
key: 'totalDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'totalDisplay').selected
},
})
// 디스플레이 설정 - 치수 표시
export const corridorDimensionSelector = selector({
key: 'corridorDimensionSelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected)
},
})
// 디스플레이 설정 - 화면 표시
export const realDimensionSelector = selector({
key: 'realDimensionSelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected)
},
})

View File

@ -18,10 +18,6 @@ export const stuffSearchState = atom({
startRow: 1,
endRow: 100,
schSortType: 'R', //정렬조건 (R:최근등록일 U:최근수정일)
selObject: {
value: '',
label: '',
},
},
dangerouslyAllowMutability: true,
})

View File

@ -1629,7 +1629,7 @@ $alert-color: #101010;
min-height: 80px;
background-color: #fff;
}
}
// 치수선 설정
@ -1655,24 +1655,33 @@ $alert-color: #101010;
.form-box{
width: 100%;
background-color: #fff;
padding: 10px 0 20px;
padding: 10px 15px 20px;
.line-form{
position: relative;
width: 102px;
height: 40px;
display: flex;
flex-direction: column;
justify-content: flex-end;
min-width: 102px;
min-height: 40px;
margin: 0 auto;
border-left: 1px dashed #101010;
border-right: 1px dashed #101010;
.line-font-box{
&::before{
content: '';
position: absolute;
bottom: -3px;
bottom: 0px;
left: 0;
width: 100%;
text-align: center;
height: 40px;
border-left: 1px dashed #101010;
border-right: 1px dashed #101010;
}
.line-font-box{
.font{
display: block;
padding-bottom: 6px;
padding-bottom: 15px;
color: #101010;
text-align: center;
line-height: 1;
}
.line{
position: relative;
@ -1687,7 +1696,7 @@ $alert-color: #101010;
transform: translateY(-50%) rotate(45deg);
left: 1px;
width: 9px;
height: 9px;
height:+ 9px;
border: 1px solid;
border-color: inherit;
border-top: none;

View File

@ -228,11 +228,19 @@
margin-bottom: 20px;
}
.design-request-grid{
.design-request-grid-tit{
font-size: 13px;
font-weight: 600;
color: #101010;
margin-bottom: 15px;
.design-request-count{
display: flex;
align-items: center;
margin-bottom: 10px;
.design-request-grid-tit{
font-size: 13px;
font-weight: 600;
color: #101010;
}
.select-wrap{
margin-left: auto;
width: 80px;
}
}
}

View File

@ -8,8 +8,10 @@ export const handleFileDown = async (file) => {
const params = new URLSearchParams({
encodeFileNo: file.encodeFileNo,
})
const options = { responseType: 'blob' }
const apiUrl = `${url}?${params.toString()}`
await promiseGet({ url: apiUrl, responseType: 'blob' })
await promiseGet({ url: apiUrl, option: options })
.then((resultData) => {
if (resultData) {
const blob = new Blob([resultData.data], { type: resultData.headers['content-type'] || 'application/octet-stream' })
@ -25,7 +27,7 @@ export const handleFileDown = async (file) => {
}
})
.catch((error) => {
alert(error.response.data.message)
alert('File does not exist.')
})
}

View File

@ -744,67 +744,6 @@ export const polygonToTurfPolygon = (polygon) => {
)
}
export const splitDormerTriangle = (triangle, direction) => {
const halfWidth = triangle.width / 2
let leftPoints = []
let rightPoints = []
let leftPointOffset = []
let rightPointOffset = []
if (direction === 'down') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - halfWidth, y: triangle.top + triangle.height },
{ x: triangle.left, y: triangle.top + triangle.height },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left, y: triangle.top + triangle.height },
{ x: triangle.left + halfWidth, y: triangle.top + triangle.height },
]
} else if (direction === 'up') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - halfWidth, y: triangle.top - triangle.height },
{ x: triangle.left, y: triangle.top - triangle.height },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left, y: triangle.top - triangle.height },
{ x: triangle.left + halfWidth, y: triangle.top - triangle.height },
]
} else if (direction === 'left') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - triangle.height, y: triangle.top - halfWidth },
{ x: triangle.left - triangle.height, y: triangle.top },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left - triangle.height, y: triangle.top },
{ x: triangle.left - triangle.height, y: triangle.top + halfWidth },
]
} else if (direction === 'right') {
leftPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top + triangle.height },
]
rightPoints = [
{ x: triangle.left, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top },
{ x: triangle.left + triangle.height, y: triangle.top - triangle.height },
]
}
return [leftPoints, rightPoints]
}
export const triangleToPolygon = (triangle) => {
const points = []
const halfWidth = triangle.width / 2
@ -853,7 +792,7 @@ export function setSurfaceShapePattern(polygon) {
patternSourceCanvas.width = polygon.width * ratio
patternSourceCanvas.height = polygon.height * ratio
const ctx = patternSourceCanvas.getContext('2d')
const offset = roofStyle === 1 ? 0 : patternSize.width / 2
let offset = roofStyle === 1 ? 0 : patternSize.width / 2
const rows = Math.floor(patternSourceCanvas.height / patternSize.height)
const cols = Math.floor(patternSourceCanvas.width / patternSize.width)
@ -861,23 +800,46 @@ export function setSurfaceShapePattern(polygon) {
ctx.strokeStyle = 'green'
ctx.lineWidth = 0.4
for (let row = 0; row <= rows; row++) {
const y = row * patternSize.height
ctx.beginPath()
ctx.moveTo(0, y) // 선 시작점
ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점
ctx.stroke()
if (polygon.direction === 'east' || polygon.direction === 'west') {
offset = roofStyle === 1 ? 0 : patternSize.height / 2
for (let col = 0; col <= cols; col++) {
const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset)
const yStart = row * patternSize.height
const yEnd = yStart + patternSize.height
const x = col * patternSize.width
const yStart = 0
const yEnd = patternSourceCanvas.height
ctx.beginPath()
ctx.moveTo(x, yStart) // 선 시작점
ctx.lineTo(x, yEnd) // 선 끝점
ctx.stroke()
for (let row = 0; row <= rows; row++) {
const y = row * patternSize.height + (col % 2 === 0 ? 0 : offset)
const xStart = col * patternSize.width
const xEnd = xStart + patternSize.width
ctx.beginPath()
ctx.moveTo(xStart, y) // 선 시작점
ctx.lineTo(xEnd, y) // 선 끝점
ctx.stroke()
}
}
} else {
for (let row = 0; row <= rows; row++) {
const y = row * patternSize.height
ctx.beginPath()
ctx.moveTo(0, y) // 선 시작점
ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점
ctx.stroke()
for (let col = 0; col <= cols; col++) {
const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset)
const yStart = row * patternSize.height
const yEnd = yStart + patternSize.height
ctx.beginPath()
ctx.moveTo(x, yStart) // 선 시작점
ctx.lineTo(x, yEnd) // 선 끝점
ctx.stroke()
}
}
}

View File

@ -273,7 +273,7 @@
resolved "https://registry.npmjs.org/@bedrock-layout/use-stateful-ref/-/use-stateful-ref-1.4.1.tgz"
integrity sha512-4eKO2KdQEXcR5LI4QcxqlJykJUDQJWDeWYAukIn6sRQYoabcfI5kDl61PUi6FR6o8VFgQ8IEP7HleKqWlSe8SQ==
"@emotion/babel-plugin@^11.11.0", "@emotion/babel-plugin@^11.12.0":
"@emotion/babel-plugin@^11.12.0":
version "11.12.0"
resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2"
integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==
@ -290,7 +290,7 @@
source-map "^0.5.7"
stylis "4.2.0"
"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.0", "@emotion/cache@^11.4.0":
"@emotion/cache@^11.13.0", "@emotion/cache@^11.4.0":
version "11.13.1"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7"
integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==
@ -306,32 +306,11 @@
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b"
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
"@emotion/is-prop-valid@^1.2.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240"
integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==
dependencies:
"@emotion/memoize" "^0.9.0"
"@emotion/memoize@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
"@emotion/react@11.11.0":
version "11.11.0"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.0.tgz#408196b7ef8729d8ad08fc061b03b046d1460e02"
integrity sha512-ZSK3ZJsNkwfjT3JpDAWJZlrGD81Z3ytNDsxw1LKq1o+xkmO5pnWfr6gmCC8gHEFf3nSSX/09YrG67jybNPxSUw==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.11.0"
"@emotion/cache" "^11.11.0"
"@emotion/serialize" "^1.1.2"
"@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
"@emotion/utils" "^1.2.1"
"@emotion/weak-memoize" "^0.3.1"
hoist-non-react-statics "^3.3.1"
"@emotion/react@^11.8.1":
version "11.13.3"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.3.tgz#a69d0de2a23f5b48e0acf210416638010e4bd2e4"
@ -346,7 +325,7 @@
"@emotion/weak-memoize" "^0.4.0"
hoist-non-react-statics "^3.3.1"
"@emotion/serialize@^1.1.2", "@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.1":
"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.1":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.2.tgz#e1c1a2e90708d5d85d81ccaee2dfeb3cc0cccf7a"
integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==
@ -362,38 +341,21 @@
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c"
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
"@emotion/styled@11.11.0":
version "11.11.0"
resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346"
integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.11.0"
"@emotion/is-prop-valid" "^1.2.1"
"@emotion/serialize" "^1.1.2"
"@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
"@emotion/utils" "^1.2.1"
"@emotion/unitless@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745"
integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==
"@emotion/use-insertion-effect-with-fallbacks@^1.0.1", "@emotion/use-insertion-effect-with-fallbacks@^1.1.0":
"@emotion/use-insertion-effect-with-fallbacks@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf"
integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==
"@emotion/utils@^1.2.1", "@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1":
"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.1.tgz#b3adbb43de12ee2149541c4f1337d2eb7774f0ad"
integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==
"@emotion/weak-memoize@^0.3.1":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
"@emotion/weak-memoize@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6"
@ -5955,14 +5917,6 @@ react-draggable@^4.4.6:
clsx "^1.1.1"
prop-types "^15.8.1"
react-dropdown-select@^4.11.3:
version "4.11.3"
resolved "https://registry.yarnpkg.com/react-dropdown-select/-/react-dropdown-select-4.11.3.tgz#b23b8906f3bedc9d6a1a2125af936b34d4057158"
integrity sha512-/mOGSqqhmKsxxrmotLM+qn1Ss3nxGN6QnYusyQ7f0wizsWrc7ZmbcZhGRtwkJwpL6JYDQVTn19EYxJU1XfXrDA==
dependencies:
"@emotion/react" "11.11.0"
"@emotion/styled" "11.11.0"
react-hook-form@^7.53.0:
version "7.53.0"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.0.tgz#3cf70951bf41fa95207b34486203ebefbd3a05ab"