This commit is contained in:
hyojun.choi 2024-10-17 14:17:23 +09:00
commit dae4de6825
21 changed files with 558 additions and 221 deletions

View File

@ -137,6 +137,9 @@ export default function Playground() {
pageSize: 10, pageSize: 10,
pagePerBlock: 10, pagePerBlock: 10,
totalCount: 501, totalCount: 501,
handleChangePage: (page) => {
console.log('page', page)
},
} }
return ( return (

View File

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

View File

@ -16,8 +16,7 @@ import Cookies from 'js-cookie'
import { useSearchParams } from 'next/navigation' import { useSearchParams } from 'next/navigation'
export default function Login() { export default function Login() {
//////////////////////////////////////////////////////////////////////////////// //
//
const initParams = useSearchParams() const initParams = useSearchParams()
const autoLoginParam = initParams.get('autoLoginParam1') const autoLoginParam = initParams.get('autoLoginParam1')
useEffect(() => { useEffect(() => {
@ -26,45 +25,27 @@ export default function Login() {
} }
}, []) }, [])
const autoLoginProcess = async (autoLoginParam) => { const autoLoginProcess = async (autoLoginParam) => {
setSession({ await promisePost({ url: '/api/login/v1.0/user/login/autoLoginDecryptData', data: { loginId: autoLoginParam } })
userId: autoLoginParam, .then((res) => {
saleStoreId: null, if (res) {
name: null, if (res.data) {
mail: null, post({ url: '/api/login/v1.0/user', data: { loginId: res.data } }).then((response) => {
tel: null, if (response) {
storeId: 'TEMP02', const result = { ...response, storeLvl: response.groupId === '60000' ? '1' : '2', pwdInitYn: 'Y' }
userNm: 'ㅇㅇ6610', setSession(result)
userNmKana: '신규사용자 16610', setSessionState(result)
category: '인상6610', router.push('/')
telNo: '336610', } else {
fax: null, router.push('/login')
email: 't10t@naver.com', }
pwdInitYn: 'Y', })
storeLvl: '2', }
groupId: '70000', }
}) })
.catch((error) => {
setSessionState({ router.push('/login')
userId: autoLoginParam, })
saleStoreId: null,
name: null,
mail: null,
tel: null,
storeId: 'TEMP02',
userNm: 'ㅇㅇ6610',
userNmKana: '신규사용자 16610',
category: '인상6610',
telNo: '336610',
fax: null,
email: 't10t@naver.com',
pwdInitYn: 'Y',
storeLvl: '2',
groupId: '70000',
})
router.push('/')
} }
////////////////////////////////////////////////////////////////////////////////
const [userId, setUserId] = useState('') const [userId, setUserId] = useState('')
const [checkId, setCheckId] = useState('') const [checkId, setCheckId] = useState('')
@ -86,12 +67,14 @@ export default function Login() {
const [passwordReset, setPasswordReset] = useState(1) const [passwordReset, setPasswordReset] = useState(1)
const { promisePost, promisePatch } = useAxios(globalLocaleState) const { promisePost, promisePatch, post } = useAxios(globalLocaleState)
// login process // login process
const loginProcess = async (e) => { const loginProcess = async (e) => {
e.preventDefault() e.preventDefault()
const formData = new FormData(e.target) const formData = new FormData(e.target)
///////////////////////////////////////////////////////////
// //
setSession({ setSession({
userId: 'NEW016610', userId: 'NEW016610',
@ -110,7 +93,6 @@ export default function Login() {
storeLvl: '1', storeLvl: '1',
groupId: '60000', groupId: '60000',
}) })
setSessionState({ setSessionState({
userId: 'NEW016610', userId: 'NEW016610',
saleStoreId: null, saleStoreId: null,
@ -128,16 +110,14 @@ export default function Login() {
storeLvl: '1', storeLvl: '1',
groupId: '60000', groupId: '60000',
}) })
// ID SAVE ,
if (chkLoginId) { if (chkLoginId) {
Cookies.set('chkLoginId', formData.get('id'), { expires: 7 }) Cookies.set('chkLoginId', formData.get('id'), { expires: 7 })
} else { } else {
Cookies.remove('chkLoginId') Cookies.remove('chkLoginId')
} }
router.push('/') router.push('/')
// //
///////////////////////////////////////////////////////////
// - ** ** // - ** **
// const param = { // const param = {
@ -173,7 +153,6 @@ export default function Login() {
loginId: checkId, loginId: checkId,
email: checkEmail, email: checkEmail,
} }
await promisePatch({ await promisePatch({
url: '/api/login/v1.0/user/init-password', url: '/api/login/v1.0/user/init-password',
data: param, data: param,

View File

@ -1,36 +1,42 @@
import usePagination from '@/hooks/usePagination' import usePagination from '@/hooks/usePagination'
export default function QPagination(props) { export default function QPagination(props) {
const { currentPage, pageRange, changePage, totalPages } = usePagination(props) const { handleChangePage = () => {}, pagePerBlock = 10 } = props
const { currentPage, changePage, pageGroup, totalPages, pages, startPage, endPage, pageRange } = usePagination(props)
const handlePage = (page) => {
handleChangePage(page)
changePage(page)
}
return ( return (
<ol className="pagination"> <ol className="pagination">
<li className="page-item first"> <li className="page-item first">
<button onClick={() => changePage(1)}></button> <button onClick={() => handlePage(1)}></button>
</li> </li>
<li className="page-item prev"> <li className="page-item prev">
<button <button
onClick={() => { onClick={() => {
if (currentPage === 1) return if (currentPage === 1) return
changePage(currentPage - 1) handlePage(Math.max(1, (pageGroup - 2) * pagePerBlock + 1))
}} }}
></button> ></button>
</li> </li>
{pageRange.map((page) => ( {pageRange.map((page) => (
<li className={page === currentPage ? `page-item on` : `page-item`} key={page}> <li className={page === currentPage ? `page-item on` : `page-item`} key={page}>
<button onClick={() => changePage(page)}>{page}</button> <button onClick={() => handlePage(page)}>{page}</button>
</li> </li>
))} ))}
<li className="page-item next"> <li className="page-item next">
<button <button
onClick={() => { onClick={() => {
if (currentPage === totalPages) return if (currentPage === totalPages) return
changePage(currentPage + 1) handlePage(Math.max(1, pageGroup * pagePerBlock + 1))
}} }}
></button> ></button>
</li> </li>
<li className="page-item last"> <li className="page-item last">
<button onClick={() => changePage(totalPages)}></button> <button onClick={() => handlePage(totalPages)}></button>
</li> </li>
</ol> </ol>
) )

View File

@ -121,13 +121,13 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.on('modified', (e) => { this.on('modified', (e) => {
this.addLengthText() this.addLengthText()
if (this.arrow) { // if (this.arrow) {
drawDirectionArrow(this) // drawDirectionArrow(this)
} // }
}) })
this.on('selected', () => { this.on('selected', () => {
drawDirectionArrow(this) // drawDirectionArrow(this)
Object.keys(this.controls).forEach((controlKey) => { Object.keys(this.controls).forEach((controlKey) => {
if (controlKey !== 'ml' && controlKey !== 'mr') { if (controlKey !== 'ml' && controlKey !== 'mr') {
this.setControlVisible(controlKey, false) this.setControlVisible(controlKey, false)

View File

@ -1,9 +1,9 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useState } from 'react' import { useState } from 'react'
import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect' import PowerConditionalSelect from '@/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect'
import CircuitAllocation from '@/components/floor-plan/modal/circuitTrestle/step/CircuitAllocation' import CircuitAllocation from '@/components/floor-plan/modal/circuitTrestle/step/CircuitAllocation'
import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp' import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/withDraggable'
export default function CircuitTrestleSetting({ setShowCircuitTrestleSettingModal }) { export default function CircuitTrestleSetting({ setShowCircuitTrestleSettingModal }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()

View File

@ -1,13 +1,13 @@
'use client' 'use client'
import { useState, useRef } from 'react' import { useState, useRef, useEffect } from 'react'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { useObjectBatch } from '@/hooks/object/useObjectBatch' import { useObjectBatch } from '@/hooks/object/useObjectBatch'
import { POLYGON_TYPE } from '@/common/common'
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import OpenSpace from '@/components/floor-plan/modal/object/type/OpenSpace' import OpenSpace from '@/components/floor-plan/modal/object/type/OpenSpace'
import Shadow from '@/components/floor-plan/modal/object/type/Shadow' import Shadow from '@/components/floor-plan/modal/object/type/Shadow'
@ -19,7 +19,17 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const [buttonAct, setButtonAct] = useState(1) const [buttonAct, setButtonAct] = useState(1)
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { applyOpeningAndShadow } = useObjectBatch() const { applyOpeningAndShadow, applyDormers } = useObjectBatch()
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
//
useEffect(() => {
canvas.discardActiveObject()
surfaceShapePolygons.forEach((obj) => {
obj.set({ selectable: false })
})
}, [])
/** /**
* 개구배치, 그림자배치 * 개구배치, 그림자배치
@ -31,17 +41,28 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
isCrossRef: useRef(null), isCrossRef: useRef(null),
} }
const applyObject = () => { const dormerPlacement = {
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === 'surfaceShapeBatch') widthRef: useRef(null),
heightRef: useRef(null),
pitchRef: useRef(null),
offsetRef: useRef(null),
directionRef: useRef(null),
}
if (surfaceShapePolygons.length === 0) { const applyObject = () => {
swalFire({ text: '지붕이 없어요 지붕부터 그리세요', icon: 'error' }) // if (surfaceShapePolygons.length === 0) {
return // swalFire({ text: ' ', icon: 'error' })
} // return
// }
//, //,
console.log(surfaceShapePolygons)
if (buttonAct === 1 || buttonAct === 2) { if (buttonAct === 1 || buttonAct === 2) {
applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons, setShowObjectSettingModal) applyOpeningAndShadow(objectPlacement, buttonAct, surfaceShapePolygons)
} else {
applyDormers(dormerPlacement, buttonAct, surfaceShapePolygons)
} }
} }
@ -72,8 +93,8 @@ export default function ObjectSetting({ setShowObjectSettingModal }) {
<div className="setting-tit">{getMessage('setting')}</div> <div className="setting-tit">{getMessage('setting')}</div>
{buttonAct === 1 && <OpenSpace ref={objectPlacement} />} {buttonAct === 1 && <OpenSpace ref={objectPlacement} />}
{buttonAct === 2 && <Shadow ref={objectPlacement} />} {buttonAct === 2 && <Shadow ref={objectPlacement} />}
{buttonAct === 3 && <TriangleDormer />} {buttonAct === 3 && <TriangleDormer ref={dormerPlacement} />}
{buttonAct === 4 && <PentagonDormer />} {buttonAct === 4 && <PentagonDormer ref={dormerPlacement} />}
</div> </div>
<div className="grid-btn-wrap"> <div className="grid-btn-wrap">
<button <button

View File

@ -1,8 +1,18 @@
import Image from 'next/image' import Image from 'next/image'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { forwardRef, useState } from 'react'
export default function TriangleDormer() { const TriangleDormer = forwardRef((props, refs) => {
const { getMessage } = useMessage() 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 ( return (
<> <>
<div className="discrimination-box mb10"> <div className="discrimination-box mb10">
@ -18,7 +28,7 @@ export default function TriangleDormer() {
<div className="eaves-keraba-td"> <div className="eaves-keraba-td">
<div className="outline-form"> <div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}> <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={1500} />
</div> </div>
<span className="thin">mm</span> <span className="thin">mm</span>
</div> </div>
@ -29,7 +39,7 @@ export default function TriangleDormer() {
<div className="eaves-keraba-td"> <div className="eaves-keraba-td">
<div className="outline-form"> <div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}> <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> </div>
<span className="thin">mm</span> <span className="thin">mm</span>
</div> </div>
@ -40,7 +50,7 @@ export default function TriangleDormer() {
<div className="eaves-keraba-td"> <div className="eaves-keraba-td">
<div className="outline-form"> <div className="outline-form">
<div className="input-grid mr5" style={{ width: '60px' }}> <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> </div>
<span className="thin"></span> <span className="thin"></span>
</div> </div>
@ -58,13 +68,15 @@ export default function TriangleDormer() {
<span className="right">{getMessage('commons.east')}</span> <span className="right">{getMessage('commons.east')}</span>
<span className="bottom">{getMessage('commons.south')}</span> <span className="bottom">{getMessage('commons.south')}</span>
<span className="left">{getMessage('commons.west')}</span> <span className="left">{getMessage('commons.west')}</span>
<button className="plane-btn up"></button> <button className={`plane-btn up ${direction === 'up' ? ' act' : ''}`} value="up" onClick={getDirection}></button>
<button className="plane-btn right"></button> <button className={`plane-btn right ${direction === 'right' ? ' act' : ''}`} value="right" onClick={getDirection}></button>
<button className="plane-btn down act"></button> <button className={`plane-btn down ${direction === 'down' ? ' act' : ''}`} value="down" onClick={getDirection}></button>
<button className="plane-btn left"></button> <button className={`plane-btn left ${direction === 'left' ? ' act' : ''}`} value="left" onClick={getDirection}></button>
</div> </div>
</div> </div>
</div> </div>
</> </>
) )
} })
export default TriangleDormer

View File

@ -4,17 +4,29 @@ import { useEffect, useState, useRef } from 'react'
import Image from 'next/image' import Image from 'next/image'
import PlacementSurface from '@/components/floor-plan/modal/placementSurface/PlacementSurface' import PlacementSurface from '@/components/floor-plan/modal/placementSurface/PlacementSurface'
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSettingModal }) { export default function PlacementSurfaceSetting({ setShowPlacementSurfaceSettingModal }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [selectedType, setSelectedType] = useState() const [selectedType, setSelectedType] = useState()
const [rotate, setRotate] = useState(0) const [rotate, setRotate] = useState(0)
const [xInversion, setXInversion] = useState(false) const [xInversion, setXInversion] = useState(false)
const [yInversion, setYInversion] = useState(false) const [yInversion, setYInversion] = useState(false)
const canvas = useRecoilValue(canvasState)
const { applySurfaceShape } = useSurfaceShapeBatch() const { applySurfaceShape } = useSurfaceShapeBatch()
const surfaceShapePolygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
//
useEffect(() => {
surfaceShapePolygons.forEach((obj) => {
obj.set({ selectable: true })
})
}, [])
const surfaceRefs = { const surfaceRefs = {
length1: useRef(null), length1: useRef(null),
length2: useRef(null), length2: useRef(null),

View File

@ -15,6 +15,7 @@ import { convertNumberToPriceDecimal } from '@/util/common-utils'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import KO from '@/locales/ko.json' import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json' import JA from '@/locales/ja.json'
import QPagination from '../common/pagination/QPagination'
import '@/styles/grid.scss' import '@/styles/grid.scss'
import { sessionStore } from '@/store/commonAtom' import { sessionStore } from '@/store/commonAtom'
@ -24,9 +25,9 @@ export default function Stuff() {
const stuffSearchParams = useRecoilValue(stuffSearchState) const stuffSearchParams = useRecoilValue(stuffSearchState)
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState) const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [curPage, setCurPage] = useState(1) // const [pageNo, setPageNo] = useState(1) //
const [defaultSize, setDefaultSize] = useState(100) // const [pageSize, setPageSize] = useState(100) //
const [gridCount, setGridCount] = useState(0) // const [totalCount, setTotalCount] = useState(0) //
const [defaultSortType, setDefaultSortType] = useState('R') const [defaultSortType, setDefaultSortType] = useState('R')
const globalLocaleState = useRecoilValue(globalLocaleStore) const globalLocaleState = useRecoilValue(globalLocaleStore)
@ -62,10 +63,6 @@ export default function Stuff() {
const [gridProps, setGridProps] = useState({ const [gridProps, setGridProps] = useState({
gridData: [], gridData: [],
isPageable: false, 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: [ gridColumns: [
{ {
field: 'lastEditDatetime', field: 'lastEditDatetime',
@ -228,56 +225,42 @@ export default function Stuff() {
// //
useEffect(() => { useEffect(() => {
if (isObjectNotEmpty(sessionState)) { if (isObjectNotEmpty(sessionState)) {
// sessionState
if (stuffSearchParams?.code === 'S') { if (stuffSearchParams?.code === 'S') {
const params = { const params = {
schObjectNo: '', schObjectNo: stuffSearchParams?.schObjectNo,
schAddress: '', schAddress: stuffSearchParams?.schAddress,
schObjectName: '', schObjectName: stuffSearchParams?.schObjectName,
schSaleStoreName: '', schSaleStoreName: stuffSearchParams?.schSaleStoreName,
schReceiveUser: '', schReceiveUser: stuffSearchParams?.schReceiveUser,
schDispCompanyName: '', schDispCompanyName: stuffSearchParams?.schDispCompanyName,
schDateType: 'U', schDateType: stuffSearchParams.schDateType,
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
schToDt: dayjs(new Date()).format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
startRow: (curPage - 1) * defaultSize + 1, startRow: (pageNo - 1) * pageSize + 1,
endRow: curPage * defaultSize, endRow: pageNo * pageSize,
schSelSaleStoreId: '', schSelSaleStoreId: '',
schSortType: 'R', schSortType: stuffSearchParams.schSortType,
} }
async function fetchData() { async function fetchData() {
//api startRow, endRow // const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}`
// let startRow const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(params)}`
// 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({ await get({
url: apiUrl, url: apiUrl,
}).then((res) => { }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt) setTotalCount(res[0].totCnt)
} }
}) })
} }
fetchData() fetchData()
} else { } else {
//
const params = { const params = {
schObjectNo: '', schObjectNo: stuffSearchParams.schObjectNo,
schAddress: '', schAddress: '',
schObjectName: '', schObjectName: '',
schSaleStoreName: '', schSaleStoreName: '',
@ -286,30 +269,13 @@ export default function Stuff() {
schDateType: 'U', schDateType: 'U',
schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'), schFromDt: dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'),
schToDt: dayjs(new Date()).format('YYYY-MM-DD'), schToDt: dayjs(new Date()).format('YYYY-MM-DD'),
startRow: (curPage - 1) * defaultSize + 1, startRow: (pageNo - 1) * pageSize + 1,
endRow: curPage * defaultSize, endRow: pageNo * pageSize,
schSelSaleStoreId: '', schSelSaleStoreId: '',
schSortType: 'R', schSortType: 'R',
} }
async function fetchData() { 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)}` const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(params)}`
await get({ await get({
@ -317,34 +283,36 @@ export default function Stuff() {
}).then((res) => { }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt) setTotalCount(res[0].totCnt)
} }
}) })
} }
fetchData() fetchData()
} }
} }
}, [sessionState]) }, [pageNo, sessionState])
useEffect(() => { useEffect(() => {
if (stuffSearchParams?.code === 'E') { if (stuffSearchParams?.code === 'E') {
//console.log('::::::::', stuffSearchParams) //console.log('::::::::', stuffSearchParams, sessionState)
stuffSearchParams.startRow = (curPage - 1) * defaultSize + 1 // stuffSearchParams.startRow = (pageNo - 1) * pageSize + 1
stuffSearchParams.endRow = curPage * defaultSize // stuffSearchParams.endRow = pageNo * pageSize
stuffSearchParams.startRow = 1
stuffSearchParams.endRow = 1 * pageSize
stuffSearchParams.schSortType = defaultSortType stuffSearchParams.schSortType = defaultSortType
setPageNo(1)
async function fetchData() { async function fetchData() {
// console.log(' :::::::::::::', sessionState) const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` // const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}`
await get({ url: apiUrl }).then((res) => { await get({ url: apiUrl }).then((res) => {
// console.log(' API:::::::', res)
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt) setTotalCount(res[0].totCnt)
} else { } else {
setGridProps({ ...gridProps, gridData: [], count: 0 }) setGridProps({ ...gridProps, gridData: [], count: 0 })
setGridCount(0) setTotalCount(0)
} }
}) })
} }
@ -354,53 +322,58 @@ export default function Stuff() {
// //
const onChangePerPage = (e) => { const onChangePerPage = (e) => {
let startRow = (curPage - 1) * e.target.value + 1 let startRow = (1 - 1) * e.target.value + 1
stuffSearchParams.startRow = startRow stuffSearchParams.startRow = startRow
stuffSearchParams.endRow = curPage * e.target.value stuffSearchParams.endRow = 1 * e.target.value
setDefaultSize(e.target.value) setPageSize(e.target.value)
setStuffSearch({ setStuffSearch({
...stuffSearch, ...stuffSearch,
code: 'S', code: 'S',
startRow: startRow, startRow: startRow,
endRow: curPage * e.target.value, endRow: 1 * e.target.value,
}) })
// console.log(' :::', stuffSearchParams)
// console.log(' sessionState:::', sessionState) setPageNo(1)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` // const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${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)}`
get({ url: apiUrl }).then((res) => { get({ url: apiUrl }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt) setTotalCount(res[0].totCnt)
} else { } else {
setGridProps({ ...gridProps, gridData: [], count: 0 }) setGridProps({ ...gridProps, gridData: [], count: 0 })
setGridCount(0) setTotalCount(0)
} }
}) })
} }
// //
const onChangeSortType = (e) => { const onChangeSortType = (e) => {
let startRow = (1 - 1) * pageSize + 1
stuffSearchParams.startRow = startRow
stuffSearchParams.endRow = 1 * pageSize
stuffSearchParams.schSortType = e.target.value stuffSearchParams.schSortType = e.target.value
// console.log(' :::', stuffSearchParams)
setDefaultSortType(e.target.value) setDefaultSortType(e.target.value)
setStuffSearch({ setStuffSearch({
...stuffSearch, ...stuffSearch,
code: 'S', code: 'S',
startRow: startRow,
endRow: 1 * pageSize,
schSortType: e.target.value, schSortType: e.target.value,
}) })
// console.log(' ::::::::::::', sessionState)
// const apiUrl = `/api/object/list?saleStoreId=201TES01&${queryStringFormatter(stuffSearchParams)}` setPageNo(1)
// const apiUrl = `/api/object/list?saleStoreId=X167&${queryStringFormatter(stuffSearchParams)}`
const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}` const apiUrl = `/api/object/list?saleStoreId=T01&${queryStringFormatter(stuffSearchParams)}`
// const apiUrl = `/api/object/list?saleStoreId=${sessionState?.storeId}&${queryStringFormatter(stuffSearchParams)}`
get({ url: apiUrl }).then((res) => { get({ url: apiUrl }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt }) setGridProps({ ...gridProps, gridData: res, count: res[0].totCnt })
setGridCount(res[0].totCnt) setTotalCount(res[0].totCnt)
} else { } else {
setGridProps({ ...gridProps, gridData: [], count: 0 }) setGridProps({ ...gridProps, gridData: [], count: 0 })
setGridCount(0) setTotalCount(0)
} }
}) })
} }
@ -413,6 +386,20 @@ export default function Stuff() {
} }
}, [globalLocaleState]) }, [globalLocaleState])
//
const handleChangePage = (page) => {
stuffSearchParams.code = 'S'
setStuffSearch({
...stuffSearch,
code: 'S',
startRow: (page - 1) * pageSize + 1,
endRow: page * pageSize,
})
setPageNo(page)
}
return ( return (
<> <>
{/* 퍼블시작 */} {/* 퍼블시작 */}
@ -423,7 +410,7 @@ export default function Stuff() {
<ul className="info-wrap"> <ul className="info-wrap">
<li> <li>
전체 전체
<span>{convertNumberToPriceDecimal(gridCount)}</span> <span>{convertNumberToPriceDecimal(totalCount)}</span>
</li> </li>
<li> <li>
선택 선택
@ -450,7 +437,9 @@ export default function Stuff() {
<div className="grid-table-wrap"> <div className="grid-table-wrap">
<div className="q-grid"> <div className="q-grid">
<StuffQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} getCellDoubleClicked={getCellDoubleClicked} gridRef={gridRef} /> <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> </div>
</div> </div>

View File

@ -488,7 +488,7 @@ export default function StuffDetail() {
</tr> </tr>
<tr> <tr>
<th> <th>
물건구분/물건명 <span className="important">*</span> {getMessage('stuff.detail.objectStatusId')} <span className="important">*</span>
</th> </th>
<td> <td>
<div className="flx-box"> <div className="flx-box">
@ -529,7 +529,9 @@ export default function StuffDetail() {
{getMessage('stuff.detail.saleStoreId')} {getMessage('stuff.detail.saleStoreId')}
<span className="important">*</span> <span className="important">*</span>
</div> </div>
<div className="tooltips"></div> <div className="tooltips">
<span>{getMessage('stuff.detail.tooltip.saleStoreId')}</span>
</div>
</div> </div>
</th> </th>
<td> <td>
@ -553,7 +555,9 @@ export default function StuffDetail() {
<th> <th>
<div className="flx-box"> <div className="flx-box">
<div className="title">{getMessage('stuff.detail.otherSaleStoreId')}</div> <div className="title">{getMessage('stuff.detail.otherSaleStoreId')}</div>
<div className="tooltips"></div> <div className="tooltips">
<span>{getMessage('stuff.detail.tooltip.saleStoreId')}</span>
</div>
</div> </div>
</th> </th>
<td> <td>
@ -568,18 +572,6 @@ export default function StuffDetail() {
isDisabled={form.watch('saleStoreId') !== '' ? false : true} isDisabled={form.watch('saleStoreId') !== '' ? false : true}
isClearable={true} isClearable={true}
/> />
{/* <Select
options={otherSaleStoreList}
value={form.watch('otherSaleStoreId')}
labelField="saleStoreName"
valueField="saleStoreId"
searchBy="saleStoreName"
clearable={true}
onChange={onSelectionChange2}
disabled={form.watch('saleStoreId') !== '' ? false : true}
onClearAll={handleClear}
ref={ref}
></Select> */}
</div> </div>
<div className="input-wrap" style={{ width: '216px' }}> <div className="input-wrap" style={{ width: '216px' }}>
<input <input
@ -662,7 +654,7 @@ export default function StuffDetail() {
</th> </th>
<td> <td>
<div className="flx-box"> <div className="flx-box">
<div className="input-wrap mr5"> <div className="input-wrap mr10">
<input type="text" className="input-light" readOnly value={form.watch('windSpeed')} {...register('windSpeed')} /> <input type="text" className="input-light" readOnly value={form.watch('windSpeed')} {...register('windSpeed')} />
</div> </div>
{/* <div className="select-wrap mr10" style={{ width: '200px' }}> {/* <div className="select-wrap mr10" style={{ width: '200px' }}>

View File

@ -323,7 +323,7 @@ export default function StuffSearchCondition() {
setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value }) setStuffSearch({ ...stuffSearch, code: 'S', schDateType: e.target.value })
}} }}
/> />
<label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}등록일</label> <label htmlFor="radio_r">{getMessage('stuff.search.schDateTypeR')}</label>
</div> </div>
</div> </div>
<div className="date-picker-wrap"> <div className="date-picker-wrap">

View File

@ -31,10 +31,6 @@ export default function FindAddressPopGrid(props) {
gridData ? setRowData(gridData) : '' gridData ? setRowData(gridData) : ''
}, [gridData]) }, [gridData])
const rowSelection = useMemo(() => {
return { mode: 'singleRow', enableClickSelection: true }
}, [])
const onGridReady = useCallback( const onGridReady = useCallback(
(params) => { (params) => {
setGridApi(params.api) setGridApi(params.api)
@ -57,7 +53,7 @@ export default function FindAddressPopGrid(props) {
rowData={rowData} rowData={rowData}
columnDefs={colDefs} columnDefs={colDefs}
defaultColDef={defaultColDef} defaultColDef={defaultColDef}
rowSelection={rowSelection} rowSelection={'singleRow'}
pagination={isPageable} pagination={isPageable}
onSelectionChanged={onSelectionChanged} onSelectionChanged={onSelectionChanged}
/> />

View File

@ -31,10 +31,6 @@ export default function PlanRequestPopQGrid(props) {
gridData ? setRowData(gridData) : '' gridData ? setRowData(gridData) : ''
}, [gridData]) }, [gridData])
const rowSelection = useMemo(() => {
return { mode: 'singleRow', enableClickSelection: true }
}, [])
const onGridReady = useCallback( const onGridReady = useCallback(
(params) => { (params) => {
setGridApi(params.api) setGridApi(params.api)
@ -51,7 +47,7 @@ export default function PlanRequestPopQGrid(props) {
rowData={rowData} rowData={rowData}
columnDefs={colDefs} columnDefs={colDefs}
defaultColDef={defaultColDef} defaultColDef={defaultColDef}
rowSelection={rowSelection} rowSelection={'singleRow'}
pagination={isPageable} pagination={isPageable}
// onSelectionChanged={onSelectionChanged} // onSelectionChanged={onSelectionChanged}
/> />

View File

@ -8,7 +8,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
const { getMessage } = useMessage() const { getMessage } = useMessage()
// api // api
const { get, promisePatch } = useAxios() const { get, promisePatch, promisePost } = useAxios()
const [info, setInfo] = useState({ const [info, setInfo] = useState({
userId: '', userId: '',
name: '', name: '',
@ -25,6 +25,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
const [showPwd, setShowPwd] = useState(false) const [showPwd, setShowPwd] = useState(false)
const [chkChgPwd, setChkChgPwd] = useState(false) const [chkChgPwd, setChkChgPwd] = useState(false)
const [chgPwd, setChgPwd] = useState('') const [chgPwd, setChgPwd] = useState('')
const pwdInput = useRef()
const chgPwdInput = useRef() const chgPwdInput = useRef()
useEffect(() => { useEffect(() => {
@ -54,7 +55,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
const handleChangePassword = async () => { const handleChangePassword = async () => {
if (chgPwd === '') { if (chgPwd === '') {
chgPwdInput.current.focus() chgPwdInput.current.focus()
return alert(getMessage('myinfo.message.validation.password1')) return alert(getMessage('myinfo.message.validation.password4'))
} }
if (password === chgPwd) { if (password === chgPwd) {
chgPwdInput.current.focus() chgPwdInput.current.focus()
@ -73,6 +74,8 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
if (res.data.result.resultCode === 'S') { if (res.data.result.resultCode === 'S') {
alert(getMessage('myinfo.message.save')) alert(getMessage('myinfo.message.save'))
setChkChgPwd(false) setChkChgPwd(false)
setPassword(chgPwd)
setChgPwd('')
} else { } else {
alert(res.data.result.resultMsg) alert(res.data.result.resultMsg)
} }
@ -83,6 +86,40 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
}) })
} }
// ,
const checkPasswordProcess = async (e) => {
if (password === '') {
pwdInput.current.focus()
return alert(getMessage('myinfo.message.validation.password1'))
}
const param = {
loginId: userId,
pwd: password,
}
await promisePost({ url: '/api/login/v1.0/login', data: param })
.then((res) => {
if (res) {
if (res.data.result.resultCode === 'S') {
setChkChgPwd(true)
setTimeout(() => {
chgPwdInput.current.focus()
}, 10)
} else {
alert(getMessage('myinfo.message.password.error'))
setChkChgPwd(false)
setChgPwd('')
setTimeout(() => {
pwdInput.current.focus()
}, 10)
}
}
})
.catch((error) => {
alert(error.response.data.message)
})
}
return ( return (
<> <>
<div className="modal-popup"> <div className="modal-popup">
@ -141,6 +178,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<input <input
type={`${showPwd ? 'text' : 'password'}`} type={`${showPwd ? 'text' : 'password'}`}
value={password} value={password}
ref={pwdInput}
onChange={(e) => { onChange={(e) => {
setPassword(e.target.value) setPassword(e.target.value)
}} }}
@ -151,11 +189,8 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
<button <button
className="btn-origin grey mr5" className="btn-origin grey mr5"
type="button" type="button"
onClick={() => { onClick={(e) => {
setChkChgPwd(true) checkPasswordProcess(e)
setTimeout(() => {
chgPwdInput.current.focus()
}, 10)
}} }}
> >
{getMessage('myinfo.btn.chg.password')} {getMessage('myinfo.btn.chg.password')}

View File

@ -4,9 +4,18 @@ import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { INPUT_TYPE, BATCH_TYPE } from '@/common/common' import { INPUT_TYPE, BATCH_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { polygonToTurfPolygon, rectToPolygon, pointsToTurfPolygon } from '@/util/canvas-util' import {
polygonToTurfPolygon,
rectToPolygon,
triangleToPolygon,
pointsToTurfPolygon,
splitDormerTriangle,
setSurfaceShapePattern,
} from '@/util/canvas-util'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import { QPolygon } from '@/components/fabric/QPolygon'
import { drawDirectionArrow } from '@/util/qpolygon-utils'
export function useObjectBatch() { export function useObjectBatch() {
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -14,11 +23,11 @@ export function useObjectBatch() {
const { addCanvasMouseEventListener, initEvent } = useEvent() const { addCanvasMouseEventListener, initEvent } = useEvent()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const applyOpeningAndShadow = (objectPlacement, buttonAct, surfaceShapePolygons, setShowObjectSettingModal) => { const applyOpeningAndShadow = (objectPlacement, buttonAct, surfaceShapePolygons) => {
const selectedType = objectPlacement.typeRef.current.find((radio) => radio.checked).value const selectedType = objectPlacement.typeRef.current.find((radio) => radio.checked).value
const isCrossChecked = buttonAct === 1 ? objectPlacement.isCrossRef.current.checked : false const isCrossChecked = buttonAct === 1 ? objectPlacement.isCrossRef.current.checked : false
const objTempName = buttonAct === 1 ? BATCH_TYPE.OPENING_TEMP : BATCH_TYPE.SHADOW_TEMP
const objName = buttonAct === 1 ? BATCH_TYPE.OPENING : BATCH_TYPE.SHADOW const objName = buttonAct === 1 ? BATCH_TYPE.OPENING : BATCH_TYPE.SHADOW
const objTempName = buttonAct === 1 ? BATCH_TYPE.OPENING_TEMP : BATCH_TYPE.SHADOW_TEMP
let rect, isDown, origX, origY let rect, isDown, origX, origY
let selectedSurface let selectedSurface
@ -94,7 +103,7 @@ export function useObjectBatch() {
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) { if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
//일단 지워 //일단 지워
deleteTempObjects(setShowObjectSettingModal) deleteTempObjects()
return return
} }
@ -105,7 +114,7 @@ export function useObjectBatch() {
if (isCross) { if (isCross) {
swalFire({ text: '겹치기 불가요...', icon: 'error' }) swalFire({ text: '겹치기 불가요...', icon: 'error' })
deleteTempObjects(setShowObjectSettingModal) deleteTempObjects()
return return
} }
} }
@ -173,7 +182,7 @@ export function useObjectBatch() {
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) { if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' }) swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
//일단 지워 //일단 지워
deleteTempObjects(setShowObjectSettingModal) deleteTempObjects()
return return
} }
@ -184,7 +193,7 @@ export function useObjectBatch() {
if (isCross) { if (isCross) {
swalFire({ text: '겹치기 불가요...', icon: 'error' }) swalFire({ text: '겹치기 불가요...', icon: 'error' })
deleteTempObjects(setShowObjectSettingModal) deleteTempObjects()
return return
} }
} }
@ -198,13 +207,209 @@ export function useObjectBatch() {
} }
} }
const deleteTempObjects = (setShowObjectSettingModal) => { const applyDormers = (dormerPlacement, buttonAct, surfaceShapePolygons) => {
const deleteTarget = canvas?.getObjects().filter((obj) => obj.name === BATCH_TYPE.OPENING_TEMP || obj.name === BATCH_TYPE.SHADOW_TEMP) 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 pitch = dormerPlacement.pitchRef.current.value
const directionRef = dormerPlacement.directionRef.current
const offsetRef = dormerPlacement.offsetRef.current.value === '' ? 0 : parseInt(dormerPlacement.offsetRef.current.value) / 10
let dormer, dormerOffset, isDown, selectedSurface
console.log('dormerPlacement', dormerPlacement)
if (height === '' || pitch === '' || height <= 0 || pitch <= 0) {
swalFire({ text: getMessage('common.canvas.validate.size'), icon: 'error' })
return
}
//삼각형 도머
if (buttonAct === 3) {
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
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
}
dormer = new fabric.Triangle({
fill: 'white',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
width: bottomLength * 2,
height: height,
left: pointer.x,
top: pointer.y,
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) {
dormerOffset = new fabric.Triangle({
fill: 'gray',
stroke: 'red',
strokeDashArray: [5, 5],
strokeWidth: 1,
width: bottomOffsetLength * 2,
height: height + offsetRef,
left: pointer.x,
top: pointer.y,
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'
}
let splitedTriangle = offsetRef > 0 ? splitDormerTriangle(dormerOffset, directionRef) : splitDormerTriangle(dormer, directionRef)
canvas?.remove(offsetRef > 0 ? dormerOffset : dormer)
if (offsetRef > 0)
dormer.set({
name: dormerName,
stroke: 'black',
strokeWidth: 1,
strokeDashArray: [0],
}) //오프셋이 있을땐 같이 도머로 만든다
const leftTriangle = new QPolygon(splitedTriangle[0], {
fill: 'transparent',
stroke: 'black',
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 rightTriangle = new QPolygon(splitedTriangle[1], {
fill: 'transparent',
stroke: 'black',
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(leftTriangle)
canvas?.add(rightTriangle)
//패턴
setSurfaceShapePattern(leftTriangle)
setSurfaceShapePattern(rightTriangle)
//방향
drawDirectionArrow(leftTriangle)
drawDirectionArrow(rightTriangle)
isDown = false
initEvent()
}
})
}
}
const deleteTempObjects = () => {
const deleteTarget = canvas
?.getObjects()
.filter(
(obj) =>
obj.name === BATCH_TYPE.OPENING_TEMP ||
obj.name === BATCH_TYPE.SHADOW_TEMP ||
obj.name === BATCH_TYPE.TRIANGLE_DORMER_TEMP ||
obj.name === BATCH_TYPE.PENTAGON_DORMER_TEMP,
)
canvas?.remove(...deleteTarget) canvas?.remove(...deleteTarget)
initEvent() //이벤트 초기화 initEvent() //이벤트 초기화
} }
return { return {
applyOpeningAndShadow, applyOpeningAndShadow,
applyDormers,
} }
} }

View File

@ -2,11 +2,10 @@
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { MENU, BATCH_TYPE } from '@/common/common' import { MENU, BATCH_TYPE, POLYGON_TYPE } from '@/common/common'
import { getIntersectionPoint, setSurfaceShapePattern } from '@/util/canvas-util' import { getIntersectionPoint, setSurfaceShapePattern } from '@/util/canvas-util'
import { degreesToRadians } from '@turf/turf' import { degreesToRadians } from '@turf/turf'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { fabric } from 'fabric'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
@ -116,7 +115,7 @@ export function useSurfaceShapeBatch() {
addCanvasMouseEventListener('mouse:down', (e) => { addCanvasMouseEventListener('mouse:down', (e) => {
isDrawing = false isDrawing = false
obj.set('name', MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH) obj.set('name', POLYGON_TYPE.ROOF)
initEvent() initEvent()
setSurfaceShapePattern(obj) setSurfaceShapePattern(obj)
setShowPlacementSurfaceSettingModal(true) setShowPlacementSurfaceSettingModal(true)
@ -567,19 +566,25 @@ export function useSurfaceShapeBatch() {
const deleteAllSurfacesAndObjects = () => { const deleteAllSurfacesAndObjects = () => {
swalFire({ swalFire({
text: '삭제 ㄱㄱ?', text: '배치면 내용을 전부 삭제하시겠습니까?',
type: 'confirm', type: 'confirm',
confirmFn: () => { confirmFn: () => {
canvas?.getObjects().forEach((obj) => { canvas?.getObjects().forEach((obj) => {
if (obj.name === MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH || obj.name === BATCH_TYPE.OPENING || obj.name === BATCH_TYPE.SHADOW) { if (
obj.name === POLYGON_TYPE.ROOF ||
obj.name === BATCH_TYPE.OPENING ||
obj.name === BATCH_TYPE.SHADOW ||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
obj.name === BATCH_TYPE.PENTAGON_DORMER
) {
canvas?.remove(obj) canvas?.remove(obj)
} }
}) })
swalFire({ text: '삭제 완료 되었습니다.' }) swalFire({ text: '삭제 완료 되었습니다.' })
}, },
denyFn: () => { // denyFn: () => {
swalFire({ text: '취소되었습니다.' }) // swalFire({ text: '취소되었습니다.', icon: 'error' })
}, // },
}) })
} }

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) setCurrentPage(page)
} }
useEffect(() => {
setCurrentPage(pageNo)
}, [pageNo])
const pageGroup = Math.floor((currentPage - 1) / pagePerBlock) + 1 const pageGroup = Math.floor((currentPage - 1) / pagePerBlock) + 1
const totalPages = Math.ceil(totalCount / pageSize) const totalPages = Math.ceil(totalCount / pageSize)
const pages = Array.from({ length: totalPages }, (_, i) => i + 1) const pages = Array.from({ length: totalPages }, (_, i) => i + 1)
@ -24,7 +28,7 @@ const usePagination = ({ pageNo = 1, pageSize = 10, pagePerBlock = 10, totalCoun
return i + startPage return i + startPage
}) })
return { currentPage, pageRange, changePage, totalPages } return { currentPage, changePage, pageGroup, totalPages, pages, startPage, endPage, pageRange }
} }
export default usePagination export default usePagination

View File

@ -376,7 +376,9 @@
"myinfo.message.validation.password1": "パスワードを入力してください。", "myinfo.message.validation.password1": "パスワードを入力してください。",
"myinfo.message.validation.password2": "既存のパスワードと同じです。", "myinfo.message.validation.password2": "既存のパスワードと同じです。",
"myinfo.message.validation.password3": "半角文字10文字以内で入力してください。", "myinfo.message.validation.password3": "半角文字10文字以内で入力してください。",
"myinfo.message.validation.password4": "変更パスワードを入力してください。",
"myinfo.message.save": "パスワードが変更されました。", "myinfo.message.save": "パスワードが変更されました。",
"myinfo.message.password.error": "パスワードが間違っています。",
"login": "ログイン", "login": "ログイン",
"login.id.save": "ID保存", "login.id.save": "ID保存",
"login.id.placeholder": "IDを入力してください。", "login.id.placeholder": "IDを入力してください。",
@ -471,6 +473,7 @@
"stuff.detail.conType0": "余剰", "stuff.detail.conType0": "余剰",
"stuff.detail.conType1": "全量", "stuff.detail.conType1": "全量",
"stuff.detail.remarks": "メモ", "stuff.detail.remarks": "メモ",
"stuff.detail.tooltip.saleStoreId": "販売代理店または販売代理店IDを1文字以上入力してください",
"stuff.planReqPopup.popTitle": "設計依頼検索", "stuff.planReqPopup.popTitle": "設計依頼検索",
"stuff.planReqPopup.btn1": "検索", "stuff.planReqPopup.btn1": "検索",
"stuff.planReqPopup.btn2": "初期化", "stuff.planReqPopup.btn2": "初期化",

View File

@ -381,7 +381,9 @@
"myinfo.message.validation.password1": "비밀번호를 입력하세요.", "myinfo.message.validation.password1": "비밀번호를 입력하세요.",
"myinfo.message.validation.password2": "기존 비밀번호와 동일합니다.", "myinfo.message.validation.password2": "기존 비밀번호와 동일합니다.",
"myinfo.message.validation.password3": "반각 문자 10자이내여야 합니다.", "myinfo.message.validation.password3": "반각 문자 10자이내여야 합니다.",
"myinfo.message.validation.password4": "변경 비밀번호를 입력하세요.",
"myinfo.message.save": "비밀번호가 변경되었습니다.", "myinfo.message.save": "비밀번호가 변경되었습니다.",
"myinfo.message.password.error": "비밀번호가 틀렸습니다.",
"login": "로그인", "login": "로그인",
"login.id.save": "ID Save", "login.id.save": "ID Save",
"login.id.placeholder": "아이디를 입력해주세요.", "login.id.placeholder": "아이디를 입력해주세요.",
@ -476,6 +478,7 @@
"stuff.detail.conType0": "잉여", "stuff.detail.conType0": "잉여",
"stuff.detail.conType1": "전량", "stuff.detail.conType1": "전량",
"stuff.detail.remarks": "메모", "stuff.detail.remarks": "메모",
"stuff.detail.tooltip.saleStoreId": "판매대리점 또는 판매대리점ID를 1자 이상 입력하세요",
"stuff.planReqPopup.popTitle": "설계 요청 검색", "stuff.planReqPopup.popTitle": "설계 요청 검색",
"stuff.planReqPopup.btn1": "검색", "stuff.planReqPopup.btn1": "검색",
"stuff.planReqPopup.btn2": "초기화", "stuff.planReqPopup.btn2": "초기화",

View File

@ -744,6 +744,79 @@ 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
const height = triangle.height
points.push({ x: triangle.left + halfWidth, y: triangle.top })
points.push({ x: triangle.left, y: triangle.top + height })
points.push({ x: triangle.left + triangle.width, y: triangle.top + height })
return points
}
export const rectToPolygon = (rect) => { export const rectToPolygon = (rect) => {
const points = [] const points = []
const left = rect.left const left = rect.left