Merge branch 'dev' into dev-yj

# Conflicts:
#	src/components/floor-plan/CanvasMenu.jsx
#	src/hooks/useContextMenu.js
This commit is contained in:
yjnoh 2024-10-30 11:20:54 +09:00
commit 50cc0f9687
58 changed files with 1664 additions and 919 deletions

View File

@ -0,0 +1,6 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="elements">
<path id="Vector" d="M6.73735 6.73726L11.2628 11.2627M11.2628 6.73726L6.73735 11.2627" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path id="Ellipse 1334" d="M17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17C13.4183 17 17 13.4183 17 9Z" stroke="white"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 9.5L7.5 12L13 6" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17C13.4183 17 17 13.4183 17 9Z" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 332 B

View File

@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.00078 5.7998V12.1998M12.2008 8.9998L5.80078 8.9998" stroke="#141B34" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 9C17 4.58172 13.4183 1 9 1C4.58172 1 1 4.58172 1 9C1 13.4183 4.58172 17 9 17C13.4183 17 17 13.4183 17 9Z" stroke="#141B34"/>
</svg>

After

Width:  |  Height:  |  Size: 371 B

View File

@ -1,11 +1,5 @@
<svg width="23" height="24" viewBox="0 0 23 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="ico"> <rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
<circle id="Ellipse 2012" cx="11.5" cy="12" r="11.5" fill="#45576F"/> <rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#0191C9"/>
<g id="elements"> <path d="M13.186 5.7898C12.6312 5.20223 11.7307 5.20223 11.1759 5.7898L6.99193 10.2206C6.03462 11.2344 6.03462 12.8767 6.99193 13.8905C7.94924 14.9043 9.50003 14.9043 10.4573 13.8905L13.9136 10.2303C14.1615 9.96779 14.5663 9.96779 14.8141 10.2303C15.062 10.4928 15.062 10.9214 14.8141 11.1839L11.3578 14.8441C9.90251 16.3853 7.54676 16.3853 6.09147 14.8441C4.63618 13.303 4.63618 10.8082 6.09147 9.26705L10.2754 4.8362C11.3282 3.72127 13.0337 3.72127 14.0865 4.8362C15.1393 5.95114 15.1393 7.75719 14.0865 8.87212L10.0844 13.1103C9.43409 13.799 8.379 13.799 7.72867 13.1103C7.07834 12.4216 7.07834 11.3043 7.72867 10.6156L11.0031 7.14795C11.2509 6.88547 11.6557 6.88547 11.9035 7.14795C12.1514 7.41042 12.1514 7.83906 11.9035 8.10154L8.62913 11.5692C8.47678 11.7305 8.47678 11.9954 8.62913 12.1567C8.78148 12.3181 9.03161 12.3181 9.18396 12.1567L13.186 7.91853C13.7408 7.33096 13.7408 6.37736 13.186 5.7898Z" fill="#0191C9" stroke="white" stroke-width="0.5"/>
<path id="Vector" d="M9.66678 12.8193C9.7612 12.9739 9.87323 13.1202 10.0029 13.2552C10.8079 14.093 12.0349 14.224 12.9718 13.6481C13.1454 13.5414 13.3091 13.4104 13.4582 13.2552L15.6178 11.0076C16.572 10.0145 16.572 8.40447 15.6178 7.41141C14.6637 6.41836 13.1166 6.41836 12.1625 7.41142L11.6868 7.90648" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
<path id="Vector_2" d="M10.313 16.0933L9.83718 16.5885C8.88301 17.5816 7.33598 17.5816 6.3818 16.5885C5.42762 15.5955 5.42762 13.9854 6.3818 12.9924L8.54141 10.7448C9.49559 9.75174 11.0426 9.75174 11.9968 10.7448C12.1264 10.8797 12.2384 11.026 12.3328 11.1806" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
<path id="Vector_3" d="M17.0003 14.6666H15.6143M13.6669 18L13.6669 16.614" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path id="Vector_4" d="M5 9.33333H6.38593M8.33333 6L8.33333 7.38593" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,7 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#909000"/>
<path d="M4 10C4 13.3137 6.68629 16 10 16C13.3137 16 16 13.3137 16 10C16 6.68629 13.3137 4 10 4" stroke="#909000" stroke-linecap="round"/>
<path d="M5.58914 5.8473C5.67215 5.75932 5.75769 5.67375 5.84566 5.59071M7.5684 4.43768C7.67731 4.38873 7.78788 4.34282 7.9 4.30005M4.3 7.90005C4.34317 7.78681 4.38955 7.67516 4.43904 7.5652" stroke="#909000" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.99999 7.59961V12.3996M12.4 9.99961L7.59999 9.99961" stroke="#909000" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 772 B

View File

@ -1,4 +1,5 @@
<svg width="15" height="16" viewBox="0 0 15 16" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="7" cy="7.5" r="6.5" fill="white" stroke="#F16A6A"/> <rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
<path d="M6.507 9.228L6.276 5.169L6.221 3.629H7.849L7.794 5.169L7.563 9.228H6.507ZM7.035 12.154C6.74167 12.154 6.49967 12.0513 6.309 11.846C6.12567 11.6407 6.034 11.3913 6.034 11.098C6.034 10.79 6.12567 10.537 6.309 10.339C6.49967 10.141 6.74167 10.042 7.035 10.042C7.32833 10.042 7.56667 10.141 7.75 10.339C7.94067 10.537 8.036 10.79 8.036 11.098C8.036 11.3913 7.94067 11.6407 7.75 11.846C7.56667 12.0513 7.32833 12.154 7.035 12.154Z" fill="#F16A6A"/> <rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#F16A6A"/>
<path d="M9.47136 11.228L9.24036 7.169L9.18536 5.629H10.8134L10.7584 7.169L10.5274 11.228H9.47136ZM9.99936 14.154C9.70602 14.154 9.46402 14.0513 9.27336 13.846C9.09002 13.6407 8.99836 13.3913 8.99836 13.098C8.99836 12.79 9.09002 12.537 9.27336 12.339C9.46402 12.141 9.70602 12.042 9.99936 12.042C10.2927 12.042 10.531 12.141 10.7144 12.339C10.905 12.537 11.0004 12.79 11.0004 13.098C11.0004 13.3913 10.905 13.6407 10.7144 13.846C10.531 14.0513 10.2927 14.154 9.99936 14.154Z" fill="#F16A6A"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 620 B

After

Width:  |  Height:  |  Size: 738 B

View File

@ -0,0 +1,6 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" fill="white"/>
<rect x="0.5" y="0.5" width="19" height="19" rx="9.5" stroke="#3BBB48"/>
<path d="M11.3571 4.95962C10.7174 4.31987 10.3975 4 10 4C9.60251 4 9.28264 4.31987 8.64289 4.95962C8.25899 5.34352 7.87857 5.52175 7.33125 5.52175C6.85336 5.52175 6.17346 5.42907 5.8 5.80567C5.4295 6.17929 5.52177 6.85639 5.52177 7.33123C5.52177 7.87857 5.34352 8.25899 4.95961 8.6429C4.31987 9.28264 4.00001 9.60251 4 9.99999C4.00001 10.3975 4.31988 10.7174 4.95963 11.3571C5.38969 11.7872 5.52177 12.0649 5.52177 12.6687C5.52177 13.1466 5.42908 13.8265 5.80569 14.2C6.17931 14.5705 6.85641 14.4782 7.33124 14.4782C7.91409 14.4782 8.19477 14.5922 8.61074 15.0082C8.96495 15.3624 9.43978 16 10 16C10.5602 16 11.0351 15.3624 11.3893 15.0082C11.8052 14.5922 12.0859 14.4782 12.6688 14.4782C13.1436 14.4782 13.8207 14.5705 14.1943 14.2M15.0404 8.6429C15.6801 9.28264 16 9.60251 16 9.99999C16 10.3975 15.6801 10.7174 15.0404 11.3571C14.6103 11.7871 14.4782 12.0649 14.4782 12.6687C14.4782 13.1466 14.5709 13.8265 14.1943 14.2M14.1943 14.2H14.2" stroke="#3BBB48" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.9 8.49998L10 10.6L15.4002 4.59998" stroke="#3BBB48" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,9 +0,0 @@
import Estimate from '@/components/estimate/Estimate'
export default function EstimatePage() {
return (
<>
<Estimate />
</>
)
}

View File

@ -0,0 +1,12 @@
import Estimate from '@/components/estimate/Estimate'
export default function EstimatePage({ params }) {
//floor-plan/estimate/mid/pid
//mid :5
//pid :
return (
<>
<Estimate params={params} />
</>
)
}

View File

@ -46,6 +46,7 @@ export default async function RootLayout({ children }) {
storeLvl: session.storeLvl, storeLvl: session.storeLvl,
groupId: session.groupId, groupId: session.groupId,
pwdInitYn: session.pwdInitYn, pwdInitYn: session.pwdInitYn,
custCd: session.custCd,
isLoggedIn: session.isLoggedIn, isLoggedIn: session.isLoggedIn,
} }
} }

View File

@ -1,3 +1,5 @@
import { fabric } from 'fabric'
export const MENU = { export const MENU = {
PLAN_DRAWING: 'planDrawing', PLAN_DRAWING: 'planDrawing',
INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정 INITIAL_CANVAS_SETTING: 'initialCanvasSetting', // 배치면 초기설정
@ -116,3 +118,41 @@ export const POLYGON_TYPE = {
ROOF: 'roof', ROOF: 'roof',
TRESTLE: 'trestle', TRESTLE: 'trestle',
} }
export const SAVE_KEY = [
'selectable',
'name',
'parentId',
'id',
'length',
'idx',
'direction',
'parentDirection',
'lines',
'points',
'lockMovementX',
'lockMovementY',
'lockRotation',
'lockScalingX',
'lockScalingY',
'opacity',
'cells',
'maxX',
'maxY',
'minX',
'minY',
'x',
'y',
'x1',
'x2',
'y1',
'y2',
'attributes',
'stickeyPoint',
'text',
'pitch',
'uuid',
'originText',
]
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]

View File

@ -98,6 +98,7 @@ export default function Login() {
pwdInitYn: 'Y', pwdInitYn: 'Y',
storeLvl: '1', storeLvl: '1',
groupId: '60000', groupId: '60000',
custCd: '100000',
}) })
setSessionState({ setSessionState({
userId: 'NEW016610', userId: 'NEW016610',
@ -115,6 +116,7 @@ export default function Login() {
pwdInitYn: 'Y', pwdInitYn: 'Y',
storeLvl: '1', storeLvl: '1',
groupId: '60000', groupId: '60000',
custCd: '100000',
}) })
if (chkLoginId) { if (chkLoginId) {
Cookies.set('chkLoginId', formData.get('id'), { expires: 7 }) Cookies.set('chkLoginId', formData.get('id'), { expires: 7 })

View File

@ -1,14 +1,59 @@
'use client' 'use client'
import { useEffect, useState } from 'react' import { useEffect, useState, useRef } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import SingleDatePicker from '../common/datepicker/SingleDatePicker' import SingleDatePicker from '../common/datepicker/SingleDatePicker'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
import { Button } from '@nextui-org/react'
import { sessionStore } from '@/store/commonAtom'
export default function Estimate() { export default function Estimate({ params }) {
const sessionState = useRecoilValue(sessionStore)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const objectRecoil = useRecoilValue(floorPlanObjectState) const objectRecoil = useRecoilValue(floorPlanObjectState)
console.log('견적서화면이군요', objectRecoil.floorPlanObjectNo) const [objectNo, setObjectNo] = useState('')
const fileInputRef = useRef(null)
const [files, setFiles] = useState([]) //
const fileId = useRef(0)
useEffect(() => {
setObjectNo(objectRecoil.floorPlanObjectNo)
}, [objectRecoil])
useEffect(() => {
if (objectNo) {
//Q101X278191023001
console.log('세션정보::::', sessionState)
//API
}
}, [objectNo])
const handleButtonClick = () => {
fileInputRef.current.click()
}
const onChangeFiles = (e) => {
// e.preventDefault()
// e.persist()
// console.log('::', e.target.files[0])
// console.log('::', e.target.files)
// let selectFiles = []
// let tempFiles = files
// selectFiles = e.target.files
// for (const file of selectFiles) {
// tempFiles = [
// ...tempFiles,
// {
// id: fileId.current++,
// object: file,
// },
// ]
// }
// setFiles(tempFiles)
// const formData = new FormData()
// formData.append('file', e.target.files[0])
}
return ( return (
<div className="sub-content estimate"> <div className="sub-content estimate">
<div className="sub-content-inner"> <div className="sub-content-inner">
@ -18,7 +63,9 @@ export default function Estimate() {
<div className="estimate-list-wrap one"> <div className="estimate-list-wrap one">
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div> <div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
<div className="estimate-name">RX524231020006 (Plan No: 1)</div> <div className="estimate-name">
{objectNo} (Plan No: {params.pid})
</div>
</div> </div>
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">{getMessage('estimate.detail.estimateNo')}</div> <div className="estimate-tit">{getMessage('estimate.detail.estimateNo')}</div>
@ -105,7 +152,7 @@ export default function Estimate() {
<tr> <tr>
{/* 주문분류 */} {/* 주문분류 */}
<th> <th>
注文分類/주문분류 <span className="important">*</span> {getMessage('estimate.detail.orderType')} <span className="important">*</span>
</th> </th>
<td colSpan={3}> <td colSpan={3}>
<div className="radio-wrap"></div> <div className="radio-wrap"></div>
@ -113,7 +160,7 @@ export default function Estimate() {
</tr> </tr>
<tr> <tr>
{/* 지붕재・사양시공 최대4개*/} {/* 지붕재・사양시공 최대4개*/}
<th>屋根材仕様施工 / 지붕재사양시공</th> <th>{getMessage('estimate.detail.roofCns')}</th>
<td colSpan={3}> <td colSpan={3}>
<div className="form-flex-wrap mb5"> <div className="form-flex-wrap mb5">
<div className="input-wrap mr5" style={{ width: '610px' }}> <div className="input-wrap mr5" style={{ width: '610px' }}>
@ -131,7 +178,7 @@ export default function Estimate() {
</tr> </tr>
<tr> <tr>
{/* 비고 */} {/* 비고 */}
<th>備考 /비고</th> <th>{getMessage('estimate.detail.note')}</th>
<td colSpan={3}> <td colSpan={3}>
<div className="input-wrap"> <div className="input-wrap">
<input type="text" className="input-light" /> <input type="text" className="input-light" />
@ -146,9 +193,9 @@ export default function Estimate() {
<div className="title-wrap"> <div className="title-wrap">
<h3>{getMessage('estimate.detail.header.fileList1')}</h3> <h3>{getMessage('estimate.detail.header.fileList1')}</h3>
<div className="d-check-box light mr5"> <div className="d-check-box light mr5">
<input type="checkbox" id="" /> <input type="checkbox" id="next" />
<label htmlFor="" style={{ color: '#101010' }}> <label htmlFor="next" style={{ color: '#101010' }}>
後日資料提出 / 후일자료제출 {getMessage('estimate.detail.nextSubmit')}
</label> </label>
</div> </div>
</div> </div>
@ -165,7 +212,17 @@ export default function Estimate() {
<td> <td>
<div className="drag-file-box"> <div className="drag-file-box">
<div className="btn-area"> <div className="btn-area">
<button className="btn-origin grey">{getMessage('estimate.detail.fileList.btn')}</button> <Button type="button" className="btn-origin grey" onClick={handleButtonClick}>
{getMessage('estimate.detail.fileList.btn')}
</Button>
<input
type="file"
id="fileUpload"
name="fileUpload"
ref={fileInputRef}
onChange={onChangeFiles}
style={{ display: 'none' }}
/>
</div> </div>
<div className="drag-file-area"> <div className="drag-file-area">
<p>Drag file here</p> <p>Drag file here</p>
@ -216,23 +273,23 @@ export default function Estimate() {
<div className="estimate-wrap"> <div className="estimate-wrap">
<div className="estimate-list-wrap one"> <div className="estimate-list-wrap one">
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">수량 (PCS)</div> <div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPcs')}</div>
<div className="estimate-name blue">74</div> <div className="estimate-name blue">74</div>
</div> </div>
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">용량 (Kw)</div> <div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vol')}</div>
<div className="estimate-name blue">8300</div> <div className="estimate-name blue">8300</div>
</div> </div>
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">공급가액</div> <div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.netAmt')}</div>
<div className="estimate-name blue">6,798,900</div> <div className="estimate-name blue">6,798,900</div>
</div> </div>
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">부가세 (10)</div> <div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.vat')}</div>
<div className="estimate-name blue">679,890</div> <div className="estimate-name blue">679,890</div>
</div> </div>
<div className="estimate-box"> <div className="estimate-box">
<div className="estimate-tit">총액</div> <div className="estimate-tit">{getMessage('estimate.detail.sepcialEstimateProductInfo.totPrice')}</div>
<div className="estimate-name red">7,478,790</div> <div className="estimate-name red">7,478,790</div>
</div> </div>
</div> </div>
@ -260,9 +317,9 @@ export default function Estimate() {
</div> </div>
</td> </td>
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th> <th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}</th>
<td>(모듈수량 * 수량) / 100)</td> <td>{getMessage('estimate.detail.sepcialEstimateProductInfo.calcFormula1')}</td>
<th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th> <th>{getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}</th>
<td>PKG단가(W) * PKG용량(W)</td> <td>{getMessage('estimate.detail.sepcialEstimateProductInfo.calcFormula2')}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>

View File

@ -21,9 +21,7 @@ export const QLine = fabric.util.createClass(fabric.Line, {
} }
this.line = this this.line = this
// 소수점 전부 제거 // 소수점 전부 제거
points.forEach((point) => { points = points.map((point) => Math.round(point))
point = Math.round(point)
})
this.idx = options.idx ?? 0 this.idx = options.idx ?? 0
this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 }) this.direction = options.direction ?? getDirectionByPoint({ x: this.x1, y: this.y1 }, { x: this.x2, y: this.y2 })
@ -41,12 +39,6 @@ export const QLine = fabric.util.createClass(fabric.Line, {
} }
}, },
toObject: function (propertiesToInclude) {
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
type: this.type,
text: this.text,
})
},
init: function () { init: function () {
this.addLengthText() this.addLengthText()

View File

@ -24,8 +24,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
initialize: function (points, options, canvas) { initialize: function (points, options, canvas) {
// 소수점 전부 제거 // 소수점 전부 제거
points.forEach((point) => { points.forEach((point) => {
point.x = Math.round(point.x) point.x = Number(point.x.toFixed(1))
point.y = Math.round(point.y) point.y = Number(point.y.toFixed(1))
}) })
options.selectable = options.selectable ?? true options.selectable = options.selectable ?? true
options.sort = options.sort ?? true options.sort = options.sort ?? true
@ -101,17 +101,6 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
this.shape = shape this.shape = shape
}, },
toObject: function (propertiesToInclude) {
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), {
id: this.id,
type: this.type,
text: this.text,
hips: this.hips,
ridges: this.ridges,
connectRidges: this.connectRidges,
})
},
init: function () { init: function () {
this.addLengthText() this.addLengthText()

View File

@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { usePathname, useRouter } from 'next/navigation'
import MenuDepth01 from './MenuDepth01' import MenuDepth01 from './MenuDepth01'
import QSelectBox from '@/components/common/select/QSelectBox' import QSelectBox from '@/components/common/select/QSelectBox'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
@ -11,52 +12,53 @@ import { useMessage } from '@/hooks/useMessage'
import { usePlan } from '@/hooks/usePlan' import { usePlan } from '@/hooks/usePlan'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { canvasState, canvasZoomState, currentCanvasPlanState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom' import {
canvasSettingState,
canvasState,
canvasZoomState,
currentCanvasPlanState,
currentMenuState,
verticalHorizontalModeState,
} from '@/store/canvasAtom'
import { sessionStore } from '@/store/commonAtom' import { sessionStore } from '@/store/commonAtom'
import { outerLinePointsState } from '@/store/outerLineAtom' import { outerLinePointsState } from '@/store/outerLineAtom'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import { settingModalFirstOptionsState, wordDisplaySelector } from '@/store/settingAtom' import { settingModalFirstOptionsState } from '@/store/settingAtom'
import { MENU } from '@/common/common'
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 { useCanvasEvent } from '@/hooks/useCanvasEvent' import { useCanvasEvent } from '@/hooks/useCanvasEvent'
import { popupState } from '@/store/popupAtom'
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01' import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom' import { placementShapeDrawingPointsState } from '@/store/placementShapeDrawingAtom'
import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting' import PlacementShapeSetting from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
import { useCommonUtils } from '@/hooks/common/useCommonUtils' import { useCommonUtils } from '@/hooks/common/useCommonUtils'
import { commonUtilsState } from '@/store/commonUtilsAtom'
const canvasMenus = [ import { commonUtilsState } from '@/store/commonUtilsAtom'
{ index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING }, import { menusState, menuTypeState } from '@/store/menuAtom'
{ index: 1, name: 'plan.menu.placement.surface.initial.setting', icon: 'con01', title: MENU.INITIAL_CANVAS_SETTING }, import useMenu from '@/hooks/common/useMenu'
{ index: 2, name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT }, import { MENU } from '@/common/common'
{ index: 3, name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
{ index: 4, name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
{ index: 5, name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
{ index: 6, name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
]
export default function CanvasMenu(props) { export default function CanvasMenu(props) {
const { menuNumber, setMenuNumber } = props const { menuNumber, setMenuNumber } = props
const pathname = usePathname()
const { addPopup, closePopup } = usePopup() const router = useRouter()
const [type, setType] = useState('') const { addPopup } = usePopup()
const canvasMenus = useRecoilValue(menusState)
const [type, setType] = useRecoilState(menuTypeState)
const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState) const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore) const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
const setCurrentMenu = useSetRecoilState(currentMenuState) const setCurrentMenu = useSetRecoilState(currentMenuState)
const setOuterLinePoints = useSetRecoilState(outerLinePointsState) const setOuterLinePoints = useSetRecoilState(outerLinePointsState)
const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState) const setPlacementPoints = useSetRecoilState(placementShapeDrawingPointsState)
const canvasSetting = useRecoilValue(canvasSettingState)
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const { handleZoomClear } = useCanvasEvent() const sessionState = useRecoilValue(sessionStore)
const globalLocale = useRecoilValue(globalLocaleStore) const globalLocale = useRecoilValue(globalLocaleStore)
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const sessionState = useRecoilValue(sessionStore) const { handleZoomClear } = useCanvasEvent()
const { handleMenu } = useMenu()
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { saveCanvas } = usePlan() const { saveCanvas } = usePlan()
@ -64,9 +66,6 @@ export default function CanvasMenu(props) {
const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useEvent() const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useEvent()
const commonUtils = useRecoilValue(commonUtilsState) const commonUtils = useRecoilValue(commonUtilsState)
const { commonFunctions } = useCommonUtils() const { commonFunctions } = useCommonUtils()
const [popup, setPopup] = useRecoilState(popupState)
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }] const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
const onClickNav = (menu) => { const onClickNav = (menu) => {
@ -88,9 +87,8 @@ export default function CanvasMenu(props) {
setType('module') setType('module')
break break
} }
}
const menuProps = { if (pathname !== '/floor-plan') router.push('/floor-plan')
type,
} }
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState) const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
@ -122,7 +120,6 @@ export default function CanvasMenu(props) {
} }
const onClickPlacementInitialMenu = () => { const onClickPlacementInitialMenu = () => {
addPopup(placementInitialId, 1, <PlacementShapeSetting {...placementInitialProps} />) addPopup(placementInitialId, 1, <PlacementShapeSetting {...placementInitialProps} />)
// setShowPlaceShapeModal(true)
} }
const handleClear = () => { const handleClear = () => {
@ -149,7 +146,19 @@ export default function CanvasMenu(props) {
} else { } else {
setAppMessageState(JA) setAppMessageState(JA)
} }
}, [menuNumber, type, globalLocale]) }, [type, globalLocale])
useEffect(() => {
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString())) {
setMenuNumber(3)
setType('surface')
setCurrentMenu(MENU.BATCH_CANVAS.BATCH_DRAWING)
} else {
setMenuNumber(2)
setType('outline')
setCurrentMenu(MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
}
}, [canvasSetting])
return ( return (
<div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}> <div className={`canvas-menu-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
@ -160,9 +169,12 @@ export default function CanvasMenu(props) {
<li <li
key={`canvas-menu-${menu.index}`} key={`canvas-menu-${menu.index}`}
className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`} className={`canvas-menu-item ${menuNumber === menu.index ? 'active' : ''}`}
onClick={() => onClickNav(menu)} onClick={() => {
if (['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2) return
onClickNav(menu)
}}
> >
<button> <button className={['2', '3'].includes(canvasSetting?.roofSizeSet?.toString()) && menu.index === 2 ? 'no-click' : ''}>
<span className={`menu-icon ${menu.icon}`}></span> <span className={`menu-icon ${menu.icon}`}></span>
{getMessage(menu.name)} {getMessage(menu.name)}
</button> </button>
@ -250,7 +262,7 @@ export default function CanvasMenu(props) {
</div> </div>
</div> </div>
<div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}> <div className={`canvas-depth2-wrap ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
{(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 {...menuProps} />} {(menuNumber === 2 || menuNumber === 3 || menuNumber === 4) && <MenuDepth01 />}
</div> </div>
</div> </div>
) )

View File

@ -2,28 +2,26 @@
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import CanvasMenu from '@/components/floor-plan/CanvasMenu' import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import '@/styles/contents.scss' import '@/styles/contents.scss'
export default function FloorPlan({ children }) { export default function FloorPlan({ children }) {
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get } = useAxios(globalLocaleState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const [objectNo, setObjectNo] = useState('test123240912001') // const [objectNo, setObjectNo] = useState('test123240912001') //
// const [menuNumber, setMenuNumber] = useState(null)
const { menuNumber, setMenuNumber } = useCanvasMenu() const { menuNumber, setMenuNumber } = useCanvasMenu()
const { fetchSettings } = useCanvasSetting()
const modalProps = { const modalProps = {
menuNumber, menuNumber,
setMenuNumber, setMenuNumber,
} }
useEffect(() => { useEffect(() => {
fetchSettings() fetchSettings()
}, [objectNo]) }, [objectNo])
@ -32,32 +30,6 @@ export default function FloorPlan({ children }) {
setMenuNumber(1) setMenuNumber(1)
}, []) }, [])
// Canvas Setting
const fetchSettings = async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({
...item,
}))
//
setSettingModalFirstOptions({
option1: optionData1,
option2: optionData2,
dimensionDisplay: optionData5,
})
setSettingModalSecondOptions({
option3: optionData3,
option4: optionData4,
})
} catch (error) {
console.error('Data fetching error:', error)
}
}
return ( return (
<> <>
<div className="canvas-wrap"> <div className="canvas-wrap">

View File

@ -1,150 +1,32 @@
'use client' 'use client'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
import { MENU } from '@/common/common'
import { currentMenuState } from '@/store/canvasAtom' import { currentMenuState } from '@/store/canvasAtom'
import { useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch' import { menuTypeState, subMenusState } from '@/store/menuAtom'
import { usePopup } from '@/hooks/usePopup' import useMenu from '@/hooks/common/useMenu'
import { v4 as uuidv4 } from 'uuid' import { useEffect } from 'react'
import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting'
import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting'
import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting'
import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing'
import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit'
import MovementSetting from '@/components/floor-plan/modal/movement/MovementSetting'
import WallLineOffsetSetting from '@/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting'
import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting'
import Slope from '@/components/floor-plan/modal/Slope'
import ObjectSetting from '@/components/floor-plan/modal/object/ObjectSetting'
import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing'
import PlacementSurfaceSetting from '@/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting'
import BasicSetting from '@/components/floor-plan/modal/basic/BasicSetting'
import CircuitTrestleSetting from '@/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting'
export default function MenuDepth01(props) { export default function MenuDepth01() {
const { type } = props const type = useRecoilValue(menuTypeState)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [activeMenu, setActiveMenu] = useState() const { handleMenu } = useMenu()
const setCurrentMenu = useSetRecoilState(currentMenuState) const [currentMenu, setCurrentMenu] = useRecoilState(currentMenuState)
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch() const subMenus = useRecoilValue(subMenusState)
const { addPopup } = usePopup()
const [outlineId, setOutlineId] = useState(uuidv4()) const onClickMenu = ({ id, menu }) => {
const onClickMenu = ({ id, menu, name }) => {
setActiveMenu(menu)
setCurrentMenu(menu) setCurrentMenu(menu)
if (type === 'outline') {
switch (id) {
case 0:
addPopup(outlineId, 1, <WallLineSetting id={outlineId} />)
break
case 1:
addPopup(outlineId, 1, <RoofShapeSetting id={outlineId} />)
break
case 2:
addPopup(outlineId, 1, <RoofShapePassivitySetting id={outlineId} />)
break
case 3:
addPopup(outlineId, 1, <AuxiliaryDrawing id={outlineId} />)
break
case 4:
addPopup(outlineId, 1, <EavesGableEdit id={outlineId} />)
break
case 5:
addPopup(outlineId, 1, <MovementSetting id={outlineId} />)
break
case 6:
addPopup(outlineId, 1, <WallLineOffsetSetting id={outlineId} />)
break
case 7:
addPopup(outlineId, 1, <RoofAllocationSetting id={outlineId} />)
break
}
}
if (type === 'surface') {
switch (id) {
case 0:
addPopup(outlineId, 1, <Slope id={outlineId} />)
break
case 1:
addPopup(outlineId, 1, <PlacementShapeDrawing id={outlineId} />)
break
case 2:
addPopup(outlineId, 1, <PlacementSurfaceSetting id={outlineId} />)
break
case 3:
addPopup(outlineId, 1, <ObjectSetting id={outlineId} />)
break
case 4:
deleteAllSurfacesAndObjects()
break
}
}
if (type === 'module') {
switch (id) {
case 0:
addPopup(outlineId, 1, <BasicSetting id={outlineId} />)
break
case 1:
addPopup(outlineId, 1, <CircuitTrestleSetting id={outlineId} />)
break
}
}
} }
useEffect(() => { useEffect(() => {
setActiveMenu(null) handleMenu(type)
}, [type]) }, [currentMenu])
const menuInfo = {
outline: [
//
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
{
id: 2,
name: 'plan.menu.roof.cover.roof.shape.passivity.setting',
menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS,
},
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
{ id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT },
{ id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN },
{ id: 6, name: 'plan.menu.roof.cover.outline.edit.offset', menu: MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET },
{ id: 7, name: 'plan.menu.roof.cover.roof.surface.alloc', menu: MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC },
],
surface: [
//
{ id: 0, name: 'plan.menu.placement.surface.slope.setting', menu: MENU.BATCH_CANVAS.SLOPE_SETTING },
{ id: 1, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
{ id: 2, name: 'plan.menu.placement.surface.arrangement', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
{ id: 3, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
{ id: 4, name: 'plan.menu.placement.surface.all.remove', menu: MENU.BATCH_CANVAS.ALL_REMOVE },
],
module: [
// ,
{ id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING },
{
id: 1,
name: 'plan.menu.module.circuit.setting.circuit.trestle.setting',
menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING,
},
{
id: 2,
name: 'plan.menu.module.circuit.setting.plan.orientation',
menu: MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION,
},
],
}
return ( return (
<div className="canvas-depth2-inner"> <div className="canvas-depth2-inner">
<ul className="canvas-depth2-list"> <ul className="canvas-depth2-list">
{menuInfo[type].map((menu) => { {subMenus[type]?.map((menu) => {
return ( return (
<li key={menu.id} className={`canvas-depth2-item ${menu.menu === activeMenu ? 'active' : ''}`}> <li key={menu.id} className={`canvas-depth2-item ${menu.menu === currentMenu ? 'active' : ''}`}>
<button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button> <button onClick={() => onClickMenu(menu)}>{getMessage(menu.name)}</button>
</li> </li>
) )

View File

@ -1,3 +1,5 @@
'use client'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'

View File

@ -1,15 +1,17 @@
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom' import { contextPopupPositionState } from '@/store/popupAtom'
import QSelectBox from '@/components/common/select/QSelectBox' import QSelectBox from '@/components/common/select/QSelectBox'
import { pitchTextSelector } from '@/store/canvasAtom'
export default function DimensionLineSetting(props) { export default function DimensionLineSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState) const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, setIsShow, pos = contextPopupPosition } = props const { id, setIsShow, pos = contextPopupPosition } = props
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
const pitchText = useRecoilState(pitchTextSelector)
const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }] const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
return ( return (
<WithDraggable isShow={true} pos={pos}> <WithDraggable isShow={true} pos={pos}>
@ -52,14 +54,14 @@ export default function DimensionLineSetting(props) {
<div className="grid-select mr10"> <div className="grid-select mr10">
<QSelectBox title={'0'} option={SelectOption01} /> <QSelectBox title={'0'} option={SelectOption01} />
</div> </div>
<span className="thin">寸法</span> <span className="thin">{pitchText}</span>
</div> </div>
<div className="outline-form"> <div className="outline-form">
<span className="mr10">傾斜</span> <span className="mr10">傾斜</span>
<div className="grid-select mr10"> <div className="grid-select mr10">
<QSelectBox title={'0'} option={SelectOption01} /> <QSelectBox title={'0'} option={SelectOption01} />
</div> </div>
<span className="thin">寸法</span> <span className="thin">{pitchText}</span>
</div> </div>
</div> </div>
<div className="warning">傾き設定されている場合入力した数値に傾き計算をした数値が表示されます</div> <div className="warning">傾き設定されている場合入力した数値に傾き計算をした数値が表示されます</div>

View File

@ -71,7 +71,7 @@ export default function DotLineGrid(props) {
// //
useEffect(() => { useEffect(() => {
console.log('DotLineGrid useEffect 실행') console.log('DotLineGrid useEffect 실행')
// fetchGridSettings() fetchGridSettings()
}, [objectNo]) }, [objectNo])
const HandleClickClose = () => { const HandleClickClose = () => {
@ -100,9 +100,9 @@ export default function DotLineGrid(props) {
const patternData = { const patternData = {
INTERVAL: { INTERVAL: {
type: res.gridType, type: res.gridType,
horizontalInterval: res.gridHorizon, horizontalInterval: res.gridHorizon * 10,
verticalInterval: res.gridVertical, verticalInterval: res.gridVertical * 10,
ratioInterval: res.gridRatio, ratioInterval: res.gridRatio * 10,
}, },
dimension: res.gridDimen, dimension: res.gridDimen,
DOT: res.dotGridDisplay, DOT: res.dotGridDisplay,

View File

@ -0,0 +1,42 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useState } from 'react'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import { useMessage } from '@/hooks/useMessage'
export default function ImageSizeSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition, size, setSize } = props
const [sizeValue, setSizeValue] = useState(100)
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xxxm`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.image.size.setting')} </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="range-wrap">
<input
type="range"
id="size"
name="volume"
min="20"
max="200"
step={10}
value={sizeValue}
onChange={(e) => setSizeValue(e.target.value)}
/>
<label htmlFor="size">{sizeValue}%</label>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -4,15 +4,18 @@ import { useState } from 'react'
import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine' import FlowLine from '@/components/floor-plan/modal/movement/type/FlowLine'
import Updown from '@/components/floor-plan/modal/movement/type/Updown' import Updown from '@/components/floor-plan/modal/movement/type/Updown'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { useMovementSetting } from '@/hooks/roofcover/useMovementSetting'
export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) { export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { TYPE, closePopup, buttonType, type, setType, FLOW_LINE_REF, UP_DOWN_REF, handleSave } = useMovementSetting(id)
const [buttonAct, setButtonAct] = useState(1)
const buttonMenu = [ const flowLineProps = {
{ id: 1, name: getMessage('modal.movement.flow.line.move') }, FLOW_LINE_REF,
{ id: 2, name: getMessage('modal.movement.flow.line.updown') }, }
] const updownProps = {
UP_DOWN_REF,
}
return ( return (
<WithDraggable isShow={true} pos={pos}> <WithDraggable isShow={true} pos={pos}>
@ -25,19 +28,21 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
</div> </div>
<div className="modal-body"> <div className="modal-body">
<div className="modal-btn-wrap"> <div className="modal-btn-wrap">
{buttonMenu.map((item) => ( {buttonType.map((item) => (
<button key={item.id} className={`btn-frame modal ${buttonAct === item.id ? 'act' : ''}`} onClick={() => setButtonAct(item.id)}> <button key={item.id} className={`btn-frame modal ${type === item.type ? 'act' : ''}`} onClick={() => setType(item.type)}>
{item.name} {item.name}
</button> </button>
))} ))}
</div> </div>
<div className="properties-setting-wrap outer"> <div className="properties-setting-wrap outer">
<div className="setting-tit">{getMessage('setting')}</div> <div className="setting-tit">{getMessage('setting')}</div>
{buttonAct === 1 && <FlowLine />} {type === TYPE.FLOW_LINE && <FlowLine {...flowLineProps} />}
{buttonAct === 2 && <Updown />} {type === TYPE.UP_DOWN && <Updown {...updownProps} />}
</div> </div>
<div className="grid-btn-wrap"> <div className="grid-btn-wrap">
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button> <button className="btn-frame modal act" onClick={handleSave}>
{getMessage('modal.common.save')}
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,24 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
export default function FlowLine({}) { const FLOW_LINE_TYPE = {
DOWN_LEFT: 'downLeft',
UP_RIGHT: 'upRight',
}
export default function FlowLine({ FLOW_LINE_REF }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [type, setType] = useState(FLOW_LINE_TYPE.DOWN_LEFT)
useEffect(() => {
if (type === FLOW_LINE_TYPE.DOWN_LEFT) {
FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.value = ''
FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.focus()
} else {
FLOW_LINE_REF.DOWN_LEFT_INPUT_REF.current.value = ''
FLOW_LINE_REF.UP_RIGHT_INPUT_REF.current.focus()
}
}, [type])
return ( return (
<> <>
@ -11,14 +28,28 @@ export default function FlowLine({}) {
<div className="eaves-keraba-item"> <div className="eaves-keraba-item">
<div className="eaves-keraba-th"> <div className="eaves-keraba-th">
<div className="d-check-radio pop"> <div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra01" /> <input
type="radio"
name="radio01"
id="ra01"
defaultChecked={true}
ref={FLOW_LINE_REF.DOWN_LEFT_RADIO_REF}
onChange={() => {
setType(FLOW_LINE_TYPE.DOWN_LEFT)
}}
/>
<label htmlFor="ra01">{getMessage('modal.movement.flow.line.bottom.left')}</label> <label htmlFor="ra01">{getMessage('modal.movement.flow.line.bottom.left')}</label>
</div> </div>
</div> </div>
<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: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} /> <input
type="text"
className="input-origin block"
readOnly={type !== FLOW_LINE_TYPE.DOWN_LEFT}
ref={FLOW_LINE_REF.DOWN_LEFT_INPUT_REF}
/>
</div> </div>
</div> </div>
</div> </div>
@ -26,14 +57,27 @@ export default function FlowLine({}) {
<div className="eaves-keraba-item"> <div className="eaves-keraba-item">
<div className="eaves-keraba-th"> <div className="eaves-keraba-th">
<div className="d-check-radio pop"> <div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra02" /> <input
type="radio"
name="radio01"
id="ra02"
ref={FLOW_LINE_REF.UP_RIGHT_RADIO_REF}
onChange={() => {
setType(FLOW_LINE_TYPE.UP_RIGHT)
}}
/>
<label htmlFor="ra02">{getMessage('modal.movement.flow.line.top.right')}</label> <label htmlFor="ra02">{getMessage('modal.movement.flow.line.top.right')}</label>
</div> </div>
</div> </div>
<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: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} /> <input
type="text"
className="input-origin block"
readOnly={type !== FLOW_LINE_TYPE.UP_RIGHT}
ref={FLOW_LINE_REF.UP_RIGHT_INPUT_REF}
/>
</div> </div>
<span className="thin">mm</span> <span className="thin">mm</span>
</div> </div>

View File

@ -1,7 +1,24 @@
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
export default function Updown({}) { const UP_DOWN_TYPE = {
UP: 'up',
DOWN: 'down',
}
export default function Updown({ UP_DOWN_REF }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const [type, setType] = useState(UP_DOWN_TYPE.UP)
useEffect(() => {
if (type === UP_DOWN_TYPE.UP) {
UP_DOWN_REF.DOWN_INPUT_REF.current.value = ''
UP_DOWN_REF.UP_INPUT_REF.current.focus()
} else {
UP_DOWN_REF.UP_INPUT_REF.current.value = ''
UP_DOWN_REF.DOWN_INPUT_REF.current.focus()
}
}, [type])
return ( return (
<> <>
@ -11,14 +28,23 @@ export default function Updown({}) {
<div className="eaves-keraba-item"> <div className="eaves-keraba-item">
<div className="eaves-keraba-th"> <div className="eaves-keraba-th">
<div className="d-check-radio pop"> <div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra01" /> <input
type="radio"
name="radio01"
id="ra01"
ref={UP_DOWN_REF.UP_RADIO_REF}
defaultChecked={true}
onChange={() => {
setType(UP_DOWN_TYPE.UP)
}}
/>
<label htmlFor="ra01">{getMessage('modal.movement.flow.line.updown.up')}</label> <label htmlFor="ra01">{getMessage('modal.movement.flow.line.updown.up')}</label>
</div> </div>
</div> </div>
<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: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} /> <input type="text" className="input-origin block" readOnly={type !== UP_DOWN_TYPE.UP} ref={UP_DOWN_REF.UP_INPUT_REF} />
</div> </div>
</div> </div>
</div> </div>
@ -26,14 +52,22 @@ export default function Updown({}) {
<div className="eaves-keraba-item"> <div className="eaves-keraba-item">
<div className="eaves-keraba-th"> <div className="eaves-keraba-th">
<div className="d-check-radio pop"> <div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra02" /> <input
type="radio"
name="radio01"
id="ra02"
ref={UP_DOWN_REF.DOWN_RADIO_REF}
onChange={() => {
setType(UP_DOWN_TYPE.DOWN)
}}
/>
<label htmlFor="ra02">{getMessage('modal.movement.flow.line.updown.down')}</label> <label htmlFor="ra02">{getMessage('modal.movement.flow.line.updown.down')}</label>
</div> </div>
</div> </div>
<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: '100px' }}> <div className="input-grid mr5" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={100} /> <input type="text" className="input-origin block" readOnly={type !== UP_DOWN_TYPE.DOWN} ref={UP_DOWN_REF.DOWN_INPUT_REF} />
</div> </div>
<span className="thin">mm</span> <span className="thin">mm</span>
</div> </div>

View File

@ -1,6 +1,8 @@
import WithDraggable from '@/components/common/draggable/withDraggable' 'use client'
import { useState } from 'react' import { useState } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/withDraggable'
export default function PanelBatchStatistics() { export default function PanelBatchStatistics() {
const { getMessage } = useMessage() const { getMessage } = useMessage()

View File

@ -18,6 +18,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const [image, setImage] = useState(null)
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { get, post } = useAxios() const { get, post } = useAxios()
@ -479,6 +480,24 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
</div> </div>
</td> </td>
</tr> </tr>
<tr>
<th>{getMessage('common.input.file')}</th>
<td>
<div className="flex-box">
<div className="img-edit-wrap">
<label className="img-edit-btn" htmlFor="img_file">
<span className="img-edit"></span>
{getMessage('common.input.file.load')}
</label>
<input type="file" id="img_file" style={{ display: 'none' }} onChange={(e) => setImage(e.target.files[0])} />
</div>
<div className="img-name-wrap">
<input type="text" className="input-origin al-l" defaultValue={''} value={image ? image.name : ''} readOnly />
{image && <button className="img-check" onClick={() => setImage(null)}></button>}
</div>
</div>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -1,211 +1,20 @@
import { useRecoilState, useRecoilValue } from 'recoil'
import { settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useAxios } from '@/hooks/useAxios' import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useSwal } from '@/hooks/useSwal' import { useMessage } from '@/hooks/useMessage'
import { useFirstOption } from '@/hooks/option/useFirstOption'
import { setSurfaceShapePattern } from '@/util/canvas-util'
import { canvasState } from '@/store/canvasAtom'
import { POLYGON_TYPE } from '@/common/common'
export default function FirstOption() { export default function FirstOption() {
const [objectNo, setObjectNo] = useState('test123240912001') // const [objectNo, setObjectNo] = useState('test123240912001') //
const { settingModalFirstOptions, setSettingModalFirstOptions } = useFirstOption() const { settingModalFirstOptions, setSettingModalFirstOptions } = useCanvasSetting()
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const { settingModalSecondOptions, setSettingModalSecondOptions } = useCanvasSetting()
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { option3, option4 } = settingModalSecondOptions
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { get, post } = useAxios()
const { swalFire } = useSwal() const { fetchSettings, frontSettings, onClickOption } = useCanvasSetting()
const canvas = useRecoilValue(canvasState)
// //
useEffect(() => { useEffect(() => {
console.log('FirstOption useEffect 실행') console.log('FirstOption useEffect 실행')
fetchSettings()
}, [objectNo]) }, [objectNo])
// Canvas Setting
const fetchSettings = async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item, selected: res[item.column] }))
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
//
setSettingModalFirstOptions({
option1: optionData1,
option2: optionData2,
dimensionDisplay: optionData5,
})
setSettingModalSecondOptions({
option3: optionData3,
option4: optionData4,
})
} catch (error) {
console.error('Data fetching error:', error)
}
}
const onClickOption = async (option) => {
option.selected = !option.selected
setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
setSettingModalSecondOptions({ option3, option4 })
try {
//
const dataToSend = {
firstOption1: option1.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption2: option2.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption3: dimensionDisplay.map((item) => ({
column: item.column,
selected: item.selected,
})),
// secondOption1: secondOptions[0].option1.map((item) => ({
// name: item.id,
// name: item.name,
// //
// })),
secondOption2: option4.map((item) => ({
column: item.column,
selected: item.selected,
})),
}
const patternData = {
objectNo,
// ()
allocDisplay: dataToSend.firstOption1[0].selected,
outlineDisplay: dataToSend.firstOption1[1].selected,
gridDisplay: dataToSend.firstOption1[2].selected,
lineDisplay: dataToSend.firstOption1[3].selected,
wordDisplay: dataToSend.firstOption1[4].selected,
circuitNumDisplay: dataToSend.firstOption1[5].selected,
flowDisplay: dataToSend.firstOption1[6].selected,
trestleDisplay: dataToSend.firstOption1[7].selected,
totalDisplay: dataToSend.firstOption1[8].selected,
// ()
corridorDimension: dataToSend.firstOption3[0].selected,
realDimension: dataToSend.firstOption3[1].selected,
noneDimension: dataToSend.firstOption3[2].selected,
// ()
onlyBorder: dataToSend.firstOption2[0].selected,
lineHatch: dataToSend.firstOption2[1].selected,
allPainted: dataToSend.firstOption2[2].selected,
// ()
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
}
// HTTP POST
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
swalFire({ text: getMessage(res.returnMessage) })
})
} catch (error) {
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
}
}
const onClickOnlyOne = async (item) => {
//
if (item.column === 'onlyBorder' || item.column === 'lineHatch' || item.column === 'allPainted') {
const options2 = settingModalFirstOptions?.option2.map((option2) => {
option2.selected = option2.id === item.id
return option2
})
const polygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
polygons.forEach((polygon) => {
setSurfaceShapePattern(polygon, item.column)
})
//
} else {
const options = settingModalFirstOptions?.dimensionDisplay.map((option) => {
option.selected = option.id === item.id
return option
})
}
setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
try {
//
const dataToSend = {
firstOption1: option1.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption2: option2.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption3: dimensionDisplay.map((item) => ({
column: item.column,
selected: item.selected,
})),
// secondOption1: secondOptions[0].option1.map((item) => ({
// name: item.id,
// name: item.name,
// //
// })),
secondOption2: option4.map((item) => ({
column: item.column,
selected: item.selected,
})),
}
const patternData = {
objectNo,
// ()
allocDisplay: dataToSend.firstOption1[0].selected,
outlineDisplay: dataToSend.firstOption1[1].selected,
gridDisplay: dataToSend.firstOption1[2].selected,
lineDisplay: dataToSend.firstOption1[3].selected,
wordDisplay: dataToSend.firstOption1[4].selected,
circuitNumDisplay: dataToSend.firstOption1[5].selected,
flowDisplay: dataToSend.firstOption1[6].selected,
trestleDisplay: dataToSend.firstOption1[7].selected,
totalDisplay: dataToSend.firstOption1[8].selected,
// ()
corridorDimension: dataToSend.firstOption3[0].selected,
realDimension: dataToSend.firstOption3[1].selected,
noneDimension: dataToSend.firstOption3[2].selected,
// ()
onlyBorder: dataToSend.firstOption2[0].selected,
lineHatch: dataToSend.firstOption2[1].selected,
allPainted: dataToSend.firstOption2[2].selected,
// ()
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
}
// HTTP POST
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
swalFire({ text: getMessage(res.returnMessage) })
})
} catch (error) {
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
}
}
return ( return (
<> <>
<div className="modal-check-btn-wrap"> <div className="modal-check-btn-wrap">
@ -225,7 +34,7 @@ export default function FirstOption() {
<div className="flex-check-box for-line"> <div className="flex-check-box for-line">
{settingModalFirstOptions && {settingModalFirstOptions &&
settingModalFirstOptions.dimensionDisplay.map((item) => ( settingModalFirstOptions.dimensionDisplay.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOnlyOne(item)}> <button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
<span className="check-area"></span> <span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span> <span className="title-area">{getMessage(item.name)}</span>
</button> </button>
@ -237,7 +46,7 @@ export default function FirstOption() {
<div className="flex-check-box for-line"> <div className="flex-check-box for-line">
{settingModalFirstOptions && {settingModalFirstOptions &&
settingModalFirstOptions.option2.map((item) => ( settingModalFirstOptions.option2.map((item) => (
<button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOnlyOne(item)}> <button key={item.id} className={`check-btn ${item.selected ? 'act' : ''}`} onClick={(e) => onClickOption(item)}>
<span className="check-area"></span> <span className="check-area"></span>
<span className="title-area">{getMessage(item.name)}</span> <span className="title-area">{getMessage(item.name)}</span>
</button> </button>

View File

@ -1,143 +1,34 @@
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal'
import { adsorptionPointModeState, adsorptionRangeState } from '@/store/canvasAtom'
import DimensionLineSetting from '@/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting' import DimensionLineSetting from '@/components/floor-plan/modal/setting01/dimensionLine/DimensionLineSetting'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import FontSetting from '@/components/common/font/FontSetting' import FontSetting from '@/components/common/font/FontSetting'
import PlanSizeSetting from '@/components/floor-plan/modal/setting01/planSize/PlanSizeSetting' import PlanSizeSetting from '@/components/floor-plan/modal/setting01/planSize/PlanSizeSetting'
import { dimensionLineSettingsState } from '@/store/commonUtilsAtom' import { dimensionLineSettingsState } from '@/store/commonUtilsAtom'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
export default function SecondOption() { export default function SecondOption() {
const [objectNo, setObjectNo] = useState('test123240912001') //
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const setAdsorptionRange = useSetRecoilState(adsorptionRangeState)
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { option3, option4 } = settingModalSecondOptions
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { get, post } = useAxios()
const { swalFire } = useSwal()
const { addPopup, closePopup, closePopups } = usePopup() const { addPopup, closePopup, closePopups } = usePopup()
const [showFontSettingModal, setShowFontSettingModal] = useState(false) const [showFontSettingModal, setShowFontSettingModal] = useState(false)
const [showDimensionLineSettingModal, setShowDimensionLineSettingModal] = useState(false) const [showDimensionLineSettingModal, setShowDimensionLineSettingModal] = useState(false)
const [showPlanSizeSettingModal, setShowPlanSizeSettingModal] = useState(false) const [showPlanSizeSettingModal, setShowPlanSizeSettingModal] = useState(false)
const dimensionSettings = useRecoilValue(dimensionLineSettingsState) const dimensionSettings = useRecoilValue(dimensionLineSettingsState)
const [objectNo, setObjectNo] = useState('test123240912001') //
const { settingModalFirstOptions, setSettingModalFirstOptions } = useCanvasSetting()
const { settingModalSecondOptions, setSettingModalSecondOptions } = useCanvasSetting()
const { adsorptionPointMode, setAdsorptionPointMode } = useCanvasSetting()
const { fetchSettings, frontSettings, onClickOption } = useCanvasSetting()
// //
useEffect(() => { useEffect(() => {
console.log('SecondOption useEffect 실행') console.log('SecondOption useEffect 실행')
fetchSettings() //fetchSettings()
}, [objectNo]) }, [objectNo])
// Canvas Setting
const fetchSettings = async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({
...item,
selected: res[item.column],
}))
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
setSettingModalFirstOptions({
option1: optionData1,
option2: optionData2,
dimensionDisplay: optionData5,
})
setSettingModalSecondOptions({
option3: optionData3,
option4: optionData4,
})
} catch (error) {
console.error('Data fetching error:', error)
}
}
const onClickOption = async (option) => {
// option4
const updatedOption4 = option4.map((item) =>
item.id === option.id
? { ...item, selected: true }
: {
...item,
selected: false,
},
)
setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
setSettingModalSecondOptions({ option3, option4: updatedOption4 })
try {
//
const dataToSend = {
firstOption1: option1.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption2: option2.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption3: dimensionDisplay.map((item) => ({
column: item.column,
selected: item.selected,
})),
// secondOption1: secondOptions[0].option3.map((item) => ({
// name: item.id,
// name: item.name,
// //
// })),
secondOption2: updatedOption4.map((item) => ({
column: item.column,
selected: item.selected,
})),
}
const patternData = {
objectNo,
// ()
allocDisplay: dataToSend.firstOption1[0].selected,
outlineDisplay: dataToSend.firstOption1[1].selected,
gridDisplay: dataToSend.firstOption1[2].selected,
lineDisplay: dataToSend.firstOption1[3].selected,
wordDisplay: dataToSend.firstOption1[4].selected,
circuitNumDisplay: dataToSend.firstOption1[5].selected,
flowDisplay: dataToSend.firstOption1[6].selected,
trestleDisplay: dataToSend.firstOption1[7].selected,
totalDisplay: dataToSend.firstOption1[8].selected,
// ()
corridorDimension: dataToSend.firstOption3[0].selected,
realDimension: dataToSend.firstOption3[1].selected,
noneDimension: dataToSend.firstOption3[2].selected,
// ()
onlyBorder: dataToSend.firstOption2[0].selected,
lineHatch: dataToSend.firstOption2[1].selected,
allPainted: dataToSend.firstOption2[2].selected,
// ()
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
}
// HTTP POST
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
swalFire({ text: getMessage(res.returnMessage) })
})
} catch (error) {
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
}
setAdsorptionRange(option.range)
}
let dimensionId = null let dimensionId = null
let fontId = null let fontId = null
let planSizeId = null let planSizeId = null
@ -192,16 +83,6 @@ export default function SecondOption() {
setShowFontSettingModal(false) setShowFontSettingModal(false)
switch (type) { switch (type) {
case 'dimensionLine':
if (!showDimensionLineSettingModal) {
setShowDimensionLineSettingModal(true)
addPopup(dimensionId, 2, <DimensionLineSetting {...dimensionProps} />)
} else {
setShowDimensionLineSettingModal(false)
closePopup(dimensionId)
}
break
case 'font1': { case 'font1': {
// //
setShowFontSettingModal(true) setShowFontSettingModal(true)
@ -210,6 +91,7 @@ export default function SecondOption() {
addPopup(fontId + 1, 2, <FontSetting {...fontProps} />) addPopup(fontId + 1, 2, <FontSetting {...fontProps} />)
break break
} }
case 'font2': { case 'font2': {
// //
setShowFontSettingModal(true) setShowFontSettingModal(true)
@ -218,6 +100,7 @@ export default function SecondOption() {
addPopup(fontId + 2, 2, <FontSetting {...fontProps} />) addPopup(fontId + 2, 2, <FontSetting {...fontProps} />)
break break
} }
case 'font3': { case 'font3': {
// //
setShowFontSettingModal(true) setShowFontSettingModal(true)
@ -226,17 +109,34 @@ export default function SecondOption() {
addPopup(fontId + 3, 2, <FontSetting {...fontProps} />) addPopup(fontId + 3, 2, <FontSetting {...fontProps} />)
break break
} }
case 'font4': //
case 'font4': {
//
setShowFontSettingModal(true) setShowFontSettingModal(true)
fontProps.type = 'circuitNumberText' fontProps.type = 'circuitNumberText'
fontProps.id = fontId fontProps.id = fontId
addPopup(fontId, 2, <FontSetting {...fontProps} />) addPopup(fontId, 2, <FontSetting {...fontProps} />)
break break
case 'planSize': }
setShowPlanSizeSettingModal(true)
case 'dimensionLine': {
//
if (!showDimensionLineSettingModal) {
setShowDimensionLineSettingModal(true)
addPopup(dimensionId, 2, <DimensionLineSetting {...dimensionProps} />)
} else {
setShowDimensionLineSettingModal(false)
closePopup(dimensionId)
}
break
}
case 'planSize': {
//
setShowPlanSizeSettingModal(true)
addPopup(planSizeId, 2, <PlanSizeSetting {...planSizeProps} />) addPopup(planSizeId, 2, <PlanSizeSetting {...planSizeProps} />)
break break
}
} }
} }

View File

@ -89,8 +89,8 @@ export default function Header(props) {
name: 'header.menus.management', name: 'header.menus.management',
url: '', url: '',
children: [ children: [
{ id: 3, name: 'header.menus.management.stuff', url: '/management/stuff', children: [] }, { id: 3, name: 'header.menus.management.newStuff', url: '/management/stuff/tempdetail', children: [] },
{ id: 4, name: 'header.menus.management.plan', url: '/floor-plan', children: [] }, { id: 4, name: 'header.menus.management.stuffList', url: '/management/stuff', children: [] },
], ],
}, },
{ {

View File

@ -43,9 +43,9 @@ export default function Stuff() {
const copyNo = async (value) => { const copyNo = async (value) => {
try { try {
await navigator.clipboard.writeText(value) await navigator.clipboard.writeText(value)
alert('물건번호가 복사되었습니다.') alert(getMessage('stuff.detail.header.message2'))
} catch (error) { } catch (error) {
alert('물건번호 복사에 실패했습니다.') alert(getMessage('stuff.detail.header.message3'))
} }
} }
@ -71,7 +71,7 @@ export default function Stuff() {
// headerCheckboxSelectionCurrentPageOnly: true, // // headerCheckboxSelectionCurrentPageOnly: true, //
// checkboxSelection: true, // checkboxSelection: true,
// showDisabledCheckboxes: true, // showDisabledCheckboxes: true,
cellStyle: { textAlign: 'center' }, cellStyle: { justifyContent: 'center' },
valueFormatter: function (params) { valueFormatter: function (params) {
if (params.value) { if (params.value) {
return dayjs(params?.value).format('YYYY.MM.DD HH:mm:ss') return dayjs(params?.value).format('YYYY.MM.DD HH:mm:ss')
@ -85,31 +85,32 @@ export default function Stuff() {
minWidth: 230, minWidth: 230,
headerName: getMessage('stuff.gridHeader.objectNo'), headerName: getMessage('stuff.gridHeader.objectNo'),
cellRenderer: function (params) { cellRenderer: function (params) {
let objectNo = params.value.substring(0, 1)
if (params.data.objectNo) { if (params.data.objectNo) {
return ( return (
<div> <div className="copy-ico-wrap" onDoubleClick={onDoubleClick}>
<Button {params.value.toLocaleString()}
size="sm" {objectNo === 'R' && (
color="default" <button
onPress={() => { type="button"
copyNo(params.value) className="copy_ico"
}} onClick={() => {
> copyNo(params.value)
복사 }}
</Button> ></button>
<span onDoubleClick={onDoubleClick}>{params.value}</span> )}
</div> </div>
) )
} }
}, },
cellRendererParams: { cellRendererParams: {
onPress: copyNo, onClick: copyNo,
}, },
}, },
{ {
field: 'planTotCnt', field: 'planTotCnt',
headerName: getMessage('stuff.gridHeader.planTotCnt'), headerName: getMessage('stuff.gridHeader.planTotCnt'),
cellStyle: { textAlign: 'right' }, cellStyle: { justifyContent: 'center' },
}, },
{ field: 'objectName', headerName: getMessage('stuff.gridHeader.objectName'), cellStyle: { textAlign: 'left' } }, { field: 'objectName', headerName: getMessage('stuff.gridHeader.objectName'), cellStyle: { textAlign: 'left' } },
{ {
@ -131,7 +132,7 @@ export default function Stuff() {
return null return null
} }
}, },
cellStyle: { textAlign: 'center' }, cellStyle: { justifyContent: 'center' },
}, },
{ {
field: 'createDatetime', field: 'createDatetime',
@ -143,7 +144,7 @@ export default function Stuff() {
return null return null
} }
}, },
cellStyle: { textAlign: 'center' }, cellStyle: { justifyContent: 'center' },
}, },
], ],
gridCount: 0, gridCount: 0,

View File

@ -22,12 +22,12 @@ import { floorPlanObjectState } from '@/store/floorPlanObjectAtom'
export default function StuffDetail() { export default function StuffDetail() {
const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) // const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //
const inputReceiveUserEl = useRef(null) //ref // const inputReceiveUserEl = useRef(null) //ref
const inputObjectNameEl = useRef(null) //ref // const inputObjectNameEl = useRef(null) //ref
const inputZipNoEl = useRef(null) //ref // const inputZipNoEl = useRef(null) //ref
const inputAddressEl = useRef(null) //ref // const inputAddressEl = useRef(null) //ref
const inputVerticalSnowCoverEl = useRef(null) //ref // const inputVerticalSnowCoverEl = useRef(null) //ref
const inputInstallHeightEl = useRef(null) //ref // const inputInstallHeightEl = useRef(null) //ref
// //
const { commonCode, findCommonCode } = useCommonCode() const { commonCode, findCommonCode } = useCommonCode()
@ -88,6 +88,9 @@ export default function StuffDetail() {
const [prefCodeList, setPrefCodeList] = useState([]) // const [prefCodeList, setPrefCodeList] = useState([]) //
const [prefValue, setPrefValue] = useState('') const [prefValue, setPrefValue] = useState('')
const [saleStoreList, setSaleStoreList] = useState([]) // const [saleStoreList, setSaleStoreList] = useState([]) //
const [favoriteStoreList, setFavoriteStoreList] = useState([]) //
const [showSaleStoreList, setShowSaleStoreList] = useState([]) //
const [otherSaleStoreList, setOtherSaleStoreList] = useState([]) const [otherSaleStoreList, setOtherSaleStoreList] = useState([])
const [originOtherSaleStoreList, setOriginOtherSaleStoreList] = useState([]) const [originOtherSaleStoreList, setOriginOtherSaleStoreList] = useState([])
@ -259,7 +262,7 @@ export default function StuffDetail() {
onClick={() => { onClick={() => {
//mid:5(), /pid: //mid:5(), /pid:
setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo }) setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo })
router.push(`/floor-plan/5/${params.data.planNo}`) router.push(`/floor-plan/estimate/5/${params.data.planNo}`)
}} }}
> >
<span className="file"></span> <span className="file"></span>
@ -318,21 +321,37 @@ export default function StuffDetail() {
//1 : X167 T01 //1 : X167 T01
//2 : 10X22, 201X112 //2 : 10X22, 201X112
get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { let url
if (sessionState?.storeId === 'T01') {
// url = `/api/object/saleStore/${sessionState?.storeId}/list?userId=an1`
url = `/api/object/saleStore/${sessionState?.storeId}/list?userId=${sessionState?.userId}`
} else {
url = `/api/object/saleStore/${sessionState?.storeId}/list`
}
get({ url: url }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
const firstList = res.filter((row) => row.saleStoreLevel === '1') const firstList = res.filter((row) => row.saleStoreLevel === '1')
let favList
if (sessionState?.storeId === 'T01') {
firstList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
favList = firstList.filter((row) => row.saleStoreId === 'T01' || row.priority !== 'B')
setSaleStoreList(firstList)
setFavoriteStoreList(favList)
setShowSaleStoreList(favList)
} else {
//1
setSaleStoreList(firstList)
}
const otherList = res.filter((row) => row.saleStoreLevel !== '1') const otherList = res.filter((row) => row.saleStoreLevel !== '1')
//1
setSaleStoreList(firstList)
let filterOtherList let filterOtherList
if (sessionState?.storeId === 'T01') { if (sessionState?.storeId === 'T01') {
filterOtherList = otherList.filter((row) => row.firstAgentId === 'T01') filterOtherList = otherList.filter((row) => row.firstAgentId === 'T01')
setOriginOtherSaleStoreList(filterOtherList) setOriginOtherSaleStoreList(filterOtherList)
setOtherSaleStoreList(filterOtherList) setOtherSaleStoreList(filterOtherList)
} else { } else {
//1 //T01 2
setOriginOtherSaleStoreList(otherList) setOriginOtherSaleStoreList(otherList)
setOtherSaleStoreList(otherList) setOtherSaleStoreList(otherList)
} }
@ -380,13 +399,29 @@ export default function StuffDetail() {
//1 : X167 T01 //1 : X167 T01
//2 : 10X22, 201X112 //2 : 10X22, 201X112
get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { let url
if (sessionState?.storeId === 'T01') {
// url = `/api/object/saleStore/${sessionState?.storeId}/list?userId=an1`
url = `/api/object/saleStore/${sessionState?.storeId}/list?userId=${sessionState?.userId}`
} else {
url = `/api/object/saleStore/${sessionState?.storeId}/list`
}
get({ url: url }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
const firstList = res.filter((row) => row.saleStoreLevel === '1') const firstList = res.filter((row) => row.saleStoreLevel === '1')
const otherList = res.filter((row) => row.saleStoreLevel !== '1') const otherList = res.filter((row) => row.saleStoreLevel !== '1')
let favList
//1 if (sessionState?.storeId === 'T01') {
setSaleStoreList(firstList) firstList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
favList = firstList.filter((row) => row.saleStoreId === 'T01' || row.priority !== 'B')
setSaleStoreList(firstList)
setFavoriteStoreList(favList)
setShowSaleStoreList(favList)
} else {
//1
setSaleStoreList(firstList)
}
let filterOtherList let filterOtherList
if (sessionState?.storeId === 'T01') { if (sessionState?.storeId === 'T01') {
@ -495,6 +530,16 @@ export default function StuffDetail() {
const onRadioChange = (key) => { const onRadioChange = (key) => {
setSelectObjectStatusId(key.target.value) setSelectObjectStatusId(key.target.value)
} }
//1 input
const onInputChange = (key) => {
if (key !== '') {
setShowSaleStoreList(saleStoreList)
} else {
setShowSaleStoreList(favoriteStoreList)
}
}
//1 //1
const onSelectionChange = (key) => { const onSelectionChange = (key) => {
if (isObjectNotEmpty(key)) { if (isObjectNotEmpty(key)) {
@ -516,7 +561,7 @@ export default function StuffDetail() {
} }
} else { } else {
// EDIT // EDIT
if (planReqNo !== null) { if (planReqNo !== null && planReqNo !== '') {
if (confirm(getMessage('stuff.detail.confirm.message1'))) { if (confirm(getMessage('stuff.detail.confirm.message1'))) {
delFlg = true delFlg = true
} else { } else {
@ -629,7 +674,7 @@ export default function StuffDetail() {
} }
} else { } else {
//EDIT //EDIT
if (planReqNo !== null) { if (planReqNo !== null && planReqNo !== '') {
if (confirm(getMessage('stuff.detail.confirm.message1'))) { if (confirm(getMessage('stuff.detail.confirm.message1'))) {
delFlg = true delFlg = true
} else { } else {
@ -849,7 +894,6 @@ export default function StuffDetail() {
errors.installHeight = true errors.installHeight = true
} }
// console.log(':::::', errors)
setIsFormValid(Object.keys(errors).length === 0 ? true : false) setIsFormValid(Object.keys(errors).length === 0 ? true : false)
} }
}, [ }, [
@ -906,20 +950,17 @@ export default function StuffDetail() {
// //
const onValid = async () => { const onValid = async () => {
const formData = form.getValues() const formData = form.getValues()
let errors = {} let errors = {}
let fieldNm let fieldNm
// //
if (!formData.receiveUser || formData.receiveUser.trim().length === 0) { if (!formData.receiveUser || formData.receiveUser.trim().length === 0) {
fieldNm = getMessage('stuff.detail.receiveUser') fieldNm = getMessage('stuff.detail.receiveUser')
errors = fieldNm errors = fieldNm
inputReceiveUserEl.current.focus()
} }
// //
if (!formData.objectName || formData.objectName.trim().length === 0) { if (!formData.objectName || formData.objectName.trim().length === 0) {
fieldNm = getMessage('stuff.detail.objectStatusId') fieldNm = getMessage('stuff.detail.objectStatusId')
errors = fieldNm errors = fieldNm
inputObjectNameEl.current.focus()
} }
// //
if (!formData.objectNameOmit) { if (!formData.objectNameOmit) {
@ -935,13 +976,11 @@ export default function StuffDetail() {
if (!formData.zipNo) { if (!formData.zipNo) {
fieldNm = getMessage('stuff.detail.zipNo') fieldNm = getMessage('stuff.detail.zipNo')
errors = fieldNm errors = fieldNm
inputZipNoEl.current.focus()
} }
// //
if (!formData.address) { if (!formData.address) {
fieldNm = getMessage('stuff.detail.address') fieldNm = getMessage('stuff.detail.address')
errors = fieldNm errors = fieldNm
inputAddressEl.current.focus()
} }
// //
if (!formData.prefId || formData.prefId === '0') { if (!formData.prefId || formData.prefId === '0') {
@ -962,7 +1001,6 @@ export default function StuffDetail() {
if (!formData.verticalSnowCover) { if (!formData.verticalSnowCover) {
fieldNm = getMessage('stuff.detail.verticalSnowCover') fieldNm = getMessage('stuff.detail.verticalSnowCover')
errors = fieldNm errors = fieldNm
inputVerticalSnowCoverEl.current.focus()
} }
// //
@ -974,7 +1012,6 @@ export default function StuffDetail() {
if (!formData.installHeight) { if (!formData.installHeight) {
fieldNm = getMessage('stuff.detail.installHeight') fieldNm = getMessage('stuff.detail.installHeight')
errors = fieldNm errors = fieldNm
inputInstallHeightEl.current.focus()
} }
if (Object.keys(errors).length > 0) { if (Object.keys(errors).length > 0) {
@ -1091,9 +1128,10 @@ export default function StuffDetail() {
// PUT // PUT
await promisePut({ url: apiUrl, data: params }).then((res) => { await promisePut({ url: apiUrl, data: params }).then((res) => {
if (res.status === 201) { if (res.status === 201) {
setFloorPlanObjectNo({ floorPlanObjectNo: res.data.objectNo })
alert(getMessage('stuff.detail.save')) alert(getMessage('stuff.detail.save'))
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo }) // router.refresh()
router.refresh() router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`)
} }
}) })
} }
@ -1136,16 +1174,15 @@ export default function StuffDetail() {
params.saleStoreLevel = sessionState.storeLvl params.saleStoreLevel = sessionState.storeLvl
} }
//, 0 //, 0
let snow = params.verticalSnowCover // let snow = params.verticalSnowCover
let height = params.installHeight // let height = params.installHeight
if (snow === '0') {
return alert(getMessage('stuff.detail.save.valierror1'))
}
if (height === '0') {
return alert(getMessage('stuff.detail.save.valierror2'))
}
// if (snow === '0') {
// return alert(getMessage('stuff.detail.save.valierror1'))
// }
// if (height === '0') {
// return alert(getMessage('stuff.detail.save.valierror2'))
// }
await promisePost({ url: '/api/object/save-object', data: params }).then((res) => { await promisePost({ url: '/api/object/save-object', data: params }).then((res) => {
if (res.status === 201) { if (res.status === 201) {
alert(getMessage('stuff.detail.tempSave.message1')) alert(getMessage('stuff.detail.tempSave.message1'))
@ -1231,7 +1268,7 @@ export default function StuffDetail() {
</th> </th>
<td> <td>
<div className="input-wrap" style={{ width: '500px' }}> <div className="input-wrap" style={{ width: '500px' }}>
<input type="text" className="input-light" {...form.register('receiveUser')} ref={inputReceiveUserEl} /> <input type="text" className="input-light" {...form.register('receiveUser')} />
</div> </div>
</td> </td>
</tr> </tr>
@ -1260,7 +1297,7 @@ export default function StuffDetail() {
})} })}
{/* 라디오끝 */} {/* 라디오끝 */}
<div className="input-wrap mr5" style={{ width: '545px' }}> <div className="input-wrap mr5" style={{ width: '545px' }}>
<input type="text" className="input-light" {...form.register('objectName')} ref={inputObjectNameEl} /> <input type="text" className="input-light" {...form.register('objectName')} />
</div> </div>
<div className="select-wrap" style={{ width: '120px' }}> <div className="select-wrap" style={{ width: '120px' }}>
<Select <Select
@ -1306,33 +1343,68 @@ export default function StuffDetail() {
</th> </th>
<td> <td>
<div className="flx-box"> <div className="flx-box">
<div className="select-wrap mr5" style={{ width: '567px' }}> {(sessionState?.storeId === 'T01' && (
<Select <>
id="long-value-select1" <div className="select-wrap mr5" style={{ width: '567px' }}>
instanceId="long-value-select1" <Select
className="react-select-custom" id="long-value-select1"
classNamePrefix="custom" instanceId="long-value-select1"
placeholder="Select" className="react-select-custom"
options={saleStoreList} classNamePrefix="custom"
onChange={onSelectionChange} placeholder="Select"
getOptionLabel={(x) => x.saleStoreName} options={showSaleStoreList}
getOptionValue={(x) => x.saleStoreId} onInputChange={onInputChange}
isClearable={sessionState?.storeLvl === '1' ? true : false} onChange={onSelectionChange}
isDisabled={sessionState?.storeLvl !== '1' ? true : false} getOptionLabel={(x) => x.saleStoreName}
value={saleStoreList.filter(function (option) { getOptionValue={(x) => x.saleStoreId}
return option.saleStoreId === selOptions isClearable={sessionState?.storeLvl === '1' ? true : false}
})} isDisabled={sessionState?.storeLvl !== '1' ? true : false}
/> value={showSaleStoreList.filter(function (option) {
</div> return option.saleStoreId === selOptions
<div className="input-wrap" style={{ width: '216px' }}> })}
<input ></Select>
type="text" </div>
className="input-light" <div className="input-wrap" style={{ width: '216px' }}>
value={form.watch('saleStoreId') || ''} <input
{...form.register('saleStoreId')} type="text"
readOnly className="input-light"
/> value={form.watch('saleStoreId') || ''}
</div> {...form.register('saleStoreId')}
readOnly
/>
</div>
</>
)) || (
<>
<div className="select-wrap mr5" style={{ width: '567px' }}>
<Select
id="long-value-select1"
instanceId="long-value-select1"
className="react-select-custom"
classNamePrefix="custom"
placeholder="Select"
options={saleStoreList}
onChange={onSelectionChange}
getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId}
isClearable={sessionState?.storeLvl === '1' ? true : false}
isDisabled={sessionState?.storeLvl !== '1' ? true : false}
value={saleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
></Select>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
<input
type="text"
className="input-light"
value={form.watch('saleStoreId') || ''}
{...form.register('saleStoreId')}
readOnly
/>
</div>
</>
)}
</div> </div>
</td> </td>
</tr> </tr>
@ -1386,7 +1458,7 @@ export default function StuffDetail() {
<td> <td>
<div className="flx-box"> <div className="flx-box">
<div className="input-wrap mr5" style={{ width: '200px' }}> <div className="input-wrap mr5" style={{ width: '200px' }}>
<input type="text" className="input-light" disabled value={form.watch('zipNo') || ''} ref={inputZipNoEl} /> <input type="text" className="input-light" disabled value={form.watch('zipNo') || ''} />
</div> </div>
<Button className="btn-origin grey" onPress={onSearchPostNumberPopOpen}> <Button className="btn-origin grey" onPress={onSearchPostNumberPopOpen}>
{getMessage('stuff.detail.btn.addressPop')} {getMessage('stuff.detail.btn.addressPop')}
@ -1422,13 +1494,7 @@ export default function StuffDetail() {
)} )}
</div> </div>
<div className="input-wrap mr5" style={{ width: '580px' }}> <div className="input-wrap mr5" style={{ width: '580px' }}>
<input <input type="text" className="input-light" value={form.watch('address') || ''} {...form.register('address')} />
type="text"
className="input-light"
value={form.watch('address') || ''}
{...form.register('address')}
ref={inputAddressEl}
/>
</div> </div>
</div> </div>
</td> </td>
@ -1503,7 +1569,6 @@ export default function StuffDetail() {
onKeyUp={handleKeyUp} onKeyUp={handleKeyUp}
value={form.watch('verticalSnowCover') || ''} value={form.watch('verticalSnowCover') || ''}
{...register('verticalSnowCover')} {...register('verticalSnowCover')}
ref={inputVerticalSnowCoverEl}
/> />
</div> </div>
<span className="mr10">cm</span> <span className="mr10">cm</span>
@ -1551,7 +1616,6 @@ export default function StuffDetail() {
onKeyUp={handleKeyUp} onKeyUp={handleKeyUp}
value={form.watch('installHeight') || ''} value={form.watch('installHeight') || ''}
{...register('installHeight')} {...register('installHeight')}
ref={inputInstallHeightEl}
/> />
</div> </div>
<span>m</span> <span>m</span>
@ -1651,13 +1715,7 @@ export default function StuffDetail() {
</th> </th>
<td> <td>
<div className="input-wrap" style={{ width: '500px' }}> <div className="input-wrap" style={{ width: '500px' }}>
<input <input type="text" className="input-light" {...form.register('receiveUser')} value={form.watch('receiveUser') || ''} />
type="text"
className="input-light"
{...form.register('receiveUser')}
value={form.watch('receiveUser') || ''}
ref={inputReceiveUserEl}
/>
</div> </div>
</td> </td>
</tr> </tr>
@ -1686,7 +1744,7 @@ export default function StuffDetail() {
})} })}
{/* 상세라디오끝 */} {/* 상세라디오끝 */}
<div className="input-wrap mr5" style={{ width: '545px' }}> <div className="input-wrap mr5" style={{ width: '545px' }}>
<input type="text" className="input-light" {...form.register('objectName')} ref={inputObjectNameEl} /> <input type="text" className="input-light" {...form.register('objectName')} />
</div> </div>
<div className="select-wrap" style={{ width: '120px' }}> <div className="select-wrap" style={{ width: '120px' }}>
<Select <Select
@ -1732,33 +1790,68 @@ export default function StuffDetail() {
</th> </th>
<td> <td>
<div className="flx-box"> <div className="flx-box">
<div className="select-wrap mr5" style={{ width: '567px' }}> {(sessionState?.storeId === 'T01' && (
<Select <>
id="long-value-select1" <div className="select-wrap mr5" style={{ width: '567px' }}>
instanceId="long-value-select1" <Select
className="react-select-custom" id="long-value-select1"
classNamePrefix="custom" instanceId="long-value-select1"
placeholder="Select" className="react-select-custom"
options={saleStoreList} classNamePrefix="custom"
onChange={onSelectionChange} placeholder="Select"
getOptionLabel={(x) => x.saleStoreName} options={showSaleStoreList}
getOptionValue={(x) => x.saleStoreId} onInputChange={onInputChange}
isClearable={sessionState?.storeLvl === '1' ? true : false} onChange={onSelectionChange}
isDisabled={sessionState?.storeLvl !== '1' ? true : false} getOptionLabel={(x) => x.saleStoreName}
value={saleStoreList.filter(function (option) { getOptionValue={(x) => x.saleStoreId}
return option.saleStoreId === selOptions isClearable={sessionState?.storeLvl === '1' ? true : false}
})} isDisabled={sessionState?.storeLvl !== '1' ? true : false}
/> value={saleStoreList.filter(function (option) {
</div> return option.saleStoreId === selOptions
<div className="input-wrap" style={{ width: '216px' }}> })}
<input />
type="text" </div>
className="input-light" <div className="input-wrap" style={{ width: '216px' }}>
value={form.watch('saleStoreId') || ''} <input
{...form.register('saleStoreId')} type="text"
readOnly className="input-light"
/> value={form.watch('saleStoreId') || ''}
</div> {...form.register('saleStoreId')}
readOnly
/>
</div>
</>
)) || (
<>
<div className="select-wrap mr5" style={{ width: '567px' }}>
<Select
id="long-value-select1"
instanceId="long-value-select1"
className="react-select-custom"
classNamePrefix="custom"
placeholder="Select"
options={saleStoreList}
onChange={onSelectionChange}
getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId}
isClearable={sessionState?.storeLvl === '1' ? true : false}
isDisabled={sessionState?.storeLvl !== '1' ? true : false}
value={saleStoreList.filter(function (option) {
return option.saleStoreId === selOptions
})}
/>
</div>
<div className="input-wrap" style={{ width: '216px' }}>
<input
type="text"
className="input-light"
value={form.watch('saleStoreId') || ''}
{...form.register('saleStoreId')}
readOnly
/>
</div>
</>
)}
</div> </div>
</td> </td>
</tr> </tr>
@ -1811,7 +1904,7 @@ export default function StuffDetail() {
<td> <td>
<div className="flx-box"> <div className="flx-box">
<div className="input-wrap mr5" style={{ width: '200px' }}> <div className="input-wrap mr5" style={{ width: '200px' }}>
<input type="text" className="input-light" disabled value={form.watch('zipNo') || ''} ref={inputZipNoEl} /> <input type="text" className="input-light" disabled value={form.watch('zipNo') || ''} />
</div> </div>
<Button className="btn-origin grey" onPress={onSearchPostNumberPopOpen}> <Button className="btn-origin grey" onPress={onSearchPostNumberPopOpen}>
{getMessage('stuff.detail.btn.addressPop')} {getMessage('stuff.detail.btn.addressPop')}
@ -1848,13 +1941,7 @@ export default function StuffDetail() {
)} )}
</div> </div>
<div className="input-wrap mr5" style={{ width: '580px' }}> <div className="input-wrap mr5" style={{ width: '580px' }}>
<input <input type="text" className="input-light" value={form.watch('address') || ''} {...form.register('address')} />
type="text"
className="input-light"
value={form.watch('address') || ''}
{...form.register('address')}
ref={inputAddressEl}
/>
</div> </div>
</div> </div>
</td> </td>
@ -1935,7 +2022,6 @@ export default function StuffDetail() {
onKeyUp={handleKeyUp} onKeyUp={handleKeyUp}
value={form.watch('verticalSnowCover') || ''} value={form.watch('verticalSnowCover') || ''}
{...register('verticalSnowCover')} {...register('verticalSnowCover')}
ref={inputVerticalSnowCoverEl}
/> />
</div> </div>
<span className="mr10">cm</span> <span className="mr10">cm</span>
@ -1987,7 +2073,6 @@ export default function StuffDetail() {
onKeyUp={handleKeyUp} onKeyUp={handleKeyUp}
value={form.watch('installHeight') || ''} value={form.watch('installHeight') || ''}
{...register('installHeight')} {...register('installHeight')}
ref={inputInstallHeightEl}
/> />
</div> </div>
<span>m</span> <span>m</span>
@ -2017,7 +2102,7 @@ export default function StuffDetail() {
<th>{getMessage('stuff.detail.remarks')}</th> <th>{getMessage('stuff.detail.remarks')}</th>
<td> <td>
<div className="input-wrap"> <div className="input-wrap">
<input type="text" className="input-light" {...form.register('remarks')} /> <input type="text" className="input-light" {...form.register('remarks')} value={form.watch('remarks') || ''} />
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -39,7 +39,7 @@ export default function StuffQGrid(props) {
return { return {
filter: false, filter: false,
flex: 1, flex: 1,
sortable: false, sortable: true,
suppressMovable: true, suppressMovable: true,
resizable: true, resizable: true,
suppressSizeToFit: false, suppressSizeToFit: false,

View File

@ -4,7 +4,6 @@ import React, { useEffect, useRef, useState } from 'react'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
// import Select from 'react-dropdown-select'
import Select from 'react-select' import Select from 'react-select'
import KO from '@/locales/ko.json' import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json' import JA from '@/locales/ja.json'
@ -57,7 +56,9 @@ export default function StuffSearchCondition() {
const [receiveUser, setReceiveUser] = useState('') // const [receiveUser, setReceiveUser] = useState('') //
const [dateType, setDateType] = useState('U') //(U)/(R) const [dateType, setDateType] = useState('U') //(U)/(R)
const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) // SELECT const [schSelSaleStoreList, setSchSelSaleStoreList] = useState([]) // SELECT
const [favoriteStoreList, setFavoriteStoreList] = useState([]) //
const [showSaleStoreList, setShowSaleStoreList] = useState([]) //
// //
const onSubmit = () => { const onSubmit = () => {
let diff = dayjs(endDate).diff(startDate, 'day') let diff = dayjs(endDate).diff(startDate, 'day')
@ -128,13 +129,25 @@ export default function StuffSearchCondition() {
useEffect(() => { useEffect(() => {
if (isObjectNotEmpty(sessionState)) { if (isObjectNotEmpty(sessionState)) {
// storeId T01 1 // storeId T01 1
get({ url: `/api/object/saleStore/${sessionState?.storeId}/list` }).then((res) => { let url
if (sessionState?.storeId === 'T01') {
// url = `/api/object/saleStore/${sessionState?.storeId}/list?userId=an1`
url = `/api/object/saleStore/${sessionState?.storeId}/list?userId=${sessionState?.userId}`
} else {
url = `/api/object/saleStore/${sessionState?.storeId}/list`
}
get({ url: url }).then((res) => {
if (!isEmptyArray(res)) { if (!isEmptyArray(res)) {
res.map((row) => { res.map((row) => {
row.value = row.saleStoreId row.value = row.saleStoreId
row.label = row.saleStoreName row.label = row.saleStoreName
}) })
setSchSelSaleStoreList(res) const allList = res
const favList = res.filter((row) => row.priority !== 'B')
setSchSelSaleStoreList(allList)
setFavoriteStoreList(favList)
setShowSaleStoreList(favList)
} }
}) })
} }
@ -147,6 +160,15 @@ export default function StuffSearchCondition() {
} }
} }
//
const onInputChange = (key) => {
if (key !== '') {
setShowSaleStoreList(schSelSaleStoreList)
} else {
setShowSaleStoreList(favoriteStoreList)
}
}
// //
const onSelectionChange = (key) => { const onSelectionChange = (key) => {
if (isObjectNotEmpty(key)) { if (isObjectNotEmpty(key)) {
@ -242,6 +264,7 @@ export default function StuffSearchCondition() {
onChange={(e) => { onChange={(e) => {
setSaleStoreName(saleStoreNameRef.current.value) setSaleStoreName(saleStoreNameRef.current.value)
}} }}
onKeyUp={handleByOnKeyUp}
/> />
</div> </div>
</td> </td>
@ -256,6 +279,7 @@ export default function StuffSearchCondition() {
onChange={(e) => { onChange={(e) => {
setAddress(addressRef.current.value) setAddress(addressRef.current.value)
}} }}
onKeyUp={handleByOnKeyUp}
/> />
</div> </div>
</td> </td>
@ -272,6 +296,7 @@ export default function StuffSearchCondition() {
onChange={(e) => { onChange={(e) => {
setobjectName(objectNameRef.current.value) setobjectName(objectNameRef.current.value)
}} }}
onKeyUp={handleByOnKeyUp}
/> />
</div> </div>
</td> </td>
@ -286,6 +311,7 @@ export default function StuffSearchCondition() {
onChange={(e) => { onChange={(e) => {
setDispCompanyName(dispCompanyNameRef.current.value) setDispCompanyName(dispCompanyNameRef.current.value)
}} }}
onKeyUp={handleByOnKeyUp}
/> />
</div> </div>
</td> </td>
@ -300,11 +326,15 @@ export default function StuffSearchCondition() {
classNamePrefix="custom" classNamePrefix="custom"
placeholder="Select" placeholder="Select"
ref={ref} ref={ref}
options={schSelSaleStoreList} // options={schSelSaleStoreList}
options={showSaleStoreList}
onInputChange={onInputChange}
onChange={onSelectionChange} onChange={onSelectionChange}
getOptionLabel={(x) => x.saleStoreName} getOptionLabel={(x) => x.saleStoreName}
getOptionValue={(x) => x.saleStoreId} getOptionValue={(x) => x.saleStoreId}
value={schSelSaleStoreList.filter(function (option) { // value={schSelSaleStoreList.filter(function (option) {
value={showSaleStoreList.filter(function (option) {
// console.log(' value::::', option)
if (stuffSearch?.code === 'S' && schSelSaleStoreId === '') { if (stuffSearch?.code === 'S' && schSelSaleStoreId === '') {
return false return false
} else if (stuffSearch?.code === 'S' && schSelSaleStoreId !== '') { } else if (stuffSearch?.code === 'S' && schSelSaleStoreId !== '') {
@ -338,6 +368,7 @@ export default function StuffSearchCondition() {
onChange={(e) => { onChange={(e) => {
setReceiveUser(receiveUserRef.current.value) setReceiveUser(receiveUserRef.current.value)
}} }}
onKeyUp={handleByOnKeyUp}
/> />
</div> </div>
</td> </td>

View File

@ -25,58 +25,90 @@ export default function StuffSubHeader({ type }) {
const moveFloorPlan = () => { const moveFloorPlan = () => {
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo }) setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
router.push('/floor-plan') //
router.push('/floor-plan/estimate/5/1')
} }
return ( return (
<div className="sub-header"> <>
<div className="sub-header-inner"> <div className="sub-header">
{type === 'list' && ( <div className="sub-header-inner">
<Link href={'#'}> {type === 'list' && (
<h1 className="sub-header-title">{getMessage('header.menus.management')}</h1> <>
</Link> <Link href={'#'}>
)} <h1 className="sub-header-title">{getMessage('header.menus.management')}</h1>
{type === 'temp' && (
<ul className="sub-header-title-wrap">
<li className="title-item">
<Link className="sub-header-title" href={'#'}>
{getMessage('stuff.temp.subTitle')}
</Link> </Link>
</li> <ul className="sub-header-location">
</ul> <li className="location-item">
)} <span className="home">
{type === 'detail' && ( <Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
<ul className="sub-header-title-wrap"> </span>
<li className="title-item"> </li>
<Link className="sub-header-title" href={'#'}> <li className="location-item">
{getMessage('stuff.temp.subTitle')} <span>{getMessage('header.menus.management')}</span>
</Link> </li>
</li> <li className="location-item">
<li className="title-item"> <span>{getMessage('header.menus.management.stuffList')}</span>
<a className="sub-header-title" onClick={moveFloorPlan}> </li>
<span className="icon drawing"></span> </ul>
{getMessage('plan.menu.plan.drawing')} </>
</a> )}
</li> {type === 'temp' && (
</ul> <>
)} <ul className="sub-header-title-wrap">
<li className="title-item">
{type !== 'detail' && ( <Link className="sub-header-title" href={'#'}>
<ul className="sub-header-location"> {getMessage('stuff.temp.subTitle')}
<li className="location-item"> </Link>
<span className="home"> </li>
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} /> </ul>
</span> <ul className="sub-header-location">
</li> <li className="location-item">
<li className="location-item"> <span className="home">
<span>{getMessage('header.menus.management')}</span> <Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
</li> </span>
<li className="location-item"> </li>
<span>{getMessage('header.menus.management.stuff')}</span> <li className="location-item">
</li> <span>{getMessage('header.menus.management')}</span>
</ul> </li>
)} <li className="location-item">
<span>{getMessage('header.menus.management.newStuff')}</span>
</li>
</ul>
</>
)}
{type === 'detail' && (
<>
<ul className="sub-header-title-wrap">
<li className="title-item">
<Link className="sub-header-title" href={'#'}>
{getMessage('stuff.temp.subTitle')}
</Link>
</li>
<li className="title-item">
<a className="sub-header-title" onClick={moveFloorPlan}>
<span className="icon drawing"></span>
{getMessage('plan.menu.plan.drawing')}
</a>
</li>
</ul>
<ul className="sub-header-location">
<li className="location-item">
<span className="home">
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
</span>
</li>
<li className="location-item">
<span>{getMessage('header.menus.management')}</span>
</li>
<li className="location-item">
<span>{getMessage('header.menus.management.newStuff')}</span>
</li>
</ul>
</>
)}
</div>
</div> </div>
</div> </>
) )
} }

View File

@ -0,0 +1,95 @@
import WallLineSetting from '@/components/floor-plan/modal/outerlinesetting/WallLineSetting'
import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting'
import RoofShapePassivitySetting from '@/components/floor-plan/modal/roofShape/RoofShapePassivitySetting'
import AuxiliaryDrawing from '@/components/floor-plan/modal/auxiliary/AuxiliaryDrawing'
import EavesGableEdit from '@/components/floor-plan/modal/eavesGable/EavesGableEdit'
import MovementSetting from '@/components/floor-plan/modal/movement/MovementSetting'
import WallLineOffsetSetting from '@/components/floor-plan/modal/wallLineOffset/WallLineOffsetSetting'
import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting'
import Slope from '@/components/floor-plan/modal/Slope'
import PlacementShapeDrawing from '@/components/floor-plan/modal/placementShape/PlacementShapeDrawing'
import PlacementSurfaceSetting from '@/components/floor-plan/modal/placementSurface/PlacementSurfaceSetting'
import ObjectSetting from '@/components/floor-plan/modal/object/ObjectSetting'
import BasicSetting from '@/components/floor-plan/modal/basic/BasicSetting'
import CircuitTrestleSetting from '@/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting'
import { usePopup } from '@/hooks/usePopup'
import { useState } from 'react'
import { v4 as uuidv4 } from 'uuid'
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
import { useRecoilValue } from 'recoil'
import { currentMenuState } from '@/store/canvasAtom'
import { MENU } from '@/common/common'
export default function useMenu() {
const menus = []
const currentMenu = useRecoilValue(currentMenuState)
const [popupId, setPopupId] = useState(uuidv4())
const { addPopup } = usePopup()
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch()
const handleMenu = (type) => {
if (type === 'outline') {
switch (currentMenu) {
case MENU.ROOF_COVERING.EXTERIOR_WALL_LINE:
addPopup(popupId, 1, <WallLineSetting id={popupId} />)
break
case MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS:
addPopup(popupId, 1, <RoofShapeSetting id={popupId} />)
break
case MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS:
addPopup(popupId, 1, <RoofShapePassivitySetting id={popupId} />)
break
case MENU.ROOF_COVERING.HELP_LINE_DRAWING:
addPopup(popupId, 1, <AuxiliaryDrawing id={popupId} />)
break
case MENU.ROOF_COVERING.EAVES_KERAVA_EDIT:
addPopup(popupId, 1, <EavesGableEdit id={popupId} />)
break
case MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN:
addPopup(popupId, 1, <MovementSetting id={popupId} />)
break
case MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET:
addPopup(popupId, 1, <WallLineOffsetSetting id={popupId} />)
break
case MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC:
addPopup(popupId, 1, <RoofAllocationSetting id={popupId} />)
break
}
}
if (type === 'surface') {
switch (currentMenu) {
case MENU.BATCH_CANVAS.SLOPE_SETTING:
addPopup(popupId, 1, <Slope id={popupId} />)
break
case MENU.BATCH_CANVAS.BATCH_DRAWING:
addPopup(popupId, 1, <PlacementShapeDrawing id={popupId} />)
break
case MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH:
addPopup(popupId, 1, <PlacementSurfaceSetting id={popupId} />)
break
case MENU.BATCH_CANVAS.OBJECT_BATCH:
addPopup(popupId, 1, <ObjectSetting id={popupId} />)
break
case MENU.BATCH_CANVAS.ALL_REMOVE:
deleteAllSurfacesAndObjects()
break
}
}
if (type === 'module') {
switch (currentMenu) {
case MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING:
addPopup(popupId, 1, <BasicSetting id={popupId} />)
break
case MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING:
addPopup(popupId, 1, <CircuitTrestleSetting id={popupId} />)
break
}
}
}
return {
menus,
handleMenu,
}
}

View File

@ -0,0 +1,305 @@
import { useEffect, useState } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { globalLocaleStore } from '@/store/localeAtom'
import { useMessage } from '@/hooks/useMessage'
import { useAxios } from '@/hooks/useAxios'
import { useSwal } from '@/hooks/useSwal'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import { setSurfaceShapePattern } from '@/util/canvas-util'
import { POLYGON_TYPE } from '@/common/common'
import { adsorptionPointModeState, adsorptionRangeState } from '@/store/canvasAtom'
export function useCanvasSetting() {
const canvas = useRecoilValue(canvasState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { option3, option4 } = settingModalSecondOptions
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get, post } = useAxios(globalLocaleState)
const { getMessage } = useMessage()
const { swalFire } = useSwal()
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
const setAdsorptionRange = useSetRecoilState(adsorptionRangeState)
const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
useEffect(() => {
console.log('useCanvasSetting useEffect 실행1')
fetchSettings()
}, [objectNo])
useEffect(() => {
console.log('useCanvasSetting useEffect 실행2')
//fetchSettings()
//onClickOption()
//fetchSettings()
}, [adsorptionPointMode])
useEffect(() => {
console.log('useCanvasSetting useEffect 실행3')
//fetchSettings()
//onClickOption()
//fetchSettings()
}, [settingModalFirstOptions, settingModalSecondOptions])
const fetchSettings = async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
console.log('res', res)
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item }))
const patternData = {
adsorpPoint: res.adsorpPoint,
}
// 데이터 설정
setSettingModalFirstOptions({
option1: optionData1,
option2: optionData2,
dimensionDisplay: optionData5,
})
setSettingModalSecondOptions({
option3: optionData3,
option4: optionData4,
})
setAdsorptionPointMode(patternData.adsorpPoint)
console.log('adsorptionPointMode', adsorptionPointMode)
} catch (error) {
console.error('Data fetching error:', error)
}
}
// 옵션 클릭 후 저장
const onClickOption = async (item) => {
//치수 표시(단 건 선택)
if (item.column === 'corridorDimension' || item.column === 'realDimension' || item.column === 'noneDimension') {
console.log('치수 표시 ', item)
const options = settingModalFirstOptions?.dimensionDisplay.map((option) => {
option.selected = option.id === item.id
return option
})
//화면 표시(단 건 선택)
} else if (item.column === 'onlyBorder' || item.column === 'lineHatch' || item.column === 'allPainted') {
console.log('화면 표시 ', item)
const options2 = settingModalFirstOptions?.option2.map((option2) => {
option2.selected = option2.id === item.id
return option2
})
const polygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
polygons.forEach((polygon) => {
setSurfaceShapePattern(polygon, item.column)
})
//흡착범위 설정(단 건 선택)
} else if (
item.column === 'adsorpRangeSmall' ||
item.column === 'adsorpRangeSmallSemi' ||
item.column === 'adsorpRangeMedium' ||
item.column === 'adsorpRangeLarge'
) {
console.log('화면 표시2 ', item, option4)
// option4에서 한 개만 선택 가능하도록 처리
const updatedOption4 = option4.map((option) =>
option.id === item.id
? { ...option, selected: true }
: {
...option,
selected: false,
},
)
setSettingModalSecondOptions({ option3, option4: updatedOption4 })
//흡착점 ON / OFF
} else if (item === 'adsorpPoint') {
console.log('흡착점 ON / OFF ', item)
const options2 = settingModalFirstOptions?.option2.map((option2) => {
option2.selected = option2.id === item.id
return option2
})
const polygons = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
polygons.forEach((polygon) => {
setSurfaceShapePattern(polygon, item.column)
})
//디스플레이 설정(다 건 선택)
} else {
//console.log('디스플레이 설정1 ', item.column)
console.log('디스플레이 설정 ', item)
item.selected = !item.selected
}
setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
try {
// 서버에 전송할 데이터
const dataToSend = {
firstOption1: option1.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption2: option2.map((item) => ({
column: item.column,
selected: item.selected,
})),
firstOption3: dimensionDisplay.map((item) => ({
column: item.column,
selected: item.selected,
})),
// secondOption1: secondOptions[0].option1.map((item) => ({
// name: item.id,
// name: item.name,
// // 필요한 경우 데이터 항목 추가
// })),
secondOption2: option4.map((item) => ({
column: item.column,
selected: item.selected,
})),
}
const patternData = {
objectNo,
//디스플레이 설정(다중)
allocDisplay: dataToSend.firstOption1[0].selected,
outlineDisplay: dataToSend.firstOption1[1].selected,
gridDisplay: dataToSend.firstOption1[2].selected,
lineDisplay: dataToSend.firstOption1[3].selected,
wordDisplay: dataToSend.firstOption1[4].selected,
circuitNumDisplay: dataToSend.firstOption1[5].selected,
flowDisplay: dataToSend.firstOption1[6].selected,
trestleDisplay: dataToSend.firstOption1[7].selected,
imageDisplay: dataToSend.firstOption1[8].selected,
totalDisplay: dataToSend.firstOption1[9].selected,
//차수 표시(단 건)
corridorDimension: dataToSend.firstOption3[0].selected,
realDimension: dataToSend.firstOption3[1].selected,
noneDimension: dataToSend.firstOption3[2].selected,
//화면 표시(단 건)
onlyBorder: dataToSend.firstOption2[0].selected,
lineHatch: dataToSend.firstOption2[1].selected,
allPainted: dataToSend.firstOption2[2].selected,
//흡착범위 설정(단 건)
adsorpRangeSmall: dataToSend.secondOption2[0].selected,
adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
adsorpRangeMedium: dataToSend.secondOption2[2].selected,
adsorpRangeLarge: dataToSend.secondOption2[3].selected,
//흡착점 ON/OFF
adsorpPoint: adsorptionPointMode,
}
console.log('patternData ', patternData)
// HTTP POST 요청 보내기
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
swalFire({ text: getMessage(res.returnMessage) })
// Canvas 디스플레이 설정 시 해당 옵션 적용
frontSettings()
})
} catch (error) {
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
}
setAdsorptionRange(item.range)
}
// Canvas 디스플레이 설정 시 해당 옵션 적용
const frontSettings = async () => {
const option1 = settingModalFirstOptions.option1
// 'allocDisplay' 할당 표시
// 'outlineDisplay' 외벽선 표시 'outerLine', 'wallLine'
// 'gridDisplay' 그리드 표시 'lindGrid', 'dotGrid'
// 'lineDisplay' 지붕선 표시 'roof', 'roofBase'
// 'wordDisplay' 문자 표시
// 'circuitNumDisplay' 회로번호 표시
// 'flowDisplay' 흐름방향 표시 'arrow'
// 'trestleDisplay' 가대 표시
// 'imageDisplay' 이미지 표시
// 'totalDisplay' 집계표 표시
let optionName //옵션명
let optionSelected //옵션상태
for (let i = 0; i < option1.length; i++) {
switch (option1[i].column) {
case 'allocDisplay': //할당 표시
optionName = ['1']
break
case 'outlineDisplay': //외벽선 표시
optionName = ['outerLine', 'wallLine']
break
case 'gridDisplay': //그리드 표시
optionName = ['lindGrid', 'dotGrid']
break
case 'lineDisplay': //지붕선 표시
optionName = ['roof', 'roofBase']
break
case 'wordDisplay': //문자 표시
optionName = ['6']
break
case 'circuitNumDisplay': //회로번호 표시
optionName = ['7']
break
case 'flowDisplay': //흐름방향 표시
optionName = ['arrow']
break
case 'trestleDisplay': //가대 표시
optionName = ['8']
break
case 'imageDisplay': //이미지 표시
optionName = ['9']
break
case 'totalDisplay': //집계표 표시
optionName = ['10']
break
}
// 표시 선택 상태(true/false)
optionSelected = option1[i].selected
canvas
.getObjects()
.filter((obj) => optionName.includes(obj.name))
//.filter((obj) => obj.name === optionName)
.forEach((obj) => {
obj.set({ visible: optionSelected })
//obj.set({ visible: !obj.visible })
})
// console.log(
// 'optionName',
// optionName,
// canvas.getObjects().filter((obj) => optionName.includes(obj.name)),
// )
}
}
return {
settingModalFirstOptions,
setSettingModalFirstOptions,
settingModalSecondOptions,
setSettingModalSecondOptions,
adsorptionPointMode,
setAdsorptionPointMode,
fetchSettings,
onClickOption,
frontSettings,
}
}

View File

@ -46,6 +46,7 @@ export const useCanvasSettingController = () => {
} }
} }
//
const onClickOption = async (option) => { const onClickOption = async (option) => {
option.selected = !option.selected option.selected = !option.selected

View File

@ -170,7 +170,10 @@ export function useEavesGableEdit(id) {
}) })
const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine') const wallLines = canvas.getObjects().filter((obj) => obj.name === 'wallLine')
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'pitchText')
removeTargets.forEach((obj) => {
canvas.remove(obj)
})
wallLines.forEach((wallLine) => { wallLines.forEach((wallLine) => {
addPitchTextsByOuterLines() addPitchTextsByOuterLines()
const roof = drawRoofPolygon(wallLine) const roof = drawRoofPolygon(wallLine)

View File

@ -0,0 +1,48 @@
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { usePopup } from '@/hooks/usePopup'
import { useMessage } from '@/hooks/useMessage'
import { useRef, useState } from 'react'
//동선이동 형 올림 내림
export function useMovementSetting(id) {
const TYPE = {
FLOW_LINE: 'flowLine', // 동선이동
UP_DOWN: 'updown', //형 올림내림
}
const canvas = useRecoilValue(canvasState)
const { closePopup } = usePopup()
const { getMessage } = useMessage()
const buttonType = [
{ id: 1, name: getMessage('modal.movement.flow.line.move'), type: TYPE.FLOW_LINE },
{ id: 2, name: getMessage('modal.movement.flow.line.updown'), type: TYPE.UP_DOWN },
]
const [type, setType] = useState(TYPE.FLOW_LINE)
const FLOW_LINE_REF = {
DOWN_LEFT_INPUT_REF: useRef(null),
UP_RIGHT_INPUT_REF: useRef(null),
DOWN_LEFT_RADIO_REF: useRef(null),
UP_RIGHT_RADIO_REF: useRef(null),
}
const UP_DOWN_REF = {
UP_INPUT_REF: useRef(null),
DOWN_INPUT_REF: useRef(null),
UP_RADIO_REF: useRef(null),
DOWN_RADIO_REF: useRef(null),
}
const handleSave = () => {}
return {
TYPE,
closePopup,
buttonType,
type,
setType,
FLOW_LINE_REF,
UP_DOWN_REF,
handleSave,
}
}

View File

@ -130,6 +130,12 @@ export function useRoofAllocationSetting(id) {
setSurfaceShapePattern(roof, roofDisplay.column) setSurfaceShapePattern(roof, roofDisplay.column)
drawDirectionArrow(roof) drawDirectionArrow(roof)
}) })
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
removeTargets.forEach((obj) => {
canvas.remove(obj)
})
closePopup(id) closePopup(id)
} }

View File

@ -13,6 +13,7 @@ import { writeImage } from '@/lib/canvas'
import { useCanvasEvent } from '@/hooks/useCanvasEvent' import { useCanvasEvent } from '@/hooks/useCanvasEvent'
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useFont } from '@/hooks/common/useFont' import { useFont } from '@/hooks/common/useFont'
import { OBJECT_PROTOTYPE, RELOAD_TYPE_PROTOTYPE, SAVE_KEY } from '@/common/common'
export function useCanvas(id) { export function useCanvas(id) {
const [canvas, setCanvas] = useRecoilState(canvasState) const [canvas, setCanvas] = useRecoilState(canvasState)
@ -103,6 +104,20 @@ export function useCanvas(id) {
fabric.Object.prototype.cornerStyle = 'rect' fabric.Object.prototype.cornerStyle = 'rect'
fabric.Object.prototype.cornerStrokeColor = '#2BEBC8' fabric.Object.prototype.cornerStrokeColor = '#2BEBC8'
fabric.Object.prototype.cornerSize = 6 fabric.Object.prototype.cornerSize = 6
// 해당 오브젝트 타입의 경우 저장한 값 그대로 불러와야함
OBJECT_PROTOTYPE.forEach((type) => {
type.toObject = function (propertiesToInclude) {
let source = {}
for (let key in this) {
if (typeof this[key] !== 'function' && SAVE_KEY.includes(key)) {
source.key = this[key]
}
}
return fabric.util.object.extend(this.callSuper('toObject', propertiesToInclude), source)
}
})
fabric.QLine = QLine fabric.QLine = QLine
fabric.QPolygon = QPolygon fabric.QPolygon = QPolygon
QPolygon.prototype.canvas = canvas QPolygon.prototype.canvas = canvas

View File

@ -25,6 +25,7 @@ import { useCommonUtils } from './common/useCommonUtils'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useCanvasEvent } from '@/hooks/useCanvasEvent' import { useCanvasEvent } from '@/hooks/useCanvasEvent'
import { contextMenuState } from '@/store/contextMenu' import { contextMenuState } from '@/store/contextMenu'
import ImageSizeSetting from '@/components/floor-plan/modal/image/ImageSizeSetting'
export function useContextMenu() { export function useContextMenu() {
const currentMenu = useRecoilValue(currentMenuState) // 현재 메뉴 const currentMenu = useRecoilValue(currentMenuState) // 현재 메뉴
@ -40,7 +41,7 @@ export function useContextMenu() {
const [qContextMenu, setQContextMenu] = useRecoilState(contextMenuState) const [qContextMenu, setQContextMenu] = useRecoilState(contextMenuState)
const { handleZoomClear } = useCanvasEvent() const { handleZoomClear } = useCanvasEvent()
const currentMenuSetting = (position) => { const currentMenuSetting = () => {
switch (currentMenu) { switch (currentMenu) {
case MENU.PLAN_DRAWING: case MENU.PLAN_DRAWING:
setContextMenu([ setContextMenu([
@ -108,6 +109,11 @@ export function useContextMenu() {
id: 'wallLineRemove', id: 'wallLineRemove',
name: getMessage('contextmenu.wallline.remove'), name: getMessage('contextmenu.wallline.remove'),
}, },
{
id: 'imageSizeEdit',
name: getMessage('modal.image.size.setting'),
component: <ImageSizeSetting id={popupId} />,
},
], ],
[ [
{ {
@ -174,6 +180,11 @@ export function useContextMenu() {
shortcut: ['c', 'C'], shortcut: ['c', 'C'],
name: `${getMessage('contextmenu.copy')}(C)`, name: `${getMessage('contextmenu.copy')}(C)`,
}, },
{
id: 'imageSizeEdit',
name: getMessage('modal.image.size.setting'),
component: <ImageSizeSetting id={popupId} />,
},
], ],
[ [
{ {

View File

@ -5,6 +5,7 @@ import { canvasState, currentCanvasPlanState, initCanvasPlansState, plansState,
import { useAxios } from '@/hooks/useAxios' import { useAxios } from '@/hooks/useAxios'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { SAVE_KEY } from '@/common/common'
export function usePlan() { export function usePlan() {
const [planNum, setPlanNum] = useState(0) const [planNum, setPlanNum] = useState(0)
@ -33,41 +34,7 @@ export function usePlan() {
} }
const addCanvas = () => { const addCanvas = () => {
const objs = canvas?.toJSON([ const objs = canvas?.toJSON(SAVE_KEY)
'selectable',
'name',
'parentId',
'id',
'length',
'idx',
'direction',
'parentDirection',
'lines',
'points',
'lockMovementX',
'lockMovementY',
'lockRotation',
'lockScalingX',
'lockScalingY',
'opacity',
'cells',
'maxX',
'maxY',
'minX',
'minY',
'x',
'y',
'x1',
'x2',
'y1',
'y2',
'attributes',
'stickeyPoint',
'text',
'pitch',
'uuid',
'originText',
])
const str = JSON.stringify(objs) const str = JSON.stringify(objs)

View File

@ -52,6 +52,7 @@ export async function setSession(data) {
session.storeLvl = data.storeLvl session.storeLvl = data.storeLvl
session.groupId = data.groupId session.groupId = data.groupId
session.pwdInitYn = data.pwdInitYn session.pwdInitYn = data.pwdInitYn
session.custCd = data.custCd
session.isLoggedIn = true session.isLoggedIn = true
// console.log('session:', session) // console.log('session:', session)

View File

@ -3,8 +3,8 @@
"welcome": "환영합니다. {0}님", "welcome": "환영합니다. {0}님",
"header.menus.home": "ホームへv", "header.menus.home": "ホームへv",
"header.menus.management": "物品及び図面管理", "header.menus.management": "物品及び図面管理",
"header.menus.management.stuff": "新規物件登録", "header.menus.management.newStuff": "新規 物件 登録",
"header.menus.management.plan": "モノ/図面管理", "header.menus.management.stuffList": "物件の状況",
"header.menus.community": "コミュニティ", "header.menus.community": "コミュニティ",
"header.menus.community.notice": "お知らせ", "header.menus.community.notice": "お知らせ",
"header.menus.community.faq": "FAQ", "header.menus.community.faq": "FAQ",
@ -214,20 +214,20 @@
"modal.canvas.setting.font.plan.absorption.dimension.display": "見る", "modal.canvas.setting.font.plan.absorption.dimension.display": "見る",
"modal.canvas.setting.font.plan.absorption.plan.size.setting": "図面サイズの設定", "modal.canvas.setting.font.plan.absorption.plan.size.setting": "図面サイズの設定",
"modal.canvas.setting.first.option.info": "※図面に表示する項目をクリックすると適用されます。", "modal.canvas.setting.first.option.info": "※図面に表示する項目をクリックすると適用されます。",
"modal.canvas.setting.first.option.alloc": "할당표시", "modal.canvas.setting.first.option.alloc": "割り当て表示",
"modal.canvas.setting.first.option.outline": "외벽선표시", "modal.canvas.setting.first.option.outline": "外壁線表示",
"modal.canvas.setting.first.option.plan": "도면표시", "modal.canvas.setting.first.option.grid": "グリッド表示",
"modal.canvas.setting.first.option.roof.line": "지붕선표시", "modal.canvas.setting.first.option.roof.line": "屋根線標示",
"modal.canvas.setting.first.option.grid": "그리드표시", "modal.canvas.setting.first.option.word": "文字表示",
"modal.canvas.setting.first.option.circuit.num": "회로 번호 표시", "modal.canvas.setting.first.option.circuit.num": "回路番号表示",
"modal.canvas.setting.first.option.word": "문자 표시", "modal.canvas.setting.first.option.flow": "流れ方向表示",
"modal.canvas.setting.first.option.trestle": "가대 표시", "modal.canvas.setting.first.option.trestle": "架台表示",
"modal.canvas.setting.first.option.flow": "흐름방향 표시", "modal.canvas.setting.first.option.image": "画像表示",
"modal.canvas.setting.first.option.total": "집계표 표시", "modal.canvas.setting.first.option.total": "集計表表示",
"modal.canvas.setting.first.option.dimension": "치수 표시(JA)", "modal.canvas.setting.first.option.dimension": "寸法表示",
"modal.canvas.setting.first.option.corridor.dimension": "복도치수 표시(JA)", "modal.canvas.setting.first.option.corridor.dimension": "廊下寸法表示",
"modal.canvas.setting.first.option.real.dimension": "실제치수 표시(JA)", "modal.canvas.setting.first.option.real.dimension": "実際の寸法表示",
"modal.canvas.setting.first.option.none.dimension": "치수표시없음(JA)", "modal.canvas.setting.first.option.none.dimension": "寸法表示なし",
"modal.canvas.setting.first.option.display": "画面表示", "modal.canvas.setting.first.option.display": "画面表示",
"modal.canvas.setting.first.option.border": "ボーダーのみ", "modal.canvas.setting.first.option.border": "ボーダーのみ",
"modal.canvas.setting.first.option.line": "ラインハッチ", "modal.canvas.setting.first.option.line": "ラインハッチ",
@ -274,6 +274,7 @@
"modal.panel.batch.statistic.total": "合計", "modal.panel.batch.statistic.total": "合計",
"modal.flow.direction.setting": "流れ方向の設定", "modal.flow.direction.setting": "流れ方向の設定",
"modal.flow.direction.setting.info": "流れ方向を選択してください。", "modal.flow.direction.setting.info": "流れ方向を選択してください。",
"modal.image.size.setting": "画像のサイズ変更",
"plan.message.confirm.save": "PLAN을 저장하시겠습니까?", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?",
"plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?",
"plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?",
@ -298,6 +299,14 @@
"contextmenu.auxiliary.cut": "보조선 절삭(JA)", "contextmenu.auxiliary.cut": "보조선 절삭(JA)",
"contextmenu.auxiliary.remove.all": "보조선 전체 삭제(JA)", "contextmenu.auxiliary.remove.all": "보조선 전체 삭제(JA)",
"contextmenu.line.property.edit": "各辺属性の変更", "contextmenu.line.property.edit": "各辺属性の変更",
"contextmenu.column.move": "열 이동(JA)",
"contextmenu.column.copy": "열 복사(JA)",
"contextmenu.column.remove": "コピー設定",
"contextmenu.column.insert": "열 삽입(JA)",
"contextmenu.row.move": "단 이동(JA)",
"contextmenu.row.copy": "단 복사(JA)",
"contextmenu.row.remove": "단 삭제(JA)",
"contextmenu.row.insert": "단 삽입(JA)",
"modal.line.property.edit.info": "属性を変更する辺を選択してください。", "modal.line.property.edit.info": "属性を変更する辺を選択してください。",
"modal.line.property.edit.selected": "選択した値", "modal.line.property.edit.selected": "選択した値",
"contextmenu.flow.direction.edit": "흐름 방향 변경(JA)", "contextmenu.flow.direction.edit": "흐름 방향 변경(JA)",
@ -398,6 +407,8 @@
"common.message.writeToConfirm": "作成解除を実行しますか?", "common.message.writeToConfirm": "作成解除を実行しますか?",
"common.message.password.init.success": "パスワード [{0}] に初期化されました。", "common.message.password.init.success": "パスワード [{0}] に初期化されました。",
"common.message.no.edit.save": "この文書は変更できません。", "common.message.no.edit.save": "この文書は変更できません。",
"common.input.file": "ファイルを読み込む",
"common.input.file.load": "ファイルの追加",
"common.require": "必須", "common.require": "必須",
"commons.west": "立つ", "commons.west": "立つ",
"commons.east": "ドン", "commons.east": "ドン",
@ -595,7 +606,7 @@
"stuff.planReqPopup.search.schDateGbnR": "受付日", "stuff.planReqPopup.search.schDateGbnR": "受付日",
"stuff.planReqPopup.error.message1": "設計依頼を選択してください。", "stuff.planReqPopup.error.message1": "設計依頼を選択してください。",
"stuff.search.title": "物件状況", "stuff.search.title": "物件状況",
"stuff.search.btn1": "物件登録", "stuff.search.btn1": "新規 物件 登録",
"stuff.search.btn2": "照会", "stuff.search.btn2": "照会",
"stuff.search.btn3": "初期化", "stuff.search.btn3": "初期化",
"stuff.search.schObjectNo": "品番", "stuff.search.schObjectNo": "品番",
@ -719,14 +730,25 @@
"estimate.detail.receiveUser": "担当者 ", "estimate.detail.receiveUser": "担当者 ",
"estimate.detail.title": "案件名", "estimate.detail.title": "案件名",
"estimate.detail.remarks": "メモ", "estimate.detail.remarks": "メモ",
"estimate.detail.orderType": "注文分類",
"estimate.detail.roofCns": "屋根材・仕様施工",
"estimate.detail.note": "備考",
"estimate.detail.nextSubmit": "後日資料提出",
"estimate.detail.header.fileList1": "ファイル添付", "estimate.detail.header.fileList1": "ファイル添付",
"estimate.detail.fileList.btn": "ファイル選択", "estimate.detail.fileList.btn": "ファイル選択",
"estimate.detail.header.fileList2": "添付ファイル一覧", "estimate.detail.header.fileList2": "添付ファイル一覧",
"estimate.detail.header.specialEstimate": "見積もりの具体的な", "estimate.detail.header.specialEstimate": "見積もりの具体的な",
"estimate.detail.header.specialEstimateProductInfo": "製品情報", "estimate.detail.header.specialEstimateProductInfo": "製品情報",
"estimate.detail.sepcialEstimateProductInfo.totPcs": "数量 (PCS)",
"estimate.detail.sepcialEstimateProductInfo.vol": "容量 (Kw)",
"estimate.detail.sepcialEstimateProductInfo.netAmt": "供給価格",
"estimate.detail.sepcialEstimateProductInfo.vat": "付加価値税 (10%)",
"estimate.detail.sepcialEstimateProductInfo.totPrice": "総額",
"estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "住宅PKG単価 (W)", "estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "住宅PKG単価 (W)",
"estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG容量 (Kw)", "estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG容量 (Kw)",
"estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG金額", "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG金額",
"estimate.detail.sepcialEstimateProductInfo.calcFormula1": "(モジュール容量 × 数量)÷1000",
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG単価 (W)×PKG容量(W)",
"estimate.detail.header.showPrice": "価格表示", "estimate.detail.header.showPrice": "価格表示",
"estimate.detail.showPrice.btn1": "Pricing", "estimate.detail.showPrice.btn1": "Pricing",
"estimate.detail.showPrice.description": "クリックして製品の特異性を確認する", "estimate.detail.showPrice.description": "クリックして製品の特異性を確認する",

View File

@ -3,8 +3,8 @@
"welcome": "환영합니다. {0}님", "welcome": "환영합니다. {0}님",
"header.menus.home": "Home", "header.menus.home": "Home",
"header.menus.management": "물건 및 도면 관리", "header.menus.management": "물건 및 도면 관리",
"header.menus.management.stuff": "신규 물건 등록", "header.menus.management.newStuff": "신규 물건 등록",
"header.menus.management.plan": "사물/도면 관리", "header.menus.management.stuffList": "물건 현황",
"header.menus.community": "커뮤니티", "header.menus.community": "커뮤니티",
"header.menus.community.notice": "공지", "header.menus.community.notice": "공지",
"header.menus.community.faq": "FAQ", "header.menus.community.faq": "FAQ",
@ -221,13 +221,13 @@
"modal.canvas.setting.first.option.info": "※도면에 표시하는 항목을 클릭하면 적용됩니다.", "modal.canvas.setting.first.option.info": "※도면에 표시하는 항목을 클릭하면 적용됩니다.",
"modal.canvas.setting.first.option.alloc": "할당표시", "modal.canvas.setting.first.option.alloc": "할당표시",
"modal.canvas.setting.first.option.outline": "외벽선표시", "modal.canvas.setting.first.option.outline": "외벽선표시",
"modal.canvas.setting.first.option.plan": "도면표시",
"modal.canvas.setting.first.option.roof.line": "지붕선표시",
"modal.canvas.setting.first.option.grid": "그리드표시", "modal.canvas.setting.first.option.grid": "그리드표시",
"modal.canvas.setting.first.option.circuit.num": "회로 번호 표시", "modal.canvas.setting.first.option.roof.line": "지붕선표시",
"modal.canvas.setting.first.option.word": "문자 표시", "modal.canvas.setting.first.option.word": "문자 표시",
"modal.canvas.setting.first.option.trestle": "가대 표시", "modal.canvas.setting.first.option.circuit.num": "회로 번호 표시",
"modal.canvas.setting.first.option.flow": "흐름방향 표시", "modal.canvas.setting.first.option.flow": "흐름방향 표시",
"modal.canvas.setting.first.option.trestle": "가대 표시",
"modal.canvas.setting.first.option.image": "이미지 표시",
"modal.canvas.setting.first.option.total": "집계표 표시", "modal.canvas.setting.first.option.total": "집계표 표시",
"modal.canvas.setting.first.option.dimension": "치수 표시", "modal.canvas.setting.first.option.dimension": "치수 표시",
"modal.canvas.setting.first.option.corridor.dimension": "복도치수 표시", "modal.canvas.setting.first.option.corridor.dimension": "복도치수 표시",
@ -279,6 +279,7 @@
"modal.panel.batch.statistic.total": "합계", "modal.panel.batch.statistic.total": "합계",
"modal.flow.direction.setting": "흐름 방향 설정", "modal.flow.direction.setting": "흐름 방향 설정",
"modal.flow.direction.setting.info": "흐름방향을 선택하세요.", "modal.flow.direction.setting.info": "흐름방향을 선택하세요.",
"modal.image.size.setting": "이미지 크기 조절",
"plan.message.confirm.save": "PLAN을 저장하시겠습니까?", "plan.message.confirm.save": "PLAN을 저장하시겠습니까?",
"plan.message.confirm.copy": "PLAN을 복사하시겠습니까?", "plan.message.confirm.copy": "PLAN을 복사하시겠습니까?",
"plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?", "plan.message.confirm.delete": "PLAN을 삭제하시겠습니까?",
@ -303,6 +304,14 @@
"contextmenu.auxiliary.cut": "보조선 절삭", "contextmenu.auxiliary.cut": "보조선 절삭",
"contextmenu.auxiliary.remove.all": "보조선 전체 삭제", "contextmenu.auxiliary.remove.all": "보조선 전체 삭제",
"contextmenu.line.property.edit": "각 변 속성 변경", "contextmenu.line.property.edit": "각 변 속성 변경",
"contextmenu.column.move": "열 이동",
"contextmenu.column.copy": "열 복사",
"contextmenu.column.remove": "열 삭제",
"contextmenu.column.insert": "열 삽입",
"contextmenu.row.move": "단 이동",
"contextmenu.row.copy": "단 복사",
"contextmenu.row.remove": "단 삭제",
"contextmenu.row.insert": "단 삽입",
"modal.line.property.edit.info": "속성을 변경할 변을 선택해주세요.", "modal.line.property.edit.info": "속성을 변경할 변을 선택해주세요.",
"modal.line.property.edit.selected": "선택한 값", "modal.line.property.edit.selected": "선택한 값",
"contextmenu.flow.direction.edit": "흐름 방향 변경", "contextmenu.flow.direction.edit": "흐름 방향 변경",
@ -403,6 +412,8 @@
"common.message.writeToConfirm": "작성 해제를 실행하시겠습니까?", "common.message.writeToConfirm": "작성 해제를 실행하시겠습니까?",
"common.message.password.init.success": "비밀번호 [{0}]로 초기화 되었습니다.", "common.message.password.init.success": "비밀번호 [{0}]로 초기화 되었습니다.",
"common.message.no.edit.save": "This document cannot be changed.", "common.message.no.edit.save": "This document cannot be changed.",
"common.input.file": "파일 불러오기",
"common.input.file.load": "불러오기",
"common.require": "필수", "common.require": "필수",
"commons.west": "서", "commons.west": "서",
"commons.east": "동", "commons.east": "동",
@ -600,7 +611,7 @@
"stuff.planReqPopup.search.schDateGbnR": "접수일", "stuff.planReqPopup.search.schDateGbnR": "접수일",
"stuff.planReqPopup.error.message1": "설계의뢰를 선택해주세요.", "stuff.planReqPopup.error.message1": "설계의뢰를 선택해주세요.",
"stuff.search.title": "물건현황", "stuff.search.title": "물건현황",
"stuff.search.btn1": "신규등록", "stuff.search.btn1": "신규 물건 등록",
"stuff.search.btn2": "조회", "stuff.search.btn2": "조회",
"stuff.search.btn3": "초기화", "stuff.search.btn3": "초기화",
"stuff.search.schObjectNo": "물건번호", "stuff.search.schObjectNo": "물건번호",
@ -724,14 +735,25 @@
"estimate.detail.receiveUser": "담당자", "estimate.detail.receiveUser": "담당자",
"estimate.detail.title": "안건명", "estimate.detail.title": "안건명",
"estimate.detail.remarks": "메모", "estimate.detail.remarks": "메모",
"estimate.detail.orderType": "주문분류",
"estimate.detail.roofCns": "지붕재・사양시공",
"estimate.detail.note": "비고",
"estimate.detail.nextSubmit": "후일자료제출",
"estimate.detail.header.fileList1": "파일첨부", "estimate.detail.header.fileList1": "파일첨부",
"estimate.detail.fileList.btn": "파일선택", "estimate.detail.fileList.btn": "파일선택",
"estimate.detail.header.fileList2": "첨부파일 목록", "estimate.detail.header.fileList2": "첨부파일 목록",
"estimate.detail.header.specialEstimate": "견적특이사항", "estimate.detail.header.specialEstimate": "견적특이사항",
"estimate.detail.header.specialEstimateProductInfo": "제품정보", "estimate.detail.header.specialEstimateProductInfo": "제품정보",
"estimate.detail.sepcialEstimateProductInfo.totPcs": "수량 (PCS)",
"estimate.detail.sepcialEstimateProductInfo.vol": "용량 (Kw)",
"estimate.detail.sepcialEstimateProductInfo.netAmt": "공급가액",
"estimate.detail.sepcialEstimateProductInfo.vat": "부가세 (10)",
"estimate.detail.sepcialEstimateProductInfo.totPrice": "총액",
"estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "주택PKG단가 (W)", "estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "주택PKG단가 (W)",
"estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG 용량 (Kw)", "estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG 용량 (Kw)",
"estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG 금액", "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG 금액",
"estimate.detail.sepcialEstimateProductInfo.calcFormula1": "(모듈수량 * 수량)÷100",
"estimate.detail.sepcialEstimateProductInfo.calcFormula2": "PKG단가(W) * PKG용량(W)",
"estimate.detail.header.showPrice": "가격표시", "estimate.detail.header.showPrice": "가격표시",
"estimate.detail.showPrice.btn1": "Pricing", "estimate.detail.showPrice.btn1": "Pricing",
"estimate.detail.showPrice.description": "클릭하여 제품 특이사항 확인", "estimate.detail.showPrice.description": "클릭하여 제품 특이사항 확인",

View File

@ -323,7 +323,6 @@ export const pitchSelector = selector({
set: ({ get, set }, newValue) => { set: ({ get, set }, newValue) => {
const basicSettingStateValue = get(basicSettingState) const basicSettingStateValue = get(basicSettingState)
const roofAngleSet = basicSettingStateValue.roofAngleSet const roofAngleSet = basicSettingStateValue.roofAngleSet
console.log(newValue)
if (roofAngleSet === 'slope') { if (roofAngleSet === 'slope') {
set(globalPitchState, newValue) set(globalPitchState, newValue)
} else { } else {

View File

@ -3,7 +3,7 @@ import { v1 } from 'uuid'
export const floorPlanObjectState = atom({ export const floorPlanObjectState = atom({
key: `floorPlanObjectState/${v1()}`, key: `floorPlanObjectState/${v1()}`,
default: { default: {
objectNo: '', //물건번호 floorPlanObjectNo: '', //물건번호
}, },
dangerouslyAllowMutability: true, dangerouslyAllowMutability: true,
}) })

View File

@ -1,6 +1,74 @@
import { atom } from 'recoil' import { atom } from 'recoil'
import { MENU } from '@/common/common'
export const menuNumberState = atom({ export const menuNumberState = atom({
key: 'menuNumberState', key: 'menuNumberState',
default: null, default: null,
}) })
export const menuTypeState = atom({
key: 'menuTypeState',
default: null,
})
export const menusState = atom({
key: 'menusState',
default: [
{ index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING },
{
index: 1,
name: 'plan.menu.placement.surface.initial.setting',
icon: 'con01',
title: MENU.INITIAL_CANVAS_SETTING,
},
{ index: 2, name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT },
{ index: 3, name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
{ index: 4, name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
{ index: 5, name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
{ index: 6, name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
],
})
export const subMenusState = atom({
key: 'subMenusState',
default: {
outline: [
// 지붕덮개
{ id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE },
{ id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS },
{
id: 2,
name: 'plan.menu.roof.cover.roof.shape.passivity.setting',
menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS,
},
{ id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING },
{ id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT },
{ id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN },
{ id: 6, name: 'plan.menu.roof.cover.outline.edit.offset', menu: MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET },
{ id: 7, name: 'plan.menu.roof.cover.roof.surface.alloc', menu: MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC },
],
surface: [
// 배치면
{ id: 0, name: 'plan.menu.placement.surface.slope.setting', menu: MENU.BATCH_CANVAS.SLOPE_SETTING },
{ id: 1, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING },
{ id: 2, name: 'plan.menu.placement.surface.arrangement', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH },
{ id: 3, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH },
{ id: 4, name: 'plan.menu.placement.surface.all.remove', menu: MENU.BATCH_CANVAS.ALL_REMOVE },
],
module: [
// 모듈, 회로 구성
{ id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING },
{
id: 1,
name: 'plan.menu.module.circuit.setting.circuit.trestle.setting',
menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING,
},
{
id: 2,
name: 'plan.menu.module.circuit.setting.plan.orientation',
menu: MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION,
},
],
},
})

View File

@ -12,10 +12,16 @@ export const settingModalFirstOptionsState = atom({
{ id: 6, column: 'circuitNumDisplay', name: 'modal.canvas.setting.first.option.circuit.num', selected: false }, { id: 6, column: 'circuitNumDisplay', name: 'modal.canvas.setting.first.option.circuit.num', selected: false },
{ id: 7, column: 'flowDisplay', name: 'modal.canvas.setting.first.option.flow', selected: false }, { id: 7, column: 'flowDisplay', name: 'modal.canvas.setting.first.option.flow', selected: false },
{ id: 8, column: 'trestleDisplay', name: 'modal.canvas.setting.first.option.trestle', selected: false }, { id: 8, column: 'trestleDisplay', name: 'modal.canvas.setting.first.option.trestle', selected: false },
{ id: 9, column: 'totalDisplay', name: 'modal.canvas.setting.first.option.total', selected: false }, { id: 9, column: 'imageDisplay', name: 'modal.canvas.setting.first.option.image', selected: false },
{ id: 10, column: 'totalDisplay', name: 'modal.canvas.setting.first.option.total', selected: false },
], ],
dimensionDisplay: [ dimensionDisplay: [
{ id: 1, column: 'corridorDimension', name: 'modal.canvas.setting.first.option.corridor.dimension', selected: true }, {
id: 1,
column: 'corridorDimension',
name: 'modal.canvas.setting.first.option.corridor.dimension',
selected: true,
},
{ id: 2, column: 'realDimension', name: 'modal.canvas.setting.first.option.real.dimension', selected: false }, { id: 2, column: 'realDimension', name: 'modal.canvas.setting.first.option.real.dimension', selected: false },
{ id: 3, column: 'noneDimension', name: 'modal.canvas.setting.first.option.none.dimension', selected: false }, { id: 3, column: 'noneDimension', name: 'modal.canvas.setting.first.option.none.dimension', selected: false },
], ],
@ -38,10 +44,34 @@ export const settingModalSecondOptionsState = atom({
{ id: 4, name: 'modal.canvas.setting.font.plan.edit.circuit.num' }, { id: 4, name: 'modal.canvas.setting.font.plan.edit.circuit.num' },
], ],
option4: [ option4: [
{ id: 1, column: 'adsorpRangeSmall', name: 'modal.canvas.setting.font.plan.absorption.small', selected: true, range: 10 }, {
{ id: 2, column: 'adsorpRangeSmallSemi', name: 'modal.canvas.setting.font.plan.absorption.small.semi', selected: false, range: 30 }, id: 1,
{ id: 3, column: 'adsorpRangeMedium', name: 'modal.canvas.setting.font.plan.absorption.medium', selected: false, range: 50 }, column: 'adsorpRangeSmall',
{ id: 4, column: 'adsorpRangeLarge', name: 'modal.canvas.setting.font.plan.absorption.large', selected: false, range: 70 }, name: 'modal.canvas.setting.font.plan.absorption.small',
selected: true,
range: 10,
},
{
id: 2,
column: 'adsorpRangeSmallSemi',
name: 'modal.canvas.setting.font.plan.absorption.small.semi',
selected: false,
range: 30,
},
{
id: 3,
column: 'adsorpRangeMedium',
name: 'modal.canvas.setting.font.plan.absorption.medium',
selected: false,
range: 50,
},
{
id: 4,
column: 'adsorpRangeLarge',
name: 'modal.canvas.setting.font.plan.absorption.large',
selected: false,
range: 70,
},
], ],
}, },
dangerouslyAllowMutability: true, dangerouslyAllowMutability: true,
@ -130,6 +160,15 @@ export const trestleDisplaySelector = selector({
}, },
}) })
// 디스플레이 설정 - 이미지 표시
export const imageDisplaySelector = selector({
key: 'imageDisplaySelector',
get: ({ get }) => {
const settingModalFirstOptions = get(settingModalFirstOptionsState)
return settingModalFirstOptions.option1.find((option) => option.column === 'imageDisplay').selected
},
})
// 디스플레이 설정 - 집계표 표시 // 디스플레이 설정 - 집계표 표시
export const totalDisplaySelector = selector({ export const totalDisplaySelector = selector({
key: 'totalDisplaySelector', key: 'totalDisplaySelector',

View File

@ -23,6 +23,7 @@
left: 0; left: 0;
display: block; display: block;
width: 100%; width: 100%;
height: 46.8px;
padding-bottom: 0; padding-bottom: 0;
background-color: #383838; background-color: #383838;
transition: padding .17s ease-in-out; transition: padding .17s ease-in-out;
@ -329,7 +330,7 @@
border-top: 1px solid #000; border-top: 1px solid #000;
width: 100%; width: 100%;
transition: all .17s ease-in-out; transition: all .17s ease-in-out;
z-index: 999; z-index: 99;
&.active{ &.active{
top: calc(92.8px + 50px); top: calc(92.8px + 50px);
} }
@ -544,9 +545,9 @@
.sub-content{ .sub-content{
padding-top: 46px; padding-top: 46px;
.sub-content-inner{ .sub-content-inner{
max-width: 1720px; max-width: 1760px;
margin: 0 auto; margin: 0 auto;
padding-top: 20px; padding: 20px 20px 0;
.sub-content-box{ .sub-content-box{
margin-bottom: 20px; margin-bottom: 20px;
&:last-child{ &:last-child{
@ -897,45 +898,63 @@
display: flex; display: flex;
align-items: center; align-items: center;
margin-right: 15px; margin-right: 15px;
.attachment-required{ .explane-item{
position: relative; position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 10px;
font-size: 12px; font-size: 12px;
font-weight: 400; font-weight: 400;
color: #45576F; span{
padding-right: 10px; width: 20px;
.ico{ height: 20px;
width: 23px;
height: 23px;
margin-right: 5px; margin-right: 5px;
background: url(../../public/static/images/sub/attachment_ico.svg)no-repeat center;
background-size: cover; background-size: cover;
background-repeat: no-repeat;
background-position: center;
} }
&::before{ &:before{
content: ''; content: '';
position: absolute; position: absolute;
top: 50%; top: 50%;
right: 0; left: 0;
transform: translateY(-50%); transform: translateY(-50%);
width: 1px; width: 1px;
height: 12px; height: 12px;
background-color: #D9D9D9; background-color: #D9D9D9;
} }
} &:first-child{
.click-check{ padding-left: 0;
display: flex; &::before{
align-items: center; display: none;
font-size: 12px; }
font-weight: 400; }
color: #F16A6A ; &:last-child{
padding-left: 10px; padding-right: 0;
.ico{ }
width: 14px; &.item01{
height: 14px; color: #3BBB48;
margin-right: 5px; span{
background: url(../../public/static/images/sub/click_check_ico.svg)no-repeat center; background-image: url(../../public/static/images/sub/open_ico.svg);
background-size: cover; }
}
&.item02{
color: #909000;
span{
background-image: url(../../public/static/images/sub/change_ico.svg);
}
}
&.item03{
color: #0191C9;
span{
background-image: url(../../public/static/images/sub/attachment_ico.svg);
}
}
&.item04{
color: #F16A6A;
span{
background-image: url(../../public/static/images/sub/click_check_ico.svg);
}
} }
} }
} }
@ -960,7 +979,6 @@
} }
} }
} }
} }
// 발전시물레이션 // 발전시물레이션

View File

@ -128,10 +128,3 @@
} }
} }
.grid-tip{
display: block;
width: 15px;
height: 15px;
background: url(../../public/static/images/sub/grid_tip.svg)no-repeat center;
background-size: cover;
}

View File

@ -1,7 +1,7 @@
.wrap{ .wrap{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-width: 1600px; min-width: 1280px;
min-height: 100vh; min-height: 100vh;
overflow-x: hidden; overflow-x: hidden;
} }

View File

@ -399,6 +399,12 @@ $alert-color: #101010;
color: $pop-color; color: $pop-color;
border-bottom: 1px solid #424242; border-bottom: 1px solid #424242;
padding-left: 20px; padding-left: 20px;
vertical-align: middle;
.flex-box{
display: flex;
align-items: center;
height: 100%;
}
} }
&:first-child{ &:first-child{
td, td,
@ -470,6 +476,52 @@ $alert-color: #101010;
} }
} }
.img-edit-wrap{
flex: none;
.img-edit-btn{
display: flex;
align-items: center;
height: 30px;
padding: 0 10px;
font-size: 12px;
font-weight: 400;
color: #101010;
background-color: #fff;
border-radius: 2px;
transition: all .15s ease-in-out;
.img-edit{
width: 16px;
height: 16px;
background: url(../../public/static/images/canvas/img_edit_ico.svg)no-repeat center;
background-size: cover;
margin-right: 5px;
}
&:hover{
background-color: #ebebeb;
}
}
}
.img-name-wrap{
display: flex;
align-items: center;
width: 100%;
margin-left: 10px;
input{
flex: 1;
}
.img-check{
flex: none;
width: 18px;
height: 18px;
margin-left: 5px;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
background-image: url(../../public/static/images/canvas/img_check_fail.svg);
}
}
// 외벽선 그리기 // 외벽선 그리기
.outline-wrap{ .outline-wrap{
padding: 24px 0; padding: 24px 0;
@ -1788,4 +1840,22 @@ $alert-color: #101010;
flex: none; flex: none;
} }
} }
}
//이미지 크기 설정
.range-wrap{
display: flex;
align-items: center;
input{
flex: 1;
margin-right: 10px;
}
label{
flex: none;
text-align: right;
width: 38px;
font-size: 13px;
color: #fff;
font-weight: 500;
}
} }

View File

@ -130,6 +130,10 @@ button{
font-family: 'Pretendard', sans-serif !important; font-family: 'Pretendard', sans-serif !important;
} }
.no-click{
cursor: no-drop !important;
}
// margin // margin
.mt5{margin-top: 5px !important;} .mt5{margin-top: 5px !important;}
.mt10{margin-top: 10px !important;} .mt10{margin-top: 10px !important;}

View File

@ -430,4 +430,82 @@ table{
} }
} }
} }
}
// 견적서 테이블
.esimate-table{
table{
table-layout: fixed;
border-collapse: separate;
thead{
tr{
th{
text-align: center;
font-size: 13px;
color: #fff;
font-weight: 600;
padding: 11px 5px;
background-color: #5D6A76;
&:first-child{
border-radius: 4px 0 0 4px;
}
&:last-child{
border-radius: 0 4px 4px 0;
}
}
}
}
tbody{
tr{
td{
padding: 5px 10px;
font-size: 13px;
color: #45576F;
font-weight: 400;
border-bottom: 1px solid #ECF0F4;
.form-flex-wrap{
display: flex;
align-items: center;
.input-wrap,
.select-wrap{
flex: 1;
}
.btn-area{
flex: none;
}
.icon-wrap{
margin-left: auto;
display: flex;
align-items: center;
gap: 5px;
}
}
.tb_ico{
display: block;
width: 20px;
height: 20px;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
&.change_check{
background-image: url(../../public/static/images/sub/change_ico.svg);
}
&.file_check{
background-image: url(../../public/static/images/sub/attachment_ico.svg);
}
&.open_check{
background-image: url(../../public/static/images/sub/open_ico.svg);
}
}
.grid-tip{
display: block;
width: 20px;
height: 20px;
background: url(../../public/static/images/sub/click_check_ico.svg)no-repeat center;
background-size: cover;
}
}
}
}
}
} }

View File

@ -268,7 +268,7 @@ export const getDegreeByChon = (chon) => {
export const getChonByDegree = (degree) => { export const getChonByDegree = (degree) => {
// tan(theta) = height / base // tan(theta) = height / base
const radians = (degree * Math.PI) / 180 const radians = (degree * Math.PI) / 180
return Number(Number(Math.tan(radians) * 10).toFixed(1)) return Number(Number(Math.tan(radians) * 10).toFixed(2))
} }
/** /**