# Conflicts:
#	src/components/common/select/QSelectBox.jsx
#	src/components/floor-plan/modal/placementShape/PlacementShapeSetting.jsx
This commit is contained in:
김민식 2024-12-26 09:39:30 +09:00
commit f5d374c443
24 changed files with 798 additions and 268 deletions

1
.gitignore vendored
View File

@ -41,3 +41,4 @@ next-env.d.ts
#lock files #lock files
yarn.lock yarn.lock
package-lock.json package-lock.json
certificates

View File

@ -6,7 +6,8 @@
"dev": "next dev", "dev": "next dev",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint",
"serve": "node server.js"
}, },
"dependencies": { "dependencies": {
"@nextui-org/react": "^2.4.2", "@nextui-org/react": "^2.4.2",
@ -21,7 +22,7 @@
"js-cookie": "^3.0.5", "js-cookie": "^3.0.5",
"mathjs": "^13.0.2", "mathjs": "^13.0.2",
"mssql": "^11.0.1", "mssql": "^11.0.1",
"next": "14.2.14", "next": "14.2.21",
"next-international": "^1.2.4", "next-international": "^1.2.4",
"react": "^18", "react": "^18",
"react-chartjs-2": "^5.2.0", "react-chartjs-2": "^5.2.0",

40
server.js Normal file
View File

@ -0,0 +1,40 @@
const http = require('http')
const { parse } = require('url')
const next = require('next')
const https = require('https')
const fs = require('fs')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
const PORT = 3000
const httpsOptions = {
key: fs.readFileSync('./certificates/key.pem'),
cert: fs.readFileSync('./certificates/cert.pem'),
}
app.prepare().then(() => {
http
.createServer((req, res) => {
const parsedUrl = parse(req.url, true)
handle(req, res, parsedUrl)
})
.listen(PORT, (err) => {
if (err) throw err
console.log(`> Ready on http://localhost:${PORT}`)
})
// https 서버 추가
https
.createServer(httpsOptions, (req, res) => {
const parsedUrl = parse(req.url, true)
handle(req, res, parsedUrl)
})
.listen(PORT + 1, (err) => {
if (err) throw err
console.log(`> HTTPS: Ready on https://localhost:${PORT + 1}`)
})
})

View File

@ -50,7 +50,6 @@ export default async function RootLayout({ children }) {
isLoggedIn: session.isLoggedIn, isLoggedIn: session.isLoggedIn,
} }
} }
if (!headerPathname.includes('/login') && !session.isLoggedIn) { if (!headerPathname.includes('/login') && !session.isLoggedIn) {
redirect('/login') redirect('/login')
} }

View File

@ -24,6 +24,7 @@ import QSelect from './common/select/QSelect'
import QPagination from './common/pagination/QPagination' import QPagination from './common/pagination/QPagination'
import { trestleRequestModels, constructionRequestModels, trestleDetailRequestModels } from '@/models/apiModels' import { trestleRequestModels, constructionRequestModels, trestleDetailRequestModels } from '@/models/apiModels'
import QSelectBox from './common/select/QSelectBox'
export default function Playground() { export default function Playground() {
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState) const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
@ -50,51 +51,8 @@ export default function Playground() {
const [users, setUsers] = useState([]) const [users, setUsers] = useState([])
const [trestleRequestData, setTrestleRequestData] = useState(trestleRequestModels)
const [constructionRequestData, setConstructionRequestData] = useState(constructionRequestModels)
const [trestleDetailRequestData, setTrestleDetailRequestData] = useState(trestleDetailRequestModels)
useEffect(() => { useEffect(() => {
console.log('textInput:', textInput) console.log('textInput:', textInput)
setTrestleRequestData({
moduleTpCd: '',
roofMatlCd: '',
raftBaseCd: '',
trestleMkrCd: '',
constMthdCd: '',
roofBaseCd: '',
})
setConstructionRequestData({
moduleTpCd: 'testData_1',
roofMatlCd: 'testData_2',
trestleMkrCd: 'testData_3',
constMthdCd: 'testData_4',
roofBaseCd: 'testData_5',
illuminationTp: 'testData_6',
instHt: 'testData_7',
stdWindSpeed: 'testData_8',
stdSnowLd: 'testData_9',
inclCd: 'testData_10',
raftBaseCd: 'testData_11',
roofPitch: 30,
})
setTrestleDetailRequestData({
moduleTpCd: 'testData_1',
roofMatlCd: 'testData_2',
trestleMkrCd: 'testData_3',
constMthdCd: 'testData_4',
roofBaseCd: 'testData_5',
illuminationTp: 'testData_6',
instHt: 'testData_7',
stdWindSpeed: 'testData_8',
stdSnowLd: 'testData_9',
inclCd: 'testData_10',
constTp: 'testData_11',
mixMatlNo: 10,
roofPitch: 20,
})
}, [textInput]) }, [textInput])
useEffect(() => { useEffect(() => {
console.log('numberInput:', numberInput) console.log('numberInput:', numberInput)
@ -199,6 +157,71 @@ export default function Playground() {
console.log('users:', users) console.log('users:', users)
}, [users]) }, [users])
const codes = [
{
clHeadCd: '203800',
clCode: 'HEI_455',
clCodeNm: '세로 455mm이하',
clPriority: 1,
name: '세로 455mm이하',
id: 'HEI_455',
},
{
clHeadCd: '203800',
clCode: 'HEI_500',
clCodeNm: '세로 500mm이하',
clPriority: 2,
name: '세로 500mm이하',
id: 'HEI_500',
},
{
clHeadCd: '203800',
clCode: 'HEI_606',
clCodeNm: '세로 606mm이하',
clPriority: 3,
name: '세로 606mm이하',
id: 'HEI_606',
},
{
clHeadCd: '203800',
clCode: 'WID_606',
clCodeNm: '가로 606mm이하',
clPriority: 4,
name: '가로 606mm이하',
id: 'WID_606',
},
{
clHeadCd: '203800',
clCode: 'ETC',
clCodeNm: '기타',
clPriority: 5,
name: '기타',
id: 'ETC',
},
]
const myData = {
roofMatlCd: 'ROOF_ID_WA_53A',
roofMatlNm: '화와 A',
roofMatlNmJp: '和瓦A',
widAuth: 'R',
widBase: '265.000',
lenAuth: 'R',
lenBase: '235.000',
roofPchAuth: null,
roofPchBase: null,
raftAuth: 'C',
raftBaseCd: 'HEI_455',
id: 'ROOF_ID_WA_53A',
name: '화와 A',
selected: true,
nameJp: '和瓦A',
length: 235,
width: 265,
layout: 'P',
hajebichi: null,
}
return ( return (
<> <>
<div className="container mx-auto p-4 m-4 border"> <div className="container mx-auto p-4 m-4 border">
@ -215,7 +238,7 @@ export default function Playground() {
<button <button
className="btn-frame deepgray" className="btn-frame deepgray"
onClick={() => { onClick={() => {
getModuleTypeItemList('ROOF_ID_HIRA_SEME') getModuleTypeItemList(['ROOF_ID_HIRA_SEME', 'ROOF_ID_ROOGA'])
}} }}
> >
모듈 타입별 아이템 목록 조회 API 호출 모듈 타입별 아이템 목록 조회 API 호출
@ -223,7 +246,7 @@ export default function Playground() {
<button <button
className="btn-frame deepgray" className="btn-frame deepgray"
onClick={() => { onClick={() => {
getTrestleList(trestleRequestData) getTrestleList({ moduleTpCd: '', roofMatlCd: '', raftBaseCd: '', trestleMkrCd: '', constMthdCd: '', roofBaseCd: '' }) //
}} }}
> >
가대 목록 조회 API 호출 가대 목록 조회 API 호출
@ -231,7 +254,21 @@ export default function Playground() {
<button <button
className="btn-frame deepgray" className="btn-frame deepgray"
onClick={() => { onClick={() => {
getConstructionList(constructionRequestData) getConstructionList({
//
moduleTpCd: 'testData_1',
roofMatlCd: 'testData_2',
trestleMkrCd: 'testData_3',
constMthdCd: 'testData_4',
roofBaseCd: 'testData_5',
illuminationTp: 'testData_6',
instHt: 'testData_7',
stdWindSpeed: 'testData_8',
stdSnowLd: 'testData_9',
inclCd: 'testData_10',
raftBaseCd: '',
roofPitch: 30,
})
}} }}
> >
시공법 목록 조회 API 호출 시공법 목록 조회 API 호출
@ -239,7 +276,22 @@ export default function Playground() {
<button <button
className="btn-frame deepgray" className="btn-frame deepgray"
onClick={() => { onClick={() => {
getTrestleDetailList(trestleDetailRequestData) getTrestleDetailList({
//
moduleTpCd: 'testData_1',
roofMatlCd: 'testData_2',
trestleMkrCd: 'testData_3',
constMthdCd: 'testData_4',
roofBaseCd: 'testData_5',
illuminationTp: 'testData_6',
instHt: 'testData_7',
stdWindSpeed: 'testData_8',
stdSnowLd: 'testData_9',
inclCd: 'testData_10',
constTp: 'testData_11',
mixMatlNo: 30,
roofPitch: 0,
})
}} }}
> >
가대 상세 조회 API 호출 가대 상세 조회 API 호출
@ -442,6 +494,9 @@ export default function Playground() {
axios post test axios post test
</Button> </Button>
</div> </div>
<div className="my-2">
<QSelectBox options={codes} value={myData} sourceKey="id" targetKey="raftBaseCd" showKey="clCodeNm" />
</div>
</div> </div>
</> </>
) )

View File

@ -5,7 +5,7 @@ import Image from 'next/image'
import Link from 'next/link' import Link from 'next/link'
import { useRecoilState } from 'recoil' import { useRecoilState } from 'recoil'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { setSession } from '@/lib/authActions' import { setSession, login } from '@/lib/authActions'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { globalLocaleStore } from '@/store/localeAtom' import { globalLocaleStore } from '@/store/localeAtom'
import { sessionStore } from '@/store/commonAtom' import { sessionStore } from '@/store/commonAtom'
@ -36,7 +36,7 @@ export default function Login() {
const result = { ...response, storeLvl: response.groupId === '60000' ? '1' : '2', pwdInitYn: 'Y' } const result = { ...response, storeLvl: response.groupId === '60000' ? '1' : '2', pwdInitYn: 'Y' }
setSession(result) setSession(result)
setSessionState(result) setSessionState(result)
router.push('/') login()
} else { } else {
router.push('/login') router.push('/login')
} }
@ -87,7 +87,6 @@ export default function Login() {
} }
await promisePost({ url: '/api/login/v1.0/login', data: param }) await promisePost({ url: '/api/login/v1.0/login', data: param })
.then((res) => { .then((res) => {
console.log('🚀 ~ .then ~ res:', res)
if (res) { if (res) {
if (res.data.result.resultCode === 'S') { if (res.data.result.resultCode === 'S') {
setSession(res.data.data) setSession(res.data.data)
@ -98,7 +97,8 @@ export default function Login() {
} else { } else {
Cookies.remove('chkLoginId') Cookies.remove('chkLoginId')
} }
router.push('/') // router.push('/')
login()
} else { } else {
alert(res.data.result.resultMsg) alert(res.data.result.resultMsg)
} }

View File

@ -1,10 +1,56 @@
'use client' 'use client'
import { useEffect, useRef, useState } from 'react' import { useRef, useState } from 'react'
import { useOnClickOutside } from 'usehooks-ts' import { useOnClickOutside } from 'usehooks-ts'
export default function QSelectBox({ title = '', options, onChange, value, disabled = false, params = {} }) { /**
*
* @param {string} title - 선택 제목 (선택이 없을때 보여질 )
* @param {array} options - 선택 옵션 객체 {}
* @param {function} onChange - 선택 변경 함수
* @param {object} value - 선택 객체 {}
* @param {boolean} disabled - 선택 비활성화 여부
* @param {string} sourceKey - options에 있는
* @param {string} targetKey - value에 있는
* @param {string} showKey - options 있는 키중 보여줄
* @param {object} params - 추가 파라미터
* @returns
*/
export default function QSelectBox({
title = '',
options,
onChange,
value,
disabled = false,
sourceKey = '',
targetKey = '',
showKey = '',
params = {},
}) {
/**
* 초기 상태 처리
* useState 초기 값으로 사용해야 해서 useState 보다 위에 작성
* @returns {string} 초기 상태
*/
const handleInitState = () => {
//title ( )
if (title !== '') {
return title
}
//value showKey
if (showKey !== '' && !value) {
return options[0][showKey]
}
//value sourceKey targetKey
if (showKey !== '' && value) {
const option = options.find((option) => option[sourceKey] === value[targetKey])
return option[showKey]
}
}
const [openSelect, setOpenSelect] = useState(false) const [openSelect, setOpenSelect] = useState(false)
const [selected, setSelected] = useState(title === '' && value ? value.name : title) const [selected, setSelected] = useState(handleInitState())
const ref = useRef(null) const ref = useRef(null)
const handleClickSelectOption = (option) => { const handleClickSelectOption = (option) => {
@ -16,9 +62,9 @@ export default function QSelectBox({ title = '', options, onChange, value, disab
setOpenSelect(false) setOpenSelect(false)
} }
useEffect(() => { // useEffect(() => {
if (value) handleClickSelectOption(value) // value && handleClickSelectOption(value)
}, []) // }, [value])
useOnClickOutside(ref, handleClose) useOnClickOutside(ref, handleClose)
@ -28,7 +74,7 @@ export default function QSelectBox({ title = '', options, onChange, value, disab
<ul className="select-item-wrap"> <ul className="select-item-wrap">
{options?.map((option, index) => ( {options?.map((option, index) => (
<li key={option.id || index} className="select-item" onClick={() => handleClickSelectOption(option)}> <li key={option.id || index} className="select-item" onClick={() => handleClickSelectOption(option)}>
<button key={option.id + 'btn'}>{option.name}</button> <button key={option.id + 'btn'}>{showKey !== '' ? option[showKey] : option.name}</button>
</li> </li>
))} ))}
</ul> </ul>

View File

@ -3,21 +3,106 @@ import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom' import { contextPopupPositionState } from '@/store/popupAtom'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useState } from 'react' import { useEffect, useState } from 'react'
import { polygonToTurfPolygon } from '@/util/canvas-util'
import { deepCopyArray } from '@/util/common-utils'
import { canvasState } from '@/store/canvasAtom'
import * as turf from '@turf/turf'
import { POLYGON_TYPE } from '@/common/common'
export default function PanelEdit(props) { export default function PanelEdit(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState) const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition, type = 'move', apply } = props const { id, pos = contextPopupPosition, type = 'move', apply } = props
const { closePopup } = usePopup() const { closePopup } = usePopup()
const [length, setLength] = useState(0) const [length, setLength] = useState(0)
const [direction, setDirection] = useState('') const [direction, setDirection] = useState('up')
const { getMessage } = useMessage() const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState)
useEffect(() => {
if (canvas) {
const isSetupModules = canvas.getObjects().filter((obj) => obj.name === 'module') // selectedObj
isSetupModules.forEach((obj) => obj.set({ lockMovementX: false, lockMovementY: false }))
}
}, [])
//
const handleApply = () => { const handleApply = () => {
apply() contextModuleMove(length, direction)
closePopup(id) closePopup(id)
} }
const contextModuleMove = (length, direction) => {
const checkModuleDisjointSurface = (squarePolygon, turfModuleSetupSurface) => {
return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface)
}
const selectedObj = canvas.getActiveObjects() //
const selectedIds = selectedObj.map((obj) => obj.id) // selectedObj ID
canvas.discardActiveObject() //
const isSetupModules = canvas.getObjects().filter((obj) => obj.name === 'module' && !selectedIds.includes(obj.id)) // selectedObj
const selectedModules = canvas.getObjects().filter((obj) => selectedIds.includes(obj.id) && obj.name === 'module') //
const setupSurface = canvas
.getObjects()
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === selectedModules[0].surfaceId)[0]
const isOverlapArray = []
const isInSurfaceArray = []
if (selectedModules) {
canvas.remove(...selectedModules)
selectedModules.forEach((module) => {
module.set({
originCoords: {
left: module.left,
top: module.top,
},
})
if (direction === 'up') {
module.set({ ...module, top: module.top - Number(length) })
} else if (direction === 'down') {
module.set({ ...module, top: module.top + Number(length) })
} else if (direction === 'left') {
module.set({ ...module, left: module.left - Number(length) })
} else if (direction === 'right') {
module.set({ ...module, left: module.left + Number(length) })
}
module.setCoords()
canvas.renderAll()
//
const isOverlap = isSetupModules.some((isSetupModule) =>
turf.booleanOverlap(polygonToTurfPolygon(module, true), polygonToTurfPolygon(isSetupModule, true)),
)
isOverlapArray.push(isOverlap)
const turfModuleSetupSurface = polygonToTurfPolygon(setupSurface, true)
const turfModule = polygonToTurfPolygon(module, true)
//
const isInSurface = turf.booleanContains(turfModuleSetupSurface, turfModule) || turf.booleanWithin(turfModule, turfModuleSetupSurface)
isInSurfaceArray.push(isInSurface)
})
const isNotOverlap = isOverlapArray.some((isOverlap) => isOverlap) // true
const isNotOutSurface = isInSurfaceArray.every((isOutSurface) => isOutSurface) //false
//
if (isNotOverlap || !isNotOutSurface) {
selectedModules.forEach((module) => {
module.set({ ...module, left: module.originCoords.left, top: module.originCoords.top })
module.setCoords()
})
}
canvas.add(...selectedModules)
canvas.renderAll()
}
}
return ( return (
<WithDraggable isShow={true} pos={pos}> <WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm mount`}> <div className={`modal-pop-wrap xm mount`}>
@ -34,33 +119,33 @@ export default function PanelEdit(props) {
<div className="grid-input-form"> <div className="grid-input-form">
<span className="mr10">{getMessage('margin')}</span> <span className="mr10">{getMessage('margin')}</span>
<div className="input-grid mr5"> <div className="input-grid mr5">
<input type="text" className="input-origin" defaultValue={0} onClick={(e) => setLength(e.target.value)} /> <input type="text" className="input-origin" defaultValue={0} onKeyUp={(e) => setLength(e.target.value)} />
</div> </div>
<span>mm</span> <span>mm</span>
</div> </div>
<div className="grid-direction"> <div className="grid-direction">
<button <button
className={`direction up ${direction === '' ? 'act' : ''}`} className={`direction up ${direction === 'up' ? 'act' : ''}`}
onClick={() => { onClick={() => {
setDirection('') setDirection('up')
}} }}
></button> ></button>
<button <button
className={`direction down ${direction === '' ? 'act' : ''}`} className={`direction down ${direction === 'down' ? 'act' : ''}`}
onClick={() => { onClick={() => {
setDirection('') setDirection('down')
}} }}
></button> ></button>
<button <button
className={`direction left ${direction === '' ? 'act' : ''}`} className={`direction left ${direction === 'left' ? 'act' : ''}`}
onClick={() => { onClick={() => {
setDirection('') setDirection('left')
}} }}
></button> ></button>
<button <button
className={`direction right ${direction === '' ? 'act' : ''}`} className={`direction right ${direction === 'right' ? 'act' : ''}`}
onClick={() => { onClick={() => {
setDirection('') setDirection('right')
}} }}
></button> ></button>
</div> </div>

View File

@ -40,10 +40,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
hajebichi: useRef(null), hajebichi: useRef(null),
} }
useEffect(() => {
console.log('🚀 ~ useEffect ~ currentRoofMaterial:', currentRoofMaterial)
}, [currentRoofMaterial])
// //
useEffect(() => { useEffect(() => {
fetchBasicSettings() fetchBasicSettings()
@ -53,8 +49,6 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
// Function to update the roofType and corresponding values // Function to update the roofType and corresponding values
const handleRoofTypeChange = (value) => { const handleRoofTypeChange = (value) => {
console.log('🚀 ~ handleRoofTypeChange ~ value:', value)
console.log('🚀 ~ handleRoofTypeChange ~ roofMaterials:', roofMaterials)
const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value) const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value)
setCurrentRoofMaterial(selectedRoofMaterial) setCurrentRoofMaterial(selectedRoofMaterial)
} }
@ -87,6 +81,16 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
roofInfo, roofInfo,
}, },
roofs: addedRoofs, roofs: addedRoofs,
roofsData: {
roofApply: true,
roofSeq: 1,
roofMatlCd: currentRoofMaterial.roofMatlCd === null ? 'ROOF_ID_WA_53A' : currentRoofMaterial.roofMatlCd,
roofWidth: currentRoofMaterial.width === null ? 0 : currentRoofMaterial.width,
roofHeight: currentRoofMaterial.length === null ? 0 : currentRoofMaterial.length,
roofHajebichi: currentRoofMaterial.hajebichi === null ? 0 : currentRoofMaterial.hajebichi,
roofGap: currentRoofMaterial.raftBaseCd === null ? 'HEI_455' : currentRoofMaterial.raftBaseCd,
roofLayout: roofLayout,
},
}) })
basicSettingSave() basicSettingSave()
} }
@ -206,7 +210,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
/> />
{/* <select {/* <select
className="select-light dark" className="select-light dark"
name="roofType" name="roofMatlCd"
ref={roofRef.roofCd} ref={roofRef.roofCd}
value={currentRoofMaterial.roofMatlCd} value={currentRoofMaterial.roofMatlCd}
onChange={(e) => { onChange={(e) => {

View File

@ -0,0 +1,198 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilState, useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import { useEffect, useState } from 'react'
import { basicSettingState } from '@/store/settingAtom'
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useCommonCode } from '@/hooks/common/useCommonCode'
export default function ContextRoofAllocationSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const {
handleSave,
onAddRoofMaterial,
onDeleteRoofMaterial,
roofMaterials,
setCurrentRoofMaterial,
roofList,
handleDefaultRoofMaterial,
handleChangeRoofMaterial,
handleChangeRaft,
handleChangeLayout,
handleSaveContext,
} = useRoofAllocationSetting(id)
const { findCommonCode } = useCommonCode()
const [raftCodes, setRaftCodes] = useState([])
useEffect(() => {
const raftCodeList = findCommonCode('203800')
setRaftCodes(raftCodeList.map((raft) => ({ ...raft, value: raft.clCode, name: raft.clCodeNm })))
}, [])
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap ml mount`}>
<div className="modal-head">
<h1 className="title">{getMessage('plan.menu.estimate.roof.alloc')}</h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="properties-guide">{getMessage('modal.roof.alloc.info')}</div>
<div className="allocation-select-wrap">
<span>{getMessage('modal.roof.alloc.select.roof.material')}</span>
<div className="grid-select">
<QSelectBox
options={roofMaterials}
onChange={(e) => {
const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id)
setCurrentRoofMaterial(selected)
}}
/>
</div>
<button
className="allocation-edit"
onClick={() => {
onAddRoofMaterial()
}}
>
<i className="edit-ico"></i>
{getMessage('modal.common.add')}
</button>
</div>
<div className="grid-option-wrap">
{roofList.map((roof, index) => {
return (
<div className="grid-option-box" key={index}>
<div className="d-check-radio pop no-text">
<input type="radio" name="radio01" checked={roof.selected && 'checked'} readOnly={true} />
<label
htmlFor="ra01"
onClick={(e) => {
handleDefaultRoofMaterial(index)
}}
></label>
</div>
<div className="grid-option-block-form">
<div className="block-box">
<div className="flex-ment">
<div className="grid-select" style={{ width: '248px' }}>
<QSelectBox
options={roofMaterials}
value={roofMaterials.find((r) => r.id === roof.id)}
onChange={(e) => handleChangeRoofMaterial(e, index)}
/>
</div>
{index === 0 && <span className="dec">基本屋根材</span>}
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(index)}></button>}
</div>
</div>
<div className="block-box">
{roof.widAuth && (
<div className="flex-ment">
<span>W</span>
<div className="input-grid" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={roof.width} readOnly />
</div>
{/* <div className="select-wrap" style={{ width: '84px' }}>
<select className="select-light dark" name="" id="">
<option>265</option>
</select>
</div> */}
</div>
)}
{roof.lenAuth && (
<div className="flex-ment">
<span>L</span>
<div className="input-grid" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={roof.length} readOnly />
</div>
{/* <div className="select-wrap" style={{ width: '84px' }}>
<select className="select-light dark" name="" id="">
<option>235</option>
</select>
</div> */}
</div>
)}
{roof.raftAuth && (
<div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
<div className="grid-select" style={{ width: '84px' }}>
{raftCodes.length > 0 && (
<QSelectBox
options={raftCodes.map((raft) => ({ name: raft.clCodeNm, value: raft.clCode }))}
onChange={(e) => handleChangeRaft(e, index)}
value={raftCodes.find((r) => r.value === roof.raft)}
/>
)}
{/* <select className="select-light dark" name="roofGap" ref={roofRef.rafter}>
{raftCodes.map((raft, index) => {
return (
<option key={index} value={raft.clCode}>
{raft.clCodeNm}
</option>
)
})}
</select> */}
</div>
</div>
)}
{roof.roofPchAuth && (
<div className="flex-ment">
<span>{getMessage('hajebichi')}</span>
<div className="input-grid" style={{ width: '84px' }}>
<input type="text" className="input-origin block" value={parseInt(roof.hajebichi)} readOnly={roof.roofPchAuth === 'R'} />
</div>
{/* <div className="grid-select no-flx" style={{ width: '84px' }}>
<select className="select-light dark" name="" id="">
<option>265</option>
</select>
</div> */}
</div>
)}
</div>
<div className="block-box">
<div className="icon-btn-wrap">
<button
className={roof.layout === ROOF_MATERIAL_LAYOUT.PARALLEL ? 'act' : ''}
onClick={() => {
handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
}}
>
{getMessage('modal.roof.alloc.select.parallel')}
<i className="allocation01"></i>
</button>
<button
className={roof.layout === ROOF_MATERIAL_LAYOUT.STAIRS ? 'act' : ''}
onClick={() => {
handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
}}
>
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
</button>
</div>
</div>
</div>
</div>
)
})}
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act" onClick={handleSaveContext}>
{getMessage('modal.roof.alloc.apply')}
</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -65,6 +65,7 @@ export function useCanvasConfigInitialize() {
roofInit() //화면표시 초기화 roofInit() //화면표시 초기화
groupDimensionInit() groupDimensionInit()
reGroupInit() //그룹 객체 재그룹 reGroupInit() //그룹 객체 재그룹
moduleInit()
} }
const gridInit = () => { const gridInit = () => {
@ -196,5 +197,19 @@ export function useCanvasConfigInitialize() {
}) })
} }
const moduleInit = () => {
canvas
.getObjects()
.filter((obj) => obj.name === 'module')
.forEach((obj) => {
obj.set({
selectable: true,
lockMovementX: false,
lockMovementY: false,
})
obj.setViewLengthText(false)
})
}
return { canvasLoadInit, gridInit } return { canvasLoadInit, gridInit }
} }

View File

@ -603,8 +603,12 @@ export function useCommonUtils() {
} }
const deleteObject = () => { const deleteObject = () => {
const obj = canvas?.getActiveObject() const selectedObj = canvas?.getActiveObjects()
commonDeleteText(obj) if (selectedObj) {
selectedObj.forEach((obj) => {
commonDeleteText(obj)
})
}
} }
const moveObject = () => { const moveObject = () => {

View File

@ -26,16 +26,15 @@ export function useMasterController() {
/** /**
* 모듈 타입별 아이템 목록 조회 * 모듈 타입별 아이템 목록 조회
* @param {지붕재 코드} roofMatlCd * @param {지붕재 코드 목록} arrRoofMatlCd
* @returns * @returns
*/ */
const getModuleTypeItemList = async (roofMatlCd) => { const getModuleTypeItemList = async (paramArr) => {
if (!roofMatlCd || roofMatlCd.trim() === '') { if (!Array.isArray(paramArr) || paramArr.length === 0 || paramArr.length > 4 || paramArr.some((item) => !item || item.trim() === '')) {
swalFire({ text: getMessage('master.moduletypeitem.message.error'), type: 'alert', icon: 'error' }) swalFire({ text: getMessage('master.moduletypeitem.message.error'), type: 'alert', icon: 'error' })
return null return null
} }
const param = { roofMatlCd: roofMatlCd } const paramString = `?${paramArr.map((item) => `arrRoofMatlCd=${item}`).join('&')}`
const paramString = getQueryString(param)
return await get({ url: `/api/v1/master/getModuleTypeItemList${paramString}` }).then((res) => { return await get({ url: `/api/v1/master/getModuleTypeItemList${paramString}` }).then((res) => {
console.log('🚀🚀 ~ getModuleTypeItemList ~ res:', res) console.log('🚀🚀 ~ getModuleTypeItemList ~ res:', res)
return res return res

View File

@ -1,17 +1,19 @@
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { selectedRoofMaterialSelector } from '@/store/settingAtom' import { selectedRoofMaterialSelector } from '@/store/settingAtom'
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
export function useRoofFn() { export function useRoofFn() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector) const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
//면형상 선택 클릭시 지붕 패턴 입히기 //면형상 선택 클릭시 지붕 패턴 입히기
function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) { function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false, roofMaterial = selectedRoofMaterial) {
const ratio = window.devicePixelRatio || 1 const ratio = window.devicePixelRatio || 1
const layout = roofMaterial.layout
let width = selectedRoofMaterial.width / 10 let width = (roofMaterial.width ?? 226) / 10
let height = selectedRoofMaterial.length / 10 let height = (roofMaterial.length ?? 158) / 10
let roofStyle = 2 let roofStyle = 2
const inputPatternSize = { width: width, height: height } //임시 사이즈 const inputPatternSize = { width: width, height: height } //임시 사이즈
const patternSize = { ...inputPatternSize } // 입력된 값을 뒤집기 위해 const patternSize = { ...inputPatternSize } // 입력된 값을 뒤집기 위해
@ -31,7 +33,7 @@ export function useRoofFn() {
const rows = Math.floor(patternSourceCanvas.height / patternSize.height) const rows = Math.floor(patternSourceCanvas.height / patternSize.height)
const cols = Math.floor(patternSourceCanvas.width / patternSize.width) const cols = Math.floor(patternSourceCanvas.width / patternSize.width)
ctx.strokeStyle = mode === 'allPainted' ? 'black' : 'green' ctx.strokeStyle = mode === 'allPainted' ? 'black' : 'blue'
ctx.lineWidth = mode === 'allPainted' ? 1 : 0.4 ctx.lineWidth = mode === 'allPainted' ? 1 : 0.4
ctx.fillStyle = mode === 'allPainted' ? 'rgba(0, 159, 64, 0.7)' : 'white' ctx.fillStyle = mode === 'allPainted' ? 'rgba(0, 159, 64, 0.7)' : 'white'
@ -58,7 +60,7 @@ export function useRoofFn() {
} }
for (let row = 0; row <= rows; row++) { for (let row = 0; row <= rows; row++) {
const y = row * patternSize.height + (col % 2 === 0 ? 0 : offset) const y = layout === ROOF_MATERIAL_LAYOUT.STAIRS ? row * patternSize.height + (col % 2 === 0 ? 0 : offset) : row * patternSize.height
const xStart = col * patternSize.width const xStart = col * patternSize.width
const xEnd = xStart + patternSize.width const xEnd = xStart + patternSize.width
ctx.beginPath() ctx.beginPath()
@ -83,7 +85,7 @@ export function useRoofFn() {
} }
for (let col = 0; col <= cols; col++) { for (let col = 0; col <= cols; col++) {
const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset) const x = layout === ROOF_MATERIAL_LAYOUT.STAIRS ? col * patternSize.width + (row % 2 === 0 ? 0 : offset) : col * patternSize.width
const yStart = row * patternSize.height const yStart = row * patternSize.height
const yEnd = yStart + patternSize.height const yEnd = yStart + patternSize.height
@ -136,6 +138,7 @@ export function useRoofFn() {
polygon.set('fill', null) polygon.set('fill', null)
polygon.set('fill', pattern) polygon.set('fill', pattern)
polygon.roofMaterial = roofMaterial
polygon.canvas?.renderAll() polygon.canvas?.renderAll()
} }
return { setSurfaceShapePattern } return { setSurfaceShapePattern }

View File

@ -1,7 +1,7 @@
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { rectToPolygon } from '@/util/canvas-util' import { rectToPolygon, setSurfaceShapePattern, polygonToTurfPolygon } from '@/util/canvas-util'
import { roofDisplaySelector } from '@/store/settingAtom' import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom'
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom' import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom'
@ -14,6 +14,7 @@ import { canvasSettingState } from '@/store/canvasAtom'
import { compasDegAtom } from '@/store/orientationAtom' import { compasDegAtom } from '@/store/orientationAtom'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
import { useRoofFn } from '@/hooks/common/useRoofFn' import { useRoofFn } from '@/hooks/common/useRoofFn'
import { useEffect } from 'react'
export function useModuleBasicSetting() { export function useModuleBasicSetting() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -25,10 +26,37 @@ export function useModuleBasicSetting() {
const canvasSetting = useRecoilValue(canvasSettingState) const canvasSetting = useRecoilValue(canvasSettingState)
const compasDeg = useRecoilValue(compasDegAtom) const compasDeg = useRecoilValue(compasDegAtom)
const { setSurfaceShapePattern } = useRoofFn() const { setSurfaceShapePattern } = useRoofFn()
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
useEffect(() => {
// console.log('basicSetting', basicSetting)
if (canvas) {
canvas.selection = true
canvas.selectionFullyContained = true
// canvas.on('selection:created', (e) => {
// console.log('selection:created', e.selected)
// })
}
}, [])
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
let selectedModuleInstSurfaceArray = [] let selectedModuleInstSurfaceArray = []
const moduleOptions = {
fill: '#BFFD9F',
stroke: 'black',
strokeWidth: 0.1,
selectable: true, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
parentId: moduleSetupSurface.parentId,
surfaceId: moduleSetupSurface.id,
name: 'module',
}
//모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화 //모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화
const restoreModuleInstArea = () => { const restoreModuleInstArea = () => {
//설치면 삭제 //설치면 삭제
@ -176,21 +204,6 @@ export function useModuleBasicSetting() {
obj.name === BATCH_TYPE.SHADOW, obj.name === BATCH_TYPE.SHADOW,
) //도머s 객체 ) //도머s 객체
const moduleOptions = {
fill: '#BFFD9F',
stroke: 'black',
strokeWidth: 0.1,
selectable: false, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
parentId: moduleSetupSurface.parentId,
name: 'module',
}
if (moduleSetupSurfaces.length !== 0) { if (moduleSetupSurfaces.length !== 0) {
let tempModule let tempModule
let manualDrawModules = [] let manualDrawModules = []
@ -229,7 +242,7 @@ export function useModuleBasicSetting() {
tempModule = new fabric.Rect({ tempModule = new fabric.Rect({
fill: 'white', fill: 'white',
stroke: 'black', stroke: 'black',
strokeWidth: 1, strokeWidth: 0.3,
width: width, width: width,
height: height, height: height,
left: mousePoint.x - width / 2, left: mousePoint.x - width / 2,
@ -240,7 +253,6 @@ export function useModuleBasicSetting() {
lockRotation: true, lockRotation: true,
lockScalingX: true, lockScalingX: true,
lockScalingY: true, lockScalingY: true,
opacity: 0.8,
name: 'tempModule', name: 'tempModule',
parentId: moduleSetupSurfaces[i].parentId, parentId: moduleSetupSurfaces[i].parentId,
}) })
@ -440,6 +452,7 @@ export function useModuleBasicSetting() {
canvas?.remove(tempModule) canvas?.remove(tempModule)
//안겹치면 넣는다 //안겹치면 넣는다
// tempModule.setCoords() // tempModule.setCoords()
moduleOptions.surfaceId = trestlePolygon.id
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions }) let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
canvas?.add(manualModule) canvas?.add(manualModule)
manualDrawModules.push(manualModule) manualDrawModules.push(manualModule)
@ -516,15 +529,15 @@ export function useModuleBasicSetting() {
const moduleOptions = { const moduleOptions = {
fill: '#BFFD9F', fill: '#BFFD9F',
stroke: 'black', stroke: 'black',
strokeWidth: 0.1, strokeWidth: 0.3,
selectable: false, // 선택 가능하게 설정 selectable: true, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금 lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금 lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금 lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금 lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
parentId: moduleSetupSurface.parentId, parentId: moduleSetupSurface.parentId,
surfaceId: moduleSetupSurface.id,
name: 'module', name: 'module',
} }
@ -593,7 +606,8 @@ export function useModuleBasicSetting() {
return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface) return turf.booleanContains(turfModuleSetupSurface, squarePolygon) || turf.booleanWithin(squarePolygon, turfModuleSetupSurface)
} }
const downFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, flowModuleLine, isCenter = false) => { const downFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => {
const flowModuleLine = moduleSetupSurface.flowLines
let startPoint = flowModuleLine.bottom let startPoint = flowModuleLine.bottom
if (isCenter) { if (isCenter) {
@ -637,9 +651,9 @@ export function useModuleBasicSetting() {
if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함 if (isMaxSetup) totalWidth = totalWidth * 2 //최대배치시 2배로 늘려서 반씩 검사하기위함
for (let j = 0; j < diffTopEndPoint; j++) { for (let j = 0; j < diffTopEndPoint; j++) {
bottomMargin = j === 0 ? 1 : 2 bottomMargin = 1 * j
for (let i = 0; i <= totalWidth; i++) { for (let i = 0; i <= totalWidth; i++) {
leftMargin = i === 0 ? 1 : 2 leftMargin = 1 * i
chidoriLength = 0 chidoriLength = 0
if (isChidori) { if (isChidori) {
chidoriLength = j % 2 === 0 ? 0 : width / 2 chidoriLength = j % 2 === 0 ? 0 : width / 2
@ -657,6 +671,7 @@ export function useModuleBasicSetting() {
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -664,7 +679,8 @@ export function useModuleBasicSetting() {
} }
} }
const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, aaa, isCenter = false) => { const leftFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => {
const flowModuleLine = moduleSetupSurface.flowLines
let startPoint = flowModuleLine.left let startPoint = flowModuleLine.left
//중앙배치일 경우에는 계산한다 //중앙배치일 경우에는 계산한다
@ -718,6 +734,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) { // if (disjointFromTrestle && isDisjoint) {
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -725,7 +742,8 @@ export function useModuleBasicSetting() {
} }
} }
const topFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, flowModuleLine, isCenter = false) => { const topFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => {
const flowModuleLine = moduleSetupSurface.flowLines
let startPoint = flowModuleLine.top let startPoint = flowModuleLine.top
if (isCenter) { if (isCenter) {
@ -789,6 +807,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) { // if (disjointFromTrestle && isDisjoint) {
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -796,7 +815,8 @@ export function useModuleBasicSetting() {
} }
} }
const rightFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, flowModuleLine, isCenter = false) => { const rightFlowSetupModule = (surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, isCenter = false) => {
const flowModuleLine = moduleSetupSurface.flowLines
let startPoint = flowModuleLine.right let startPoint = flowModuleLine.right
if (isCenter) { if (isCenter) {
@ -850,6 +870,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) { // if (disjointFromTrestle && isDisjoint) {
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -883,44 +904,44 @@ export function useModuleBasicSetting() {
if (setupLocation === 'eaves') { if (setupLocation === 'eaves') {
// 흐름방향이 남쪽일때 // 흐름방향이 남쪽일때
if (moduleSetupSurface.flowDirection === 'south') { if (moduleSetupSurface.flowDirection === 'south') {
downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
if (moduleSetupSurface.flowDirection === 'west') { if (moduleSetupSurface.flowDirection === 'west') {
leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
if (moduleSetupSurface.flowDirection === 'east') { if (moduleSetupSurface.flowDirection === 'east') {
rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
if (moduleSetupSurface.flowDirection === 'north') { if (moduleSetupSurface.flowDirection === 'north') {
topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
} else if (setupLocation === 'ridge') { } else if (setupLocation === 'ridge') {
//용마루 //용마루
if (moduleSetupSurface.flowDirection === 'south') { if (moduleSetupSurface.flowDirection === 'south') {
topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
if (moduleSetupSurface.flowDirection === 'west') { if (moduleSetupSurface.flowDirection === 'west') {
rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
if (moduleSetupSurface.flowDirection === 'east') { if (moduleSetupSurface.flowDirection === 'east') {
leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
if (moduleSetupSurface.flowDirection === 'north') { if (moduleSetupSurface.flowDirection === 'north') {
downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines) downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface)
} }
} else if (setupLocation === 'center') { } else if (setupLocation === 'center') {
//중가면 //중가면
if (moduleSetupSurface.flowDirection === 'south') { if (moduleSetupSurface.flowDirection === 'south') {
downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines, true) downFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true)
} }
if (moduleSetupSurface.flowDirection === 'west') { if (moduleSetupSurface.flowDirection === 'west') {
leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines, true) leftFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true)
} }
if (moduleSetupSurface.flowDirection === 'east') { if (moduleSetupSurface.flowDirection === 'east') {
rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines, true) rightFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true)
} }
if (moduleSetupSurface.flowDirection === 'north') { if (moduleSetupSurface.flowDirection === 'north') {
topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface.flowLines, true) topFlowSetupModule(surfaceMaxLines, width, height, moduleSetupArray, moduleSetupSurface, true)
} }
} }
@ -1214,20 +1235,6 @@ export function useModuleBasicSetting() {
return turf.polygon([coordinates]) return turf.polygon([coordinates])
} }
const polygonToTurfPolygon = (object, current = false) => {
let coordinates
coordinates = object.points.map((point) => [point.x, point.y])
if (current) coordinates = object.getCurrentPoints().map((point) => [point.x, point.y])
coordinates.push(coordinates[0])
return turf.polygon(
[coordinates],
{},
{
parentId: object.parentId,
},
)
}
const batchObjectGroupToTurfPolygon = (group) => { const batchObjectGroupToTurfPolygon = (group) => {
const polygons = group.getObjects().filter((obj) => obj.type === 'QPolygon') const polygons = group.getObjects().filter((obj) => obj.type === 'QPolygon')
let allPoints = [] let allPoints = []
@ -1547,14 +1554,14 @@ export function useModuleBasicSetting() {
fill: '#BFFD9F', fill: '#BFFD9F',
stroke: 'black', stroke: 'black',
strokeWidth: 0.1, strokeWidth: 0.1,
selectable: false, // 선택 가능하게 설정 selectable: true, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금 lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금 lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금 lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금 lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
parentId: moduleSetupSurface.parentId, parentId: moduleSetupSurface.parentId,
surfaceId: moduleSetupSurface.id,
name: 'module', name: 'module',
} }
@ -1602,7 +1609,7 @@ export function useModuleBasicSetting() {
const mousePoint = canvas.getPointer(e.e) const mousePoint = canvas.getPointer(e.e)
for (let i = 0; i < moduleSetupSurfaces.length; i++) { for (let i = 0; i < moduleSetupSurfaces.length; i++) {
turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i]) turfPolygon = polygonToTurfPolygon(moduleSetupSurfaces[i], true)
trestlePolygon = moduleSetupSurfaces[i] trestlePolygon = moduleSetupSurfaces[i]
manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨 manualDrawModules = moduleSetupSurfaces[i].modules // 앞에서 자동으로 했을때 추가됨
flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향 flowDirection = moduleSetupSurfaces[i].flowDirection //도형의 방향
@ -1627,7 +1634,7 @@ export function useModuleBasicSetting() {
tempModule = new fabric.Rect({ tempModule = new fabric.Rect({
fill: 'white', fill: 'white',
stroke: 'black', stroke: 'black',
strokeWidth: 1, strokeWidth: 0.3,
width: width, width: width,
height: height, height: height,
left: mousePoint.x - width / 2, left: mousePoint.x - width / 2,
@ -1638,7 +1645,6 @@ export function useModuleBasicSetting() {
lockRotation: true, lockRotation: true,
lockScalingX: true, lockScalingX: true,
lockScalingY: true, lockScalingY: true,
opacity: 0.8,
name: 'tempModule', name: 'tempModule',
parentId: moduleSetupSurfaces[i].parentId, parentId: moduleSetupSurfaces[i].parentId,
}) })
@ -1833,8 +1839,7 @@ export function useModuleBasicSetting() {
//마우스 클릭시 set으로 해당 위치에 셀을 넣음 //마우스 클릭시 set으로 해당 위치에 셀을 넣음
const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인 const isOverlap = manualDrawModules.some((module) => turf.booleanOverlap(tempTurfModule, polygonToTurfPolygon(module))) //겹치는지 확인
if (!isOverlap) { if (!isOverlap) {
console.log('tempModule.points', tempModule.points) moduleOptions.surfaceId = trestlePolygon.id
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions }) let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
canvas?.add(manualModule) canvas?.add(manualModule)
manualDrawModules.push(tempModule) manualDrawModules.push(tempModule)
@ -1956,14 +1961,14 @@ export function useModuleBasicSetting() {
fill: '#BFFD9F', fill: '#BFFD9F',
stroke: 'black', stroke: 'black',
strokeWidth: 0.1, strokeWidth: 0.1,
selectable: false, // 선택 가능하게 설정 selectable: true, // 선택 가능하게 설정
lockMovementX: true, // X 축 이동 잠금 lockMovementX: true, // X 축 이동 잠금
lockMovementY: true, // Y 축 이동 잠금 lockMovementY: true, // Y 축 이동 잠금
lockRotation: true, // 회전 잠금 lockRotation: true, // 회전 잠금
lockScalingX: true, // X 축 크기 조정 잠금 lockScalingX: true, // X 축 크기 조정 잠금
lockScalingY: true, // Y 축 크기 조정 잠금 lockScalingY: true, // Y 축 크기 조정 잠금
opacity: 0.8,
parentId: moduleSetupSurface.parentId, parentId: moduleSetupSurface.parentId,
surfaceId: moduleSetupSurface.id,
name: 'module', name: 'module',
} }
@ -2066,6 +2071,7 @@ export function useModuleBasicSetting() {
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1) let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -2105,6 +2111,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) { // if (disjointFromTrestle && isDisjoint) {
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -2147,6 +2154,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) { // if (disjointFromTrestle && isDisjoint) {
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -2187,6 +2195,7 @@ export function useModuleBasicSetting() {
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] })) let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
// if (disjointFromTrestle && isDisjoint) { // if (disjointFromTrestle && isDisjoint) {
moduleOptions.surfaceId = moduleSetupSurface.id
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon }) let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
canvas?.add(tempModule) canvas?.add(tempModule)
moduleSetupArray.push(tempModule) moduleSetupArray.push(tempModule)
@ -2274,6 +2283,8 @@ export function useModuleBasicSetting() {
// canvas.add(groupTest) // canvas.add(groupTest)
}) })
// console.log(calculateForApi()) // console.log(calculateForApi())
//드래그 하기위해 기능 활성화
} }
return { return {

View File

@ -120,7 +120,7 @@ export function useCanvasSetting() {
} }
const { id } = selectedRoofMaterial const { id } = selectedRoofMaterial
console.log(getModuleTypeItemList(id)) if (id !== undefined) console.log(getModuleTypeItemList(id))
}, [selectedRoofMaterial]) }, [selectedRoofMaterial])
//지붕재 초기세팅 //지붕재 초기세팅
@ -129,6 +129,7 @@ export function useCanvasSetting() {
return return
} }
const { data } = await getRoofMaterialList() const { data } = await getRoofMaterialList()
const roofLists = data.map((item, idx) => ({ const roofLists = data.map((item, idx) => ({
...item, ...item,
id: item.roofMatlCd, id: item.roofMatlCd,
@ -138,7 +139,7 @@ export function useCanvasSetting() {
length: item.lenBase && parseInt(item.lenBase), length: item.lenBase && parseInt(item.lenBase),
width: item.widBase && parseInt(item.widBase), width: item.widBase && parseInt(item.widBase),
raft: item.raftBase && parseInt(item.raftBase), raft: item.raftBase && parseInt(item.raftBase),
layout: ROOF_MATERIAL_LAYOUT.PARALLEL, layout: ['ROOF_ID_SLATE', 'ROOF_ID_SINGLE'].includes(item.roofMatlCd) ? ROOF_MATERIAL_LAYOUT.STAIRS : ROOF_MATERIAL_LAYOUT.PARALLEL,
hajebichi: item.roofPchBase && parseInt(item.roofPchBase), hajebichi: item.roofPchBase && parseInt(item.roofPchBase),
})) }))
setRoofMaterials(roofLists) setRoofMaterials(roofLists)
@ -178,15 +179,6 @@ export function useCanvasSetting() {
canvas?.renderAll() canvas?.renderAll()
}, [corridorDimension]) }, [corridorDimension])
// 배치면 초기설정 변경 시
useEffect(() => {
//console.log('useCanvasSetting canvasSetting 실행', canvasSetting)
if (canvasSetting.flag) {
basicSettingSave()
}
}, [canvasSetting])
useEffect(() => { useEffect(() => {
console.log('🚀 ~ useEffect ~ settingsDataSave:', settingsDataSave) console.log('🚀 ~ useEffect ~ settingsDataSave:', settingsDataSave)
if (settingsDataSave !== undefined) onClickOption2() if (settingsDataSave !== undefined) onClickOption2()
@ -268,57 +260,75 @@ export function useCanvasSetting() {
try { try {
await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}` }).then((res) => { await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}` }).then((res) => {
console.log('fetchBasicSettings res ', res) console.log('fetchBasicSettings res ', res)
if (res.length == 0) return //if (res.length == 0) return
// 'roofs' 배열을 생성하여 각 항목을 추가 let roofsRow = {}
const roofsRow = res.map((item) => { let roofsArray = {}
if (res.length > 0) {
roofsRow = res.map((item) => {
return { return {
roofSizeSet: item.roofSizeSet, roofSizeSet: item.roofSizeSet,
roofAngleSet: item.roofAngleSet, roofAngleSet: item.roofAngleSet,
} }
}) })
const roofsArray = res.some((item) => !item.roofSeq) roofsArray = res.map((item) => {
? //최초 지붕재 추가 정보의 경우 roofsArray를 초기화 설정 return {
res.map(() => ({ roofApply: item.roofApply === '' || item.roofApply === false ? false : true,
flag: false, roofSeq: item.roofSeq,
roofApply: true, roofMatlCd: item.roofMatlCd,
roofSeq: 1, roofWidth: item.roofWidth,
roofType: 1, roofHeight: item.roofHeight,
roofWidth: 265, roofHajebichi: item.roofHajebichi,
roofHeight: 235, roofGap: item.roofGap,
roofHajebichi: 0, roofLayout: item.roofLayout,
roofGap: 455, }
// roofType: 1, })
// roofWidth: 200,
// roofHeight: 200,
// roofHajebichi: 200,
// roofGap: 0,
roofLayout: 'parallel',
}))
: res.map((item) => ({
flag: false,
roofApply: item.roofApply === '' || item.roofApply === false ? false : true,
roofSeq: item.roofSeq,
roofType: item.roofType,
roofWidth: item.roofWidth,
roofHeight: item.roofHeight,
roofHajebichi: item.roofHajebichi,
roofGap: item.roofGap,
roofLayout: item.roofLayout,
}))
console.log('roofsArray ', roofsArray)
// 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음
const patternData = {
roofSizeSet: roofsRow[0].roofSizeSet, // 첫 번째 항목의 값을 사용
roofAngleSet: roofsRow[0].roofAngleSet, // 첫 번째 항목의 값을 사용
roofs: roofsArray, // 만들어진 roofs 배열
}
//console.error('patternData', patternData) } else {
roofsRow = [{
roofSizeSet: 1,
roofAngleSet: 'slope',
}]
roofsArray = [{
roofApply: true,
roofSeq: 1,
roofMatlCd: 'ROOF_ID_WA_53A',
roofWidth: 265,
roofHeight: 235,
roofHajebichi: 0,
roofGap: 'HEI_455',
roofLayout: 'P',
}]
}
// 나머지 데이터와 함께 'roofs' 배열을 patternData에 넣음
const patternData = {
roofSizeSet: roofsRow[0].roofSizeSet,
roofAngleSet: roofsRow[0].roofAngleSet,
roofs: roofsArray, // 만들어진 roofs 배열
}
console.log('patternData', patternData)
// 데이터 설정
//setBasicSettings({ ...basicSetting, roofSizeSet: roofsRow[0].roofSizeSet, roofAngleSet: roofsRow[0].roofAngleSet, roofsData: roofsArray})
const addRoofs = []
roofMaterials.map((material) => {
if (material.id === roofsArray[0].roofMatlCd) {
//setRoofMaterials({ ...roofMaterials, layout: roofsArray[0].roofLayout })
addRoofs.push({ ...material, selected: true, layout: roofsArray[0].roofLayout })
setBasicSettings({ ...basicSetting, roofMaterials: material
, roofs: addRoofs
, roofSizeSet: roofsRow[0].roofSizeSet
, roofAngleSet: roofsRow[0].roofAngleSet
, roofsData: roofsArray })
}
})
// 데이터 설정
setBasicSettings({ ...patternData })
}) })
} catch (error) { } catch (error) {
console.error('Data fetching error:', error) console.error('Data fetching error:', error)
@ -337,15 +347,26 @@ export function useCanvasSetting() {
objectNo: correntObjectNo, objectNo: correntObjectNo,
roofSizeSet: basicSetting.roofSizeSet, roofSizeSet: basicSetting.roofSizeSet,
roofAngleSet: basicSetting.roofAngleSet, roofAngleSet: basicSetting.roofAngleSet,
roofMaterialsAddList: basicSetting.roofs, // TODO : 선택된 roof로 변경해야함 roofMaterialsAddList: [{
roofApply: true,
roofSeq: 1,
roofMatlCd: basicSetting.roofsData.roofMatlCd === null ? 'ROOF_ID_WA_53A' : basicSetting.roofsData.roofMatlCd,
roofWidth: basicSetting.roofsData.roofWidth === null ? 0 : basicSetting.roofsData.roofWidth,
roofHeight: basicSetting.roofsData.roofHeight === null ? 0 : basicSetting.roofsData.roofHeight,
roofHajebichi: basicSetting.roofsData.roofHajebichi === null ? 0 : basicSetting.roofsData.roofHajebichi,
roofGap: basicSetting.roofsData.roofGap === null ? 'HEI_455' : basicSetting.roofsData.roofGap,
roofLayout: basicSetting.roofsData.roofLayout,
}],
} }
console.log('patternData 55', patternData)
await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => { await post({ url: `/api/canvas-management/canvas-basic-settings`, data: patternData }).then((res) => {
swalFire({ text: getMessage(res.returnMessage) }) swalFire({ text: getMessage(res.returnMessage) })
}) })
//Recoil 설정 //Recoil 설정
setCanvasSetting({ ...basicSetting, flag: false }) setCanvasSetting({ ...basicSetting })
} catch (error) { } catch (error) {
swalFire({ text: getMessage(res.returnMessage), icon: 'error' }) swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
} }

View File

@ -100,6 +100,13 @@ export function useRoofAllocationSetting(id) {
} }
} }
// 지붕재 오른쪽 마우스 클릭 후 단일로 지붕재 변경 필요한 경우
const handleSaveContext = () => {
const selectedRoofMaterial = roofList.find((roof) => roof.selected)
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial)
closeAll()
}
const handleAlloc = () => { const handleAlloc = () => {
if (!checkInnerLines()) { if (!checkInnerLines()) {
apply() apply()
@ -161,6 +168,7 @@ export function useRoofAllocationSetting(id) {
return { return {
...prev, ...prev,
roofs: roofList, roofs: roofList,
selectedRoofMaterial: roofList.find((roof) => roof.selected),
} }
}) })
@ -203,9 +211,6 @@ export function useRoofAllocationSetting(id) {
canvas?.renderAll() canvas?.renderAll()
} }
//roof input값 변경
const handleChangeInput = (type, value, index) => {}
// 지붕재 변경 // 지붕재 변경
const handleChangeRoofMaterial = (value, index) => { const handleChangeRoofMaterial = (value, index) => {
if (isFirstRef.current === 0) { if (isFirstRef.current === 0) {
@ -275,5 +280,6 @@ export function useRoofAllocationSetting(id) {
handleChangeRoofMaterial, handleChangeRoofMaterial,
handleChangeRaft, handleChangeRaft,
handleChangeLayout, handleChangeLayout,
handleSaveContext,
} }
} }

View File

@ -86,10 +86,21 @@ export function useRoofShapePassivitySetting(id) {
useEffect(() => { useEffect(() => {
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
let stroke, strokeWidth
lines.forEach((line) => { lines.forEach((line) => {
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES || line.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
stroke = '#45CD7D'
strokeWidth = 4
} else if (line.attributes.type === LINE_TYPE.WALLLINE.GABLE || line.attributes.type === LINE_TYPE.WALLLINE.JERKINHEAD) {
stroke = '#3FBAE6'
strokeWidth = 4
} else {
stroke = '#000000'
strokeWidth = 4
}
line.set({ line.set({
stroke: '#000000', stroke,
strokeWidth: 4, strokeWidth,
}) })
}) })
if (!currentObject) { if (!currentObject) {
@ -125,6 +136,10 @@ export function useRoofShapePassivitySetting(id) {
const index = lines.findIndex((line) => line === selectedLine) const index = lines.findIndex((line) => line === selectedLine)
const nextLine = lines[index + 1] || lines[0] const nextLine = lines[index + 1] || lines[0]
if (nextLine.attributes.isFixed) {
canvas.discardActiveObject()
return
}
canvas.setActiveObject(nextLine) canvas.setActiveObject(nextLine)
} }
@ -155,7 +170,7 @@ export function useRoofShapePassivitySetting(id) {
} }
currentLineRef.current.set({ currentLineRef.current.set({
attributes, attributes: { ...attributes, isFixed: true },
}) })
history.current.push(currentLineRef.current) history.current.push(currentLineRef.current)

View File

@ -185,9 +185,19 @@ export function useRoofShapeSetting(id) {
} }
case 4: { case 4: {
outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
outerLines.forEach((line) => { const pitch = outerLines.find((line) => line.attributes.type === LINE_TYPE.WALLLINE.SHED)?.attributes.pitch
// hideLine(line) // 변별로 설정중 한쪽흐름일 경우 한쪽흐름의 pitch로 설정
}) if (pitch) {
outerLines.forEach((line) => {
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
line.attributes = {
...line.attributes,
pitch: pitch,
}
}
})
}
break break
} }
@ -595,17 +605,23 @@ export function useRoofShapeSetting(id) {
break break
} }
} }
selectedLine.attributes = attributes selectedLine.attributes = { ...attributes, isFixed: true }
history.current.push(selectedLine)
canvas.renderAll() canvas.renderAll()
nextLineFocus(selectedLine) nextLineFocus(selectedLine)
} }
const nextLineFocus = (selectedLine) => { const nextLineFocus = (selectedLine) => {
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
const index = lines.findIndex((line) => line.idx === selectedLine.idx) const index = lines.findIndex((line) => line.idx === selectedLine.idx)
const nextLine = lines[index + 1] || lines[0] const nextLine = lines[index + 1] || lines[0]
if (nextLine.attributes.isFixed) {
canvas.discardActiveObject()
return
}
history.current.push(selectedLine)
canvas.setActiveObject(nextLine) canvas.setActiveObject(nextLine)
} }

View File

@ -35,6 +35,7 @@ import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
import { fontSelector, globalFontAtom } from '@/store/fontAtom' import { fontSelector, globalFontAtom } from '@/store/fontAtom'
import { useLine } from '@/hooks/useLine' import { useLine } from '@/hooks/useLine'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import ContextRoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/ContextRoofAllocationSetting'
export function useContextMenu() { export function useContextMenu() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -377,7 +378,7 @@ export function useContextMenu() {
{ {
id: 'roofMaterialEdit', id: 'roofMaterialEdit',
name: getMessage('contextmenu.roof.material.edit'), name: getMessage('contextmenu.roof.material.edit'),
component: <RoofAllocationSetting id={popupId} />, component: <ContextRoofAllocationSetting id={popupId} />,
}, },
{ {
id: 'linePropertyEdit', id: 'linePropertyEdit',
@ -597,12 +598,13 @@ export function useContextMenu() {
], ],
]) ])
break break
case 'panel': case 'module':
setContextMenu([ setContextMenu([
[ [
{ {
id: 'remove', id: 'remove',
name: getMessage('contextmenu.remove'), name: getMessage('contextmenu.remove'),
fn: () => deleteObject(),
}, },
{ {
id: 'move', id: 'move',
@ -661,7 +663,7 @@ export function useContextMenu() {
], ],
]) ])
break break
case 'module': case 'moduleSetupSurface':
case 'dimensionLineText': case 'dimensionLineText':
setContextMenu([ setContextMenu([
[ [

View File

@ -59,33 +59,36 @@ export async function setSession(data) {
await session.save() await session.save()
} }
export async function login(formData) { export async function login() {
const session = await getSession() const session = await getSession()
if (session) {
const userId = formData.get('id') redirect('/')
const password = formData.get('password')
console.log('id:', userId)
console.log('password:', password)
// const loginUser = await getUserByIdAndPassword({ userId, password })
const loginUser = {
id: 1,
userId: 'test123',
name: 'jinsoo Kim',
email: 'jinsoo.kim@example.com',
} }
if (!loginUser) { // const userId = formData.get('id')
throw Error('Wrong Credentials!') // const password = formData.get('password')
}
session.name = loginUser.name // console.log('id:', userId)
session.userId = loginUser.userId // console.log('password:', password)
session.email = loginUser.email
session.isLoggedIn = true
console.log('session:', session)
await session.save() // // const loginUser = await getUserByIdAndPassword({ userId, password })
redirect('/') // const loginUser = {
// id: 1,
// userId: 'test123',
// name: 'jinsoo Kim',
// email: 'jinsoo.kim@example.com',
// }
// if (!loginUser) {
// throw Error('Wrong Credentials!')
// }
// session.name = loginUser.name
// session.userId = loginUser.userId
// session.email = loginUser.email
// session.isLoggedIn = true
// console.log('session:', session)
// await session.save()
// redirect('/')
} }

View File

@ -3,8 +3,8 @@ export const defaultSession = {}
export const sessionOptions = { export const sessionOptions = {
password: process.env.SESSION_SECRET, password: process.env.SESSION_SECRET,
cookieName: 'lama-session', cookieName: 'lama-session',
// cookieOptions: { cookieOptions: {
// httpOnly: true, httpOnly: true,
// secure: process.env.NODE_ENV === 'production', secure: process.env.NODE_ENV === 'production',
// }, },
} }

View File

@ -220,7 +220,11 @@ export const selectedRoofMaterialSelector = selector({
key: 'selectedRoofMaterialSelector', key: 'selectedRoofMaterialSelector',
get: ({ get }) => { get: ({ get }) => {
const basicSetting = get(basicSettingState) const basicSetting = get(basicSettingState)
return basicSetting.selectedRoofMaterial const addedRoofs = get(addedRoofsSelector)
// addedRoofs에서 selectedRoofMaterial을 찾아 index를 반환
const index = addedRoofs.findIndex((roof) => roof === basicSetting.selectedRoofMaterial)
return { ...basicSetting.selectedRoofMaterial, index }
}, },
}) })

View File

@ -751,18 +751,6 @@ export const pointsToTurfPolygon = (points) => {
return turf.polygon([coordinates]) return turf.polygon([coordinates])
} }
export const polygonToTurfPolygon = (polygon) => {
const coordinates = polygon.points.map((point) => [point.x, point.y])
coordinates.push(coordinates[0])
return turf.polygon(
[coordinates],
{},
{
parentId: polygon.parentId,
},
)
}
export const triangleToPolygon = (triangle) => { export const triangleToPolygon = (triangle) => {
const points = [] const points = []
const halfWidth = triangle.width / 2 const halfWidth = triangle.width / 2
@ -1003,3 +991,17 @@ export function findAndRemoveClosestPoint(targetPoint, points) {
return closestPoint return closestPoint
} }
export function polygonToTurfPolygon(object, current = false) {
let coordinates
coordinates = object.points.map((point) => [point.x, point.y])
if (current) coordinates = object.getCurrentPoints().map((point) => [point.x, point.y])
coordinates.push(coordinates[0])
return turf.polygon(
[coordinates],
{},
{
parentId: object.parentId,
},
)
}