Compare commits
333 Commits
main
...
feature/de
| Author | SHA1 | Date | |
|---|---|---|---|
| a652d09b8d | |||
| 4b8287579c | |||
| f03d35ec8d | |||
| 56b8917345 | |||
|
|
dbae3380d7 | ||
|
|
35708f65e9 | ||
| 391fe39a2d | |||
|
|
d1af28987b | ||
|
|
b8dad62116 | ||
| 6949236960 | |||
| e961648d85 | |||
| cbde82b0ab | |||
|
|
b2065e7699 | ||
|
|
c0c3295b04 | ||
| cbdbade89f | |||
| 704fe887f1 | |||
| 47245e438c | |||
| 0fc7ed857d | |||
| f3b8ee40fa | |||
| 3a66920104 | |||
| d244ba3b97 | |||
| d6b0e4994a | |||
|
|
f846644145 | ||
|
|
655f0781a2 | ||
| c01ed83b40 | |||
|
|
76dd1aaa43 | ||
|
|
9a800d307b | ||
| e3df21f827 | |||
| f5c098546c | |||
| 08722e8b51 | |||
|
|
7f1ef1ace4 | ||
|
|
f52fe72d2a | ||
| d5bba49ca9 | |||
| 234e7f1cf7 | |||
| c40ba2586f | |||
| fc8e85b76c | |||
| ed27f2ed93 | |||
| 1c7b81c99f | |||
| fe957102d9 | |||
| 034bfb374e | |||
| 71d3a33bf4 | |||
| 0f079080a1 | |||
| 9bf961441b | |||
| 3b96344943 | |||
| 4be94e41a2 | |||
| bd62bf7028 | |||
| 93c8bad986 | |||
| 203ddfbdf3 | |||
| b11424e70e | |||
| 49d85d437b | |||
| 88e2c8ed05 | |||
| 6b56af6119 | |||
| 287ce5c85a | |||
| 737fcf0b30 | |||
| f3dfc50f6e | |||
| 5b74a8ee6b | |||
|
|
77e34d849d | ||
|
|
b6549e06b2 | ||
| abe0ddb731 | |||
| 4a8428f9f7 | |||
|
|
7ff0178b19 | ||
|
|
6d310a6a32 | ||
|
|
ebd84967f2 | ||
| 8de8416160 | |||
| 82c8b25895 | |||
|
|
2b81cc192e | ||
|
|
028fa7f9bf | ||
| e0d0eaf017 | |||
| 04d49e6aa6 | |||
| e938feec2f | |||
| d4a83c4ec5 | |||
| 3d8e8dfed1 | |||
| ac4449f3f3 | |||
| 159bbf2e6e | |||
|
|
98d5af6d50 | ||
|
|
11a7061e0a | ||
| 61d8c083b2 | |||
| 479f5d342a | |||
| da162ac259 | |||
|
|
c0b38a00b3 | ||
|
|
bee4ee3e74 | ||
|
|
0fb3a0bb2a | ||
|
|
b12b7aaa3a | ||
|
|
cb3e5dfc47 | ||
|
|
77b473c0a1 | ||
|
|
253ddc258a | ||
|
|
cb960baa0c | ||
|
|
51a2782d3c | ||
| d1ea6229a2 | |||
|
|
e717c28758 | ||
| a08c609caa | |||
| 76938af446 | |||
| a3b62db4fa | |||
|
|
21dcdfb3ef | ||
|
|
29ccf72c5e | ||
|
|
4c219ddce9 | ||
|
|
ed721f36d0 | ||
|
|
30414568e0 | ||
| 06812b77af | |||
| bcc91e7609 | |||
| bdcacd5542 | |||
| 51e1f70c24 | |||
| 3c14f5de52 | |||
| 8f4e53c759 | |||
| a1871e105f | |||
| ed69943dc6 | |||
|
|
2897dc26e3 | ||
| 61f1036a24 | |||
|
|
08a29aec26 | ||
|
|
a742fc1f9c | ||
|
|
cf900c3e92 | ||
|
|
e2b8bc19b1 | ||
|
|
14aa4227f4 | ||
|
|
af63891df2 | ||
| 070e9d933f | |||
| e67fc749f4 | |||
|
|
adf9febc8c | ||
|
|
089ffed7af | ||
|
|
990de88caf | ||
| d53d7f4220 | |||
|
|
134becaa93 | ||
| 97f0749f5c | |||
|
|
74b3c6dac7 | ||
| 82210a99c9 | |||
| 76693640cf | |||
| 546133c27e | |||
| 8662a37177 | |||
| defebb21d7 | |||
| 11cf3b8403 | |||
| c869e9d5a3 | |||
|
|
e71c655d05 | ||
|
|
29e8ca25a5 | ||
| 0673567900 | |||
| c42e244f24 | |||
|
|
e940884312 | ||
| 115544edb4 | |||
|
|
9e9bd8f9c4 | ||
| 2da7ea0c78 | |||
| 00a201704b | |||
| 62517870b7 | |||
| 7ff52a7b19 | |||
|
|
597aaa6d42 | ||
|
|
468980abbc | ||
|
|
91ccfcb20e | ||
|
|
c35f3c1adb | ||
|
|
468c7fda6f | ||
|
|
9976ff59d6 | ||
|
|
f548506179 | ||
| d6d626f2d7 | |||
| c0cbcd18a2 | |||
| 2e86c793c3 | |||
| d38acba7c9 | |||
|
|
f3a0504d0b | ||
| b8f05a6ff0 | |||
| 0a493884c6 | |||
|
|
a316664b20 | ||
| 804911af3e | |||
|
|
59f9377cc9 | ||
|
|
15cb2cf270 | ||
|
|
1cad8eaf76 | ||
|
|
9400ee7707 | ||
| 22f8cd3fa7 | |||
| e872df680d | |||
|
|
02a0e4a67f | ||
|
|
d524b33f56 | ||
| e7b50ca642 | |||
| 3f40725647 | |||
| aa2685e558 | |||
| f32e772141 | |||
| 7d76929689 | |||
|
|
6c6e5845ef | ||
|
|
001143954e | ||
| 265593f6dd | |||
|
|
ce7c90eb6f | ||
| 2e60e848c8 | |||
|
|
51aaf342fa | ||
|
|
82632b962e | ||
|
|
bfc7b3fe32 | ||
|
|
648c2e208a | ||
| d386c42c08 | |||
| ee6f62b4ba | |||
| de8ba00e55 | |||
|
|
ebbf010e6e | ||
| b7cbc3ec47 | |||
| 8c33611440 | |||
|
|
d8e43b0d81 | ||
| cb87d6cd23 | |||
|
|
8ba79d6a06 | ||
|
|
ba06fde9cc | ||
| 1588b8cda7 | |||
|
|
9c1df779e4 | ||
|
|
2dbbd3a957 | ||
|
|
d165267ec1 | ||
| da8e0856cb | |||
|
|
78ce43969a | ||
|
|
fe10ecf476 | ||
|
|
b16174ec0d | ||
|
|
964d9bdcc7 | ||
|
|
4b6f0b1b06 | ||
|
|
9df16cad02 | ||
|
|
8354508a2b | ||
|
|
ced0eb9fc6 | ||
| 655fef744c | |||
| 0a5b6ce132 | |||
| d6b9634a89 | |||
| 66f1293b95 | |||
| 167740f33d | |||
| 87ef010ae6 | |||
| 7d37deb048 | |||
| 97ca91aa29 | |||
| be54df76f7 | |||
| c2fbc83485 | |||
| 09e985e9b5 | |||
| d10642d6d5 | |||
| 826739fb0e | |||
| 482b6b5477 | |||
| 3509e5fbb6 | |||
| a5fb44ad36 | |||
| c88a07a227 | |||
| 5982a2aa10 | |||
| 3fd81e771d | |||
| c9a53b7159 | |||
| 24ba8bfb14 | |||
| b82901271d | |||
| 25957a37e1 | |||
| 83f0eef9eb | |||
| 46f90aff1f | |||
| 11f69a01bb | |||
| c8f70e0746 | |||
| 2bb1b71a0b | |||
| de5901492b | |||
| 6f5b70342d | |||
| b88299b78d | |||
| 63d8ae092c | |||
| 7b1c9b681e | |||
| 25e8dcc050 | |||
| 3027f47d5d | |||
| 1f723c9ce7 | |||
| 5e9c22a928 | |||
| 54d06f7d51 | |||
| 7f402d5b45 | |||
| 2473cfac17 | |||
| e293d5dfde | |||
| cf9acde872 | |||
| 93b645e9e8 | |||
| 25778a099f | |||
| ba9a49501c | |||
| a2d192084b | |||
| 7fcaaece53 | |||
| cdaeab1d42 | |||
| 47e3ae7d29 | |||
|
|
5597f8ad70 | ||
| 65ec3d5153 | |||
|
|
a7e9aba26c | ||
|
|
592275c0de | ||
| 5e27ab282c | |||
| 75549b66b5 | |||
|
|
437d552b3a | ||
|
|
c631c6344e | ||
| 85d9aca6d3 | |||
|
|
0ec917b09f | ||
|
|
82e3527432 | ||
|
|
7ec9854173 | ||
|
|
b458b4e853 | ||
| 1ba9853a32 | |||
| f1d976521d | |||
|
|
dc8f033e9f | ||
|
|
943fd16e4b | ||
|
|
70c706341e | ||
|
|
c704207d2f | ||
| a7ddfacdd2 | |||
| b51dacf421 | |||
| f25dac0ae3 | |||
| c99deaf93f | |||
| 8d65765daf | |||
| 2f8ca712c9 | |||
|
|
9285caf422 | ||
| f2470b346c | |||
| 1a5f78a970 | |||
| 5979555bcb | |||
| 26047df3c8 | |||
|
|
12936ec1f9 | ||
|
|
1bb92a975e | ||
| f2a083f022 | |||
| 786c35e656 | |||
|
|
88bcf27bfb | ||
|
|
617afb8b1f | ||
|
|
414d6fa0c5 | ||
| 6919dac8f1 | |||
|
|
79d873c135 | ||
|
|
0e8ce8b2e2 | ||
|
|
c4d17d2147 | ||
| e75db5ace1 | |||
| 8848713c72 | |||
| 39d48e61f3 | |||
| e624aa0de0 | |||
| e7410e5373 | |||
| 05dd069e53 | |||
|
|
ad14bf091f | ||
|
|
c34a7fc54d | ||
| ac015123cd | |||
| f7fe0f6528 | |||
| 6b76108d8b | |||
|
|
590040fa1d | ||
|
|
9bb72bfa3a | ||
|
|
8ea6f43ddb | ||
|
|
325c2c1cc0 | ||
|
|
521bfd4303 | ||
|
|
b136bc213c | ||
| 84e8af50b8 | |||
|
|
8a5bd9f505 | ||
| 11438773a1 | |||
| 2e762537fc | |||
| 57446fa6d8 | |||
| 1fa02de62f | |||
| 06fa1766d6 | |||
| 63297328ed | |||
| 7c15da2b4c | |||
| 3432d64a3c | |||
| 9be21fc2b2 | |||
|
|
c467fc7fa8 | ||
|
|
63db694efa | ||
|
|
f915dab239 | ||
|
|
16423de079 | ||
|
|
e99a1a3854 | ||
|
|
8ca01757c9 | ||
|
|
15ff2989f4 | ||
|
|
83b27582f7 | ||
|
|
9e66b3ef7d | ||
|
|
ae2171c633 | ||
|
|
f9766a7d21 | ||
|
|
83038a7c81 | ||
|
|
3df466a717 |
3
.gitmessage.txt
Normal file
3
.gitmessage.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
[일감번호] : [제목]
|
||||||
|
|
||||||
|
[작업내용] :
|
||||||
@ -34,3 +34,5 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next
|
|||||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||||
|
|
||||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
||||||
|
|
||||||
|
deploy test
|
||||||
|
|||||||
13
dev.ecosystem.config.js
Normal file
13
dev.ecosystem.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: 'qcast-front-development',
|
||||||
|
script: 'node_modules/next/dist/bin/next',
|
||||||
|
instances: 1,
|
||||||
|
exec_mode: 'fork',
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'development',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
13
ecosystem.config.js
Normal file
13
ecosystem.config.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
module.exports = {
|
||||||
|
apps: [
|
||||||
|
{
|
||||||
|
name: 'qcast-front-production',
|
||||||
|
script: 'node_modules/next/dist/bin/next',
|
||||||
|
instances: 2,
|
||||||
|
exec_mode: 'cluster',
|
||||||
|
env: {
|
||||||
|
NODE_ENV: 'production',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@ -5,7 +5,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start -p 5000",
|
"start:cluster1": "next start -p 5000",
|
||||||
|
"start:cluster2": "next start -p 5001",
|
||||||
"start:dev": "next start -p 5010",
|
"start:dev": "next start -p 5010",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
"serve": "node server.js"
|
"serve": "node server.js"
|
||||||
@ -23,7 +24,7 @@
|
|||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"mathjs": "^13.0.2",
|
"mathjs": "^13.0.2",
|
||||||
"mssql": "^11.0.1",
|
"mssql": "^11.0.1",
|
||||||
"next": "14.2.21",
|
"next": "14.2.26",
|
||||||
"next-international": "^1.2.4",
|
"next-international": "^1.2.4",
|
||||||
"react": "^18",
|
"react": "^18",
|
||||||
"react-chartjs-2": "^5.2.0",
|
"react-chartjs-2": "^5.2.0",
|
||||||
|
|||||||
3
public/static/images/canvas/hide-check-arr.svg
Normal file
3
public/static/images/canvas/hide-check-arr.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="14" viewBox="0 0 16 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M8 0L15.7942 13.5H0.205771L8 0Z" fill="white"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 160 B |
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 11 KiB |
4
public/static/images/sub/oneonone_profile_icon.svg
Normal file
4
public/static/images/sub/oneonone_profile_icon.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="12" cy="12" r="8.25" stroke="#101010" stroke-width="1.5"/>
|
||||||
|
<path d="M7.94995 16.5C10.0485 14.302 13.9289 14.1986 16.05 16.5M14.2455 9.75C14.2455 10.9926 13.2367 12 11.9923 12C10.7479 12 9.73912 10.9926 9.73912 9.75C9.73912 8.50736 10.7479 7.5 11.9923 7.5C13.2367 7.5 14.2455 8.50736 14.2455 9.75Z" stroke="#101010" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 474 B |
@ -1,21 +1,13 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { createContext, useEffect, useState } from 'react'
|
import { createContext, useState } from 'react'
|
||||||
import { useLocalStorage } from 'usehooks-ts'
|
|
||||||
|
|
||||||
export const GlobalDataContext = createContext(null)
|
export const GlobalDataContext = createContext(null)
|
||||||
|
|
||||||
const GlobalDataProvider = ({ children }) => {
|
const GlobalDataProvider = ({ children }) => {
|
||||||
const [managementState, setManagementState] = useState(null)
|
const [managementState, setManagementState] = useState(null)
|
||||||
const [managementStateLoaded, setManagementStateLoaded] = useLocalStorage('managementStateLoaded', null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
return <GlobalDataContext.Provider value={{ managementState, setManagementState }}>{children}</GlobalDataContext.Provider>
|
||||||
if (managementState !== null) {
|
|
||||||
setManagementStateLoaded(managementState)
|
|
||||||
}
|
|
||||||
}, [managementState])
|
|
||||||
|
|
||||||
return <GlobalDataContext.Provider value={{ managementState, setManagementState, managementStateLoaded }}>{children}</GlobalDataContext.Provider>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GlobalDataProvider
|
export default GlobalDataProvider
|
||||||
|
|||||||
@ -21,8 +21,8 @@ import GlobalLoadingProvider from './GlobalLoadingProvider'
|
|||||||
* 서버 컴포넌트에 한해서 개별로 설정할 수 있음
|
* 서버 컴포넌트에 한해서 개별로 설정할 수 있음
|
||||||
*/
|
*/
|
||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: 'HANASYS設計',
|
title: 'HANASYS DESIGN',
|
||||||
description: 'HANASYS設計',
|
description: 'HANASYS DESIGN',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -58,6 +58,7 @@ export default async function RootLayout({ children }) {
|
|||||||
pwdInitYn: session.pwdInitYn,
|
pwdInitYn: session.pwdInitYn,
|
||||||
custCd: session.custCd,
|
custCd: session.custCd,
|
||||||
isLoggedIn: session.isLoggedIn,
|
isLoggedIn: session.isLoggedIn,
|
||||||
|
builderNo: session.builderNo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!headerPathname.includes('/login') && !session.isLoggedIn) {
|
if (!headerPathname.includes('/login') && !session.isLoggedIn) {
|
||||||
|
|||||||
@ -125,6 +125,11 @@ export const TRESTLE_MATERIAL = {
|
|||||||
BRACKET: 'bracket',
|
BRACKET: 'bracket',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const MODULE_SETUP_TYPE = {
|
||||||
|
LAYOUT: 'layout',
|
||||||
|
AUTO: 'auto',
|
||||||
|
}
|
||||||
|
|
||||||
export const SAVE_KEY = [
|
export const SAVE_KEY = [
|
||||||
'selectable',
|
'selectable',
|
||||||
'name',
|
'name',
|
||||||
@ -203,6 +208,7 @@ export const SAVE_KEY = [
|
|||||||
'fontWeight',
|
'fontWeight',
|
||||||
'dormerAttributes',
|
'dormerAttributes',
|
||||||
'toFixed',
|
'toFixed',
|
||||||
|
'isSortedPoints',
|
||||||
]
|
]
|
||||||
|
|
||||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
|
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
|
||||||
|
|||||||
@ -2,26 +2,111 @@
|
|||||||
|
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { setSession, login } from '@/lib/authActions'
|
||||||
|
import { sessionStore } from '@/store/commonAtom'
|
||||||
|
import { useRecoilState } from 'recoil'
|
||||||
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
|
import { useRouter } from 'next/navigation'
|
||||||
|
|
||||||
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
||||||
|
|
||||||
export default function AutoLoginPage() {
|
export default function AutoLoginPage({ autoLoginParam }) {
|
||||||
const [isLoading, setIsLoading] = useState(true)
|
const router = useRouter()
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(autoLoginParam === 'Y' ? false : true)
|
||||||
|
const [globalLocaleState, setGlbalLocaleState] = useRecoilState(globalLocaleStore)
|
||||||
|
|
||||||
|
const { promisePost } = useAxios(globalLocaleState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
const [userId, setUserId] = useState('')
|
||||||
|
const [sessionState, setSessionState] = useRecoilState(sessionStore)
|
||||||
|
|
||||||
|
const [idFocus, setIdFocus] = useState(false)
|
||||||
|
|
||||||
|
const loginProcess = async () => {
|
||||||
|
setIsLoading(true)
|
||||||
|
await promisePost({ url: '/api/login/v1.0/user', data: { loginId: userId } }).then((response) => {
|
||||||
|
setIsLoading(false)
|
||||||
|
if (response.data) {
|
||||||
|
const res = response.data
|
||||||
|
const result = { ...res, storeLvl: res.groupId === '60000' ? '1' : '2', pwdInitYn: 'Y' }
|
||||||
|
setSession(result)
|
||||||
|
setSessionState(result)
|
||||||
|
login()
|
||||||
|
} else {
|
||||||
|
alert(getMessage('login.fail'))
|
||||||
|
router.push('/login?autoLoginParam1=Y')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{isLoading && <GlobalSpinner />}
|
{isLoading && <GlobalSpinner />}
|
||||||
<div className="login-input-frame">
|
{autoLoginParam !== 'Y' ? (
|
||||||
<div className="login-frame-tit ">
|
<>
|
||||||
<span>{getMessage('site.name')}</span>
|
<div className="login-input-frame">
|
||||||
{getMessage('site.sub_name')}
|
<div className="login-frame-tit ">
|
||||||
</div>
|
<span>{getMessage('site.name')}</span>
|
||||||
<div className="login-input-wrap">
|
{getMessage('site.sub_name')}
|
||||||
<div className="login-area id" style={{ fontWeight: 'bolder' }}>
|
</div>
|
||||||
{getMessage('login.auto.page.text')}
|
<div className="login-input-wrap">
|
||||||
|
<div className="login-area id" style={{ fontWeight: 'bolder' }}>
|
||||||
|
{getMessage('login.auto.page.text')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</>
|
||||||
</div>
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="login-input-frame">
|
||||||
|
<form
|
||||||
|
onSubmit={(e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
loginProcess()
|
||||||
|
}}
|
||||||
|
className="space-y-6"
|
||||||
|
>
|
||||||
|
<div className="login-frame-tit">
|
||||||
|
<span>{getMessage('site.name')}</span>
|
||||||
|
{getMessage('site.sub_name')}
|
||||||
|
</div>
|
||||||
|
<div className="login-input-wrap">
|
||||||
|
<div className={`login-area id ${idFocus ? 'focus' : ''}`}>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="login-input"
|
||||||
|
id="userId"
|
||||||
|
name="id"
|
||||||
|
required
|
||||||
|
value={userId}
|
||||||
|
placeholder={getMessage('login.id.placeholder')}
|
||||||
|
onChange={(e) => {
|
||||||
|
setUserId(e.target.value)
|
||||||
|
}}
|
||||||
|
onFocus={() => setIdFocus(true)}
|
||||||
|
onBlur={() => setIdFocus(false)}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="id-delete"
|
||||||
|
onClick={(e) => {
|
||||||
|
setUserId('')
|
||||||
|
}}
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div className="login-btn-box">
|
||||||
|
<button type="submit" className="login-btn">
|
||||||
|
{getMessage('login')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,7 +25,9 @@ export default function Login() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (autoLoginParam) {
|
if (autoLoginParam) {
|
||||||
autoLoginProcess(autoLoginParam)
|
if (autoLoginParam !== 'Y') {
|
||||||
|
autoLoginProcess(autoLoginParam)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// console.log('🚀 ~ checkSession ~ checkSession():', checkSession())
|
// console.log('🚀 ~ checkSession ~ checkSession():', checkSession())
|
||||||
@ -334,7 +336,7 @@ export default function Login() {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{autoLoginParam && <AutoLogin />}
|
{autoLoginParam && <AutoLogin autoLoginParam={autoLoginParam} />}
|
||||||
</div>
|
</div>
|
||||||
<div className="login-copyright">COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</div>
|
<div className="login-copyright">COPYRIGHT©2024 Hanwha Japan All Rights Reserved.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,29 +6,19 @@ import { contextMenuListState, contextMenuState } from '@/store/contextMenu'
|
|||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
import { useContextMenu } from '@/hooks/useContextMenu'
|
import { useContextMenu } from '@/hooks/useContextMenu'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||||
|
|
||||||
export default function QContextMenu(props) {
|
export default function QContextMenu(props) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { contextRef, canvasProps } = props
|
const { contextRef, canvasProps } = props
|
||||||
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
const [contextMenu, setContextMenu] = useRecoilState(contextMenuState)
|
||||||
const contextMenuList = useRecoilValue(contextMenuListState)
|
const contextMenuList = useRecoilValue(contextMenuListState)
|
||||||
const activeObject = canvasProps?.getActiveObject() //액티브된 객체를 가져옴
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
const { tempGridMode, setTempGridMode } = useTempGrid()
|
const { tempGridMode, setTempGridMode } = useTempGrid()
|
||||||
const { handleKeyup } = useContextMenu()
|
const { handleKeyup } = useContextMenu()
|
||||||
const { addDocumentEventListener, removeDocumentEvent } = useEvent()
|
const { addDocumentEventListener, removeDocumentEvent } = useEvent()
|
||||||
// const { addDocumentEventListener, removeDocumentEvent } = useContext(EventContext)
|
// const { addDocumentEventListener, removeDocumentEvent } = useContext(EventContext)
|
||||||
|
|
||||||
let contextType = ''
|
|
||||||
|
|
||||||
if (activeObject) {
|
|
||||||
if (activeObject.initOptions && activeObject.initOptions.name) {
|
|
||||||
//이건 바뀔 가능성이 있음
|
|
||||||
if (activeObject.initOptions?.name?.indexOf('guide') > -1) {
|
|
||||||
contextType = 'surface' //면형상
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const getYPosition = (e) => {
|
const getYPosition = (e) => {
|
||||||
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
const contextLength = contextMenuList.reduce((acc, cur, index) => {
|
||||||
return acc + cur.length
|
return acc + cur.length
|
||||||
@ -36,11 +26,13 @@ export default function QContextMenu(props) {
|
|||||||
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
return e?.clientY - (contextLength * 25 + contextMenuList.length * 2 * 17)
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
const handleContextMenu = (e) => {
|
||||||
if (!contextRef.current) return
|
// e.preventDefault() //기존 contextmenu 막고
|
||||||
|
|
||||||
|
if (currentObject) {
|
||||||
|
const isArray = currentObject.hasOwnProperty('arrayData')
|
||||||
|
if (isArray && currentObject.arrayData.length === 0) return
|
||||||
|
|
||||||
const handleContextMenu = (e) => {
|
|
||||||
e.preventDefault() //기존 contextmenu 막고
|
|
||||||
if (tempGridMode) return
|
if (tempGridMode) return
|
||||||
const position = {
|
const position = {
|
||||||
x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX,
|
x: window.innerWidth / 2 < e.pageX ? e.pageX - 240 : e.pageX,
|
||||||
@ -48,21 +40,24 @@ export default function QContextMenu(props) {
|
|||||||
}
|
}
|
||||||
setContextMenu({ visible: true, ...position, currentMousePos: canvasProps.getPointer(e) })
|
setContextMenu({ visible: true, ...position, currentMousePos: canvasProps.getPointer(e) })
|
||||||
addDocumentEventListener('keyup', document, handleKeyup)
|
addDocumentEventListener('keyup', document, handleKeyup)
|
||||||
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleClick = (e) => {
|
const handleClick = (e) => {
|
||||||
// e.preventDefault()
|
// e.preventDefault()
|
||||||
|
setContextMenu({ ...contextMenu, visible: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOutsideClick = (e) => {
|
||||||
|
// e.preventDefault()
|
||||||
|
if (contextMenu.visible) {
|
||||||
setContextMenu({ ...contextMenu, visible: false })
|
setContextMenu({ ...contextMenu, visible: false })
|
||||||
|
removeDocumentEvent('keyup')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const handleOutsideClick = (e) => {
|
useEffect(() => {
|
||||||
// e.preventDefault()
|
if (!contextRef.current) return
|
||||||
if (contextMenu.visible) {
|
|
||||||
setContextMenu({ ...contextMenu, visible: false })
|
|
||||||
removeDocumentEvent('keyup')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
canvasProps?.upperCanvasEl.addEventListener('contextmenu', handleContextMenu)
|
canvasProps?.upperCanvasEl.addEventListener('contextmenu', handleContextMenu)
|
||||||
document.addEventListener('click', handleClick)
|
document.addEventListener('click', handleClick)
|
||||||
@ -72,43 +67,9 @@ export default function QContextMenu(props) {
|
|||||||
removeDocumentEvent('keyup')
|
removeDocumentEvent('keyup')
|
||||||
document.removeEventListener('click', handleClick)
|
document.removeEventListener('click', handleClick)
|
||||||
document.removeEventListener('click', handleOutsideClick)
|
document.removeEventListener('click', handleOutsideClick)
|
||||||
|
canvasProps?.upperCanvasEl.removeEventListener('contextmenu', handleContextMenu) //한번 노출 후 이벤트 삭제
|
||||||
}
|
}
|
||||||
}, [contextRef, contextMenuList])
|
}, [contextRef, contextMenuList, currentObject])
|
||||||
|
|
||||||
const handleObjectMove = () => {
|
|
||||||
activeObject.set({
|
|
||||||
lockMovementX: false, // X 축 이동 잠금
|
|
||||||
lockMovementY: false, // Y 축 이동 잠금
|
|
||||||
})
|
|
||||||
|
|
||||||
canvasProps?.on('object:modified', function (e) {
|
|
||||||
activeObject.set({
|
|
||||||
lockMovementX: true, // X 축 이동 잠금
|
|
||||||
lockMovementY: true, // Y 축 이동 잠금
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleObjectDelete = () => {
|
|
||||||
if (confirm('삭제하실거?')) {
|
|
||||||
canvasProps.remove(activeObject)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleObjectCopy = () => {
|
|
||||||
activeObject.clone((cloned) => {
|
|
||||||
cloned.set({
|
|
||||||
left: activeObject.left + activeObject.width + 20,
|
|
||||||
initOptions: { ...activeObject.initOptions },
|
|
||||||
lockMovementX: true, // X 축 이동 잠금
|
|
||||||
lockMovementY: true, // Y 축 이동 잠금
|
|
||||||
lockRotation: true, // 회전 잠금
|
|
||||||
lockScalingX: true, // X 축 크기 조정 잠금
|
|
||||||
lockScalingY: true, // Y 축 크기 조정 잠금
|
|
||||||
})
|
|
||||||
canvasProps?.add(cloned)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export default function QSelectBox({
|
|||||||
targetKey = '',
|
targetKey = '',
|
||||||
showKey = '',
|
showKey = '',
|
||||||
params = {},
|
params = {},
|
||||||
|
tagTitle = '',
|
||||||
}) {
|
}) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ export default function QSelectBox({
|
|||||||
if (showKey !== '' && !value) {
|
if (showKey !== '' && !value) {
|
||||||
//value가 없으면 showKey가 있으면 우선 보여준다
|
//value가 없으면 showKey가 있으면 우선 보여준다
|
||||||
// return options[0][showKey]
|
// return options[0][showKey]
|
||||||
return title
|
return title !== '' ? title : getMessage('selectbox.title')
|
||||||
} else if (showKey !== '' && value) {
|
} else if (showKey !== '' && value) {
|
||||||
//value가 있으면 sourceKey와 targetKey를 비교하여 보여준다
|
//value가 있으면 sourceKey와 targetKey를 비교하여 보여준다
|
||||||
|
|
||||||
@ -82,12 +83,13 @@ export default function QSelectBox({
|
|||||||
className={`sort-select ${openSelect ? 'active' : ''} ${disabled ? 'disabled' : ''}`}
|
className={`sort-select ${openSelect ? 'active' : ''} ${disabled ? 'disabled' : ''}`}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}
|
onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}
|
||||||
|
title={tagTitle}
|
||||||
>
|
>
|
||||||
<p>{selected}</p>
|
<p>{selected}</p>
|
||||||
<ul className="select-item-wrap">
|
<ul className="select-item-wrap">
|
||||||
{options?.length > 0 &&
|
{options?.length > 0 &&
|
||||||
options?.map((option, index) => (
|
options?.map((option, index) => (
|
||||||
<li key={option.id || index} className="select-item" onClick={() => handleClickSelectOption(option)}>
|
<li key={option.id + '_' + index} className="select-item" onClick={() => handleClickSelectOption(option)}>
|
||||||
<button key={option.id + 'btn'}>{showKey !== '' ? option[showKey] : option.name}</button>
|
<button key={option.id + 'btn'}>{showKey !== '' ? option[showKey] : option.name}</button>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import dayjs from 'dayjs'
|
|||||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||||
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
import { useEstimateController } from '@/hooks/floorPlan/estimate/useEstimateController'
|
||||||
import { SessionContext } from '@/app/SessionProvider'
|
import { SessionContext } from '@/app/SessionProvider'
|
||||||
import Select from 'react-select'
|
import Select, { components } from 'react-select'
|
||||||
import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from '@/util/common-utils'
|
import { convertNumberToPriceDecimal, convertNumberToPriceDecimalToFixed } from '@/util/common-utils'
|
||||||
import ProductFeaturesPop from './popup/ProductFeaturesPop'
|
import ProductFeaturesPop from './popup/ProductFeaturesPop'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
@ -175,7 +175,10 @@ export default function Estimate({}) {
|
|||||||
row.check = false
|
row.check = false
|
||||||
estimateOption.map((row2) => {
|
estimateOption.map((row2) => {
|
||||||
if (row.pkgYn === '0') {
|
if (row.pkgYn === '0') {
|
||||||
if (row2 === row.code) {
|
// if (row2 === row.code) {
|
||||||
|
// row.check = true
|
||||||
|
// }
|
||||||
|
if (row.code.split('、').includes(row2)) {
|
||||||
row.check = true
|
row.check = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -217,7 +220,10 @@ export default function Estimate({}) {
|
|||||||
row.check = false
|
row.check = false
|
||||||
estimateOption.map((row2) => {
|
estimateOption.map((row2) => {
|
||||||
if (row.pkgYn === '0') {
|
if (row.pkgYn === '0') {
|
||||||
if (row2 === row.code) {
|
// if (row2 === row.code) {
|
||||||
|
// row.check = true
|
||||||
|
// }
|
||||||
|
if (row.code.split('、').includes(row2)) {
|
||||||
row.check = true
|
row.check = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -240,7 +246,6 @@ export default function Estimate({}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setSpecialNoteList(res)
|
setSpecialNoteList(res)
|
||||||
|
|
||||||
setSpecialNoteFirstFlg(true)
|
setSpecialNoteFirstFlg(true)
|
||||||
@ -377,8 +382,8 @@ export default function Estimate({}) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (estimateContextState.estimateType !== '') {
|
if (estimateContextState.estimateType !== '') {
|
||||||
const param = {
|
const param = {
|
||||||
saleStoreId: session.storeId,
|
saleStoreId: estimateContextState.sapSaleStoreId,
|
||||||
sapSalesStoreCd: session.custCd,
|
sapSalesStoreCd: estimateContextState.sapSalesStoreCd,
|
||||||
docTpCd: estimateContextState?.estimateType,
|
docTpCd: estimateContextState?.estimateType,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,6 +392,8 @@ export default function Estimate({}) {
|
|||||||
if (isNotEmptyArray(res?.data)) {
|
if (isNotEmptyArray(res?.data)) {
|
||||||
setStorePriceList(res.data)
|
setStorePriceList(res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setItemChangeYn(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
if (estimateContextState.estimateType === 'YJSS') {
|
if (estimateContextState.estimateType === 'YJSS') {
|
||||||
@ -416,8 +423,6 @@ export default function Estimate({}) {
|
|||||||
handlePricing('UNIT_PRICE')
|
handlePricing('UNIT_PRICE')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setItemChangeYn(true)
|
|
||||||
}
|
}
|
||||||
}, [estimateContextState?.estimateType])
|
}, [estimateContextState?.estimateType])
|
||||||
|
|
||||||
@ -469,6 +474,21 @@ export default function Estimate({}) {
|
|||||||
} else {
|
} else {
|
||||||
item.check = false
|
item.check = false
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let codes = item.code.split('、')
|
||||||
|
let flg = '0'
|
||||||
|
if (codes.length > 1) {
|
||||||
|
for (let i = 0; i < pushData.length; i++) {
|
||||||
|
if (codes.indexOf(pushData[i]) > -1) {
|
||||||
|
flg = '1'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (flg === '1') {
|
||||||
|
item.check = true
|
||||||
|
} else {
|
||||||
|
item.check = false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -478,12 +498,26 @@ export default function Estimate({}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Pricing 버튼클릭시 confirm 노출
|
||||||
|
const handlePricingBtn = (showPriceCd) => {
|
||||||
|
swalFire({
|
||||||
|
text: getMessage('estimate.detail.showPrice.pricingBtn.confirm'),
|
||||||
|
type: 'confirm',
|
||||||
|
icon: 'warning',
|
||||||
|
confirmFn: () => {
|
||||||
|
handlePricing(showPriceCd)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
//Pricing 버튼
|
//Pricing 버튼
|
||||||
const handlePricing = async (showPriceCd) => {
|
const handlePricing = async (showPriceCd) => {
|
||||||
const param = {
|
const param = {
|
||||||
saleStoreId: session.storeId,
|
saleStoreId: estimateContextState.sapSaleStoreId,
|
||||||
sapSalesStoreCd: session.custCd,
|
sapSalesStoreCd: estimateContextState.sapSalesStoreCd,
|
||||||
docTpCd: estimateContextState.estimateType,
|
docTpCd: estimateContextState.estimateType,
|
||||||
|
secSapSalesStoreCd:
|
||||||
|
estimateContextState.secSapSalesStoreCd?.length > 0 && showPriceCd === 'QSP_PRICE' ? estimateContextState.secSapSalesStoreCd : '',
|
||||||
priceCd: showPriceCd,
|
priceCd: showPriceCd,
|
||||||
itemIdList: estimateContextState.itemList.filter((item) => item.delFlg === '0' && item.paDispOrder === null),
|
itemIdList: estimateContextState.itemList.filter((item) => item.delFlg === '0' && item.paDispOrder === null),
|
||||||
}
|
}
|
||||||
@ -506,7 +540,6 @@ export default function Estimate({}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => {
|
await promisePost({ url: '/api/estimate/price/item-price-list', data: param }).then((res) => {
|
||||||
let updateList = []
|
let updateList = []
|
||||||
@ -531,6 +564,7 @@ export default function Estimate({}) {
|
|||||||
updateList.push({
|
updateList.push({
|
||||||
...item,
|
...item,
|
||||||
openFlg: data.data2[i].unitPrice === '0.0' ? '1' : '0',
|
openFlg: data.data2[i].unitPrice === '0.0' ? '1' : '0',
|
||||||
|
unitOpenFlg: (showPriceCd === 'QSP_PRICE' && item.openFlg === '1') ? '1' : '0',
|
||||||
salePrice: data.data2[i].unitPrice === null ? '0' : data.data2[i].unitPrice,
|
salePrice: data.data2[i].unitPrice === null ? '0' : data.data2[i].unitPrice,
|
||||||
saleTotPrice: (item.amount * data.data2[i].unitPrice).toString(),
|
saleTotPrice: (item.amount * data.data2[i].unitPrice).toString(),
|
||||||
})
|
})
|
||||||
@ -696,7 +730,7 @@ export default function Estimate({}) {
|
|||||||
/* 케이블 select 변경시 */
|
/* 케이블 select 변경시 */
|
||||||
const onChangeDisplayCableItem = (value, itemList) => {
|
const onChangeDisplayCableItem = (value, itemList) => {
|
||||||
itemList.map((item, index) => {
|
itemList.map((item, index) => {
|
||||||
if (item.dispCableFlg === '1') {
|
if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') {
|
||||||
if (value !== '') {
|
if (value !== '') {
|
||||||
onChangeDisplayItem(value, item.dispOrder, index, true)
|
onChangeDisplayItem(value, item.dispOrder, index, true)
|
||||||
}
|
}
|
||||||
@ -1054,7 +1088,7 @@ export default function Estimate({}) {
|
|||||||
item.showSaleTotPrice = '0'
|
item.showSaleTotPrice = '0'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.dispCableFlg === '1') {
|
if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') {
|
||||||
dispCableFlgCnt++
|
dispCableFlgCnt++
|
||||||
setCableItem(item.itemId)
|
setCableItem(item.itemId)
|
||||||
}
|
}
|
||||||
@ -1125,7 +1159,7 @@ export default function Estimate({}) {
|
|||||||
dispCableFlgCnt++
|
dispCableFlgCnt++
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.dispCableFlg === '1') {
|
if (item.dispCableFlg === '1' && item.itemTpCd !== 'M12') {
|
||||||
setCableItem(item.itemId)
|
setCableItem(item.itemId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1197,6 +1231,21 @@ export default function Estimate({}) {
|
|||||||
}
|
}
|
||||||
}, [estimateContextState?.itemList, cableItemList])
|
}, [estimateContextState?.itemList, cableItemList])
|
||||||
|
|
||||||
|
const [agencyCustList, setAgencyCustList] = useState([])
|
||||||
|
useEffect(() => {
|
||||||
|
// 952 - 2차점 특가 sapSalesStoreCd
|
||||||
|
if (estimateContextState?.sapSalesStoreCd && session?.storeLvl === '1') {
|
||||||
|
const param = {
|
||||||
|
sapSalesStoreCd: estimateContextState.sapSalesStoreCd,
|
||||||
|
}
|
||||||
|
const apiUrl = `api/estimate/agency-cust-list?${queryStringFormatter(param)}`
|
||||||
|
get({ url: apiUrl }).then((res) => {
|
||||||
|
if (isNotEmptyArray(res?.data)) {
|
||||||
|
setAgencyCustList(res?.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, [estimateContextState?.sapSalesStoreCd])
|
||||||
return (
|
return (
|
||||||
<div className="sub-content estimate">
|
<div className="sub-content estimate">
|
||||||
<div className="sub-content-inner">
|
<div className="sub-content-inner">
|
||||||
@ -1341,36 +1390,79 @@ export default function Estimate({}) {
|
|||||||
{getMessage('estimate.detail.estimateType')} <span className="important">*</span>
|
{getMessage('estimate.detail.estimateType')} <span className="important">*</span>
|
||||||
</th>
|
</th>
|
||||||
<td colSpan={3}>
|
<td colSpan={3}>
|
||||||
<div className="radio-wrap">
|
<div className="form-flex-wrap">
|
||||||
<div className="d-check-radio light mr10">
|
<div className="radio-wrap">
|
||||||
<input
|
{/*pkgRank is null, empty 인 경우 : 사용불가, 이전에 등록된 경우 사용가능, style로 제어*/}
|
||||||
type="radio"
|
<div
|
||||||
name="estimateType"
|
className="d-check-radio light mr10"
|
||||||
id="YJSS"
|
style={{
|
||||||
value={'YJSS'}
|
display:
|
||||||
checked={estimateContextState?.estimateType === 'YJSS' ? true : false}
|
(isNotEmptyArray(storePriceList) > 0 && storePriceList[0].pkgRank !== null && storePriceList[0].pkgRank !== '') ||
|
||||||
onChange={(e) => {
|
estimateContextState?.estimateType === 'YJSS'
|
||||||
//주문분류
|
? ''
|
||||||
setHandlePricingFlag(true)
|
: 'none',
|
||||||
setEstimateContextState({ estimateType: e.target.value })
|
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
<label htmlFor="YJSS">{getMessage('estimate.detail.estimateType.yjss')}</label>
|
<input
|
||||||
</div>
|
type="radio"
|
||||||
<div className="d-check-radio light">
|
name="estimateType"
|
||||||
<input
|
id="YJSS"
|
||||||
type="radio"
|
value={'YJSS'}
|
||||||
name="estimateType"
|
checked={estimateContextState?.estimateType === 'YJSS' ? true : false}
|
||||||
id="YJOD"
|
onChange={(e) => {
|
||||||
value={'YJOD'}
|
//주문분류
|
||||||
checked={estimateContextState?.estimateType === 'YJOD' ? true : false}
|
setHandlePricingFlag(true)
|
||||||
onChange={(e) => {
|
setEstimateContextState({ estimateType: e.target.value })
|
||||||
setHandlePricingFlag(true)
|
}}
|
||||||
setEstimateContextState({ estimateType: e.target.value })
|
/>
|
||||||
}}
|
<label htmlFor="YJSS">{getMessage('estimate.detail.estimateType.yjss')}</label>
|
||||||
/>
|
</div>
|
||||||
<label htmlFor="YJOD">{getMessage('estimate.detail.estimateType.yjod')}</label>
|
<div className="d-check-radio light">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="estimateType"
|
||||||
|
id="YJOD"
|
||||||
|
value={'YJOD'}
|
||||||
|
checked={estimateContextState?.estimateType === 'YJOD' ? true : false}
|
||||||
|
onChange={(e) => {
|
||||||
|
setHandlePricingFlag(true)
|
||||||
|
setEstimateContextState({ estimateType: e.target.value })
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label htmlFor="YJOD">{getMessage('estimate.detail.estimateType.yjod')}</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{session?.storeLvl === '1' && agencyCustList.length > 0 ? (
|
||||||
|
<div className="form-flex-select ml10">
|
||||||
|
<label htmlFor="">{getMessage('estimate.detail.agency')}</label>
|
||||||
|
<div className="select-wrap" style={{ width: '400px' }}>
|
||||||
|
<Select
|
||||||
|
id="agencyName"
|
||||||
|
instanceId="agencyName"
|
||||||
|
className="react-select-custom"
|
||||||
|
classNamePrefix="custom"
|
||||||
|
placeholder="Select"
|
||||||
|
options={agencyCustList}
|
||||||
|
onChange={(e) => {
|
||||||
|
if (isObjectNotEmpty(e)) {
|
||||||
|
setEstimateContextState({ secSapSalesStoreCd: e.sapSalesStoreCd })
|
||||||
|
} else {
|
||||||
|
setEstimateContextState({ secSapSalesStoreCd: '' })
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
getOptionLabel={(x) => x.sapSalesStoreNm}
|
||||||
|
getOptionValue={(x) => x.sapSalesStoreCd}
|
||||||
|
isClearable={true}
|
||||||
|
isSearchable={true}
|
||||||
|
value={agencyCustList.filter(function (option) {
|
||||||
|
return option.sapSalesStoreCd === estimateContextState.secSapSalesStoreCd
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -1729,9 +1821,10 @@ export default function Estimate({}) {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn-origin grey ml5"
|
className="btn-origin grey ml5"
|
||||||
onClick={() => {
|
onClick={(event) => {
|
||||||
|
|
||||||
setHandlePricingFlag(true)
|
setHandlePricingFlag(true)
|
||||||
handlePricing(showPriceCd)
|
handlePricingBtn(showPriceCd)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{getMessage('estimate.detail.showPrice.pricingBtn')}
|
{getMessage('estimate.detail.showPrice.pricingBtn')}
|
||||||
@ -1859,8 +1952,13 @@ export default function Estimate({}) {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
menuPlacement={'auto'}
|
menuPlacement={'auto'}
|
||||||
getOptionLabel={(x) => x.itemName}
|
getOptionLabel={(x) => x.itemName + ' (' + x.itemNo + ')'}
|
||||||
getOptionValue={(x) => x.itemNo}
|
getOptionValue={(x) => x.itemNo}
|
||||||
|
components={{
|
||||||
|
SingleValue: ({ children, ...props }) => {
|
||||||
|
return <components.SingleValue {...props}>{props.data.itemName}</components.SingleValue>
|
||||||
|
},
|
||||||
|
}}
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
isDisabled={!!item?.paDispOrder}
|
isDisabled={!!item?.paDispOrder}
|
||||||
value={displayItemList.filter(function (option) {
|
value={displayItemList.filter(function (option) {
|
||||||
@ -1880,12 +1978,17 @@ export default function Estimate({}) {
|
|||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
options={cableItemList}
|
options={cableItemList}
|
||||||
menuPlacement={'auto'}
|
menuPlacement={'auto'}
|
||||||
getOptionLabel={(x) => x.clRefChr3}
|
getOptionLabel={(x) => x.clRefChr3 + ' (' + x.clRefChr1 + ')'}
|
||||||
getOptionValue={(x) => x.clRefChr1}
|
getOptionValue={(x) => x.clRefChr1}
|
||||||
|
components={{
|
||||||
|
SingleValue: ({ children, ...props }) => {
|
||||||
|
return <components.SingleValue {...props}>{(item.itemTpCd === 'M12')? item.itemName : props.data.clRefChr3}</components.SingleValue>
|
||||||
|
},
|
||||||
|
}}
|
||||||
isClearable={false}
|
isClearable={false}
|
||||||
isDisabled={true}
|
isDisabled={true}
|
||||||
value={cableItemList.filter(function (option) {
|
value={cableItemList.filter(function (option) {
|
||||||
return option.clRefChr1 === item.itemId
|
return (item.itemTpCd === 'M12')? item.itemId : option.clRefChr1 === item.itemId
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -1936,7 +2039,11 @@ export default function Estimate({}) {
|
|||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="input-light al-r"
|
className="input-light al-r"
|
||||||
value={convertNumberToPriceDecimal(item?.showSalePrice === '0' ? null : item?.salePrice?.replaceAll(',', ''))}
|
value={
|
||||||
|
item.openFlg === '1'
|
||||||
|
? 'OPEN'
|
||||||
|
: convertNumberToPriceDecimal(item?.showSalePrice === '0' ? null : item?.salePrice?.replaceAll(',', ''))
|
||||||
|
}
|
||||||
disabled={
|
disabled={
|
||||||
item.openFlg === '1'
|
item.openFlg === '1'
|
||||||
? true
|
? true
|
||||||
@ -1964,15 +2071,17 @@ export default function Estimate({}) {
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="al-r">
|
<td className="al-r">
|
||||||
{convertNumberToPriceDecimal(
|
{item?.openFlg === '1'
|
||||||
item?.showSaleTotPrice === '0'
|
? 'OPEN'
|
||||||
? null
|
: convertNumberToPriceDecimal(
|
||||||
: item?.amount === ''
|
item?.showSaleTotPrice === '0'
|
||||||
? null
|
|
||||||
: item?.saleTotPrice === '0'
|
|
||||||
? null
|
? null
|
||||||
: item?.saleTotPrice?.replaceAll(',', ''),
|
: item?.amount === ''
|
||||||
)}
|
? null
|
||||||
|
: item?.saleTotPrice === '0'
|
||||||
|
? null
|
||||||
|
: item?.saleTotPrice?.replaceAll(',', ''),
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -45,8 +45,11 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
options.sort = options.sort ?? true
|
options.sort = options.sort ?? true
|
||||||
options.parentId = options.parentId ?? null
|
options.parentId = options.parentId ?? null
|
||||||
|
|
||||||
|
this.isSortedPoints = false
|
||||||
|
|
||||||
if (!options.sort && points.length <= 8) {
|
if (!options.sort && points.length <= 8) {
|
||||||
points = sortedPointLessEightPoint(points)
|
points = sortedPointLessEightPoint(points)
|
||||||
|
this.isSortedPoints = true
|
||||||
} else {
|
} else {
|
||||||
let isDiagonal = false
|
let isDiagonal = false
|
||||||
points.forEach((point, i) => {
|
points.forEach((point, i) => {
|
||||||
@ -62,6 +65,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
if (!isDiagonal) {
|
if (!isDiagonal) {
|
||||||
points = sortedPoints(points)
|
points = sortedPoints(points)
|
||||||
|
this.isSortedPoints = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,10 +123,12 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
|
|
||||||
this.on('moving', () => {
|
this.on('moving', () => {
|
||||||
|
this.initLines()
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.on('modified', (e) => {
|
this.on('modified', (e) => {
|
||||||
|
this.initLines()
|
||||||
this.addLengthText()
|
this.addLengthText()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -183,8 +189,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
|||||||
|
|
||||||
this.lines = []
|
this.lines = []
|
||||||
|
|
||||||
this.points.forEach((point, i) => {
|
this.getCurrentPoints().forEach((point, i) => {
|
||||||
const nextPoint = this.points[(i + 1) % this.points.length]
|
const nextPoint = this.getCurrentPoints()[(i + 1) % this.points.length]
|
||||||
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
const line = new QLine([point.x, point.y, nextPoint.x, nextPoint.y], {
|
||||||
stroke: this.stroke,
|
stroke: this.stroke,
|
||||||
strokeWidth: this.strokeWidth,
|
strokeWidth: this.strokeWidth,
|
||||||
|
|||||||
@ -30,11 +30,14 @@ import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
|||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
import { useEvent } from '@/hooks/useEvent'
|
||||||
import { compasDegAtom } from '@/store/orientationAtom'
|
import { compasDegAtom } from '@/store/orientationAtom'
|
||||||
|
import { hotkeyStore } from '@/store/hotkeyAtom'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
|
||||||
export default function CanvasFrame() {
|
export default function CanvasFrame() {
|
||||||
const canvasRef = useRef(null)
|
const canvasRef = useRef(null)
|
||||||
const { canvas } = useCanvas('canvas')
|
const { canvas } = useCanvas('canvas')
|
||||||
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
||||||
|
const { closeAll } = usePopup()
|
||||||
const currentMenu = useRecoilValue(currentMenuState)
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
const { floorPlanState } = useContext(FloorPlanContext)
|
const { floorPlanState } = useContext(FloorPlanContext)
|
||||||
const { contextMenu, handleClick } = useContextMenu()
|
const { contextMenu, handleClick } = useContextMenu()
|
||||||
@ -92,6 +95,8 @@ export default function CanvasFrame() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
|
// 혹시 모를 팝업이 떠있는 경우 닫고 시작한다.
|
||||||
|
closeAll()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
canvas?.clear()
|
canvas?.clear()
|
||||||
@ -110,6 +115,38 @@ export default function CanvasFrame() {
|
|||||||
resetPcsCheckState()
|
resetPcsCheckState()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 캔버스가 있을 경우 핫키 이벤트 처리
|
||||||
|
* hotkeyStore에 핫키 이벤트 리스너 추가
|
||||||
|
*
|
||||||
|
* const hotkeys = [
|
||||||
|
{ key: 'c', fn: () => asdf() },
|
||||||
|
{ key: 'v', fn: () => qwer() },
|
||||||
|
]
|
||||||
|
setHotkeyStore(hotkeys)
|
||||||
|
*/
|
||||||
|
const hotkeyState = useRecoilValue(hotkeyStore)
|
||||||
|
const hotkeyHandlerRef = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
hotkeyHandlerRef.current = (e) => {
|
||||||
|
hotkeyState.forEach((hotkey) => {
|
||||||
|
if (e.key === hotkey.key) {
|
||||||
|
hotkey.fn()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keyup', hotkeyHandlerRef.current)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (hotkeyHandlerRef.current) {
|
||||||
|
document.removeEventListener('keyup', hotkeyHandlerRef.current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [hotkeyState])
|
||||||
|
/** 핫키 이벤트 처리 끝 */
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="canvas-frame">
|
<div className="canvas-frame">
|
||||||
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
<canvas ref={canvasRef} id="canvas" style={{ position: 'relative' }}></canvas>
|
||||||
|
|||||||
@ -31,12 +31,13 @@ export default function CanvasLayout({ children }) {
|
|||||||
return (
|
return (
|
||||||
<div className="canvas-layout">
|
<div className="canvas-layout">
|
||||||
<div className={`canvas-page-list ${['outline', 'surface', 'module'].includes(selectedMenu) ? 'active' : ''}`}>
|
<div className={`canvas-page-list ${['outline', 'surface', 'module'].includes(selectedMenu) ? 'active' : ''}`}>
|
||||||
|
<div className="canvas-id">{objectNo}</div>
|
||||||
<div className="canvas-plane-wrap">
|
<div className="canvas-plane-wrap">
|
||||||
{plans.map((plan, index) => (
|
{plans.map((plan, index) => (
|
||||||
<button
|
<button
|
||||||
key={`plan-${plan.id}`}
|
key={`plan-${plan.id}`}
|
||||||
className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`}
|
className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`}
|
||||||
onClick={() => handleCurrentPlan(plan.id)}
|
onClick={() => (plan.isCurrent ? '' : handleCurrentPlan(plan.id))}
|
||||||
>
|
>
|
||||||
<span>{`Plan ${plan.planNo}`}</span>
|
<span>{`Plan ${plan.planNo}`}</span>
|
||||||
{plans.length > 1 && !pathname.includes('/estimate') && !pathname.includes('/simulator') && (
|
{plans.length > 1 && !pathname.includes('/estimate') && !pathname.includes('/simulator') && (
|
||||||
|
|||||||
@ -548,13 +548,26 @@ export default function CanvasMenu(props) {
|
|||||||
{
|
{
|
||||||
<div className={`vertical-horizontal ${verticalHorizontalMode ? 'on' : ''}`}>
|
<div className={`vertical-horizontal ${verticalHorizontalMode ? 'on' : ''}`}>
|
||||||
<span>{getMessage('plan.mode.vertical.horizontal')}</span>
|
<span>{getMessage('plan.mode.vertical.horizontal')}</span>
|
||||||
<button onClick={() => setVerticalHorizontalMode(!verticalHorizontalMode)}>{verticalHorizontalMode ? 'ON' : 'OFF'}</button>
|
<button
|
||||||
|
title={`${getMessage('plan.mode.vertical.horizontal')} ${verticalHorizontalMode ? 'ON' : 'OFF'}`}
|
||||||
|
onClick={() => setVerticalHorizontalMode(!verticalHorizontalMode)}
|
||||||
|
>
|
||||||
|
{verticalHorizontalMode ? 'ON' : 'OFF'}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className="btn-from">
|
<div className="btn-from">
|
||||||
<button className={`btn01 ${commonUtils.text ? 'active' : ''}`} onClick={() => commonFunctions('text')}></button>
|
<button className={`btn01 ${commonUtils.text ? 'active' : ''}`} onClick={() => commonFunctions('text')} title="文字作成"></button>
|
||||||
<button className={`btn02 ${commonUtils.dimension ? 'active' : ''} `} onClick={() => commonFunctions('dimension')}></button>
|
<button
|
||||||
<button className={`btn03 ${commonUtils.distance ? 'active' : ''} `} onClick={() => commonFunctions('distance')}></button>
|
className={`btn02 ${commonUtils.dimension ? 'active' : ''} `}
|
||||||
|
onClick={() => commonFunctions('dimension')}
|
||||||
|
title="寸法作成"
|
||||||
|
></button>
|
||||||
|
<button
|
||||||
|
className={`btn03 ${commonUtils.distance ? 'active' : ''} `}
|
||||||
|
onClick={() => commonFunctions('distance')}
|
||||||
|
title="定規"
|
||||||
|
></button>
|
||||||
</div>
|
</div>
|
||||||
{isObjectNotEmpty(selectedRoofMaterial) && addedRoofs.length > 0 && (
|
{isObjectNotEmpty(selectedRoofMaterial) && addedRoofs.length > 0 && (
|
||||||
<div className="select-box">
|
<div className="select-box">
|
||||||
@ -580,6 +593,7 @@ export default function CanvasMenu(props) {
|
|||||||
sourceKey={'index'}
|
sourceKey={'index'}
|
||||||
targetKey={'index'}
|
targetKey={'index'}
|
||||||
disabled={+basicSetting.roofSizeSet === 3}
|
disabled={+basicSetting.roofSizeSet === 3}
|
||||||
|
tagTitle={'屋根材変更'}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -588,9 +602,10 @@ export default function CanvasMenu(props) {
|
|||||||
<button
|
<button
|
||||||
className={`btn10 ${floorPlanState.refFileModalOpen && 'active'}`}
|
className={`btn10 ${floorPlanState.refFileModalOpen && 'active'}`}
|
||||||
onClick={() => setFloorPlanState({ ...floorPlanState, refFileModalOpen: true })}
|
onClick={() => setFloorPlanState({ ...floorPlanState, refFileModalOpen: true })}
|
||||||
|
title="読込"
|
||||||
></button>
|
></button>
|
||||||
{/*<button className="btn04" onClick={() => setShowCanvasSettingModal(true)}></button>*/}
|
{/*<button className="btn04" onClick={() => setShowCanvasSettingModal(true)}></button>*/}
|
||||||
<button className="btn04" onClick={handlePopup}></button>
|
<button className="btn04" onClick={handlePopup} title="設定"></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="size-control">
|
<div className="size-control">
|
||||||
<button
|
<button
|
||||||
@ -599,7 +614,9 @@ export default function CanvasMenu(props) {
|
|||||||
handleZoom(false)
|
handleZoom(false)
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
<span onClick={handleZoomClear}>{canvasZoom}%</span>
|
<span onClick={handleZoomClear} title="拡大・縮小">
|
||||||
|
{canvasZoom}%
|
||||||
|
</span>
|
||||||
<button
|
<button
|
||||||
className="control-btn plus"
|
className="control-btn plus"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -608,8 +625,8 @@ export default function CanvasMenu(props) {
|
|||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
<div className="btn-from">
|
<div className="btn-from">
|
||||||
<button className="btn08" onClick={handleSaveCanvas}></button>
|
<button className="btn08" onClick={handleSaveCanvas} title="保存"></button>
|
||||||
<button className="btn09" onClick={handleLeaveCanvas}></button>
|
<button className="btn09" onClick={handleLeaveCanvas} title="物件検索画面へ移動"></button>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -634,7 +651,7 @@ export default function CanvasMenu(props) {
|
|||||||
onClick={() => setEstimatePopupOpen(true)}
|
onClick={() => setEstimatePopupOpen(true)}
|
||||||
>
|
>
|
||||||
<span className="ico ico01"></span>
|
<span className="ico ico01"></span>
|
||||||
<span className="name">{getMessage('plan.menu.estimate.docDown')}</span>
|
<span className="name">{getMessage('plan.menu.estimate.docDownload')}</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" style={{ display: saveButtonStyle }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
<button type="button" style={{ display: saveButtonStyle }} className="btn-frame gray ico-flx" onClick={handleEstimateSubmit}>
|
||||||
<span className="ico ico02"></span>
|
<span className="ico ico02"></span>
|
||||||
|
|||||||
@ -1,15 +1,18 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useEffect } from 'react'
|
import { useContext, useEffect } from 'react'
|
||||||
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
||||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||||
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import '@/styles/contents.scss'
|
import '@/styles/contents.scss'
|
||||||
import { notFound, useSearchParams } from 'next/navigation'
|
import { notFound, useSearchParams } from 'next/navigation'
|
||||||
import { useRecoilState, useResetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { correntObjectNoState } from '@/store/settingAtom'
|
import { correntObjectNoState } from '@/store/settingAtom'
|
||||||
import { currentMenuState } from '@/store/canvasAtom'
|
import { currentMenuState } from '@/store/canvasAtom'
|
||||||
|
import { globalLocaleStore } from '@/store/localeAtom'
|
||||||
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
|
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||||
|
|
||||||
export default function FloorPlan({ children }) {
|
export default function FloorPlan({ children }) {
|
||||||
const [correntObjectNo, setCurrentObjectNo] = useRecoilState(correntObjectNoState)
|
const [correntObjectNo, setCurrentObjectNo] = useRecoilState(correntObjectNoState)
|
||||||
@ -20,12 +23,39 @@ export default function FloorPlan({ children }) {
|
|||||||
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
const { selectedMenu, setSelectedMenu } = useCanvasMenu()
|
||||||
const { fetchSettings } = useCanvasSetting()
|
const { fetchSettings } = useCanvasSetting()
|
||||||
const resetCurrentMenu = useResetRecoilState(currentMenuState)
|
const resetCurrentMenu = useResetRecoilState(currentMenuState)
|
||||||
|
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||||
|
const { promiseGet } = useAxios(globalLocaleState)
|
||||||
|
const { setManagementState } = useContext(GlobalDataContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
getStuffDetailInfo()
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
resetCurrentMenu()
|
resetCurrentMenu()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const getStuffDetailInfo = () => {
|
||||||
|
promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => {
|
||||||
|
if (res.status === 200) {
|
||||||
|
const { data } = res
|
||||||
|
console.log(data)
|
||||||
|
|
||||||
|
let surfaceTypeValue
|
||||||
|
if (res.data.surfaceType === 'Ⅲ・Ⅳ') {
|
||||||
|
surfaceTypeValue = '3'
|
||||||
|
} else if (res.data.surfaceType === 'Ⅱ') {
|
||||||
|
surfaceTypeValue = '2'
|
||||||
|
}
|
||||||
|
//설치높이 0이면 빈값으로로 셋팅
|
||||||
|
if (res.data.installHeight === '0') {
|
||||||
|
res.data.installHeight = ''
|
||||||
|
}
|
||||||
|
setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL 파라미터에서 objectNo 설정
|
* URL 파라미터에서 objectNo 설정
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -40,15 +40,15 @@ export default function AuxiliaryEdit(props) {
|
|||||||
if (currentObject) {
|
if (currentObject) {
|
||||||
copy(
|
copy(
|
||||||
currentObject,
|
currentObject,
|
||||||
arrow2 ? (arrow2 === '←' ? Number(horizonSize) * -1 : Number(horizonSize)) : 0,
|
arrow2 ? (arrow2 === '←' ? Number(+horizonSize / 10) * -1 : Number(+horizonSize / 10)) : 0,
|
||||||
arrow1 ? (arrow1 === '↑' ? Number(verticalSize) * -1 : Number(verticalSize)) : 0,
|
arrow1 ? (arrow1 === '↑' ? Number(+verticalSize / 10) * -1 : Number(+verticalSize / 10)) : 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
move(
|
move(
|
||||||
currentObject,
|
currentObject,
|
||||||
arrow2 ? (arrow2 === '←' ? Number(horizonSize) * -1 : Number(horizonSize)) : 0,
|
arrow2 ? (arrow2 === '←' ? Number(+horizonSize / 10) * -1 : Number(+horizonSize / 10)) : 0,
|
||||||
arrow1 ? (arrow1 === '↑' ? Number(verticalSize) * -1 : Number(verticalSize)) : 0,
|
arrow1 ? (arrow1 === '↑' ? Number(+verticalSize / 10) * -1 : Number(+verticalSize / 10)) : 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,109 +1,88 @@
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { POLYGON_TYPE, MODULE_SETUP_TYPE } from '@/common/common'
|
||||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||||
import { useContext, useEffect, useRef, useState } from 'react'
|
import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation'
|
||||||
import Module from '@/components/floor-plan/modal/basic/step/Module'
|
|
||||||
import PitchModule from '@/components/floor-plan/modal/basic/step/pitch/PitchModule'
|
|
||||||
import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement'
|
import PitchPlacement from '@/components/floor-plan/modal/basic/step/pitch/PitchPlacement'
|
||||||
import Placement from '@/components/floor-plan/modal/basic/step/Placement'
|
import Placement from '@/components/floor-plan/modal/basic/step/Placement'
|
||||||
import { useRecoilValue, useRecoilState } from 'recoil'
|
|
||||||
import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState } from '@/store/canvasAtom'
|
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
|
||||||
import { Orientation } from '@/components/floor-plan/modal/basic/step/Orientation'
|
|
||||||
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
|
||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
|
||||||
import { addedRoofsState, corridorDimensionSelector, basicSettingState } from '@/store/settingAtom'
|
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
|
||||||
import Swal from 'sweetalert2'
|
|
||||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||||
|
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||||
|
import { useModuleSelection } from '@/hooks/module/useModuleSelection'
|
||||||
|
import { useOrientation } from '@/hooks/module/useOrientation'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import {
|
||||||
|
canvasState,
|
||||||
|
checkedModuleState,
|
||||||
|
currentCanvasPlanState,
|
||||||
|
isManualModuleLayoutSetupState,
|
||||||
|
isManualModuleSetupState,
|
||||||
|
toggleManualSetupModeState,
|
||||||
|
} from '@/store/canvasAtom'
|
||||||
import { loginUserStore } from '@/store/commonAtom'
|
import { loginUserStore } from '@/store/commonAtom'
|
||||||
import { currentCanvasPlanState } from '@/store/canvasAtom'
|
import { roofsState } from '@/store/roofAtom'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||||
|
import { addedRoofsState, basicSettingState } from '@/store/settingAtom'
|
||||||
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
|
import { useEffect, useRef, useState } from 'react'
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
import Swal from 'sweetalert2'
|
||||||
|
import Trestle from './step/Trestle'
|
||||||
|
|
||||||
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { closePopup } = usePopup()
|
const { closePopup } = usePopup()
|
||||||
const [tabNum, setTabNum] = useState(1)
|
const [tabNum, setTabNum] = useState(1)
|
||||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
|
||||||
const orientationRef = useRef(null)
|
const orientationRef = useRef(null)
|
||||||
const { initEvent } = useEvent()
|
|
||||||
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
|
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
|
||||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
const [isManualModuleLayoutSetup, setIsManualModuleLayoutSetup] = useRecoilState(isManualModuleLayoutSetupState)
|
||||||
const addedRoofs = useRecoilValue(addedRoofsState)
|
const trestleRef = useRef(null)
|
||||||
|
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
||||||
|
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
|
||||||
const loginUserState = useRecoilValue(loginUserStore)
|
const loginUserState = useRecoilValue(loginUserStore)
|
||||||
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
|
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
|
||||||
const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 })
|
const [isClosePopup, setIsClosePopup] = useState({ close: false, id: 0 })
|
||||||
const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState)
|
const [checkedModules, setCheckedModules] = useRecoilState(checkedModuleState)
|
||||||
|
const [roofs, setRoofs] = useState(addedRoofs)
|
||||||
|
const [manualSetupMode, setManualSetupMode] = useRecoilState(toggleManualSetupModeState)
|
||||||
|
const [layoutSetup, setLayoutSetup] = useState([{}])
|
||||||
|
const {
|
||||||
|
selectedModules,
|
||||||
|
roughnessCodes,
|
||||||
|
windSpeedCodes,
|
||||||
|
managementState,
|
||||||
|
setManagementState,
|
||||||
|
moduleList,
|
||||||
|
setSelectedModules,
|
||||||
|
selectedSurfaceType,
|
||||||
|
setSelectedSurfaceType,
|
||||||
|
installHeight,
|
||||||
|
setInstallHeight,
|
||||||
|
standardWindSpeed,
|
||||||
|
setStandardWindSpeed,
|
||||||
|
verticalSnowCover,
|
||||||
|
setVerticalSnowCover,
|
||||||
|
handleChangeModule,
|
||||||
|
handleChangeSurfaceType,
|
||||||
|
handleChangeWindSpeed,
|
||||||
|
handleChangeInstallHeight,
|
||||||
|
handleChangeVerticalSnowCover,
|
||||||
|
} = useModuleSelection({ addedRoofs })
|
||||||
|
const { nextStep, compasDeg, setCompasDeg } = useOrientation()
|
||||||
|
const { trigger: orientationTrigger } = useCanvasPopupStatusController(1)
|
||||||
|
const { trigger: trestleTrigger } = useCanvasPopupStatusController(2)
|
||||||
|
const { trigger: placementTrigger } = useCanvasPopupStatusController(3)
|
||||||
|
const [roofsStore, setRoofsStore] = useRecoilState(roofsState)
|
||||||
|
|
||||||
// const { initEvent } = useContext(EventContext)
|
// const { initEvent } = useContext(EventContext)
|
||||||
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting(tabNum)
|
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup, manualModuleLayoutSetup, restoreModuleInstArea } =
|
||||||
|
useModuleBasicSetting(tabNum)
|
||||||
const { updateObjectDate } = useMasterController()
|
const { updateObjectDate } = useMasterController()
|
||||||
|
|
||||||
const handleBtnNextStep = () => {
|
|
||||||
if (tabNum === 1) {
|
|
||||||
orientationRef.current.handleNextStep()
|
|
||||||
} else if (tabNum === 2) {
|
|
||||||
if (basicSetting.roofSizeSet !== '3') {
|
|
||||||
if (!isObjectNotEmpty(moduleSelectionData.module)) {
|
|
||||||
Swal.fire({
|
|
||||||
title: getMessage('module.not.found'),
|
|
||||||
icon: 'warning',
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) {
|
|
||||||
Swal.fire({
|
|
||||||
title: getMessage('construction.length.difference'),
|
|
||||||
icon: 'warning',
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//물건정보 갱신일 수정
|
|
||||||
updateObjectDataApi({
|
|
||||||
objectNo: currentCanvasPlan.objectNo, //오브젝트_no
|
|
||||||
standardWindSpeedId: moduleSelectionData.common.stdWindSpeed, //기준풍속코드
|
|
||||||
verticalSnowCover: moduleSelectionData.common.stdSnowLd, //적설량
|
|
||||||
surfaceType: moduleSelectionData.common.illuminationTpNm, //면조도구분
|
|
||||||
installHeight: moduleSelectionData.common.instHt, //설치높이
|
|
||||||
userId: loginUserState.userId, //작성자아아디
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
if (!isObjectNotEmpty(moduleSelectionData.module)) {
|
|
||||||
Swal.fire({
|
|
||||||
title: getMessage('module.not.found'),
|
|
||||||
icon: 'warning',
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setTabNum(tabNum + 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const placementRef = {
|
|
||||||
isChidori: useRef('false'),
|
|
||||||
setupLocation: useRef('eaves'),
|
|
||||||
isMaxSetup: useRef('false'),
|
|
||||||
}
|
|
||||||
|
|
||||||
const placementFlatRef = {
|
|
||||||
setupLocation: useRef('south'),
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleManualModuleSetup = () => {
|
|
||||||
setIsManualModuleSetup(!isManualModuleSetup)
|
|
||||||
}
|
|
||||||
|
|
||||||
const updateObjectDataApi = async (params) => {
|
|
||||||
const res = await updateObjectDate(params)
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const moduleTabNum = basicSetting.roofSizeSet != 3 ? 3 : 2
|
||||||
|
|
||||||
let hasModules = canvas
|
let hasModules = canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
@ -111,23 +90,42 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
|
|
||||||
if (hasModules) {
|
if (hasModules) {
|
||||||
orientationRef.current.handleNextStep()
|
orientationRef.current.handleNextStep()
|
||||||
setTabNum(3)
|
setTabNum(moduleTabNum)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
//팝업 닫기 버튼 이벤트
|
useEffect(() => {
|
||||||
const handleClosePopup = (id) => {
|
if (roofsStore && addedRoofs) {
|
||||||
if (tabNum == 3) {
|
setRoofs(
|
||||||
if (isManualModuleSetup) {
|
addedRoofs.map((roof, index) => {
|
||||||
setIsManualModuleSetup(false)
|
return {
|
||||||
}
|
...roof,
|
||||||
|
...roofsStore[index]?.addRoof,
|
||||||
|
construction: roofsStore[index]?.construction,
|
||||||
|
trestle: roofsStore[index]?.trestle,
|
||||||
|
trestleDetail: roofsStore[index]?.trestleDetail,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
setModuleSelectionData({
|
||||||
|
...moduleSelectionData,
|
||||||
|
roofConstructions: roofsStore.map((roof) => {
|
||||||
|
return {
|
||||||
|
roofIndex: roof.roofIndex,
|
||||||
|
addRoof: roof.addRoof,
|
||||||
|
construction: roof.construction,
|
||||||
|
trestle: roof.trestle,
|
||||||
|
trestleDetail: roof.trestleDetail,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
setIsClosePopup({ close: true, id: id })
|
}, [roofsStore, addedRoofs])
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (basicSetting.roofSizeSet !== '3') {
|
if (basicSetting.roofSizeSet !== '3') {
|
||||||
manualModuleSetup(placementRef)
|
manualModuleSetup()
|
||||||
} else {
|
} else {
|
||||||
manualFlatroofModuleSetup(placementFlatRef)
|
manualFlatroofModuleSetup(placementFlatRef)
|
||||||
}
|
}
|
||||||
@ -140,55 +138,224 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
setIsManualModuleSetup(false)
|
setIsManualModuleSetup(false)
|
||||||
}, [checkedModules])
|
}, [checkedModules])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (basicSetting.roofSizeSet !== '3') {
|
||||||
|
if (manualSetupMode.indexOf('manualSetup') > -1) {
|
||||||
|
manualModuleSetup()
|
||||||
|
} else if (manualSetupMode.indexOf('manualLayoutSetup') > -1) {
|
||||||
|
manualModuleLayoutSetup(layoutSetup)
|
||||||
|
} else if (manualSetupMode.indexOf('off') > -1) {
|
||||||
|
manualModuleSetup()
|
||||||
|
manualModuleLayoutSetup(layoutSetup)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
manualFlatroofModuleSetup(placementFlatRef)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isClosePopup.close) {
|
||||||
|
closePopup(isClosePopup.id)
|
||||||
|
}
|
||||||
|
}, [manualSetupMode, isClosePopup])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isManualModuleLayoutSetup) {
|
||||||
|
manualModuleLayoutSetup(layoutSetup)
|
||||||
|
}
|
||||||
|
}, [layoutSetup])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsManualModuleSetup(false)
|
||||||
|
setIsManualModuleLayoutSetup(false)
|
||||||
|
setManualSetupMode(`off`)
|
||||||
|
}, [checkedModules])
|
||||||
|
|
||||||
|
const handleBtnNextStep = () => {
|
||||||
|
if (tabNum === 1) {
|
||||||
|
orientationRef.current.handleNextStep()
|
||||||
|
setAddedRoofs(roofs)
|
||||||
|
// setTabNum(tabNum + 1)
|
||||||
|
return
|
||||||
|
} else if (tabNum === 2) {
|
||||||
|
if (basicSetting.roofSizeSet !== '3') {
|
||||||
|
// if (addedRoofs.length !== moduleSelectionData.roofConstructions.length) {
|
||||||
|
// Swal.fire({
|
||||||
|
// title: getMessage('construction.length.difference'),
|
||||||
|
// icon: 'warning',
|
||||||
|
// })
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
trestleRef.current.isComplete().then((res) => {
|
||||||
|
if (!res) return
|
||||||
|
})
|
||||||
|
//물건정보 갱신일 수정
|
||||||
|
} else {
|
||||||
|
if (!isObjectNotEmpty(moduleSelectionData.module)) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('module.not.found'),
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setTabNum(tabNum + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const placementFlatRef = {
|
||||||
|
setupLocation: useRef('south'),
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleManualModuleSetup = () => {
|
||||||
|
setManualSetupMode(`manualSetup_${!isManualModuleSetup}`)
|
||||||
|
setIsManualModuleSetup(!isManualModuleSetup)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleManualModuleLayoutSetup = () => {
|
||||||
|
setManualSetupMode(`manualLayoutSetup_${!isManualModuleLayoutSetup}`)
|
||||||
|
setIsManualModuleLayoutSetup(!isManualModuleLayoutSetup)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateObjectDataApi = async (params) => {
|
||||||
|
const res = await updateObjectDate(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
//팝업 닫기 버튼 이벤트
|
||||||
|
const handleClosePopup = (id) => {
|
||||||
|
if (tabNum == 3) {
|
||||||
|
if (isManualModuleSetup) {
|
||||||
|
setIsManualModuleSetup(false)
|
||||||
|
}
|
||||||
|
if (isManualModuleLayoutSetup) {
|
||||||
|
setIsManualModuleLayoutSetup(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setIsClosePopup({ close: true, id: id })
|
||||||
|
}
|
||||||
|
|
||||||
|
const orientationProps = {
|
||||||
|
roofs,
|
||||||
|
setRoofs,
|
||||||
|
tabNum,
|
||||||
|
setTabNum,
|
||||||
|
compasDeg, // 방위각
|
||||||
|
setCompasDeg,
|
||||||
|
selectedModules,
|
||||||
|
moduleSelectionData,
|
||||||
|
setModuleSelectionData,
|
||||||
|
roughnessCodes, // 면조도 목록
|
||||||
|
windSpeedCodes, // 기준풍속 목록
|
||||||
|
managementState,
|
||||||
|
setManagementState,
|
||||||
|
moduleList, // 모듈 리스트
|
||||||
|
setSelectedModules,
|
||||||
|
selectedSurfaceType,
|
||||||
|
setSelectedSurfaceType,
|
||||||
|
installHeight, // 설치높이
|
||||||
|
setInstallHeight,
|
||||||
|
standardWindSpeed, // 기준풍속
|
||||||
|
setStandardWindSpeed,
|
||||||
|
verticalSnowCover, // 적설량
|
||||||
|
setVerticalSnowCover,
|
||||||
|
currentCanvasPlan,
|
||||||
|
loginUserState,
|
||||||
|
handleChangeModule,
|
||||||
|
handleChangeSurfaceType,
|
||||||
|
handleChangeWindSpeed,
|
||||||
|
handleChangeInstallHeight,
|
||||||
|
handleChangeVerticalSnowCover,
|
||||||
|
orientationTrigger,
|
||||||
|
nextStep,
|
||||||
|
updateObjectDataApi,
|
||||||
|
}
|
||||||
|
const trestleProps = {
|
||||||
|
roofs,
|
||||||
|
setRoofs,
|
||||||
|
setRoofsStore,
|
||||||
|
tabNum,
|
||||||
|
setTabNum,
|
||||||
|
moduleSelectionData,
|
||||||
|
setModuleSelectionData,
|
||||||
|
trestleTrigger,
|
||||||
|
}
|
||||||
|
const placementProps = {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos} className="lx-2">
|
<WithDraggable isShow={true} pos={pos} className={basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' ? 'll' : 'lx-2'}>
|
||||||
<WithDraggable.Header title={getMessage('plan.menu.module.circuit.setting.default')} onClose={() => handleClosePopup(id)} />
|
<WithDraggable.Header title={getMessage('plan.menu.module.circuit.setting.default')} onClose={() => handleClosePopup(id)} />
|
||||||
<WithDraggable.Body>
|
<WithDraggable.Body>
|
||||||
<div className="roof-module-tab">
|
<div className="roof-module-tab">
|
||||||
<div className={`module-tab-bx act`}>{getMessage('modal.module.basic.setting.orientation.setting')}</div>
|
<div className={`module-tab-bx act`}>{getMessage('modal.module.basic.setting.orientation.setting')}</div>
|
||||||
<span className={`tab-arr ${tabNum !== 1 ? 'act' : ''}`}></span>
|
<span className={`tab-arr ${tabNum !== 1 ? 'act' : ''}`}></span>
|
||||||
<div className={`module-tab-bx ${tabNum !== 1 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.setting')}</div>
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && (
|
||||||
<span className={`tab-arr ${tabNum === 3 ? 'act' : ''}`}></span>
|
<>
|
||||||
<div className={`module-tab-bx ${tabNum === 3 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.placement')}</div>
|
<div className={`module-tab-bx ${tabNum !== 1 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.setting')}</div>
|
||||||
|
<span className={`tab-arr ${tabNum === 3 ? 'act' : ''}`}></span>
|
||||||
|
<div className={`module-tab-bx ${tabNum === 3 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.placement')}</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && (
|
||||||
|
<>
|
||||||
|
<div className={`module-tab-bx ${tabNum === 2 ? 'act' : ''}`}>{getMessage('modal.module.basic.setting.module.placement')}</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{tabNum === 1 && <Orientation ref={orientationRef} tabNum={tabNum} setTabNum={setTabNum} />}
|
{tabNum === 1 && <Orientation ref={orientationRef} {...orientationProps} />}
|
||||||
{/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/}
|
{/*배치면 초기설정 - 입력방법: 복시도 입력 || 실측값 입력*/}
|
||||||
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && <Module setTabNum={setTabNum} />}
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 2 && <Trestle ref={trestleRef} {...trestleProps} />}
|
||||||
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && <Placement setTabNum={setTabNum} ref={placementRef} />}
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && tabNum === 3 && (
|
||||||
|
<Placement setTabNum={setTabNum} layoutSetup={layoutSetup} setLayoutSetup={setLayoutSetup} />
|
||||||
|
)}
|
||||||
{/*배치면 초기설정 - 입력방법: 육지붕*/}
|
{/*배치면 초기설정 - 입력방법: 육지붕*/}
|
||||||
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && <PitchModule setTabNum={setTabNum} />}
|
{/* {basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && <PitchModule setTabNum={setTabNum} />} */}
|
||||||
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 3 && (
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && tabNum === 2 && (
|
||||||
<PitchPlacement setTabNum={setTabNum} ref={placementFlatRef} />
|
<PitchPlacement setTabNum={setTabNum} ref={placementFlatRef} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="grid-btn-wrap">
|
<div className="grid-btn-wrap">
|
||||||
{tabNum !== 1 && (
|
{/* {tabNum === 1 && <button className="btn-frame modal mr5">{getMessage('modal.common.save')}</button>} */}
|
||||||
<button className="btn-frame modal mr5" onClick={() => setTabNum(tabNum - 1)}>
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && (
|
||||||
{getMessage('modal.module.basic.setting.prev')}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{/*{tabNum !== 3 && <button className="btn-frame modal act mr5">{getMessage('modal.common.save')}</button>}*/}
|
|
||||||
{tabNum !== 3 && (
|
|
||||||
<button className="btn-frame modal" onClick={handleBtnNextStep}>
|
|
||||||
Next
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{tabNum === 3 && (
|
|
||||||
<>
|
<>
|
||||||
{basicSetting.roofSizeSet && basicSetting.roofSizeSet != '3' && (
|
{tabNum !== 1 && (
|
||||||
|
<button className="btn-frame modal mr5" onClick={() => setTabNum(tabNum - 1)}>
|
||||||
|
{getMessage('modal.module.basic.setting.prev')}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{tabNum !== 3 && (
|
||||||
|
<button className="btn-frame modal" onClick={handleBtnNextStep}>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{tabNum === 3 && (
|
||||||
<>
|
<>
|
||||||
|
<button className={`btn-frame modal mr5 ${isManualModuleLayoutSetup ? 'act' : ''}`} onClick={handleManualModuleLayoutSetup}>
|
||||||
|
{getMessage('modal.module.basic.setting.row.batch')}
|
||||||
|
</button>
|
||||||
|
<button className="btn-frame modal mr5" onClick={() => autoModuleSetup(MODULE_SETUP_TYPE.LAYOUT, layoutSetup)}>
|
||||||
|
{getMessage('modal.module.basic.setting.auto.row.batch')}
|
||||||
|
</button>
|
||||||
<button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
|
<button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
|
||||||
{getMessage('modal.module.basic.setting.passivity.placement')}
|
{getMessage('modal.module.basic.setting.passivity.placement')}
|
||||||
</button>
|
</button>
|
||||||
<button className="btn-frame modal act" onClick={() => autoModuleSetup(placementRef)}>
|
<button className="btn-frame modal act mr5" onClick={() => autoModuleSetup(MODULE_SETUP_TYPE.AUTO)}>
|
||||||
{getMessage('modal.module.basic.setting.auto.placement')}
|
{getMessage('modal.module.basic.setting.auto.placement')}
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && (
|
</>
|
||||||
|
)}
|
||||||
|
{basicSetting.roofSizeSet && basicSetting.roofSizeSet == '3' && (
|
||||||
|
<>
|
||||||
|
{tabNum === 1 && (
|
||||||
|
<button className="btn-frame modal" onClick={handleBtnNextStep}>
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
{tabNum === 2 && (
|
||||||
<>
|
<>
|
||||||
|
<button className="btn-frame modal mr5" onClick={() => setTabNum(tabNum - 1)}>
|
||||||
|
{getMessage('modal.module.basic.setting.prev')}
|
||||||
|
</button>
|
||||||
<button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
|
<button className={`btn-frame modal mr5 ${isManualModuleSetup ? 'act' : ''}`} onClick={handleManualModuleSetup}>
|
||||||
{getMessage('modal.module.basic.setting.passivity.placement')}
|
{getMessage('modal.module.basic.setting.passivity.placement')}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -1,115 +1,465 @@
|
|||||||
import { forwardRef, useContext, useEffect, useImperativeHandle, useState } from 'react'
|
import { forwardRef, use, useContext, useEffect, useImperativeHandle, useState } from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useOrientation } from '@/hooks/module/useOrientation'
|
|
||||||
import { getDegreeInOrientation } from '@/util/canvas-util'
|
import { getDegreeInOrientation } from '@/util/canvas-util'
|
||||||
import { numberCheck } from '@/util/common-utils'
|
import { numberCheck } from '@/util/common-utils'
|
||||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
import { addedRoofsState, basicSettingState } from '@/store/settingAtom'
|
||||||
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { roofsState } from '@/store/roofAtom'
|
||||||
|
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||||
|
import Swal from 'sweetalert2'
|
||||||
|
|
||||||
export const Orientation = forwardRef(({ tabNum }, ref) => {
|
export const Orientation = forwardRef((props, ref) => {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController(1)
|
|
||||||
|
|
||||||
const { nextStep, compasDeg, setCompasDeg } = useOrientation()
|
|
||||||
|
|
||||||
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
|
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
|
||||||
|
const basicSetting = useRecoilValue(basicSettingState)
|
||||||
|
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) //지붕재 선택
|
||||||
|
const [roofsStore, setRoofsStore] = useRecoilState(roofsState)
|
||||||
|
const [roofTab, setRoofTab] = useState(0) //지붕재 탭
|
||||||
|
const {
|
||||||
|
roofs,
|
||||||
|
setRoofs,
|
||||||
|
tabNum,
|
||||||
|
setTabNum,
|
||||||
|
compasDeg,
|
||||||
|
setCompasDeg,
|
||||||
|
selectedModules,
|
||||||
|
roughnessCodes,
|
||||||
|
windSpeedCodes,
|
||||||
|
managementState,
|
||||||
|
setManagementState,
|
||||||
|
moduleList,
|
||||||
|
moduleSelectionData,
|
||||||
|
setModuleSelectionData,
|
||||||
|
setSelectedModules,
|
||||||
|
selectedSurfaceType,
|
||||||
|
setSelectedSurfaceType,
|
||||||
|
installHeight,
|
||||||
|
setInstallHeight,
|
||||||
|
standardWindSpeed,
|
||||||
|
setStandardWindSpeed,
|
||||||
|
verticalSnowCover,
|
||||||
|
setVerticalSnowCover,
|
||||||
|
orientationTrigger,
|
||||||
|
nextStep,
|
||||||
|
currentCanvasPlan,
|
||||||
|
loginUserState,
|
||||||
|
updateObjectDataApi,
|
||||||
|
} = props
|
||||||
|
const [inputCompasDeg, setInputCompasDeg] = useState(compasDeg ?? 0)
|
||||||
|
const [inputInstallHeight, setInputInstallHeight] = useState('0')
|
||||||
|
const [inputMargin, setInputMargin] = useState('0')
|
||||||
|
const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState('0')
|
||||||
|
const [inputRoughness, setInputRoughness] = useState(selectedSurfaceType)
|
||||||
|
const [inputStandardWindSpeed, setInputStandardWindSpeed] = useState(standardWindSpeed)
|
||||||
|
const { restoreModuleInstArea } = useModuleBasicSetting()
|
||||||
|
const moduleData = {
|
||||||
|
header: [
|
||||||
|
{ name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' },
|
||||||
|
{
|
||||||
|
name: `${getMessage('height')} (mm)`,
|
||||||
|
prop: 'height',
|
||||||
|
},
|
||||||
|
{ name: `${getMessage('width')} (mm)`, prop: 'width' },
|
||||||
|
{ name: `${getMessage('output')} (W)`, prop: 'output' },
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (basicSetting.roofSizeSet == '3') {
|
||||||
|
restoreModuleInstArea()
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (moduleSelectionData?.common) {
|
||||||
|
setInputMargin(moduleSelectionData?.common?.margin)
|
||||||
|
}
|
||||||
|
}, [moduleSelectionData])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedModules) {
|
||||||
|
setSelectedModules(moduleList.find((module) => module.itemId === selectedModules.itemId))
|
||||||
|
}
|
||||||
|
}, [selectedModules])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedSurfaceType) {
|
||||||
|
setInputRoughness(roughnessCodes.find((code) => code.clCode === managementState?.surfaceTypeValue))
|
||||||
|
}
|
||||||
|
}, [selectedSurfaceType])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (standardWindSpeed) setInputStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === managementState?.standardWindSpeedId))
|
||||||
|
}, [standardWindSpeed])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (managementState?.installHeight && managementState?.installHeight) {
|
||||||
|
setSelectedSurfaceType(roughnessCodes.find((code) => code.clCode === managementState?.surfaceTypeValue))
|
||||||
|
setInputInstallHeight(managementState?.installHeight)
|
||||||
|
setStandardWindSpeed(windSpeedCodes.find((code) => code.clCode === managementState?.standardWindSpeedId))
|
||||||
|
setInputVerticalSnowCover(managementState?.verticalSnowCover)
|
||||||
|
}
|
||||||
|
}, [managementState])
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
handleNextStep,
|
handleNextStep,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const handleNextStep = () => {
|
const handleNextStep = () => {
|
||||||
nextStep()
|
if (isComplete()) {
|
||||||
canvasPopupStatusTrigger(compasDeg)
|
const common = {
|
||||||
|
illuminationTp: inputRoughness.clCode,
|
||||||
|
illuminationTpNm: inputRoughness.clCodeNm,
|
||||||
|
instHt: inputInstallHeight,
|
||||||
|
stdWindSpeed: inputStandardWindSpeed?.clCode,
|
||||||
|
stdSnowLd: inputVerticalSnowCover,
|
||||||
|
saleStoreNorthFlg: managementState?.saleStoreNorthFlg,
|
||||||
|
moduleTpCd: selectedModules.itemTp,
|
||||||
|
moduleItemId: selectedModules.itemId,
|
||||||
|
margin: inputMargin,
|
||||||
|
}
|
||||||
|
setCompasDeg(inputCompasDeg)
|
||||||
|
setInstallHeight(inputInstallHeight)
|
||||||
|
setVerticalSnowCover(inputVerticalSnowCover)
|
||||||
|
setSelectedSurfaceType(inputRoughness)
|
||||||
|
setStandardWindSpeed(inputStandardWindSpeed)
|
||||||
|
nextStep(inputCompasDeg)
|
||||||
|
setManagementState({
|
||||||
|
...managementState,
|
||||||
|
installHeight: inputInstallHeight,
|
||||||
|
verticalSnowCover: inputVerticalSnowCover,
|
||||||
|
standardWindSpeedId: inputStandardWindSpeed?.clCode,
|
||||||
|
surfaceType: inputRoughness.clCodeNm,
|
||||||
|
surfaceTypeValue: inputRoughness.clCode,
|
||||||
|
})
|
||||||
|
setModuleSelectionData({
|
||||||
|
...moduleSelectionData,
|
||||||
|
module: {
|
||||||
|
...selectedModules,
|
||||||
|
},
|
||||||
|
common,
|
||||||
|
})
|
||||||
|
orientationTrigger({
|
||||||
|
compasDeg: inputCompasDeg,
|
||||||
|
common: common,
|
||||||
|
module: {
|
||||||
|
...selectedModules,
|
||||||
|
},
|
||||||
|
margin: inputMargin,
|
||||||
|
})
|
||||||
|
updateObjectDataApi({
|
||||||
|
objectNo: currentCanvasPlan.objectNo, //오브젝트_no
|
||||||
|
standardWindSpeedId: inputStandardWindSpeed?.clCode, //기준풍속코드
|
||||||
|
verticalSnowCover: inputVerticalSnowCover, //적설량
|
||||||
|
surfaceType: inputRoughness.clCodeNm, //면조도구분
|
||||||
|
installHeight: inputInstallHeight, //설치높이
|
||||||
|
userId: loginUserState.userId, //작성자아아디
|
||||||
|
})
|
||||||
|
setTabNum(2)
|
||||||
|
} else {
|
||||||
|
if (!selectedModules || !selectedModules.itemId) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('module.not.found'),
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
checkDegree(compasDeg)
|
|
||||||
}, [compasDeg])
|
|
||||||
|
|
||||||
const checkDegree = (e) => {
|
const checkDegree = (e) => {
|
||||||
if (e === '-0' || e === '-') {
|
if (e === '-0' || e === '-') {
|
||||||
setCompasDeg('-')
|
setInputCompasDeg('-')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (e === '0-') {
|
if (e === '0-') {
|
||||||
setCompasDeg('-0')
|
setInputCompasDeg('-0')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (Number(e) >= -180 && Number(e) <= 180) {
|
if (Number(e) >= -180 && Number(e) <= 180) {
|
||||||
if (numberCheck(Number(e))) {
|
if (numberCheck(Number(e))) {
|
||||||
setCompasDeg(Number(e))
|
setInputCompasDeg(Number(e))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setCompasDeg(compasDeg)
|
setInputCompasDeg(compasDeg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isComplete = () => {
|
||||||
|
if (!selectedModules || !selectedModules.itemId) return false
|
||||||
|
if (basicSetting && basicSetting.roofSizeSet !== '3') {
|
||||||
|
if (inputInstallHeight <= 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (+inputVerticalSnowCover <= 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inputStandardWindSpeed) return false
|
||||||
|
if (!inputRoughness) return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeModule = (e) => {
|
||||||
|
resetRoofs()
|
||||||
|
setSelectedModules(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeRoughness = (e) => {
|
||||||
|
resetRoofs()
|
||||||
|
setInputRoughness(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeInstallHeight = (e) => {
|
||||||
|
resetRoofs()
|
||||||
|
setInputInstallHeight(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeStandardWindSpeed = (e) => {
|
||||||
|
resetRoofs()
|
||||||
|
setInputStandardWindSpeed(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeVerticalSnowCover = (e) => {
|
||||||
|
resetRoofs()
|
||||||
|
setInputVerticalSnowCover(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetRoofs = () => {
|
||||||
|
const newRoofs = addedRoofs.map((roof) => {
|
||||||
|
return {
|
||||||
|
...roof,
|
||||||
|
trestle: {
|
||||||
|
lengthBase: null,
|
||||||
|
trestleMkrCd: null,
|
||||||
|
constMthdCd: null,
|
||||||
|
constTp: null,
|
||||||
|
roofBaseCd: null,
|
||||||
|
roofPchBase: null,
|
||||||
|
},
|
||||||
|
addRoof: {
|
||||||
|
...roof.addRoof,
|
||||||
|
lengthBase: null,
|
||||||
|
eavesMargin: null,
|
||||||
|
kerabaMargin: null,
|
||||||
|
ridgeMargin: null,
|
||||||
|
},
|
||||||
|
construction: {
|
||||||
|
constTp: null,
|
||||||
|
cvrYn: 'N',
|
||||||
|
snowGdPossYn: 'N',
|
||||||
|
cvrChecked: false,
|
||||||
|
snowGdChecked: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// setRoofs(newRoofs)
|
||||||
|
// setAddedRoofs(newRoofs)
|
||||||
|
setRoofsStore(newRoofs)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="properties-setting-wrap">
|
<div className="properties-setting-wrap">
|
||||||
<div className="outline-wrap">
|
<div className="outline-wrap">
|
||||||
<div className="guide">{getMessage('modal.module.basic.setting.orientation.setting.info')}</div>
|
<div className="roof-module-inner">
|
||||||
<div className="roof-module-compas">
|
<div className="compas-wrapper">
|
||||||
<div className="compas-box">
|
<div className="guide">{getMessage('modal.module.basic.setting.orientation.setting.info')}</div>
|
||||||
<div className="compas-box-inner">
|
<div className="roof-module-compas">
|
||||||
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
<div className="compas-box">
|
||||||
<div
|
<div className="compas-box-inner">
|
||||||
key={index}
|
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
||||||
className={`circle ${getDegreeInOrientation(compasDeg) === -1 * (-15 * index + 180) || (index === 0 && compasDeg >= 172 && index === 0 && compasDeg <= 180) || (compasDeg === -180 && index === 0) ? 'act' : ''}`}
|
<div
|
||||||
onClick={() => {
|
key={index}
|
||||||
if (index === 0) {
|
className={`circle ${getDegreeInOrientation(inputCompasDeg) === -1 * (-15 * index + 180) || (index === 0 && inputCompasDeg >= 172 && index === 0 && inputCompasDeg <= 180) || (inputCompasDeg === -180 && index === 0) ? 'act' : ''}`}
|
||||||
setCompasDeg(180)
|
onClick={() => {
|
||||||
return
|
if (index === 0) {
|
||||||
}
|
setInputCompasDeg(180)
|
||||||
setCompasDeg(-1 * (-15 * index + 180))
|
return
|
||||||
}}
|
}
|
||||||
>
|
setInputCompasDeg(-1 * (-15 * index + 180))
|
||||||
{index === 0 && <i>180°</i>}
|
}}
|
||||||
{index === 6 && <i>-90°</i>}
|
>
|
||||||
|
{index === 0 && <i>180°</i>}
|
||||||
|
{index === 6 && <i>-90°</i>}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`circle ${inputCompasDeg !== 180 && getDegreeInOrientation(inputCompasDeg) === 15 * index ? 'act' : ''}`}
|
||||||
|
onClick={() => setInputCompasDeg(15 * index)}
|
||||||
|
>
|
||||||
|
{index === 0 && <i>0°</i>}
|
||||||
|
{index === 6 && <i>90°</i>}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<div className="compas">
|
||||||
|
<div className="compas-arr" style={{ transform: `rotate(${getDegreeInOrientation(inputCompasDeg)}deg)` }}></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
</div>
|
||||||
{Array.from({ length: 180 / 15 }).map((dot, index) => (
|
</div>
|
||||||
<div
|
<div className="center-wrap">
|
||||||
key={index}
|
<div className="outline-form">
|
||||||
className={`circle ${compasDeg !== 180 && getDegreeInOrientation(compasDeg) === 15 * index ? 'act' : ''}`}
|
<div className="d-check-box pop mr10">
|
||||||
onClick={() => setCompasDeg(15 * index)}
|
<input type="checkbox" id="ch99" checked={hasAnglePassivity} onChange={() => setHasAnglePassivity(!hasAnglePassivity)} />
|
||||||
>
|
<label htmlFor="ch99">{getMessage('modal.module.basic.setting.orientation.setting.angle.passivity')}</label>
|
||||||
{index === 0 && <i>0°</i>}
|
|
||||||
{index === 6 && <i>90°</i>}
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
<div className="input-grid mr10" style={{ width: '60px' }}>
|
||||||
<div className="compas">
|
<input
|
||||||
<div className="compas-arr" style={{ transform: `rotate(${getDegreeInOrientation(compasDeg)}deg)` }}></div>
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
value={inputCompasDeg}
|
||||||
|
readOnly={!hasAnglePassivity}
|
||||||
|
placeholder={0}
|
||||||
|
onChange={(e) => checkDegree(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="thin">°</span>
|
||||||
|
<span className="thin">( -180 〜 180 )</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="compas-table-wrap">
|
||||||
<div className="center-wrap">
|
<div className="compas-table-box mb10">
|
||||||
<div className="d-check-box pop">
|
<div className="outline-form mb10">
|
||||||
<input type="checkbox" id="ch99" checked={hasAnglePassivity} onChange={() => setHasAnglePassivity(!hasAnglePassivity)} />
|
<span>{getMessage('modal.module.basic.setting.module.setting')}</span>
|
||||||
<label htmlFor="ch99">{getMessage('modal.module.basic.setting.orientation.setting.angle.passivity')}(-180 〜 180)</label>
|
<div className="grid-select">
|
||||||
</div>
|
{moduleList && (
|
||||||
<div className="outline-form">
|
<QSelectBox
|
||||||
<div className="input-grid mr10" style={{ width: '160px' }}>
|
options={moduleList}
|
||||||
<input
|
value={selectedModules}
|
||||||
type="text"
|
targetKey={'itemId'}
|
||||||
className="input-origin block"
|
sourceKey={'itemId'}
|
||||||
value={compasDeg}
|
showKey={'itemNm'}
|
||||||
readOnly={!hasAnglePassivity}
|
onChange={(e) => handleChangeModule(e)}
|
||||||
placeholder={0}
|
/>
|
||||||
onChange={
|
)}
|
||||||
(e) => checkDegree(e.target.value)
|
</div>
|
||||||
// setCompasDeg(
|
</div>
|
||||||
|
<div className="roof-module-table">
|
||||||
// e.target.value === '-' || (e.target.value !== '' && parseInt(e.target.value) <= 180 && parseInt(e.target.value) >= -180)
|
<table>
|
||||||
// ? e.target.value
|
<thead>
|
||||||
// : 0,
|
<tr>
|
||||||
// )
|
{moduleData.header.map((header) => {
|
||||||
}
|
return (
|
||||||
/>
|
<th key={header.prop} style={{ width: header.width ? header.width + 'px' : '' }}>
|
||||||
|
{header.name}
|
||||||
|
</th>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{Array.from({ length: 3 }).map((_, index) => {
|
||||||
|
return selectedModules && selectedModules?.itemList && selectedModules?.itemList?.length >= index + 1 ? (
|
||||||
|
<tr key={index}>
|
||||||
|
<td>
|
||||||
|
<div className="color-wrap">
|
||||||
|
<span
|
||||||
|
className="color-box"
|
||||||
|
style={{
|
||||||
|
backgroundColor: selectedModules.itemList[index].color,
|
||||||
|
}}
|
||||||
|
></span>
|
||||||
|
<span className="name">{selectedModules.itemList[index].itemNm}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="al-r">{Number(selectedModules.itemList[index].shortAxis).toFixed(0)}</td>
|
||||||
|
<td className="al-r">{Number(selectedModules.itemList[index].longAxis).toFixed(0)}</td>
|
||||||
|
<td className="al-r">{Number(selectedModules.itemList[index].wpOut).toFixed(0)}</td>
|
||||||
|
</tr>
|
||||||
|
) : (
|
||||||
|
<tr key={index}>
|
||||||
|
<td>
|
||||||
|
<div className="color-wrap"></div>
|
||||||
|
</td>
|
||||||
|
<td className="al-r"></td>
|
||||||
|
<td className="al-r"></td>
|
||||||
|
<td className="al-r"></td>
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{basicSetting && basicSetting.roofSizeSet == '3' && (
|
||||||
|
<div className="outline-form mt15">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.placement.area')}</span>
|
||||||
|
<div className="input-grid mr10" style={{ width: '60px' }}>
|
||||||
|
<input type="number" className="input-origin block" value={inputMargin} onChange={(e) => setInputMargin(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<span className="thin">m</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<span className="thin">°</span>
|
|
||||||
|
{basicSetting && basicSetting.roofSizeSet != '3' && (
|
||||||
|
<div className="compas-table-box">
|
||||||
|
<div className="compas-grid-table">
|
||||||
|
<div className="outline-form">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.surface.type')}</span>
|
||||||
|
<div className="grid-select">
|
||||||
|
{roughnessCodes.length > 0 && managementState && (
|
||||||
|
<QSelectBox
|
||||||
|
options={roughnessCodes}
|
||||||
|
value={inputRoughness}
|
||||||
|
targetKey={'clCode'}
|
||||||
|
sourceKey={'clCode'}
|
||||||
|
showKey={'clCodeNm'}
|
||||||
|
onChange={(e) => handleChangeRoughness(e)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.fitting.height')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="input-origin block"
|
||||||
|
value={inputInstallHeight}
|
||||||
|
onChange={(e) => handleChangeInstallHeight(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="thin">m</span>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.standard.wind.speed')}</span>
|
||||||
|
<div className="grid-select">
|
||||||
|
{windSpeedCodes.length > 0 && managementState && (
|
||||||
|
<QSelectBox
|
||||||
|
title={''}
|
||||||
|
options={windSpeedCodes}
|
||||||
|
value={inputStandardWindSpeed}
|
||||||
|
targetKey={'clCode'}
|
||||||
|
sourceKey={'clCode'}
|
||||||
|
showKey={'clCodeNm'}
|
||||||
|
onChange={(e) => handleChangeStandardWindSpeed(e)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.standard.snowfall.amount')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="input-origin block"
|
||||||
|
value={inputVerticalSnowCover}
|
||||||
|
onChange={(e) => handleChangeVerticalSnowCover(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="thin">cm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,29 +1,43 @@
|
|||||||
import { forwardRef, useEffect, useState } from 'react'
|
import { forwardRef, useEffect, useState } from 'react'
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||||
import { checkedModuleState, currentCanvasPlanState, isManualModuleSetupState } from '@/store/canvasAtom'
|
import {
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
checkedModuleState,
|
||||||
|
isManualModuleLayoutSetupState,
|
||||||
|
isManualModuleSetupState,
|
||||||
|
moduleRowColArrayState,
|
||||||
|
moduleSetupOptionState,
|
||||||
|
toggleManualSetupModeState,
|
||||||
|
} from '@/store/canvasAtom'
|
||||||
|
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
|
|
||||||
const Placement = forwardRef((props, refs) => {
|
const Placement = forwardRef((props, refs) => {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const [isChidori, setIsChidori] = useState(false)
|
const [useTab, setUseTab] = useState(true)
|
||||||
|
|
||||||
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
|
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
|
||||||
|
|
||||||
const [setupLocation, setSetupLocation] = useState('eaves')
|
|
||||||
const [isMaxSetup, setIsMaxSetup] = useState('false')
|
|
||||||
const [selectedItems, setSelectedItems] = useState({})
|
const [selectedItems, setSelectedItems] = useState({})
|
||||||
|
|
||||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState)
|
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState)
|
||||||
|
|
||||||
const setCheckedModules = useSetRecoilState(checkedModuleState)
|
const setCheckedModules = useSetRecoilState(checkedModuleState)
|
||||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
||||||
const { makeModuleInitArea } = useModuleBasicSetting(3)
|
const { makeModuleInitArea, roofOutlineColor } = useModuleBasicSetting(3)
|
||||||
|
|
||||||
const [isMultiModule, setIsMultiModule] = useState(false)
|
const [isMultiModule, setIsMultiModule] = useState(false)
|
||||||
|
|
||||||
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
|
//언마운트시 버튼 초기화
|
||||||
|
const setIsManualModuleSetup = useSetRecoilState(isManualModuleSetupState)
|
||||||
|
const setIsManualModuleLayoutSetup = useSetRecoilState(isManualModuleLayoutSetupState)
|
||||||
|
const setManualSetupMode = useSetRecoilState(toggleManualSetupModeState)
|
||||||
|
|
||||||
|
const [moduleSetupOption, setModuleSetupOption] = useRecoilState(moduleSetupOptionState) //모듈 설치 옵션
|
||||||
|
const resetModuleSetupOption = useResetRecoilState(moduleSetupOptionState)
|
||||||
|
|
||||||
|
const [colspan, setColspan] = useState(1)
|
||||||
|
const moduleRowColArray = useRecoilValue(moduleRowColArrayState)
|
||||||
|
|
||||||
//모듈 배치면 생성
|
//모듈 배치면 생성
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -36,11 +50,24 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
makeModuleInitArea(moduleSelectionData)
|
makeModuleInitArea(moduleSelectionData)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (moduleSelectionData.module.itemList.length > 1) {
|
||||||
|
setColspan(2)
|
||||||
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
// refs.isChidori.current = 'false'
|
||||||
|
// refs.setupLocation.current = 'eaves'
|
||||||
setIsManualModuleSetup(false)
|
setIsManualModuleSetup(false)
|
||||||
|
setIsManualModuleLayoutSetup(false)
|
||||||
|
setManualSetupMode('off')
|
||||||
|
resetModuleSetupOption()
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// console.log('moduleRowColArray', moduleRowColArray)
|
||||||
|
// }, [moduleRowColArray])
|
||||||
|
|
||||||
//최초 지입시 체크
|
//최초 지입시 체크
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isObjectNotEmpty(moduleSelectionData)) {
|
if (isObjectNotEmpty(moduleSelectionData)) {
|
||||||
@ -54,8 +81,10 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
initCheckedModule = { ...initCheckedModule, [obj.itemId]: true }
|
initCheckedModule = { ...initCheckedModule, [obj.itemId]: true }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
setSelectedItems(initCheckedModule)
|
setSelectedItems(initCheckedModule)
|
||||||
setSelectedModules(moduleSelectionData.module)
|
setSelectedModules(moduleSelectionData.module)
|
||||||
|
props.setLayoutSetup(moduleSelectionData.module.itemList.map((item) => ({ moduleId: item.itemId, col: 0, row: 0, checked: true })))
|
||||||
}
|
}
|
||||||
|
|
||||||
//모듈 배치면 생성
|
//모듈 배치면 생성
|
||||||
@ -80,63 +109,79 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
header: [
|
header: [
|
||||||
{ type: 'check', name: '', prop: 'check', width: 70 },
|
{ type: 'check', name: '', prop: 'check', width: 70 },
|
||||||
{ type: 'color-box', name: getMessage('module'), prop: 'module' },
|
{ type: 'color-box', name: getMessage('module'), prop: 'module' },
|
||||||
{ type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 },
|
{ type: 'text', name: getMessage('modal.module.basic.setting.module.placement.mix.asg.yn'), prop: 'mixAsgYn', width: 50 },
|
||||||
|
{ type: 'text', name: `段数`, prop: 'rows', width: 60 },
|
||||||
|
{ type: 'text', name: `列数`, prop: 'cols', width: 60 },
|
||||||
],
|
],
|
||||||
rows: [],
|
rows: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeChidori = (e) => {
|
const handleChangeChidori = (e) => {
|
||||||
const bool = e.target.value === 'true' ? true : false
|
const bool = e.target.value === 'true' ? true : false
|
||||||
setIsChidori(bool)
|
setModuleSetupOption({ ...moduleSetupOption, isChidori: bool })
|
||||||
refs.isChidori.current = e.target.value
|
|
||||||
|
//변경하면 수동 다 꺼짐
|
||||||
|
setIsManualModuleSetup(false)
|
||||||
|
setIsManualModuleLayoutSetup(false)
|
||||||
|
setManualSetupMode('off')
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSetupLocation = (e) => {
|
const handleSetupLocation = (e) => {
|
||||||
setSetupLocation(e.target.value)
|
setModuleSetupOption({ ...moduleSetupOption, setupLocation: e.target.value })
|
||||||
refs.setupLocation.current = e.target.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleMaxSetup = (e) => {
|
//변경하면 수동 다 꺼짐
|
||||||
if (e.target.checked) {
|
setIsManualModuleSetup(false)
|
||||||
setIsMaxSetup('true')
|
setIsManualModuleLayoutSetup(false)
|
||||||
refs.isMaxSetup.current = 'true'
|
setManualSetupMode('off')
|
||||||
} else {
|
|
||||||
setIsMaxSetup('false')
|
|
||||||
refs.isMaxSetup.current = 'false'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//체크된 모듈 아이디 추출
|
//체크된 모듈 아이디 추출
|
||||||
const handleSelectedItem = (e) => {
|
const handleSelectedItem = (e, itemId) => {
|
||||||
setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked })
|
setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked })
|
||||||
|
|
||||||
|
const newLayoutSetup = [...props.layoutSetup]
|
||||||
|
props.layoutSetup.forEach((item, index) => {
|
||||||
|
if (item.moduleId === itemId) {
|
||||||
|
newLayoutSetup[index] = { ...props.layoutSetup[index], checked: e.target.checked }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
props.setLayoutSetup(newLayoutSetup)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleLayoutSetup = (e, itemId, index) => {
|
||||||
|
const newLayoutSetup = [...props.layoutSetup]
|
||||||
|
newLayoutSetup[index] = {
|
||||||
|
...newLayoutSetup[index],
|
||||||
|
moduleId: itemId,
|
||||||
|
[e.target.name]: Number(e.target.value),
|
||||||
|
}
|
||||||
|
props.setLayoutSetup(newLayoutSetup)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="module-table-flex-wrap mb10">
|
<div className="module-table-flex-wrap">
|
||||||
<div className="module-table-box">
|
<div className="module-table-box">
|
||||||
<div className="module-table-inner">
|
<div className="module-table-inner">
|
||||||
<div className="roof-module-table">
|
<div className="roof-module-table">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
{moduleData.header.map((data) => (
|
||||||
{moduleData.header.map((data) => (
|
<th key={data.prop} style={{ width: data.width ? data.width : '' }}>
|
||||||
<th key={data.prop} style={{ width: data.width ? data.width : '' }}>
|
{data.type === 'check' ? (
|
||||||
{data.type === 'check' ? (
|
<div className="d-check-box no-text pop">
|
||||||
<div className="d-check-box no-text pop">
|
<input type="checkbox" id="ch01" disabled />
|
||||||
<input type="checkbox" id="ch01" disabled />
|
<label htmlFor="ch01"></label>
|
||||||
<label htmlFor="ch01"></label>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
data.name
|
||||||
data.name
|
)}
|
||||||
)}
|
</th>
|
||||||
</th>
|
))}
|
||||||
))}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{selectedModules.itemList &&
|
{selectedModules?.itemList &&
|
||||||
selectedModules.itemList.map((item, index) => (
|
selectedModules?.itemList?.map((item, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td className="al-c">
|
<td className="al-c">
|
||||||
<div className="d-check-box no-text pop">
|
<div className="d-check-box no-text pop">
|
||||||
@ -145,7 +190,7 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
id={item.itemId}
|
id={item.itemId}
|
||||||
name={item.itemId}
|
name={item.itemId}
|
||||||
checked={selectedItems[item.itemId]}
|
checked={selectedItems[item.itemId]}
|
||||||
onChange={handleSelectedItem}
|
onChange={(e) => handleSelectedItem(e, item.itemId)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={item.itemId}></label>
|
<label htmlFor={item.itemId}></label>
|
||||||
</div>
|
</div>
|
||||||
@ -156,93 +201,178 @@ const Placement = forwardRef((props, refs) => {
|
|||||||
<span className="name">{item.itemNm}</span>
|
<span className="name">{item.itemNm}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="al-r">{item.wpOut}</td>
|
<td className="al-c">
|
||||||
|
<div className="color-wrap">
|
||||||
|
<span className="name">{item.mixAsgYn}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="al-r">
|
||||||
|
<div className="input-grid">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
name="row"
|
||||||
|
value={props.layoutSetup[index]?.row ?? 1}
|
||||||
|
defaultValue={0}
|
||||||
|
onChange={(e) => handleLayoutSetup(e, item.itemId, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td className="al-r">
|
||||||
|
<div className="input-grid">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
name="col"
|
||||||
|
value={props.layoutSetup[index]?.col ?? 1}
|
||||||
|
defaultValue={0}
|
||||||
|
onChange={(e) => handleLayoutSetup(e, item.itemId, index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
))}
|
))}
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="module-table-box">
|
<div className="module-table-box non-flex">
|
||||||
<div className="module-table-inner">
|
<div className="module-table-inner">
|
||||||
<div className="self-table-tit">{getMessage('modal.module.basic.setting.module.placement.select.fitting.type')}</div>
|
<div className="roof-module-table">
|
||||||
<div className="module-self-table">
|
<table>
|
||||||
<div className="self-table-item">
|
<thead>
|
||||||
<div className="self-item-th">{getMessage('modal.module.basic.setting.module.placement.waterfowl.arrangement')}</div>
|
<tr>
|
||||||
<div className="self-item-td">
|
<th>{getMessage('modal.module.basic.setting.module.placement.waterfowl.arrangement')}</th>
|
||||||
<div className="pop-form-radio">
|
<th>{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}</th>
|
||||||
<div className="d-check-radio pop">
|
</tr>
|
||||||
<input
|
</thead>
|
||||||
type="radio"
|
<tbody>
|
||||||
name="radio01"
|
<tr>
|
||||||
id="ra01"
|
<td>
|
||||||
checked={isChidori}
|
<div className="hexagonal-radio-wrap">
|
||||||
disabled={isChidoriNotAble}
|
<div className="d-check-radio pop mb10">
|
||||||
value={'true'}
|
<input
|
||||||
onChange={(e) => handleChangeChidori(e)}
|
type="radio"
|
||||||
/>
|
name="radio02"
|
||||||
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.module.placement.do')}</label>
|
id="ra03"
|
||||||
</div>
|
checked={moduleSetupOption.isChidori}
|
||||||
<div className="d-check-radio pop">
|
disabled={isChidoriNotAble}
|
||||||
<input type="radio" name="radio02" id="ra02" checked={!isChidori} value={'false'} onChange={(e) => handleChangeChidori(e)} />
|
value={'true'}
|
||||||
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.module.placement.do.not')}</label>
|
onChange={(e) => handleChangeChidori(e)}
|
||||||
</div>
|
/>
|
||||||
</div>
|
<label htmlFor="ra03">{getMessage('modal.module.basic.setting.module.placement.do')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="d-check-radio pop">
|
||||||
<div className="self-table-item">
|
<input
|
||||||
<div className="self-item-th">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard')}</div>
|
type="radio"
|
||||||
<div className="self-item-td">
|
name="radio02"
|
||||||
<div className="pop-form-radio">
|
id="ra04"
|
||||||
<div className="d-check-radio pop">
|
checked={!moduleSetupOption.isChidori}
|
||||||
<input
|
value={'false'}
|
||||||
type="radio"
|
onChange={(e) => handleChangeChidori(e)}
|
||||||
name="radio03"
|
/>
|
||||||
id="ra03"
|
<label htmlFor="ra04">{getMessage('modal.module.basic.setting.module.placement.do.not')}</label>
|
||||||
checked={setupLocation === 'center'}
|
</div>
|
||||||
value={'center'}
|
</div>
|
||||||
onChange={handleSetupLocation}
|
</td>
|
||||||
disabled={isMultiModule}
|
<td>
|
||||||
/>
|
<div className="hexagonal-radio-wrap">
|
||||||
<label htmlFor="ra03">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.center')}</label>
|
<div className="d-check-radio pop mb10">
|
||||||
</div>
|
<input
|
||||||
<div className="d-check-radio pop">
|
type="radio"
|
||||||
<input
|
name="radio03"
|
||||||
type="radio"
|
id="ra05"
|
||||||
name="radio04"
|
checked={moduleSetupOption.setupLocation === 'eaves'}
|
||||||
id="ra04"
|
value={'eaves'}
|
||||||
checked={setupLocation === 'eaves'}
|
onChange={handleSetupLocation}
|
||||||
value={'eaves'}
|
/>
|
||||||
onChange={handleSetupLocation}
|
<label htmlFor="ra05">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.eaves')}</label>
|
||||||
/>
|
</div>
|
||||||
<label htmlFor="ra04">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.eaves')}</label>
|
<div className="d-check-radio pop">
|
||||||
</div>
|
<input
|
||||||
<div className="d-check-radio pop">
|
type="radio"
|
||||||
<input
|
name="radio03"
|
||||||
type="radio"
|
id="ra06"
|
||||||
name="radio05"
|
checked={moduleSetupOption.setupLocation === 'ridge'}
|
||||||
id="ra05"
|
value={'ridge'}
|
||||||
checked={setupLocation === 'ridge'}
|
onChange={handleSetupLocation}
|
||||||
value={'ridge'}
|
disabled={isMultiModule}
|
||||||
onChange={handleSetupLocation}
|
/>
|
||||||
disabled={isMultiModule}
|
<label htmlFor="ra06">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.ridge')}</label>
|
||||||
/>
|
</div>
|
||||||
<label htmlFor="ra05">{getMessage('modal.module.basic.setting.module.placement.arrangement.standard.ridge')}</label>
|
</div>
|
||||||
</div>
|
</td>
|
||||||
</div>
|
</tr>
|
||||||
</div>
|
</tbody>
|
||||||
</div>
|
</table>
|
||||||
</div>
|
|
||||||
<div className="self-table-flx">
|
|
||||||
{/* <div className="d-check-box pop">
|
|
||||||
<input type="checkbox" id="ch04" checked={isMaxSetup === 'true'} value={'true'} onChange={handleMaxSetup} />
|
|
||||||
<label htmlFor="ch04">{getMessage('modal.module.basic.setting.module.placement.maximum')}</label>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="hide-check-guide">
|
||||||
|
{getMessage('modal.module.basic.setting.module.placement.max.size.check')}
|
||||||
|
<button className={`arr ${!useTab ? 'act' : ''}`} onClick={() => setUseTab(!useTab)}></button>
|
||||||
|
</div>
|
||||||
|
<div className={`module-table-box mt10 ${useTab ? 'hide' : ''}`}>
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="roof-module-table">
|
||||||
|
<table className="">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th rowSpan={2} style={{ width: '22%' }}></th>
|
||||||
|
{selectedModules &&
|
||||||
|
selectedModules.itemList?.map((item) => (
|
||||||
|
// <th colSpan={colspan}>
|
||||||
|
<th>
|
||||||
|
<div className="color-wrap">
|
||||||
|
<span className="color-box" style={{ backgroundColor: item.color }}></span>
|
||||||
|
<span className="name">{item.itemNm}</span>
|
||||||
|
</div>
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
{colspan > 1 && <th rowSpan={2}>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{selectedModules &&
|
||||||
|
selectedModules.itemList?.map((item) => (
|
||||||
|
<>
|
||||||
|
<th>{getMessage('modal.module.basic.setting.module.placement.max.row')}</th>
|
||||||
|
{/* {colspan > 1 && <th>{getMessage('modal.module.basic.setting.module.placement.max.rows.multiple')}</th>} */}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{moduleSelectionData.roofConstructions.map((item, index) => (
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div className="color-wrap">
|
||||||
|
<span className="color-box" style={{ backgroundColor: roofOutlineColor(item.addRoof?.index) }}></span>
|
||||||
|
<span className="name">{item.addRoof?.roofMatlNmJp}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{moduleRowColArray[index]?.map((item, index2) => (
|
||||||
|
<>
|
||||||
|
<td className="al-c">{item.moduleMaxRows}</td>
|
||||||
|
{/* {colspan > 1 && <td className="al-c">{item.mixModuleMaxRows}</td>} */}
|
||||||
|
{colspan > 1 && index2 === moduleRowColArray[index].length - 1 && <td className="al-c">{item.maxRow}</td>}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
769
src/components/floor-plan/modal/basic/step/Trestle.jsx
Normal file
769
src/components/floor-plan/modal/basic/step/Trestle.jsx
Normal file
@ -0,0 +1,769 @@
|
|||||||
|
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||||
|
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||||
|
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||||
|
import { useModuleTrestle } from '@/hooks/module/useModuleTrestle'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
import { currentAngleTypeSelector, pitchTextSelector } from '@/store/canvasAtom'
|
||||||
|
import { roofsState } from '@/store/roofAtom'
|
||||||
|
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
|
import { forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState } from 'react'
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
import Swal from 'sweetalert2'
|
||||||
|
|
||||||
|
const Trestle = forwardRef((props, ref) => {
|
||||||
|
const { tabNum, setTabNum, trestleTrigger, roofs, setRoofs, moduleSelectionData, setModuleSelectionData, setRoofsStore } = props
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
// const [selectedTrestle, setSelectedTrestle] = useState()
|
||||||
|
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||||
|
const pitchText = useRecoilValue(pitchTextSelector)
|
||||||
|
const [selectedRoof, setSelectedRoof] = useState(null)
|
||||||
|
const {
|
||||||
|
trestleState,
|
||||||
|
trestleDetail,
|
||||||
|
dispatch,
|
||||||
|
raftBaseList,
|
||||||
|
trestleList,
|
||||||
|
constMthdList,
|
||||||
|
roofBaseList,
|
||||||
|
constructionList,
|
||||||
|
eavesMargin,
|
||||||
|
ridgeMargin,
|
||||||
|
kerabaMargin,
|
||||||
|
setEavesMargin,
|
||||||
|
setRidgeMargin,
|
||||||
|
setKerabaMargin,
|
||||||
|
lengthBase,
|
||||||
|
setLengthBase,
|
||||||
|
hajebichi,
|
||||||
|
setHajebichi,
|
||||||
|
cvrYn,
|
||||||
|
cvrChecked,
|
||||||
|
snowGdPossYn,
|
||||||
|
snowGdChecked,
|
||||||
|
setCvrYn,
|
||||||
|
setCvrChecked,
|
||||||
|
setSnowGdPossYn,
|
||||||
|
setSnowGdChecked,
|
||||||
|
} = useModuleTrestle({
|
||||||
|
selectedRoof,
|
||||||
|
})
|
||||||
|
const selectedModules = useRecoilValue(selectedModuleState) //선택된 모듈
|
||||||
|
// const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
||||||
|
const [selectedRaftBase, setSelectedRaftBase] = useState(null)
|
||||||
|
const [selectedTrestle, setSelectedTrestle] = useState(null)
|
||||||
|
const [selectedConstMthd, setSelectedConstMthd] = useState(null)
|
||||||
|
const [selectedConstruction, setSelectedConstruction] = useState(null)
|
||||||
|
const [selectedRoofBase, setSelectedRoofBase] = useState(null)
|
||||||
|
const { managementState } = useContext(GlobalDataContext)
|
||||||
|
const { restoreModuleInstArea } = useModuleBasicSetting()
|
||||||
|
const [flag, setFlag] = useState(false)
|
||||||
|
const tempModuleSelectionData = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (roofs && !selectedRoof) {
|
||||||
|
setSelectedRoof(roofs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
//모듈 설치 영역 복구
|
||||||
|
restoreModuleInstArea()
|
||||||
|
}, [roofs])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (flag && moduleSelectionData) {
|
||||||
|
if (JSON.stringify(tempModuleSelectionData.current) === JSON.stringify(moduleSelectionData)) {
|
||||||
|
setTabNum(tabNum + 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [flag, moduleSelectionData])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedRoof) {
|
||||||
|
if (moduleSelectionData?.roofConstructions?.length >= selectedRoof.index + 1) {
|
||||||
|
const { construction, trestle, trestleDetail } = moduleSelectionData?.roofConstructions[selectedRoof.index]
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_INITIALIZE',
|
||||||
|
roof: { common: moduleSelectionData.common, module: moduleSelectionData.module, construction, trestle, trestleDetail, ...selectedRoof },
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dispatch({ type: 'SET_INITIALIZE', roof: { ...selectedRoof, common: moduleSelectionData.common, module: moduleSelectionData.module } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [selectedRoof])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (raftBaseList.length > 0) {
|
||||||
|
setSelectedRaftBase(raftBaseList.find((raft) => raft.clCode === selectedRoof?.raft) ?? null)
|
||||||
|
} else {
|
||||||
|
setSelectedRaftBase(null)
|
||||||
|
}
|
||||||
|
}, [raftBaseList])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (trestleList.length > 0) {
|
||||||
|
setSelectedTrestle(trestleList.find((trestle) => trestle.trestleMkrCd === trestleState?.trestleMkrCd) ?? null)
|
||||||
|
} else {
|
||||||
|
setSelectedTrestle(null)
|
||||||
|
}
|
||||||
|
}, [trestleList])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (roofBaseList.length > 0) {
|
||||||
|
setSelectedRoofBase(roofBaseList.find((roofBase) => roofBase.roofBaseCd === trestleState?.roofBaseCd) ?? null)
|
||||||
|
} else {
|
||||||
|
setSelectedRoofBase(null)
|
||||||
|
}
|
||||||
|
}, [roofBaseList])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (constMthdList.length > 0) {
|
||||||
|
setSelectedConstMthd(constMthdList.find((constMthd) => constMthd.constMthdCd === trestleState?.constMthdCd) ?? null)
|
||||||
|
} else {
|
||||||
|
setSelectedConstMthd(null)
|
||||||
|
}
|
||||||
|
}, [constMthdList])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (constructionList.length > 0) {
|
||||||
|
setSelectedConstruction(constructionList.find((construction) => construction.constTp === trestleState?.construction?.constTp) ?? null)
|
||||||
|
if (constructionList.filter((construction) => construction.constPossYn === 'Y').length === 0) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error4', [selectedRoof?.nameJp]), // 시공법법을 선택해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSelectedConstruction(null)
|
||||||
|
}
|
||||||
|
}, [constructionList])
|
||||||
|
|
||||||
|
const getConstructionState = (index) => {
|
||||||
|
if (constructionList && constructionList.length > 0) {
|
||||||
|
if (constructionList[index].constPossYn === 'Y') {
|
||||||
|
if (trestleState && trestleState.constTp === constructionList[index].constTp) {
|
||||||
|
return 'blue'
|
||||||
|
}
|
||||||
|
return 'white'
|
||||||
|
}
|
||||||
|
return 'no-click'
|
||||||
|
}
|
||||||
|
return 'no-click'
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeLength = (e) => {
|
||||||
|
setLengthBase(e)
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_LENGTH',
|
||||||
|
roof: {
|
||||||
|
length: e,
|
||||||
|
moduleTpCd: selectedModules.itemTp ?? '',
|
||||||
|
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeRaftBase = (e) => {
|
||||||
|
setSelectedRaftBase(e)
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_RAFT_BASE',
|
||||||
|
roof: {
|
||||||
|
moduleTpCd: selectedModules.itemTp ?? '',
|
||||||
|
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
|
||||||
|
raft: e.clCode,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeTrestleMaker = (e) => {
|
||||||
|
setSelectedTrestle(e)
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_TRESTLE_MAKER',
|
||||||
|
roof: {
|
||||||
|
moduleTpCd: selectedModules.itemTp ?? '',
|
||||||
|
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
trestleMkrCd: e.trestleMkrCd,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeConstMthd = (e) => {
|
||||||
|
setSelectedConstMthd(e)
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_CONST_MTHD',
|
||||||
|
roof: {
|
||||||
|
moduleTpCd: selectedModules.itemTp ?? '',
|
||||||
|
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
trestleMkrCd: selectedTrestle.trestleMkrCd,
|
||||||
|
constMthdCd: e.constMthdCd,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onChangeRoofBase = (e) => {
|
||||||
|
setSelectedRoofBase(e)
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_ROOF_BASE',
|
||||||
|
roof: {
|
||||||
|
moduleTpCd: selectedModules.itemTp ?? '',
|
||||||
|
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
trestleMkrCd: selectedTrestle.trestleMkrCd,
|
||||||
|
constMthdCd: selectedConstMthd.constMthdCd,
|
||||||
|
roofBaseCd: e.roofBaseCd,
|
||||||
|
illuminationTp: managementState?.surfaceTypeValue ?? '',
|
||||||
|
instHt: managementState?.installHeight ?? '',
|
||||||
|
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
|
||||||
|
stdSnowLd: managementState?.verticalSnowCover ?? '',
|
||||||
|
inclCd: selectedRoof?.pitch ?? 0,
|
||||||
|
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConstruction = (index) => {
|
||||||
|
if (constructionList[index]?.constPossYn === 'Y') {
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_CONSTRUCTION',
|
||||||
|
roof: {
|
||||||
|
moduleTpCd: selectedModules.itemTp ?? '',
|
||||||
|
roofMatlCd: selectedRoof?.roofMatlCd ?? '',
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
trestleMkrCd: selectedTrestle.trestleMkrCd,
|
||||||
|
constMthdCd: selectedConstMthd.constMthdCd,
|
||||||
|
roofBaseCd: selectedRoofBase.roofBaseCd,
|
||||||
|
illuminationTp: managementState?.surfaceTypeValue ?? '',
|
||||||
|
instHt: managementState?.installHeight ?? '',
|
||||||
|
stdWindSpeed: managementState?.standardWindSpeedId ?? '',
|
||||||
|
stdSnowLd: +managementState?.verticalSnowCover ?? '',
|
||||||
|
inclCd: selectedRoof?.pitch ?? 0,
|
||||||
|
roofPitch: Math.round(selectedRoof?.roofPchBase ?? 0),
|
||||||
|
constTp: constructionList[index].constTp,
|
||||||
|
snowGdPossYn: constructionList[index].snowGdPossYn,
|
||||||
|
cvrYn: constructionList[index].cvrYn,
|
||||||
|
mixMatlNo: selectedModules.mixMatlNo,
|
||||||
|
// workingWidth: selectedRoof?.length?.toString() ?? '',
|
||||||
|
workingWidth: lengthBase,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
setCvrYn(constructionList[index].cvrYn)
|
||||||
|
setSnowGdPossYn(constructionList[index].snowGdPossYn)
|
||||||
|
setCvrChecked(false)
|
||||||
|
setSnowGdChecked(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleChangeRoofMaterial = (index) => {
|
||||||
|
const newAddedRoofs = roofs.map((roof, i) => {
|
||||||
|
if (i === selectedRoof.index) {
|
||||||
|
return {
|
||||||
|
...selectedRoof,
|
||||||
|
hajebichi,
|
||||||
|
length: lengthBase,
|
||||||
|
eavesMargin,
|
||||||
|
ridgeMargin,
|
||||||
|
kerabaMargin,
|
||||||
|
roofIndex: selectedRoof.index,
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
trestle: {
|
||||||
|
hajebichi: hajebichi,
|
||||||
|
length: lengthBase,
|
||||||
|
...selectedRaftBase,
|
||||||
|
...selectedTrestle,
|
||||||
|
...selectedConstMthd,
|
||||||
|
...selectedRoofBase,
|
||||||
|
},
|
||||||
|
construction: {
|
||||||
|
...constructionList.find((data) => data.constTp === trestleState.constTp),
|
||||||
|
cvrYn: cvrYn,
|
||||||
|
snowGdPossYn: snowGdPossYn,
|
||||||
|
cvrChecked: cvrChecked,
|
||||||
|
snowGdChecked: snowGdChecked,
|
||||||
|
setupCover: cvrChecked ?? false,
|
||||||
|
setupSnowCover: snowGdChecked ?? false,
|
||||||
|
},
|
||||||
|
trestleDetail: trestleDetail,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return roof
|
||||||
|
})
|
||||||
|
setRoofs(newAddedRoofs)
|
||||||
|
setSelectedRoof(newAddedRoofs[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
const isComplete = async () => {
|
||||||
|
const newAddedRoofs = roofs.map((roof, i) => {
|
||||||
|
if (i === selectedRoof?.index) {
|
||||||
|
return {
|
||||||
|
...selectedRoof,
|
||||||
|
length: lengthBase,
|
||||||
|
eavesMargin,
|
||||||
|
ridgeMargin,
|
||||||
|
kerabaMargin,
|
||||||
|
roofIndex: roof.index,
|
||||||
|
raft: selectedRaftBase?.clCode,
|
||||||
|
trestle: {
|
||||||
|
length: lengthBase,
|
||||||
|
hajebichi: hajebichi,
|
||||||
|
...selectedRaftBase,
|
||||||
|
...selectedTrestle,
|
||||||
|
...selectedConstMthd,
|
||||||
|
...selectedRoofBase,
|
||||||
|
},
|
||||||
|
construction: {
|
||||||
|
...constructionList.find((data) => data.constTp === trestleState.constTp),
|
||||||
|
cvrYn,
|
||||||
|
snowGdPossYn,
|
||||||
|
cvrChecked,
|
||||||
|
snowGdChecked,
|
||||||
|
setupCover: cvrChecked ?? false,
|
||||||
|
setupSnowCover: snowGdChecked ?? false,
|
||||||
|
},
|
||||||
|
trestleDetail: trestleDetail,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return roof
|
||||||
|
})
|
||||||
|
|
||||||
|
let result = true
|
||||||
|
for (let i = 0; i < newAddedRoofs.length; i++) {
|
||||||
|
const roof = newAddedRoofs[i]
|
||||||
|
|
||||||
|
if (!roof.trestle?.trestleMkrCd) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error1', [roof.nameJp]), // 가대메이커를 선택해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roof.trestle?.constMthdCd) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error2', [roof.nameJp]), // 공법을 선택해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!roof.trestle?.roofBaseCd) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error3', [roof.nameJp]), // 지붕밑바탕을 선택해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if (!roof.construction?.constTp) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error12', [roof.nameJp]), // 시공법법을 선택해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roof.lenAuth === 'C') {
|
||||||
|
if (!roof.trestle?.length) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error5', [roof.nameJp]), // L 값을 입력해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (['C', 'R'].includes(roof.raftAuth)) {
|
||||||
|
if (!roof?.raft) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error6', [roof.nameJp]), // 서까래 간격을 입력해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (['C', 'R'].includes(roof.roofPchAuth)) {
|
||||||
|
if (!roof?.roofPchBase) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error7', [roof.nameJp]), // 하제비치를 입력해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!roof?.eavesMargin || !roof?.ridgeMargin || !roof?.kerabaMargin) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error8', [roof.nameJp]), // 모듈 배치 영영 값을 입력해주세요.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roof.trestle.trestleMkrCd !== 'NO_DATA') {
|
||||||
|
// 가매 없음이 아닐때는 가대 정보보다 작을 수 없음
|
||||||
|
if (roof.trestleDetail?.eaveIntvl > roof.eavesMargin) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error9', [roof.trestleDetail?.eaveIntvl, roof.nameJp]), // 모듈 배치 영역은 {0}mm 이상이어야 합니다.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roof.trestleDetail?.ridgeIntvl > roof.ridgeMargin) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error10', [roof.trestleDetail?.ridgeIntvl, roof.nameJp]), // 모듈 배치 영역은 {0}mm 이상이어야 합니다.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (roof.trestleDetail?.kerabaIntvl > roof.kerabaMargin) {
|
||||||
|
Swal.fire({
|
||||||
|
title: getMessage('modal.module.basic.settting.module.error11', [roof.trestleDetail?.kerabaIntvl, roof.nameJp]), // 모듈 배치 영역은 {0}mm 이상이어야 합니다.
|
||||||
|
icon: 'warning',
|
||||||
|
})
|
||||||
|
result = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
const newRoofs = newAddedRoofs.map((roof) => {
|
||||||
|
const { addRoof, construction, trestle, trestleDetail, roofConstructions, ...rest } = roof
|
||||||
|
return rest
|
||||||
|
})
|
||||||
|
|
||||||
|
setModuleSelectionData({
|
||||||
|
...moduleSelectionData,
|
||||||
|
roofConstructions: newAddedRoofs.map((roof, index) => ({
|
||||||
|
roofIndex: newRoofs[index].index,
|
||||||
|
trestle: roof.trestle,
|
||||||
|
addRoof: newRoofs[index],
|
||||||
|
construction: roof.construction,
|
||||||
|
trestleDetail: roof.trestleDetail,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
setFlag(true)
|
||||||
|
tempModuleSelectionData.current = {
|
||||||
|
...moduleSelectionData,
|
||||||
|
roofConstructions: newAddedRoofs.map((roof, index) => ({
|
||||||
|
roofIndex: newRoofs[index].index,
|
||||||
|
trestle: roof.trestle,
|
||||||
|
addRoof: newRoofs[index],
|
||||||
|
construction: roof.construction,
|
||||||
|
trestleDetail: roof.trestleDetail,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
const updatePromises = [
|
||||||
|
// new Promise((resolve) => {
|
||||||
|
// resolve()
|
||||||
|
// }),
|
||||||
|
new Promise((resolve) => {
|
||||||
|
setRoofs(newRoofs)
|
||||||
|
resolve()
|
||||||
|
}),
|
||||||
|
|
||||||
|
new Promise((resolve) => {
|
||||||
|
const roofConstructions = newAddedRoofs.map((roof, index) => ({
|
||||||
|
roofIndex: newRoofs[index].index,
|
||||||
|
addRoof: newRoofs[index],
|
||||||
|
trestle: {
|
||||||
|
...roof.trestle,
|
||||||
|
raft: roof.raftBaseCd,
|
||||||
|
},
|
||||||
|
construction: {
|
||||||
|
// ...constructionList.find((construction) => newAddedRoofs[index].construction.constTp === construction.constTp),
|
||||||
|
...roof.construction,
|
||||||
|
roofIndex: roof.index,
|
||||||
|
selectedIndex: roof.index,
|
||||||
|
},
|
||||||
|
trestleDetail: roof.trestleDetail,
|
||||||
|
}))
|
||||||
|
trestleTrigger({
|
||||||
|
roofConstructions,
|
||||||
|
})
|
||||||
|
setRoofsStore(roofConstructions)
|
||||||
|
resolve()
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
|
||||||
|
await Promise.all(updatePromises)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
isComplete,
|
||||||
|
}))
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="roof-module-tab2-overflow">
|
||||||
|
<div className="module-table-box mb10">
|
||||||
|
<div className="module-box-tab">
|
||||||
|
{roofs &&
|
||||||
|
roofs.map((roof, index) => (
|
||||||
|
<button
|
||||||
|
key={index}
|
||||||
|
className={`module-btn ${selectedRoof?.index === index ? 'act' : ''}`}
|
||||||
|
onClick={() => (roof ? handleChangeRoofMaterial(index) : null)}
|
||||||
|
>
|
||||||
|
{roof !== undefined ? `${roof.nameJp} (${currentAngleType === 'slope' ? roof.pitch : roof.angle}${pitchText})` : '-'}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div className="module-table-inner">
|
||||||
|
<div className="module-table-flex-wrap tab2">
|
||||||
|
<div className="module-flex-item">
|
||||||
|
<div className="eaves-keraba-table">
|
||||||
|
{selectedRoof && selectedRoof.lenAuth === 'C' && (
|
||||||
|
<>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">L</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="grid-select">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
value={lengthBase}
|
||||||
|
onChange={(e) => onChangeLength(e.target.value)}
|
||||||
|
disabled={selectedRoof.lenAuth === 'R'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{selectedRoof && ['C', 'R'].includes(selectedRoof.raftAuth) && (
|
||||||
|
<>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.rafter.margin')}</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="grid-select">
|
||||||
|
{raftBaseList.length > 0 && (
|
||||||
|
<QSelectBox
|
||||||
|
options={raftBaseList}
|
||||||
|
value={selectedRaftBase}
|
||||||
|
sourceKey={'clCode'}
|
||||||
|
targetKey={'clCode'}
|
||||||
|
showKey={'clCodeNm'}
|
||||||
|
disabled={selectedRoof.raftAuth === 'R'}
|
||||||
|
onChange={(e) => onChangeRaftBase(e)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{selectedRoof && ['C', 'R'].includes(selectedRoof.roofPchAuth) && (
|
||||||
|
<>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.hajebichi')}</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="grid-select">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="input-origin block"
|
||||||
|
disabled={selectedRoof.roofPchAuth === 'R'}
|
||||||
|
onChange={(e) => setHajebichi(e.target.value)}
|
||||||
|
value={hajebichi}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.trestle.maker')}</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="grid-select">
|
||||||
|
{trestleList && (
|
||||||
|
<QSelectBox
|
||||||
|
title={getMessage('selectbox.title')}
|
||||||
|
options={trestleList}
|
||||||
|
value={selectedTrestle}
|
||||||
|
sourceKey={'trestleMkrCd'}
|
||||||
|
targetKey={'trestleMkrCd'}
|
||||||
|
showKey={'trestleMkrCdJp'}
|
||||||
|
onChange={(e) => onChangeTrestleMaker(e)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.construction.method')}</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="grid-select">
|
||||||
|
{constMthdList && (
|
||||||
|
<QSelectBox
|
||||||
|
title={getMessage('selectbox.title')}
|
||||||
|
options={constMthdList}
|
||||||
|
value={selectedConstMthd}
|
||||||
|
sourceKey={'constMthdCd'}
|
||||||
|
targetKey={'constMthdCd'}
|
||||||
|
showKey={'constMthdCdJp'}
|
||||||
|
onChange={(e) => onChangeConstMthd(e)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="eaves-keraba-item">
|
||||||
|
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.under.roof')}</div>
|
||||||
|
<div className="eaves-keraba-td">
|
||||||
|
<div className="grid-select">
|
||||||
|
{roofBaseList && (
|
||||||
|
<QSelectBox
|
||||||
|
title={getMessage('selectbox.title')}
|
||||||
|
options={roofBaseList}
|
||||||
|
sourceKey={'roofBaseCd'}
|
||||||
|
targetKey={'roofBaseCd'}
|
||||||
|
showKey={'roofBaseCdJp'}
|
||||||
|
value={selectedRoofBase}
|
||||||
|
onChange={(e) => onChangeRoofBase(e)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="module-flex-item non-flex">
|
||||||
|
<div className="flex-item-btn-wrap">
|
||||||
|
<button className={`btn-frame roof ${getConstructionState(0)}`} onClick={() => handleConstruction(0)}>
|
||||||
|
{getMessage('modal.module.basic.setting.module.standard.construction')}(I)
|
||||||
|
</button>
|
||||||
|
<button className={`btn-frame roof ${getConstructionState(3)}`} onClick={() => handleConstruction(3)}>
|
||||||
|
{getMessage('modal.module.basic.setting.module.multiple.construction')}
|
||||||
|
</button>
|
||||||
|
<button className={`btn-frame roof ${getConstructionState(1)}`} onClick={() => handleConstruction(1)}>
|
||||||
|
{getMessage('modal.module.basic.setting.module.standard.construction')}
|
||||||
|
</button>
|
||||||
|
<button className={`btn-frame roof ${getConstructionState(4)}`} onClick={() => handleConstruction(4)}>
|
||||||
|
{getMessage('modal.module.basic.setting.module.multiple.construction')}(II)
|
||||||
|
</button>
|
||||||
|
<button className={`btn-frame roof ${getConstructionState(2)}`} onClick={() => handleConstruction(2)}>
|
||||||
|
{getMessage('modal.module.basic.setting.module.enforce.construction')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="grid-check-form-flex">
|
||||||
|
<div className="d-check-box pop">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={`ch01`}
|
||||||
|
disabled={!cvrYn || cvrYn === 'N'}
|
||||||
|
checked={cvrChecked || false}
|
||||||
|
// onChange={() => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, cvrChecked: !trestleState.cvrChecked } })}
|
||||||
|
onChange={() => setCvrChecked(!cvrChecked)}
|
||||||
|
/>
|
||||||
|
<label htmlFor={`ch01`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
|
||||||
|
</div>
|
||||||
|
<div className="d-check-box pop">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
id={`ch02`}
|
||||||
|
disabled={!snowGdPossYn || snowGdPossYn === 'N'}
|
||||||
|
checked={snowGdChecked || false}
|
||||||
|
// onChange={() => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, snowGdChecked: !trestleState.snowGdChecked } })}
|
||||||
|
onChange={() => setSnowGdChecked(!snowGdChecked)}
|
||||||
|
/>
|
||||||
|
<label htmlFor={`ch02`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="module-input-area">
|
||||||
|
<div className="module-area-title">{getMessage('modal.module.basic.setting.module.placement.area')}</div>
|
||||||
|
<div className="module-input-wrap">
|
||||||
|
<div className="outline-form mr15">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.placement.area.eaves')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="input-origin block"
|
||||||
|
value={eavesMargin ?? 0}
|
||||||
|
// onChange={(e) => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, eavesMargin: e.target.value } })}
|
||||||
|
onChange={(e) => setEavesMargin(+e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form mr15">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.placement.area.ridge')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="input-origin block"
|
||||||
|
value={ridgeMargin ?? 0}
|
||||||
|
// onChange={(e) => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, ridgeMargin: e.target.value } })}
|
||||||
|
onChange={(e) => setRidgeMargin(+e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form ">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.placement.area.keraba')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
className="input-origin block"
|
||||||
|
value={kerabaMargin ?? 0}
|
||||||
|
// onChange={(e) => dispatch({ type: 'SET_TRESTLE_DETAIL', roof: { ...trestleState, kerabaMargin: e.target.value } })}
|
||||||
|
onChange={(e) => setKerabaMargin(+e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="module-input-area">
|
||||||
|
<div className="module-area-title">{getMessage('modal.module.basic.setting.module.placement.margin')}</div>
|
||||||
|
<div className="module-input-wrap">
|
||||||
|
<div className="outline-form">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.placement.margin.horizontal')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input type="text" className="input-origin block" defaultValue={trestleDetail?.moduleIntvlHor} readOnly />
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
<div className="outline-form">
|
||||||
|
<span>{getMessage('modal.module.basic.setting.module.placement.margin.vertical')}</span>
|
||||||
|
<div className="input-grid mr10">
|
||||||
|
<input type="text" className="input-origin block" defaultValue={trestleDetail?.moduleIntvlVer} readOnly />
|
||||||
|
</div>
|
||||||
|
<span className="thin">mm</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="module-bottom">
|
||||||
|
<div className="module-table-box ">
|
||||||
|
<div className="warning-guide">
|
||||||
|
<div className="warning">
|
||||||
|
{getMessage('modal.module.basic.setting.module.setting.info1')}
|
||||||
|
<br />
|
||||||
|
{getMessage('modal.module.basic.setting.module.setting.info2')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Trestle
|
||||||
@ -33,14 +33,6 @@ const PitchPlacement = forwardRef((props, refs) => {
|
|||||||
setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked })
|
setSelectedItems({ ...selectedItems, [e.target.name]: e.target.checked })
|
||||||
}
|
}
|
||||||
|
|
||||||
const moduleData = {
|
|
||||||
header: [
|
|
||||||
{ type: 'check', name: '', prop: 'check', width: 70 },
|
|
||||||
{ type: 'color-box', name: getMessage('module'), prop: 'module' },
|
|
||||||
{ type: 'text', name: `${getMessage('output')} (W)`, prop: 'output', width: 70 },
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
//체크된 모듈 데이터
|
//체크된 모듈 데이터
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key])
|
const checkedModuleIds = Object.keys(selectedItems).filter((key) => selectedItems[key])
|
||||||
@ -105,87 +97,91 @@ const PitchPlacement = forwardRef((props, refs) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="module-table-box mb10">
|
<div className="hexagonal-flex-wrap">
|
||||||
<div className="module-table-inner">
|
<div className="module-table-box ">
|
||||||
<div className="roof-module-table">
|
<div className="module-table-inner">
|
||||||
<table>
|
<div className="roof-module-table">
|
||||||
<thead>
|
<table>
|
||||||
<tr>
|
<thead>
|
||||||
{moduleData.header.map((data) => (
|
<tr>
|
||||||
<th key={data.prop} style={{ width: data.width ? data.width : '' }}>
|
<th style={{ width: '70px' }}>
|
||||||
{data.type === 'check' ? (
|
<div className="d-check-box no-text pop">
|
||||||
<div className="d-check-box no-text pop">
|
<input type="checkbox" id="ch01" disabled />
|
||||||
<input type="checkbox" id="ch01" disabled />
|
<label htmlFor="ch01"></label>
|
||||||
<label htmlFor="ch01"></label>
|
</div>
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
data.name
|
|
||||||
)}
|
|
||||||
</th>
|
</th>
|
||||||
))}
|
<th>{getMessage('module')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{selectedModules.itemList &&
|
{selectedModules.itemList &&
|
||||||
selectedModules.itemList.map((item, index) => (
|
selectedModules.itemList.map((item, index) => (
|
||||||
<tr key={index}>
|
<tr key={index}>
|
||||||
<td className="al-c">
|
<td className="al-c">
|
||||||
<div className="d-check-box no-text pop">
|
<div className="d-check-box no-text pop">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id={item.itemId}
|
id={item.itemId}
|
||||||
name={item.itemId}
|
name={item.itemId}
|
||||||
checked={selectedItems[item.itemId]}
|
checked={selectedItems[item.itemId]}
|
||||||
onChange={handleSelectedItem}
|
onChange={handleSelectedItem}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={item.itemId}></label>
|
<label htmlFor={item.itemId}></label>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div className="color-wrap">
|
<div className="color-wrap">
|
||||||
<span className="color-box" style={{ backgroundColor: item.color }}></span>
|
<span className="color-box" style={{ backgroundColor: item.color }}></span>
|
||||||
<span className="name">{item.itemNm}</span>
|
<span className="name">{item.itemNm}</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td className="al-r">{item.wpOut}</td>
|
</tr>
|
||||||
</tr>
|
))}
|
||||||
))}
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="module-table-box non-flex">
|
||||||
<div className="module-table-box mb10">
|
<div className="module-table-inner">
|
||||||
<div className="module-table-inner">
|
<div className="roof-module-table">
|
||||||
<div className="hexagonal-wrap">
|
<table>
|
||||||
<div className="hexagonal-item">
|
<thead>
|
||||||
<div className="bold-font">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting')}</div>
|
<tr>
|
||||||
</div>
|
<th>{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting')}</th>
|
||||||
<div className="hexagonal-item">
|
</tr>
|
||||||
<div className="pop-form-radio">
|
</thead>
|
||||||
<div className="d-check-radio pop">
|
<tbody>
|
||||||
<input
|
<tr>
|
||||||
type="radio"
|
<td>
|
||||||
name="radio01"
|
<div className="hexagonal-radio-wrap">
|
||||||
id="ra01"
|
<div className="d-check-radio pop mb10">
|
||||||
value={'south'}
|
<input
|
||||||
defaultChecked={setupLocation === 'south'}
|
type="radio"
|
||||||
onClick={handleSetupLocation}
|
name="radio01"
|
||||||
/>
|
id="ra01"
|
||||||
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
|
value={'south'}
|
||||||
</div>
|
defaultChecked={setupLocation === 'south'}
|
||||||
<div className="d-check-radio pop">
|
onClick={handleSetupLocation}
|
||||||
<input
|
/>
|
||||||
type="radio"
|
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.south')}</label>
|
||||||
name="radio01"
|
</div>
|
||||||
id="ra02"
|
<div className="d-check-radio pop">
|
||||||
value={'excreta'}
|
<input
|
||||||
defaultChecked={setupLocation === 'excreta'}
|
type="radio"
|
||||||
onClick={handleSetupLocation}
|
name="radio01"
|
||||||
/>
|
id="ra02"
|
||||||
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
|
value={'excreta'}
|
||||||
</div>
|
defaultChecked={setupLocation === 'excreta'}
|
||||||
</div>
|
onClick={handleSetupLocation}
|
||||||
|
/>
|
||||||
|
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.pitch.module.placement.standard.setting.select')}</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
const [tabNum, setTabNum] = useState(1)
|
const [tabNum, setTabNum] = useState(1)
|
||||||
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
|
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
|
||||||
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
||||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
const { managementState, setManagementState } = useContext(GlobalDataContext)
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
const selectedModules = useRecoilValue(selectedModuleState)
|
||||||
const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController()
|
const { getPcsAutoRecommendList, getPcsVoltageChk, getPcsVoltageStepUpList, getPcsManualConfChk } = useMasterController()
|
||||||
|
|
||||||
@ -84,7 +84,6 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
// const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
// const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!managementState) {
|
if (!managementState) {
|
||||||
setManagementState(managementStateLoaded)
|
|
||||||
}
|
}
|
||||||
// setCircuitData({
|
// setCircuitData({
|
||||||
// makers,
|
// makers,
|
||||||
@ -479,7 +478,7 @@ export default function CircuitTrestleSetting({ id }) {
|
|||||||
console.log(stepUpListData)
|
console.log(stepUpListData)
|
||||||
stepUpListData[0].pcsItemList.map((item, index) => {
|
stepUpListData[0].pcsItemList.map((item, index) => {
|
||||||
return item.serQtyList
|
return item.serQtyList
|
||||||
.filter((serQty) => serQty.selected)
|
.filter((serQty) => serQty.selected && serQty.paralQty > 0)
|
||||||
.forEach((serQty) => {
|
.forEach((serQty) => {
|
||||||
pcs.push({
|
pcs.push({
|
||||||
pcsMkrCd: item.pcsMkrCd,
|
pcsMkrCd: item.pcsMkrCd,
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export default function PowerConditionalSelect(props) {
|
|||||||
const { getPcsMakerList, getPcsModelList } = useMasterController()
|
const { getPcsMakerList, getPcsModelList } = useMasterController()
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
const selectedModules = useRecoilValue(selectedModuleState)
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
// const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||||
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
||||||
const modelHeader = [
|
const modelHeader = [
|
||||||
{ name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.series'), width: '15%', prop: 'pcsSerNm', type: 'color-box' },
|
{ name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.series'), width: '15%', prop: 'pcsSerNm', type: 'color-box' },
|
||||||
@ -110,6 +110,7 @@ export default function PowerConditionalSelect(props) {
|
|||||||
selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : false,
|
selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
setSelectedModels([])
|
||||||
}
|
}
|
||||||
setSeries(copySeries)
|
setSeries(copySeries)
|
||||||
handleSetmodels(copySeries.filter((s) => s.selected))
|
handleSetmodels(copySeries.filter((s) => s.selected))
|
||||||
|
|||||||
@ -42,7 +42,6 @@ export default function StepUp(props) {
|
|||||||
const [arrayLength, setArrayLength] = useState(3) //module-table-inner의 반복 개수
|
const [arrayLength, setArrayLength] = useState(3) //module-table-inner의 반복 개수
|
||||||
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
||||||
const { getPcsVoltageStepUpList, getPcsAutoRecommendList, getPcsVoltageChk, getPcsConnOptionItemList } = useMasterController()
|
const { getPcsVoltageStepUpList, getPcsAutoRecommendList, getPcsVoltageChk, getPcsConnOptionItemList } = useMasterController()
|
||||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
const selectedModules = useRecoilValue(selectedModuleState)
|
||||||
const [optCodes, setOptCodes] = useState([])
|
const [optCodes, setOptCodes] = useState([])
|
||||||
@ -573,7 +572,7 @@ export default function StepUp(props) {
|
|||||||
value={seletedMainOption}
|
value={seletedMainOption}
|
||||||
sourceKey="code"
|
sourceKey="code"
|
||||||
targetKey="code"
|
targetKey="code"
|
||||||
showKey="name"
|
showKey={`${globalLocale === 'ja' ? 'nameJp' : 'name'}`}
|
||||||
onChange={(e) => setSeletedMainOption(e)}
|
onChange={(e) => setSeletedMainOption(e)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -586,7 +585,7 @@ export default function StepUp(props) {
|
|||||||
value={seletedSubOption}
|
value={seletedSubOption}
|
||||||
sourceKey="code"
|
sourceKey="code"
|
||||||
targetKey="code"
|
targetKey="code"
|
||||||
showKey="name"
|
showKey={`${globalLocale === 'ja' ? 'nameJp' : 'name'}`}
|
||||||
onChange={(e) => setSeletedSubOption(e)}
|
onChange={(e) => setSeletedSubOption(e)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export default function PassivityCircuitAllocation(props) {
|
|||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
const { managementState } = useContext(GlobalDataContext)
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
const selectedModules = useRecoilValue(selectedModuleState)
|
||||||
const [selectedPcs, setSelectedPcs] = useState(selectedModels[0])
|
const [selectedPcs, setSelectedPcs] = useState(selectedModels[0])
|
||||||
const { header, rows, footer } = useRecoilValue(moduleStatisticsState)
|
const { header, rows, footer } = useRecoilValue(moduleStatisticsState)
|
||||||
@ -38,7 +38,6 @@ export default function PassivityCircuitAllocation(props) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setModuleStatisticsData()
|
setModuleStatisticsData()
|
||||||
if (!managementState) {
|
if (!managementState) {
|
||||||
setManagementState(managementStateLoaded)
|
|
||||||
}
|
}
|
||||||
canvas
|
canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { useMessage } from '@/hooks/useMessage'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
|
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||||
|
|
||||||
const FLOW_DIRECTION_TYPE = {
|
const FLOW_DIRECTION_TYPE = {
|
||||||
EIGHT_AZIMUTH: 'eightAzimuth',
|
EIGHT_AZIMUTH: 'eightAzimuth',
|
||||||
@ -19,6 +20,8 @@ export default function FlowDirectionSetting(props) {
|
|||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
|
const { changeSurfaceLineType } = useSurfaceShapeBatch({})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
canvas?.discardActiveObject()
|
canvas?.discardActiveObject()
|
||||||
@ -53,6 +56,7 @@ export default function FlowDirectionSetting(props) {
|
|||||||
})
|
})
|
||||||
drawDirectionArrow(roof)
|
drawDirectionArrow(roof)
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
|
changeSurfaceLineType(roof)
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,11 @@ export default function PanelEdit(props) {
|
|||||||
const isSetupModules = canvas.getObjects().filter((obj) => obj.name === 'module') // selectedObj에 없는 객체만 필터링
|
const isSetupModules = canvas.getObjects().filter((obj) => obj.name === 'module') // selectedObj에 없는 객체만 필터링
|
||||||
isSetupModules.forEach((obj) => obj.set({ lockMovementX: false, lockMovementY: false }))
|
isSetupModules.forEach((obj) => obj.set({ lockMovementX: false, lockMovementY: false }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//팝업 닫을때 선택 해제
|
||||||
|
return () => {
|
||||||
|
canvas?.discardActiveObject() //선택해제
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
//모듈 이동 적용
|
//모듈 이동 적용
|
||||||
@ -87,7 +92,7 @@ export default function PanelEdit(props) {
|
|||||||
moduleMultiCopy('row', length, direction)
|
moduleMultiCopy('row', length, direction)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
closePopup(id)
|
// closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -100,7 +100,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos} className="lrr" style={{ visibility: isHidden ? 'hidden' : 'visible' }}>
|
<WithDraggable isShow={true} pos={pos} className="lrr" isHidden={isHidden}>
|
||||||
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.object')} onClose={() => closePopup(id)} />
|
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.object')} onClose={() => closePopup(id)} />
|
||||||
<WithDraggable.Body>
|
<WithDraggable.Body>
|
||||||
<div className="modal-btn-wrap">
|
<div className="modal-btn-wrap">
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
|
|||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 지붕 레이아웃
|
* 지붕 레이아웃
|
||||||
@ -53,7 +54,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
rafter: useRef(null),
|
rafter: useRef(null),
|
||||||
hajebichi: useRef(null),
|
hajebichi: useRef(null),
|
||||||
}
|
}
|
||||||
|
const { saveCanvas } = usePlan()
|
||||||
/**
|
/**
|
||||||
* 치수 입력방법(복시도입력/실측값입력/육지붕)
|
* 치수 입력방법(복시도입력/실측값입력/육지붕)
|
||||||
*/
|
*/
|
||||||
@ -205,7 +206,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
/**
|
/**
|
||||||
* 배치면초기설정 저장 버튼 클릭
|
* 배치면초기설정 저장 버튼 클릭
|
||||||
*/
|
*/
|
||||||
const handleSaveBtn = () => {
|
const handleSaveBtn = async () => {
|
||||||
const roofInfo = {
|
const roofInfo = {
|
||||||
...currentRoof,
|
...currentRoof,
|
||||||
planNo: basicSetting.planNo,
|
planNo: basicSetting.planNo,
|
||||||
@ -254,14 +255,13 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
|
|
||||||
/* 저장 후 화면 닫기 */
|
/* 저장 후 화면 닫기 */
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
|
await saveCanvas(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<WithDraggable isShow={true} pos={pos} className="ll">
|
<WithDraggable isShow={true} pos={pos} className="ll">
|
||||||
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.initial.setting')} />
|
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.initial.setting')} />
|
||||||
<WithDraggable.Body>
|
<WithDraggable.Body>
|
||||||
<div className="left-bar modal-handle"></div>
|
|
||||||
<div className="right-bar modal-handle"></div>
|
|
||||||
<div className="placement-table">
|
<div className="placement-table">
|
||||||
<table>
|
<table>
|
||||||
<colgroup>
|
<colgroup>
|
||||||
@ -271,7 +271,11 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<th>{getMessage('modal.placement.initial.setting.plan.drawing')}</th>
|
<th>{getMessage('modal.placement.initial.setting.plan.drawing')}</th>
|
||||||
<td>{getMessage('modal.placement.initial.setting.plan.drawing.size.stuff')}</td>
|
<td>
|
||||||
|
{getMessage('modal.placement.initial.setting.plan.drawing.size.stuff')}
|
||||||
|
|
||||||
|
{getMessage('modal.placement.initial.setting.plan.drawing.only.number')}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
|
|||||||
@ -75,19 +75,19 @@ export default function Header(props) {
|
|||||||
userSession.storeId === 'T01'
|
userSession.storeId === 'T01'
|
||||||
? [
|
? [
|
||||||
{ id: 0, name: getMessage('site.header.link1'), target: '_blank' },
|
{ id: 0, name: getMessage('site.header.link1'), target: '_blank' },
|
||||||
{ id: 1, name: 'Q.ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
{ id: 1, name: 'HANASYS ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
||||||
{ id: 2, name: 'Q.Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
{ id: 2, name: 'HANASYS Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
||||||
{ id: 3, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' },
|
{ id: 3, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' },
|
||||||
]
|
]
|
||||||
: userSession.groupId === '60000'
|
: userSession.groupId === '60000'
|
||||||
? [
|
? [
|
||||||
{ id: 0, name: getMessage('site.header.link1'), target: '_blank' },
|
{ id: 0, name: getMessage('site.header.link1'), target: '_blank' },
|
||||||
{ id: 1, name: 'Q.ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
{ id: 1, name: 'HANASYS ORDER', link: `${qOrderUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
||||||
{ id: 2, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' },
|
{ id: 2, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' },
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
{ id: 0, name: getMessage('site.header.link1'), target: '_blank' },
|
{ id: 0, name: getMessage('site.header.link1'), target: '_blank' },
|
||||||
{ id: 1, name: 'Q.Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
{ id: 1, name: 'HANASYS Musubi', link: `${qMusubiUrl}?autoLoginParam1=${encodeURIComponent(res.data)}`, target: '_blank' },
|
||||||
{ id: 2, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' },
|
{ id: 2, name: getMessage('site.header.link2'), link: `https://q-warranty.q-cells.jp/seller_login`, target: '_blank' },
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
@ -203,7 +203,7 @@ export default function Stuff() {
|
|||||||
if (event.column.colId === 'objectNo') {
|
if (event.column.colId === 'objectNo') {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
//T 면 임시 R은 진짜
|
//T 면 임시 S는 진짜
|
||||||
if (event.data.objectNo) {
|
if (event.data.objectNo) {
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
if (event.data.tempFlg === '0') {
|
if (event.data.tempFlg === '0') {
|
||||||
@ -238,6 +238,8 @@ export default function Stuff() {
|
|||||||
schSortType: stuffSearchParams.schSortType,
|
schSortType: stuffSearchParams.schSortType,
|
||||||
pageNo: stuffSearchParams?.pageNo ? stuffSearchParams.pageNo : 1,
|
pageNo: stuffSearchParams?.pageNo ? stuffSearchParams.pageNo : 1,
|
||||||
pageSize: stuffSearchParams?.pageSize ? stuffSearchParams.pageSize : 100,
|
pageSize: stuffSearchParams?.pageSize ? stuffSearchParams.pageSize : 100,
|
||||||
|
builderNo: session.builderNo,
|
||||||
|
userId: session.userId
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.saleStoreId) {
|
if (!params.saleStoreId) {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export default function StuffDetail() {
|
|||||||
const { get, promiseGet, del, promisePost, promisePut } = useAxios(globalLocaleState)
|
const { get, promiseGet, del, promisePost, promisePut } = useAxios(globalLocaleState)
|
||||||
//form
|
//form
|
||||||
const formInitValue = {
|
const formInitValue = {
|
||||||
// 물건번호 T...(임시) R...(진짜)
|
// 물건번호 T...(임시) S...(진짜)
|
||||||
planReqNo: '', //설계의뢰No
|
planReqNo: '', //설계의뢰No
|
||||||
receiveUser: session?.userNm, //담당자 로그인사용자명 디폴트
|
receiveUser: session?.userNm, //담당자 로그인사용자명 디폴트
|
||||||
objectStatusId: '0', //물건구분(신축:0 기축 : 1)
|
objectStatusId: '0', //물건구분(신축:0 기축 : 1)
|
||||||
@ -1033,8 +1033,7 @@ export default function StuffDetail() {
|
|||||||
const _saleStoreId = watch('saleStoreId')
|
const _saleStoreId = watch('saleStoreId')
|
||||||
// 2차 판매점명
|
// 2차 판매점명
|
||||||
const _otherSaleStoreId = watch('otherSaleStoreId')
|
const _otherSaleStoreId = watch('otherSaleStoreId')
|
||||||
// zipNo: '', //우편번호
|
// zipNo: '', //우편번호 필수값제거 #947
|
||||||
const _zipNo = watch('zipNo')
|
|
||||||
// prefId: '', //도도부현
|
// prefId: '', //도도부현
|
||||||
const _prefId = watch('prefId')
|
const _prefId = watch('prefId')
|
||||||
// address: '', //주소
|
// address: '', //주소
|
||||||
@ -1071,10 +1070,6 @@ export default function StuffDetail() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.zipNo) {
|
|
||||||
errors.zipNo = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!formData.prefId) {
|
if (!formData.prefId) {
|
||||||
errors.prefId = true
|
errors.prefId = true
|
||||||
}
|
}
|
||||||
@ -1115,10 +1110,6 @@ export default function StuffDetail() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!formData.zipNo) {
|
|
||||||
errors.zipNo = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!formData.prefId || formData.prefId === '0') {
|
if (!formData.prefId || formData.prefId === '0') {
|
||||||
errors.prefId = true
|
errors.prefId = true
|
||||||
}
|
}
|
||||||
@ -1144,7 +1135,6 @@ export default function StuffDetail() {
|
|||||||
_objectName,
|
_objectName,
|
||||||
_saleStoreId,
|
_saleStoreId,
|
||||||
_otherSaleStoreId,
|
_otherSaleStoreId,
|
||||||
_zipNo,
|
|
||||||
_prefId,
|
_prefId,
|
||||||
_address,
|
_address,
|
||||||
_areaId,
|
_areaId,
|
||||||
@ -1189,6 +1179,14 @@ export default function StuffDetail() {
|
|||||||
}
|
}
|
||||||
}, [prefValue])
|
}, [prefValue])
|
||||||
|
|
||||||
|
// 도도부현 /주소 disabled제거 변경
|
||||||
|
const onChangePrefCode = (e) => {
|
||||||
|
setPrefValue(e.prefId)
|
||||||
|
|
||||||
|
form.setValue('prefId', e.prefId)
|
||||||
|
form.setValue('prefName', e.prefName)
|
||||||
|
}
|
||||||
|
|
||||||
// 발전량 시뮬레이션 변경
|
// 발전량 시뮬레이션 변경
|
||||||
const handleAreaIdOnChange = (e) => {
|
const handleAreaIdOnChange = (e) => {
|
||||||
form.setValue('areaId', e.areaId)
|
form.setValue('areaId', e.areaId)
|
||||||
@ -1243,12 +1241,6 @@ export default function StuffDetail() {
|
|||||||
errors = fieldNm
|
errors = fieldNm
|
||||||
}
|
}
|
||||||
|
|
||||||
//우편번호
|
|
||||||
if (!formData.zipNo) {
|
|
||||||
fieldNm = getMessage('stuff.detail.zipNo')
|
|
||||||
errors = fieldNm
|
|
||||||
}
|
|
||||||
|
|
||||||
//1차판매점명
|
//1차판매점명
|
||||||
if (!formData.saleStoreId) {
|
if (!formData.saleStoreId) {
|
||||||
fieldNm = getMessage('stuff.detail.saleStoreId')
|
fieldNm = getMessage('stuff.detail.saleStoreId')
|
||||||
@ -1558,7 +1550,7 @@ export default function StuffDetail() {
|
|||||||
type: 'alert',
|
type: 'alert',
|
||||||
icon: 'error',
|
icon: 'error',
|
||||||
})
|
})
|
||||||
console.log('error::::::', error)
|
console.error('error::::::', error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2004,9 +1996,7 @@ export default function StuffDetail() {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>{getMessage('stuff.detail.zipNo')}</th>
|
||||||
{getMessage('stuff.detail.zipNo')} <span className="important">*</span>
|
|
||||||
</th>
|
|
||||||
<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' }}>
|
||||||
@ -2038,10 +2028,10 @@ export default function StuffDetail() {
|
|||||||
getOptionLabel={(x) => x.prefName}
|
getOptionLabel={(x) => x.prefName}
|
||||||
getOptionValue={(x) => x.prefId}
|
getOptionValue={(x) => x.prefId}
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
|
onChange={onChangePrefCode}
|
||||||
value={prefCodeList.filter(function (option) {
|
value={prefCodeList.filter(function (option) {
|
||||||
return option.prefId === prefValue
|
return option.prefId === prefValue
|
||||||
})}
|
})}
|
||||||
isDisabled={true}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -2571,9 +2561,7 @@ export default function StuffDetail() {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>{getMessage('stuff.detail.zipNo')}</th>
|
||||||
{getMessage('stuff.detail.zipNo')} <span className="important">*</span>
|
|
||||||
</th>
|
|
||||||
<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' }}>
|
||||||
@ -2606,10 +2594,10 @@ export default function StuffDetail() {
|
|||||||
getOptionLabel={(x) => x.prefName}
|
getOptionLabel={(x) => x.prefName}
|
||||||
getOptionValue={(x) => x.prefId}
|
getOptionValue={(x) => x.prefId}
|
||||||
isSearchable={false}
|
isSearchable={false}
|
||||||
|
onChange={onChangePrefCode}
|
||||||
value={prefCodeList.filter(function (option) {
|
value={prefCodeList.filter(function (option) {
|
||||||
return option.prefId === prefValue
|
return option.prefId === prefValue
|
||||||
})}
|
})}
|
||||||
isDisabled={true}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -7,8 +7,6 @@ import { POLYGON_TYPE } from '@/common/common'
|
|||||||
|
|
||||||
export const useCanvasMenu = () => {
|
export const useCanvasMenu = () => {
|
||||||
const [selectedMenu, setSelectedMenu] = useRecoilState(selectedMenuState)
|
const [selectedMenu, setSelectedMenu] = useRecoilState(selectedMenuState)
|
||||||
const canvas = useRecoilValue(canvasState)
|
|
||||||
const { drawDirectionArrow } = usePolygon()
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectedMenu,
|
selectedMenu,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||||
import useSWRMutation from 'swr/mutation'
|
import useSWRMutation from 'swr/mutation'
|
||||||
import { useAxios } from '../useAxios'
|
import { useAxios } from '../useAxios'
|
||||||
import { unescapeString } from '@/util/common-utils'
|
import { unescapeString } from '@/util/common-utils'
|
||||||
@ -9,7 +9,10 @@ import { compasDegAtom } from '@/store/orientationAtom'
|
|||||||
import { canvasState, currentCanvasPlanState } from '@/store/canvasAtom'
|
import { canvasState, currentCanvasPlanState } from '@/store/canvasAtom'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { useCircuitTrestle } from '../useCirCuitTrestle'
|
import { useCircuitTrestle } from '../useCirCuitTrestle'
|
||||||
import { useEffect } from 'react'
|
import { useContext } from 'react'
|
||||||
|
import { addedRoofsState } from '@/store/settingAtom'
|
||||||
|
import { roofsState } from '@/store/roofAtom'
|
||||||
|
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 캔버스 팝업 상태 관리
|
* 캔버스 팝업 상태 관리
|
||||||
@ -19,13 +22,15 @@ import { useEffect } from 'react'
|
|||||||
export function useCanvasPopupStatusController(param = 1) {
|
export function useCanvasPopupStatusController(param = 1) {
|
||||||
const popupType = parseInt(param)
|
const popupType = parseInt(param)
|
||||||
|
|
||||||
const [compasDeg, setCompasDeg] = useRecoilState(compasDegAtom)
|
const setCompasDeg = useSetRecoilState(compasDegAtom)
|
||||||
const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState)
|
const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState)
|
||||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState)
|
const setSelectedModules = useSetRecoilState(selectedModuleState)
|
||||||
const { get, promiseGet, getFetcher, postFetcher } = useAxios()
|
const { get, promiseGet, getFetcher, postFetcher } = useAxios()
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
||||||
|
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
|
||||||
|
const [roofs, setRoofs] = useRecoilState(roofsState)
|
||||||
|
const { managementState, setManagementState } = useContext(GlobalDataContext)
|
||||||
/**
|
/**
|
||||||
* 팝업 상태 조회
|
* 팝업 상태 조회
|
||||||
* @param {number} popupTypeParam
|
* @param {number} popupTypeParam
|
||||||
@ -51,23 +56,36 @@ export function useCanvasPopupStatusController(param = 1) {
|
|||||||
* 조회 후 전체 데이터 recoil에 저장
|
* 조회 후 전체 데이터 recoil에 저장
|
||||||
*/
|
*/
|
||||||
const handleModuleSelectionTotal = async () => {
|
const handleModuleSelectionTotal = async () => {
|
||||||
|
let resultData = {}
|
||||||
for (let i = 1; i < 3; i++) {
|
for (let i = 1; i < 3; i++) {
|
||||||
const result = await getModuleSelection(i)
|
const result = await getModuleSelection(i)
|
||||||
console.log('🚀 ~ handleModuleSelectionTotal ~ result:', result)
|
|
||||||
if (!result.objectNo) return
|
if (!result.objectNo) return
|
||||||
if (i === 1) {
|
if (i === 1) {
|
||||||
setCompasDeg(result.popupStatus)
|
if (result.popupStatus && unescapeString(result.popupStatus)) {
|
||||||
|
const data = JSON.parse(unescapeString(result.popupStatus))
|
||||||
|
|
||||||
|
if (data?.compasDeg) setCompasDeg(data.compasDeg)
|
||||||
|
if (data?.module) setSelectedModules(data.module)
|
||||||
|
// setModuleSelectionDataStore(data)
|
||||||
|
resultData = { ...data }
|
||||||
|
}
|
||||||
} else if (i === 2) {
|
} else if (i === 2) {
|
||||||
const data = JSON.parse(unescapeString(result.popupStatus))
|
const data = JSON.parse(unescapeString(result.popupStatus))
|
||||||
setModuleSelectionDataStore(data)
|
|
||||||
const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
roofSurfaceList.forEach((surface) => {
|
roofSurfaceList.forEach((surface) => {
|
||||||
surface.modules = modules.filter((module) => module.surfaceId === surface.id)
|
surface.modules = modules.filter((module) => module.surfaceId === surface.id)
|
||||||
})
|
})
|
||||||
if (data.module) setSelectedModules(data.module)
|
if (data.roofConstructions) {
|
||||||
|
setRoofs(data.roofConstructions)
|
||||||
|
// setManagementState({ ...managementState, roofs: data.roofConstructions.map((roof) => roof.construction.managementState) })
|
||||||
|
// setModuleSelectionDataStore({ ...moduleSelectionDataStore, roofConstructions: data.roofConstruction })
|
||||||
|
resultData = { ...resultData, roofConstructions: data.roofConstructions }
|
||||||
|
}
|
||||||
|
// if (data?.module) setManagementState(data.common.managementState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
setModuleSelectionDataStore(resultData)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,7 +98,8 @@ export function useCanvasPopupStatusController(param = 1) {
|
|||||||
objectNo: currentCanvasPlan.objectNo,
|
objectNo: currentCanvasPlan.objectNo,
|
||||||
planNo: parseInt(currentCanvasPlan.planNo),
|
planNo: parseInt(currentCanvasPlan.planNo),
|
||||||
popupType: popupType.toString(),
|
popupType: popupType.toString(),
|
||||||
popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'),
|
// popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'),
|
||||||
|
popupStatus: JSON.stringify(arg).replace(/"/g, '\"'),
|
||||||
}
|
}
|
||||||
postFetcher(`/api/v1/canvas-popup-status`, params)
|
postFetcher(`/api/v1/canvas-popup-status`, params)
|
||||||
},
|
},
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export function useMasterController() {
|
|||||||
*/
|
*/
|
||||||
const getRoofMaterialList = async () => {
|
const getRoofMaterialList = async () => {
|
||||||
return await get({ url: '/api/v1/master/getRoofMaterialList' }).then((res) => {
|
return await get({ url: '/api/v1/master/getRoofMaterialList' }).then((res) => {
|
||||||
console.log('🚀🚀 ~ getRoofMaterialList ~ res:', res)
|
// console.log('🚀🚀 ~ getRoofMaterialList ~ res:', res)
|
||||||
return res
|
return res
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,12 +16,13 @@ import { usePopup } from '@/hooks/usePopup'
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
import { useSurfaceShapeBatch } from '@/hooks/surface/useSurfaceShapeBatch'
|
||||||
import { useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
import { canvasState, currentMenuState } from '@/store/canvasAtom'
|
||||||
import { MENU } from '@/common/common'
|
import { MENU } from '@/common/common'
|
||||||
import { useTrestle } from '@/hooks/module/useTrestle'
|
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { useOrientation } from '@/hooks/module/useOrientation'
|
import { useOrientation } from '@/hooks/module/useOrientation'
|
||||||
|
import { corridorDimensionSelector, settingModalFirstOptionsState } from '@/store/settingAtom'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 메뉴 처리 훅
|
* 메뉴 처리 훅
|
||||||
@ -36,8 +37,11 @@ export default function useMenu() {
|
|||||||
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch({})
|
const { deleteAllSurfacesAndObjects } = useSurfaceShapeBatch({})
|
||||||
const { clear: trestleClear, setAllModuleSurfaceIsComplete } = useTrestle()
|
const { clear: trestleClear, setAllModuleSurfaceIsComplete } = useTrestle()
|
||||||
const { nextStep } = useOrientation()
|
const { nextStep } = useOrientation()
|
||||||
|
const [corridorDimension, setCorridorDimension] = useRecoilState(corridorDimensionSelector)
|
||||||
const handleMenu = (type) => {
|
const handleMenu = (type) => {
|
||||||
if (type === 'outline') {
|
if (type === 'outline') {
|
||||||
|
// 지붕 덮개 메뉴의 경우는 복도치수로 적용한다.
|
||||||
|
setCorridorDimension(0)
|
||||||
switch (currentMenu) {
|
switch (currentMenu) {
|
||||||
case MENU.ROOF_COVERING.EXTERIOR_WALL_LINE:
|
case MENU.ROOF_COVERING.EXTERIOR_WALL_LINE:
|
||||||
addPopup(popupId, 1, <WallLineSetting id={popupId} />)
|
addPopup(popupId, 1, <WallLineSetting id={popupId} />)
|
||||||
@ -67,6 +71,8 @@ export default function useMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'surface') {
|
if (type === 'surface') {
|
||||||
|
// 배치면 메뉴의 경우는 실치수로 적용한다.
|
||||||
|
setCorridorDimension(1)
|
||||||
switch (currentMenu) {
|
switch (currentMenu) {
|
||||||
// case MENU.BATCH_CANVAS.SLOPE_SETTING:
|
// case MENU.BATCH_CANVAS.SLOPE_SETTING:
|
||||||
// addPopup(popupId, 1, <Slope id={popupId} />)
|
// addPopup(popupId, 1, <Slope id={popupId} />)
|
||||||
@ -87,6 +93,8 @@ export default function useMenu() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type === 'module') {
|
if (type === 'module') {
|
||||||
|
// 모듈,회로 구성 메뉴의 경우는 실치수로 적용한다.
|
||||||
|
setCorridorDimension(1)
|
||||||
switch (currentMenu) {
|
switch (currentMenu) {
|
||||||
case MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING:
|
case MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING:
|
||||||
trestleClear()
|
trestleClear()
|
||||||
|
|||||||
@ -130,13 +130,14 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
addFlg: true,
|
addFlg: true,
|
||||||
paDispOrder: null,
|
paDispOrder: null,
|
||||||
dispCableFlg: '0',
|
dispCableFlg: '0',
|
||||||
|
itemTpCd: '',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setEstimateData({ ...estimateContextState, userId: session.userId, sapSalesStoreCd: session.custCd })
|
setEstimateData({ ...estimateContextState, userId: session.userId })
|
||||||
}, [estimateContextState])
|
}, [estimateContextState])
|
||||||
|
|
||||||
// 첨부파일 다운로드
|
// 첨부파일 다운로드
|
||||||
@ -309,6 +310,7 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
|
|
||||||
//봄 컴포넌트 제품은 0으로
|
//봄 컴포넌트 제품은 0으로
|
||||||
item.openFlg = '0'
|
item.openFlg = '0'
|
||||||
|
item.unitOpenFlg = '0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -321,6 +323,7 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (delCnt === estimateData.itemList.length) {
|
if (delCnt === estimateData.itemList.length) {
|
||||||
|
itemFlg = false
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
return swalFire({ text: getMessage('estimate.detail.save.requiredItem'), type: 'alert', icon: 'warning' })
|
return swalFire({ text: getMessage('estimate.detail.save.requiredItem'), type: 'alert', icon: 'warning' })
|
||||||
}
|
}
|
||||||
@ -452,8 +455,6 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
saleStoreId: session.storeId,
|
|
||||||
sapSalesStoreCd: session.custCd,
|
|
||||||
objectNo: estimateData.objectNo,
|
objectNo: estimateData.objectNo,
|
||||||
planNo: sendPlanNo,
|
planNo: sendPlanNo,
|
||||||
copySaleStoreId: otherSaleStoreId ? otherSaleStoreId : saleStoreId,
|
copySaleStoreId: otherSaleStoreId ? otherSaleStoreId : saleStoreId,
|
||||||
@ -462,24 +463,30 @@ export const useEstimateController = (planNo, flag) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setIsGlobalLoading(true)
|
setIsGlobalLoading(true)
|
||||||
await promisePost({ url: '/api/estimate/save-estimate-copy', data: params }).then((res) => {
|
await promisePost({ url: '/api/estimate/save-estimate-copy', data: params })
|
||||||
setIsGlobalLoading(false)
|
.then((res) => {
|
||||||
if (res.status === 201) {
|
|
||||||
if (isObjectNotEmpty(res.data)) {
|
|
||||||
let newObjectNo = res.data.objectNo
|
|
||||||
swalFire({
|
|
||||||
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
|
|
||||||
type: 'alert',
|
|
||||||
confirmFn: () => {
|
|
||||||
setEstimateCopyPopupOpen(false) //팝업닫고
|
|
||||||
router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false })
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setIsGlobalLoading(false)
|
setIsGlobalLoading(false)
|
||||||
}
|
if (res.status === 201) {
|
||||||
})
|
if (isObjectNotEmpty(res.data)) {
|
||||||
|
let newObjectNo = res.data.objectNo
|
||||||
|
swalFire({
|
||||||
|
text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessage'),
|
||||||
|
type: 'alert',
|
||||||
|
confirmFn: () => {
|
||||||
|
setEstimateCopyPopupOpen(false) //팝업닫고
|
||||||
|
router.push(`/management/stuff/detail?objectNo=${newObjectNo.toString()}`, { scroll: false })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error('캔버스 복사 중 오류 발생')
|
||||||
|
swalFire({ text: getMessage('estimate.detail.estimateCopyPopup.copy.alertMessageError'), type: 'alert', icon: 'error' })
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkLength = (value) => {
|
const checkLength = (value) => {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export const useMainContentsController = () => {
|
|||||||
*/
|
*/
|
||||||
const fetchObjectList = async () => {
|
const fetchObjectList = async () => {
|
||||||
try {
|
try {
|
||||||
const apiUrl = `/api/main-page/object/${session?.storeId}/list`
|
const apiUrl = `/api/main-page/object/${session?.storeId}/${session?.userId}/${session?.builderNo}/list`
|
||||||
await promiseGet({
|
await promiseGet({
|
||||||
url: apiUrl,
|
url: apiUrl,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
|
|||||||
@ -54,7 +54,7 @@ export function useModule() {
|
|||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
canvas.discardActiveObject() //선택해제
|
// canvas.discardActiveObject() //선택해제
|
||||||
|
|
||||||
const isSetupModules = getOtherModules(selectedObj)
|
const isSetupModules = getOtherModules(selectedObj)
|
||||||
const selectedModules = canvas.getObjects().filter((obj) => selectedIds.includes(obj.id) && obj.name === 'module') //선택했던 객체들만 가져옴
|
const selectedModules = canvas.getObjects().filter((obj) => selectedIds.includes(obj.id) && obj.name === 'module') //선택했던 객체들만 가져옴
|
||||||
@ -991,14 +991,14 @@ export function useModule() {
|
|||||||
const getRowModules = (target) => {
|
const getRowModules = (target) => {
|
||||||
return canvas
|
return canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && obj.top === target.top)
|
.filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && Math.abs(obj.top - target.top) < 1)
|
||||||
.sort((a, b) => a.left - b.left)
|
.sort((a, b) => a.left - b.left)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getColumnModules = (target) => {
|
const getColumnModules = (target) => {
|
||||||
return canvas
|
return canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && obj.left === target.left)
|
.filter((obj) => target.surfaceId === obj.surfaceId && obj.name === POLYGON_TYPE.MODULE && Math.abs(obj.left - target.left) < 1)
|
||||||
.sort((a, b) => a.top - b.top)
|
.sort((a, b) => a.top - b.top)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,35 +0,0 @@
|
|||||||
import { useEffect, useState } from 'react'
|
|
||||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
|
||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
|
||||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
|
||||||
import { canvasSettingState, canvasState, currentCanvasPlanState, moduleSetupSurfaceState } from '@/store/canvasAtom'
|
|
||||||
import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
|
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
|
||||||
import offsetPolygon from '@/util/qpolygon-utils'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
|
||||||
import { useEvent } from '@/hooks/useEvent'
|
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
|
||||||
import { useMessage } from '@/hooks/useMessage'
|
|
||||||
|
|
||||||
export function useModulePlace() {
|
|
||||||
const canvas = useRecoilValue(canvasState)
|
|
||||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
|
||||||
const [trestleDetailParams, setTrestleDetailParams] = useState([])
|
|
||||||
const [trestleDetailList, setTrestleDetailList] = useState([])
|
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
|
||||||
const { getTrestleDetailList } = useMasterController()
|
|
||||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
|
||||||
const { setSurfaceShapePattern } = useRoofFn()
|
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
|
||||||
const { addTargetMouseEventListener } = useEvent()
|
|
||||||
const setModuleSetupSurface = useSetRecoilState(moduleSetupSurfaceState)
|
|
||||||
const [saleStoreNorthFlg, setSaleStoreNorthFlg] = useState(false)
|
|
||||||
const { swalFire } = useSwal()
|
|
||||||
const { getMessage } = useMessage()
|
|
||||||
|
|
||||||
return {
|
|
||||||
selectedModules,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,7 +3,7 @@ import { useContext, useEffect, useState } from 'react'
|
|||||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||||
import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
import { selectedModuleState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||||
import { canvasState } from '@/store/canvasAtom'
|
import { canvasState } from '@/store/canvasAtom'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
@ -12,23 +12,20 @@ import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
|||||||
|
|
||||||
export function useModuleSelection(props) {
|
export function useModuleSelection(props) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
const { managementState, setManagementState } = useContext(GlobalDataContext)
|
||||||
|
|
||||||
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
|
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
|
||||||
const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록
|
const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록
|
||||||
const [moduleList, setModuleList] = useState([{}]) //모듈 목록
|
const [moduleList, setModuleList] = useState([{}]) //모듈 목록
|
||||||
|
|
||||||
const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도
|
const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도
|
||||||
const [installHeight, setInstallHeight] = useState() //설치 높이
|
const [installHeight, setInstallHeight] = useState(managementState?.installHeight) //설치 높이
|
||||||
const [standardWindSpeed, setStandardWindSpeed] = useState({}) //기준풍속
|
const [standardWindSpeed, setStandardWindSpeed] = useState() //기준풍속
|
||||||
const [verticalSnowCover, setVerticalSnowCover] = useState() //수직적설량
|
const [verticalSnowCover, setVerticalSnowCover] = useState(managementState?.verticalSnowCover) //수직적설량
|
||||||
|
|
||||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
|
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
|
||||||
const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
|
|
||||||
|
// const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
|
||||||
const { getModuleTypeItemList } = useMasterController()
|
const { getModuleTypeItemList } = useMasterController()
|
||||||
const { findCommonCode } = useCommonCode()
|
const { findCommonCode } = useCommonCode()
|
||||||
const resetStatisticsData = useResetRecoilState(moduleStatisticsState)
|
const resetStatisticsData = useResetRecoilState(moduleStatisticsState)
|
||||||
|
|
||||||
const { restoreModuleInstArea } = useModuleBasicSetting()
|
const { restoreModuleInstArea } = useModuleBasicSetting()
|
||||||
|
|
||||||
const bindInitData = () => {
|
const bindInitData = () => {
|
||||||
@ -43,21 +40,21 @@ export function useModuleSelection(props) {
|
|||||||
//탭별 파라메터 초기화
|
//탭별 파라메터 초기화
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
bindInitData()
|
bindInitData()
|
||||||
const initParams = {
|
// const initParams = {
|
||||||
illuminationTp: managementState?.surfaceTypeValue, //면조도
|
// illuminationTp: managementState?.surfaceTypeValue, //면조도
|
||||||
illuminationTpNm: managementState?.surfaceType, //면조도명
|
// illuminationTpNm: managementState?.surfaceType, //면조도명
|
||||||
instHt: managementState?.installHeight, //설치높이
|
// instHt: managementState?.installHeight, //설치높이
|
||||||
stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
|
// stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
|
||||||
stdSnowLd: managementState?.verticalSnowCover, //기준적설량
|
// stdSnowLd: managementState?.verticalSnowCover, //기준적설량
|
||||||
saleStoreNorthFlg: managementState?.saleStoreNorthFlg, //북쪽 설치 여부
|
// saleStoreNorthFlg: managementState?.saleStoreNorthFlg, //북쪽 설치 여부
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (selectedModules) {
|
// if (selectedModules) {
|
||||||
initParams.moduleTpCd = selectedModules.itemTp
|
// initParams.moduleTpCd = selectedModules.itemTp
|
||||||
initParams.moduleItemId = selectedModules.itemId
|
// initParams.moduleItemId = selectedModules.itemId
|
||||||
}
|
// }
|
||||||
|
|
||||||
setModuleSelectionInitParams(initParams)
|
// setModuleSelectionInitParams(initParams)
|
||||||
}, [managementState])
|
}, [managementState])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -87,7 +84,7 @@ export function useModuleSelection(props) {
|
|||||||
|
|
||||||
//새로고침시 데이터 날아가는거 방지
|
//새로고침시 데이터 날아가는거 방지
|
||||||
if (managementState === null) {
|
if (managementState === null) {
|
||||||
setManagementState(managementStateLoaded)
|
setManagementState(managementState)
|
||||||
} else {
|
} else {
|
||||||
bindInitData()
|
bindInitData()
|
||||||
}
|
}
|
||||||
@ -95,7 +92,7 @@ export function useModuleSelection(props) {
|
|||||||
getModuleData(roofsIds)
|
getModuleData(roofsIds)
|
||||||
|
|
||||||
//모듈설치면 초기화
|
//모듈설치면 초기화
|
||||||
restoreModuleInstArea()
|
// restoreModuleInstArea()
|
||||||
resetStatisticsData()
|
resetStatisticsData()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@ -125,19 +122,19 @@ export function useModuleSelection(props) {
|
|||||||
setSelectedModules(option) //선택값 저장
|
setSelectedModules(option) //선택값 저장
|
||||||
|
|
||||||
//init 데이터에 선택된 모듈 추가
|
//init 데이터에 선택된 모듈 추가
|
||||||
setModuleSelectionInitParams({
|
// setModuleSelectionInitParams({
|
||||||
...moduleSelectionInitParams,
|
// ...moduleSelectionInitParams,
|
||||||
moduleTpCd: option.itemTp,
|
// moduleTpCd: option.itemTp,
|
||||||
moduleItemId: option.itemId,
|
// moduleItemId: option.itemId,
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeSurfaceType = (option) => {
|
const handleChangeSurfaceType = (option) => {
|
||||||
setModuleSelectionInitParams({
|
// setModuleSelectionInitParams({
|
||||||
...moduleSelectionInitParams,
|
// ...moduleSelectionInitParams,
|
||||||
illuminationTp: option.clCode,
|
// illuminationTp: option.clCode,
|
||||||
illuminationTpNm: option.clCodeNm,
|
// illuminationTpNm: option.clCodeNm,
|
||||||
})
|
// })
|
||||||
|
|
||||||
setManagementState({
|
setManagementState({
|
||||||
...managementState,
|
...managementState,
|
||||||
@ -147,10 +144,10 @@ export function useModuleSelection(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeWindSpeed = (option) => {
|
const handleChangeWindSpeed = (option) => {
|
||||||
setModuleSelectionInitParams({
|
// setModuleSelectionInitParams({
|
||||||
...moduleSelectionInitParams,
|
// ...moduleSelectionInitParams,
|
||||||
stdWindSpeed: option.clCode,
|
// stdWindSpeed: option.clCode,
|
||||||
})
|
// })
|
||||||
|
|
||||||
setManagementState({
|
setManagementState({
|
||||||
...managementState,
|
...managementState,
|
||||||
@ -160,10 +157,10 @@ export function useModuleSelection(props) {
|
|||||||
|
|
||||||
const handleChangeInstallHeight = (option) => {
|
const handleChangeInstallHeight = (option) => {
|
||||||
setInstallHeight(option)
|
setInstallHeight(option)
|
||||||
setModuleSelectionInitParams({
|
// setModuleSelectionInitParams({
|
||||||
...moduleSelectionInitParams,
|
// ...moduleSelectionInitParams,
|
||||||
instHt: option,
|
// instHt: option,
|
||||||
})
|
// })
|
||||||
|
|
||||||
setManagementState({
|
setManagementState({
|
||||||
...managementState,
|
...managementState,
|
||||||
@ -173,10 +170,10 @@ export function useModuleSelection(props) {
|
|||||||
|
|
||||||
const handleChangeVerticalSnowCover = (option) => {
|
const handleChangeVerticalSnowCover = (option) => {
|
||||||
setVerticalSnowCover(option)
|
setVerticalSnowCover(option)
|
||||||
setModuleSelectionInitParams({
|
// setModuleSelectionInitParams({
|
||||||
...moduleSelectionInitParams,
|
// ...moduleSelectionInitParams,
|
||||||
stdSnowLd: option,
|
// stdSnowLd: option,
|
||||||
})
|
// })
|
||||||
|
|
||||||
setManagementState({
|
setManagementState({
|
||||||
...managementState,
|
...managementState,
|
||||||
@ -184,53 +181,23 @@ export function useModuleSelection(props) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// console.log('installHeight', installHeight)
|
|
||||||
}, [installHeight])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// console.log('verticalSnowCover', verticalSnowCover)
|
|
||||||
}, [verticalSnowCover])
|
|
||||||
|
|
||||||
//TODO: 설치높이, 기준적설량 debounce 적용해서 추가해야됨
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// getConstructionListData(constructionListParams)
|
|
||||||
// }, [constructionListParams])
|
|
||||||
|
|
||||||
// const getConstructionListData = async (params) => {
|
|
||||||
// if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
|
|
||||||
// const optionsList = await getConstructionList(params)
|
|
||||||
// console.log('optionsList', optionsList)
|
|
||||||
// setConstructionList(optionsList.data)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//state 배열에 데이터 추가 함수
|
|
||||||
// const addRoofTabParams = (key, value, excludeArray = []) => {
|
|
||||||
// const index = roofTabParams.findIndex((obj) => obj.roofTab === roofTab)
|
|
||||||
// if (index !== -1) {
|
|
||||||
// roofTabParams[index][key] = value
|
|
||||||
// if (excludeArray.length > 0) {
|
|
||||||
// excludeArray.forEach((exclude) => {
|
|
||||||
// roofTabParams[index][exclude] = ''
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// setRoofTabParams((prev) => [...prev.slice(0, index), roofTabParams[index], ...prev.slice(index + 1)])
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
moduleSelectionInitParams,
|
// moduleSelectionInitParams,
|
||||||
selectedModules,
|
selectedModules,
|
||||||
roughnessCodes,
|
roughnessCodes,
|
||||||
windSpeedCodes,
|
windSpeedCodes,
|
||||||
managementState,
|
managementState,
|
||||||
|
setManagementState,
|
||||||
moduleList,
|
moduleList,
|
||||||
|
setSelectedModules,
|
||||||
selectedSurfaceType,
|
selectedSurfaceType,
|
||||||
|
setSelectedSurfaceType,
|
||||||
installHeight,
|
installHeight,
|
||||||
|
setInstallHeight,
|
||||||
standardWindSpeed,
|
standardWindSpeed,
|
||||||
|
setStandardWindSpeed,
|
||||||
verticalSnowCover,
|
verticalSnowCover,
|
||||||
|
setVerticalSnowCover,
|
||||||
handleChangeModule,
|
handleChangeModule,
|
||||||
handleChangeSurfaceType,
|
handleChangeSurfaceType,
|
||||||
handleChangeWindSpeed,
|
handleChangeWindSpeed,
|
||||||
|
|||||||
302
src/hooks/module/useModuleTrestle.js
Normal file
302
src/hooks/module/useModuleTrestle.js
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
import { use, useContext, useEffect, useReducer, useState } from 'react'
|
||||||
|
import { useCommonCode } from '../common/useCommonCode'
|
||||||
|
import { useMasterController } from '../common/useMasterController'
|
||||||
|
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
|
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||||
|
import { popSpinnerState } from '@/store/popupAtom'
|
||||||
|
|
||||||
|
const RAFT_BASE_CODE = '203800'
|
||||||
|
|
||||||
|
const trestleReducer = (state, action) => {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'SET_LENGTH':
|
||||||
|
case 'SET_RAFT_BASE':
|
||||||
|
case 'SET_TRESTLE_MAKER':
|
||||||
|
case 'SET_CONST_MTHD':
|
||||||
|
case 'SET_ROOF_BASE':
|
||||||
|
case 'SET_CONSTRUCTION':
|
||||||
|
case 'SET_TRESTLE_DETAIL':
|
||||||
|
return {
|
||||||
|
...action.roof,
|
||||||
|
}
|
||||||
|
case 'SET_INITIALIZE':
|
||||||
|
return {
|
||||||
|
moduleTpCd: action.roof.module?.itemTp ?? '',
|
||||||
|
roofMatlCd: action.roof?.roofMatlCd ?? '',
|
||||||
|
hajebichi: action.roof?.hajebichi ?? 0,
|
||||||
|
raft: action.roof?.raft ?? null,
|
||||||
|
trestleMkrCd: action.roof.trestle?.trestleMkrCd ?? null,
|
||||||
|
constMthdCd: action.roof.trestle?.constMthdCd ?? null,
|
||||||
|
constTp: action.roof.construction?.constTp ?? null,
|
||||||
|
roofBaseCd: action.roof.trestle?.roofBaseCd ?? null,
|
||||||
|
workingWidth: action.roof.workingWidth ?? 0,
|
||||||
|
lengthBase: action.roof?.length ?? 0,
|
||||||
|
illuminationTp: action.roof.common?.illuminationTp ?? null,
|
||||||
|
instHt: action.roof.common?.instHt ?? null,
|
||||||
|
stdWindSpeed: action.roof.common?.stdWindSpeed ?? null,
|
||||||
|
stdSnowLd: action.roof.common?.stdSnowLd ?? null,
|
||||||
|
inclCd: action.roof?.pitch ?? null,
|
||||||
|
roofPitch: action.roof?.roofPchBase ?? 0,
|
||||||
|
eavesMargin: action.roof?.eavesMargin ?? null,
|
||||||
|
ridgeMargin: action.roof?.ridgeMargin ?? null,
|
||||||
|
kerabaMargin: action.roof?.kerabaMargin ?? null,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useModuleTrestle(props) {
|
||||||
|
const { selectedRoof } = props
|
||||||
|
const { findCommonCode } = useCommonCode()
|
||||||
|
const [raftBaseList, setRaftBaseList] = useState([])
|
||||||
|
const [trestleList, setTrestleList] = useState([])
|
||||||
|
const [constMthdList, setConstMthdList] = useState([])
|
||||||
|
const [roofBaseList, setRoofBaseList] = useState([])
|
||||||
|
const [constructionList, setConstructionList] = useState([])
|
||||||
|
const { getTrestleList, getConstructionList, getTrestleDetailList } = useMasterController()
|
||||||
|
|
||||||
|
const [lengthBase, setLengthBase] = useState(0)
|
||||||
|
const [hajebichi, setHajebichi] = useState(0)
|
||||||
|
const [cvrYn, setCvrYn] = useState('N')
|
||||||
|
const [cvrChecked, setCvrChecked] = useState(false)
|
||||||
|
const [snowGdPossYn, setSnowGdPossYn] = useState('N')
|
||||||
|
const [snowGdChecked, setSnowGdChecked] = useState(false)
|
||||||
|
const [eavesMargin, setEavesMargin] = useState(0)
|
||||||
|
const [ridgeMargin, setRidgeMargin] = useState(0)
|
||||||
|
const [kerabaMargin, setKerabaMargin] = useState(0)
|
||||||
|
const [trestleState, dispatch] = useReducer(trestleReducer, null)
|
||||||
|
const [trestleDetail, setTrestleDetail] = useState(null)
|
||||||
|
const [popSpinnerStore, setPopSpinnerStore] = useRecoilState(popSpinnerState)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const raftCodeList = findCommonCode(RAFT_BASE_CODE)
|
||||||
|
setRaftBaseList(raftCodeList)
|
||||||
|
setTrestleList([])
|
||||||
|
setConstMthdList([])
|
||||||
|
setRoofBaseList([])
|
||||||
|
setConstructionList([])
|
||||||
|
// setEavesMargin(selectedRoof?.addRoof?.eavesMargin ?? 0)
|
||||||
|
// setRidgeMargin(selectedRoof?.addRoof?.ridgeMargin ?? 0)
|
||||||
|
// setKerabaMargin(selectedRoof?.addRoof?.kerabaMargin ?? 0)
|
||||||
|
|
||||||
|
setHajebichi(selectedRoof?.hajebichi ?? 0)
|
||||||
|
setEavesMargin(selectedRoof?.eavesMargin ?? 0)
|
||||||
|
setRidgeMargin(selectedRoof?.ridgeMargin ?? 0)
|
||||||
|
setKerabaMargin(selectedRoof?.kerabaMargin ?? 0)
|
||||||
|
setLengthBase(Math.round(selectedRoof?.length ?? 0))
|
||||||
|
setCvrYn(selectedRoof?.construction?.cvrYn ?? 'N')
|
||||||
|
setCvrChecked(selectedRoof?.construction?.cvrChecked ?? false)
|
||||||
|
setSnowGdPossYn(selectedRoof?.construction?.snowGdPossYn ?? 'N')
|
||||||
|
setSnowGdChecked(selectedRoof?.construction?.snowGdChecked ?? false)
|
||||||
|
setTrestleDetail(selectedRoof?.trestleDetail)
|
||||||
|
}, [selectedRoof])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (trestleState) {
|
||||||
|
handleSetTrestleList()
|
||||||
|
|
||||||
|
if (!trestleState?.trestleMkrCd) {
|
||||||
|
setConstMthdList([])
|
||||||
|
setRoofBaseList([])
|
||||||
|
setConstructionList([])
|
||||||
|
setTrestleDetail(null)
|
||||||
|
setEavesMargin(0)
|
||||||
|
setRidgeMargin(0)
|
||||||
|
setKerabaMargin(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSetConstMthdList()
|
||||||
|
if (!trestleState?.constMthdCd) {
|
||||||
|
setRoofBaseList([])
|
||||||
|
setConstructionList([])
|
||||||
|
setTrestleDetail(null)
|
||||||
|
setEavesMargin(0)
|
||||||
|
setRidgeMargin(0)
|
||||||
|
setKerabaMargin(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSetRoofBaseList()
|
||||||
|
if (!trestleState?.roofBaseCd) {
|
||||||
|
setConstructionList([])
|
||||||
|
setTrestleDetail(null)
|
||||||
|
setEavesMargin(0)
|
||||||
|
setRidgeMargin(0)
|
||||||
|
setKerabaMargin(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSetConstructionList()
|
||||||
|
if (!trestleState?.constTp) {
|
||||||
|
setTrestleDetail(null)
|
||||||
|
setEavesMargin(0)
|
||||||
|
setRidgeMargin(0)
|
||||||
|
setKerabaMargin(0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trestleState?.eavesMargin) {
|
||||||
|
handleSetTrestleDetailData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [trestleState])
|
||||||
|
|
||||||
|
const handleSetTrestleList = () => {
|
||||||
|
setPopSpinnerStore(true)
|
||||||
|
getTrestleList({
|
||||||
|
moduleTpCd: trestleState?.moduleTpCd ?? '',
|
||||||
|
roofMatlCd: trestleState?.roofMatlCd ?? '',
|
||||||
|
raftBaseCd: trestleState?.raft ?? '',
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res?.data) setTrestleList(res.data)
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetConstMthdList = () => {
|
||||||
|
setPopSpinnerStore(true)
|
||||||
|
getTrestleList({
|
||||||
|
moduleTpCd: trestleState?.moduleTpCd ?? '',
|
||||||
|
roofMatlCd: trestleState?.roofMatlCd ?? '',
|
||||||
|
raftBaseCd: trestleState?.raft ?? '',
|
||||||
|
trestleMkrCd: trestleState?.trestleMkrCd ?? '',
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res?.data) setConstMthdList(res.data)
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetRoofBaseList = () => {
|
||||||
|
setPopSpinnerStore(true)
|
||||||
|
getTrestleList({
|
||||||
|
moduleTpCd: trestleState?.moduleTpCd ?? '',
|
||||||
|
roofMatlCd: trestleState?.roofMatlCd ?? '',
|
||||||
|
raftBaseCd: trestleState?.raft ?? '',
|
||||||
|
trestleMkrCd: trestleState?.trestleMkrCd ?? '',
|
||||||
|
constMthdCd: trestleState?.constMthdCd ?? '',
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res?.data) setRoofBaseList(res.data)
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetConstructionList = () => {
|
||||||
|
setPopSpinnerStore(true)
|
||||||
|
getConstructionList({
|
||||||
|
moduleTpCd: trestleState?.moduleTpCd ?? '',
|
||||||
|
roofMatlCd: trestleState?.roofMatlCd ?? '',
|
||||||
|
trestleMkrCd: trestleState?.trestleMkrCd ?? '',
|
||||||
|
constMthdCd: trestleState?.constMthdCd ?? '',
|
||||||
|
roofBaseCd: trestleState?.roofBaseCd ?? '',
|
||||||
|
illuminationTp: trestleState.illuminationTp ?? '',
|
||||||
|
instHt: trestleState.instHt ?? '',
|
||||||
|
stdWindSpeed: trestleState.stdWindSpeed ?? '',
|
||||||
|
stdSnowLd: trestleState.stdSnowLd ?? '',
|
||||||
|
inclCd: trestleState.inclCd ?? '',
|
||||||
|
raftBaseCd: trestleState.raft ?? '',
|
||||||
|
roofPitch: Math.round(trestleState.roofPitch) ?? '',
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res?.data) setConstructionList(res.data)
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSetTrestleDetailData = () => {
|
||||||
|
setPopSpinnerStore(true)
|
||||||
|
getTrestleDetailList([
|
||||||
|
{
|
||||||
|
moduleTpCd: trestleState.moduleTpCd ?? '',
|
||||||
|
roofMatlCd: trestleState.roofMatlCd ?? '',
|
||||||
|
trestleMkrCd: trestleState.trestleMkrCd ?? '',
|
||||||
|
constMthdCd: trestleState.constMthdCd ?? '',
|
||||||
|
roofBaseCd: trestleState.roofBaseCd ?? '',
|
||||||
|
illuminationTp: trestleState.illuminationTp ?? '',
|
||||||
|
instHt: trestleState.instHt ?? '',
|
||||||
|
stdWindSpeed: trestleState.stdWindSpeed ?? '',
|
||||||
|
stdSnowLd: trestleState.stdSnowLd ?? '',
|
||||||
|
inclCd: trestleState.inclCd ?? '',
|
||||||
|
constTp: trestleState.constTp ?? '',
|
||||||
|
mixMatlNo: trestleState.mixMatlNo ?? '',
|
||||||
|
roofPitch: trestleState.roofPitch ?? '',
|
||||||
|
// workingWidth: trestleState.length ?? '',
|
||||||
|
workingWidth: lengthBase ?? '',
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.then((res) => {
|
||||||
|
if (res.length > 0) {
|
||||||
|
if (!res[0].data) return
|
||||||
|
setEavesMargin(res[0].data.eaveIntvl)
|
||||||
|
setRidgeMargin(res[0].data.ridgeIntvl)
|
||||||
|
setKerabaMargin(res[0].data.kerabaIntvl)
|
||||||
|
setTrestleDetail(res[0].data)
|
||||||
|
|
||||||
|
// dispatch({
|
||||||
|
// type: 'SET_TRESTLE_DETAIL',
|
||||||
|
// roof: {
|
||||||
|
// ...trestleState,
|
||||||
|
// eavesMargin: res[0].data.eaveIntvl,
|
||||||
|
// ridgeMargin: res[0].data.ridgeIntvl,
|
||||||
|
// kerabaMargin: res[0].data.kerabaIntvl,
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
}
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
setPopSpinnerStore(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
trestleState,
|
||||||
|
trestleDetail,
|
||||||
|
dispatch,
|
||||||
|
raftBaseList,
|
||||||
|
trestleList,
|
||||||
|
constMthdList,
|
||||||
|
roofBaseList,
|
||||||
|
constructionList,
|
||||||
|
handleSetTrestleList,
|
||||||
|
handleSetConstMthdList,
|
||||||
|
handleSetRoofBaseList,
|
||||||
|
handleSetConstructionList,
|
||||||
|
handleSetTrestleDetailData,
|
||||||
|
lengthBase,
|
||||||
|
setLengthBase,
|
||||||
|
hajebichi,
|
||||||
|
setHajebichi,
|
||||||
|
cvrYn,
|
||||||
|
cvrChecked,
|
||||||
|
snowGdPossYn,
|
||||||
|
snowGdChecked,
|
||||||
|
eavesMargin,
|
||||||
|
ridgeMargin,
|
||||||
|
kerabaMargin,
|
||||||
|
setEavesMargin,
|
||||||
|
setRidgeMargin,
|
||||||
|
setKerabaMargin,
|
||||||
|
setCvrYn,
|
||||||
|
setCvrChecked,
|
||||||
|
setSnowGdPossYn,
|
||||||
|
setSnowGdChecked,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,8 +22,8 @@ export function useOrientation() {
|
|||||||
})
|
})
|
||||||
}, [])*/
|
}, [])*/
|
||||||
|
|
||||||
const nextStep = () => {
|
const nextStep = (compas = compasDeg) => {
|
||||||
if (isNaN(compasDeg)) {
|
if (isNaN(compas)) {
|
||||||
setCompasDeg(0)
|
setCompasDeg(0)
|
||||||
}
|
}
|
||||||
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
@ -36,7 +36,7 @@ export function useOrientation() {
|
|||||||
|
|
||||||
roofs.forEach((roof) => {
|
roofs.forEach((roof) => {
|
||||||
roof.set({
|
roof.set({
|
||||||
moduleCompass: isNaN(compasDeg) ? 0 : compasDeg,
|
moduleCompass: isNaN(compas) ? 0 : compas,
|
||||||
})
|
})
|
||||||
drawDirectionArrow(roof)
|
drawDirectionArrow(roof)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import { useSwal } from '@/hooks/useSwal'
|
|||||||
import { useContext } from 'react'
|
import { useContext } from 'react'
|
||||||
import { QcastContext } from '@/app/QcastProvider'
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
|
import { useCircuitTrestle } from '@/hooks/useCirCuitTrestle'
|
||||||
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
|
|
||||||
// 모듈간 같은 행, 열의 마진이 10 이하인 경우는 같은 행, 열로 간주
|
// 모듈간 같은 행, 열의 마진이 10 이하인 경우는 같은 행, 열로 간주
|
||||||
const MODULE_MARGIN = 10
|
const MODULE_MARGIN = 10
|
||||||
@ -26,6 +27,7 @@ export const useTrestle = () => {
|
|||||||
|
|
||||||
const { getSelectedPcsItemList } = useCircuitTrestle()
|
const { getSelectedPcsItemList } = useCircuitTrestle()
|
||||||
const { resetCircuits } = useCircuitTrestle()
|
const { resetCircuits } = useCircuitTrestle()
|
||||||
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
const apply = () => {
|
const apply = () => {
|
||||||
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
||||||
@ -58,7 +60,6 @@ export const useTrestle = () => {
|
|||||||
}
|
}
|
||||||
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
const construction = moduleSelectionData?.roofConstructions?.find((construction) => construction.roofIndex === roofMaterialIndex).construction
|
||||||
if (!construction) {
|
if (!construction) {
|
||||||
swalFire({ text: 'construction 존재안함', icon: 'error' })
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,9 +132,9 @@ export const useTrestle = () => {
|
|||||||
surface.isChidory = isChidory
|
surface.isChidory = isChidory
|
||||||
|
|
||||||
if (plvrYn === 'N' && isChidory) {
|
if (plvrYn === 'N' && isChidory) {
|
||||||
swalFire({ text: '치조불가공법입니다.', icon: 'error' })
|
swalFire({ text: getMessage('chidory.can.not.install'), icon: 'error' })
|
||||||
clear()
|
clear()
|
||||||
throw new Error('치조불가공법입니다.')
|
throw new Error(getMessage('chidory.can.not.install'))
|
||||||
}
|
}
|
||||||
|
|
||||||
surface.set({ isChidory: isChidory })
|
surface.set({ isChidory: isChidory })
|
||||||
@ -370,11 +371,16 @@ export const useTrestle = () => {
|
|||||||
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
//C1C2C3인 경우
|
||||||
|
let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
|
rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp &&
|
||||||
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
||||||
Number(rack.value.moduleTpRows1) === leftRowsInfo.rowsInfo[0].count &&
|
newLeftRowsInfo.rowsInfo.every((row, index) => {
|
||||||
Number(rack.value.moduleTpRows2) === leftRowsInfo.rowsInfo[1].count
|
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
|
||||||
|
return rackRowCount === row.count
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})?.value.racks
|
})?.value.racks
|
||||||
@ -387,11 +393,15 @@ export const useTrestle = () => {
|
|||||||
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
|
rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp &&
|
||||||
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
||||||
Number(rack.value.moduleTpRows1) === rightRowsInfo.rowsInfo[0].count &&
|
newRightRowsInfo.rowsInfo.every((row, index) => {
|
||||||
Number(rack.value.moduleTpRows2) === rightRowsInfo.rowsInfo[1].count
|
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
|
||||||
|
return rackRowCount === row.count
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})?.value.racks
|
})?.value.racks
|
||||||
@ -404,11 +414,15 @@ export const useTrestle = () => {
|
|||||||
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
let newCenterRowsInfo = normalizeModules(rack.value.moduleTpCd, centerRowsInfo)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
rack.value.moduleTpCd === centerRowsInfo.moduleTotalTp &&
|
rack.value.moduleTpCd === newCenterRowsInfo.moduleTotalTp &&
|
||||||
rack.value.moduleRows === centerRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
rack.value.moduleRows === newCenterRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
||||||
Number(rack.value.moduleTpRows1) === centerRowsInfo.rowsInfo[0].count &&
|
newCenterRowsInfo.rowsInfo.every((row, index) => {
|
||||||
Number(rack.value.moduleTpRows2) === centerRowsInfo.rowsInfo[1].count
|
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
|
||||||
|
return rackRowCount === row.count
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})?.value.racks
|
})?.value.racks
|
||||||
@ -499,11 +513,15 @@ export const useTrestle = () => {
|
|||||||
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
let newLeftRowsInfo = normalizeModules(rack.value.moduleTpCd, leftRowsInfo)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
rack.value.moduleTpCd === leftRowsInfo.moduleTotalTp &&
|
rack.value.moduleTpCd === newLeftRowsInfo.moduleTotalTp &&
|
||||||
rack.value.moduleRows === leftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
rack.value.moduleRows === newLeftRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
||||||
Number(rack.value.moduleTpRows1) === leftRowsInfo.rowsInfo[0].count &&
|
newLeftRowsInfo.rowsInfo.every((row, index) => {
|
||||||
Number(rack.value.moduleTpRows2) === leftRowsInfo.rowsInfo[1].count
|
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
|
||||||
|
return rackRowCount === row.count
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})?.value.racks
|
})?.value.racks
|
||||||
@ -575,11 +593,16 @@ export const useTrestle = () => {
|
|||||||
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
// 변환 C1C2만 있는경우 C3 0개로 추가해준다.
|
||||||
|
let newRightRowsInfo = normalizeModules(rack.value.moduleTpCd, rightRowsInfo)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
rack.value.moduleTpCd === rightRowsInfo.moduleTotalTp &&
|
rack.value.moduleTpCd === newRightRowsInfo.moduleTotalTp &&
|
||||||
rack.value.moduleRows === rightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
rack.value.moduleRows === newRightRowsInfo.rowsInfo.reduce((acc, row) => acc + row.count, 0) &&
|
||||||
Number(rack.value.moduleTpRows1) === rightRowsInfo.rowsInfo[0].count &&
|
newRightRowsInfo.rowsInfo.every((row, index) => {
|
||||||
Number(rack.value.moduleTpRows2) === rightRowsInfo.rowsInfo[1].count
|
const rackRowCount = Number(rack.value[`moduleTpRows${index + 1}`]) // 동적으로 접근
|
||||||
|
return rackRowCount === row.count
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})?.value.racks
|
})?.value.racks
|
||||||
@ -634,6 +657,31 @@ export const useTrestle = () => {
|
|||||||
return { moduleTotalTp, rowsInfo }
|
return { moduleTotalTp, rowsInfo }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeModules(rackTpCd, data) {
|
||||||
|
// rackTpCd를 숫자를 기준으로 자른다.
|
||||||
|
const allModules = rackTpCd.match(/[A-Za-z]+\d+/g) || [] // 모든 모듈 유형
|
||||||
|
|
||||||
|
// 현재 존재하는 모듈 유형을 추출
|
||||||
|
const existingModules = data.rowsInfo.map((row) => row.moduleTpCd)
|
||||||
|
|
||||||
|
const result = { ...data, rowsInfo: [...data.rowsInfo] }
|
||||||
|
|
||||||
|
// 없는 모듈을 추가 (count: 0)
|
||||||
|
allModules.forEach((module) => {
|
||||||
|
if (!existingModules.includes(module)) {
|
||||||
|
result.rowsInfo.push({ moduleTpCd: module, count: 0 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// rowsInfo를 C1, C2, C3 순서로 정렬
|
||||||
|
result.rowsInfo.sort((a, b) => allModules.indexOf(a.moduleTpCd) - allModules.indexOf(b.moduleTpCd))
|
||||||
|
|
||||||
|
// moduleTotalTp를 C1C2C3로 설정
|
||||||
|
result.moduleTotalTp = allModules.join('')
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// itemList 조회 후 estimateParam에 저장
|
// itemList 조회 후 estimateParam에 저장
|
||||||
const getEstimateData = async () => {
|
const getEstimateData = async () => {
|
||||||
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
@ -660,13 +708,18 @@ export const useTrestle = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// trestles 배열에서 null인 경우 제거
|
// trestles 배열에서 null인 경우 제거
|
||||||
const params = { trestles, pcses, modules }
|
|
||||||
|
const dblCblTotCnt = getTotalConnectCableCnt()
|
||||||
|
const params = { trestles, pcses, modules, dblCblTotCnt }
|
||||||
|
|
||||||
//견적서 itemList 조회
|
//견적서 itemList 조회
|
||||||
const { data, data2, result } = await getQuotationItem(params)
|
const { data, data2, result } = await getQuotationItem(params)
|
||||||
|
|
||||||
if (result.resultCode === 'E') {
|
if (result.resultCode === 'E') {
|
||||||
swalFire({ text: result.resultMsg, icon: 'error' })
|
swalFire({ text: result.resultMsg, icon: 'error' })
|
||||||
|
clear()
|
||||||
|
setViewCircuitNumberTexts(true)
|
||||||
|
setIsGlobalLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -999,9 +1052,7 @@ export const useTrestle = () => {
|
|||||||
if (!rackInfos) {
|
if (!rackInfos) {
|
||||||
const maxRows = surface.trestleDetail.moduleMaxRows
|
const maxRows = surface.trestleDetail.moduleMaxRows
|
||||||
const maxCols = surface.trestleDetail.moduleMaxCols
|
const maxCols = surface.trestleDetail.moduleMaxCols
|
||||||
const msg = `選択した家で設置可能
|
const msg = `段数の上限は${maxRows}段です。 上限より上の段には設置できません`
|
||||||
モジュールの最大段数は${maxRows}、最大列数は${maxCols}です。
|
|
||||||
上限より上部に取り付けたモジュールを削除してください。`
|
|
||||||
swalFire({ title: msg, type: 'alert' })
|
swalFire({ title: msg, type: 'alert' })
|
||||||
throw new Error('rackInfos is null')
|
throw new Error('rackInfos is null')
|
||||||
}
|
}
|
||||||
@ -2130,12 +2181,13 @@ export const useTrestle = () => {
|
|||||||
const visited = new Set()
|
const visited = new Set()
|
||||||
const width = Math.floor(moduleExample.width)
|
const width = Math.floor(moduleExample.width)
|
||||||
const height = Math.floor(moduleExample.height)
|
const height = Math.floor(moduleExample.height)
|
||||||
const horizonPadding = 0 // 가로 패딩
|
const horizonPadding = 3 // 가로 패딩
|
||||||
const verticalPadding = 0 // 세로 패딩
|
const verticalPadding = 7 // 세로 패딩
|
||||||
|
|
||||||
function isAdjacent(p1, p2) {
|
function isAdjacent(p1, p2) {
|
||||||
const dx = Math.abs(p1.x - p2.x)
|
const dx = Math.abs(p1.x - p2.x)
|
||||||
const dy = Math.abs(p1.y - p2.y)
|
const dy = Math.abs(p1.y - p2.y)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
|
(Math.abs(width + horizonPadding - dx) < 2 && dy < 2) ||
|
||||||
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
|
(dx < 2 && Math.abs(dy - height + verticalPadding)) < 2 ||
|
||||||
@ -2167,6 +2219,136 @@ export const useTrestle = () => {
|
|||||||
return groups
|
return groups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function areConnected(m1, m2, surface) {
|
||||||
|
/*const m1Fill = m1.fill
|
||||||
|
const m2Fill = m2.fill
|
||||||
|
m1.set({ fill: 'red' })
|
||||||
|
m2.set({ fill: 'blue' })
|
||||||
|
canvas.renderAll()*/
|
||||||
|
|
||||||
|
let sizes = []
|
||||||
|
|
||||||
|
const { width: currentWidth, height: currentHeight, moduleInfo: currentModuleInfo } = m1
|
||||||
|
const { width: neighborWidth, height: neighborHeight, moduleInfo: neighborModuleInfo } = m2
|
||||||
|
|
||||||
|
const { moduleTpCd: currentModuleTpCd } = currentModuleInfo
|
||||||
|
const { moduleTpCd: neighborModuleTpCd } = neighborModuleInfo
|
||||||
|
const { x: m1X, y: m1Y } = m1.getCenterPoint()
|
||||||
|
const { x: m2X, y: m2Y } = m2.getCenterPoint()
|
||||||
|
sizes.push({ width: currentWidth, height: currentHeight })
|
||||||
|
|
||||||
|
if (currentModuleTpCd !== neighborModuleTpCd) {
|
||||||
|
sizes.push({ width: neighborWidth, height: neighborHeight })
|
||||||
|
}
|
||||||
|
|
||||||
|
/*m1.set({ fill: m1Fill })
|
||||||
|
m2.set({ fill: m2Fill })
|
||||||
|
canvas.renderAll()*/
|
||||||
|
|
||||||
|
return sizes.some(({ width, height }) => {
|
||||||
|
let maxX
|
||||||
|
let maxY
|
||||||
|
let halfMaxX
|
||||||
|
let halfMaxY
|
||||||
|
const { direction, trestleDetail } = surface
|
||||||
|
let moduleIntvlHor, moduleIntvlVer
|
||||||
|
if (+roofSizeSet === 3) {
|
||||||
|
//육지붕의 경우 값 고정
|
||||||
|
moduleIntvlHor = 300
|
||||||
|
moduleIntvlVer = 100
|
||||||
|
} else {
|
||||||
|
moduleIntvlHor = trestleDetail.moduleIntvlHor
|
||||||
|
moduleIntvlVer = trestleDetail.moduleIntvlVer
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction === 'south' || direction === 'north') {
|
||||||
|
maxX = width + moduleIntvlHor / 10
|
||||||
|
maxY = height + moduleIntvlVer / 10
|
||||||
|
halfMaxX = moduleIntvlHor / 10
|
||||||
|
halfMaxY = moduleIntvlVer / 10
|
||||||
|
|
||||||
|
if (currentModuleTpCd !== neighborModuleTpCd) {
|
||||||
|
maxX = currentWidth / 2 + neighborWidth / 2 + moduleIntvlHor / 10
|
||||||
|
maxY = currentHeight / 2 + neighborHeight / 2 + moduleIntvlVer / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(maxX, maxY, halfMaxX, halfMaxY)
|
||||||
|
|
||||||
|
if (Math.abs(m1X - m2X) < 1) {
|
||||||
|
return Math.abs(Math.abs(m1Y - m2Y) - maxY) < 1
|
||||||
|
} else if (Math.abs(m1Y - m2Y) < 1) {
|
||||||
|
return Math.abs(Math.abs(m1X - m2X) - maxX) < 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
(Math.abs(m1X - m2X) < maxX - moduleIntvlHor / 10 && Math.abs(m1Y - m2Y) < maxY - moduleIntvlVer / 10) ||
|
||||||
|
(Math.abs(Math.abs(m1X - m2X) - maxX / 2) < halfMaxX + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxY) < halfMaxY + 1) ||
|
||||||
|
(Math.abs(Math.abs(m1X - m2X) - maxX) < halfMaxX + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxY / 2) < halfMaxY + 1)
|
||||||
|
)
|
||||||
|
} else if (direction === 'east' || direction === 'west') {
|
||||||
|
maxX = height + moduleIntvlHor / 10
|
||||||
|
maxY = width + moduleIntvlVer / 10
|
||||||
|
halfMaxX = moduleIntvlVer / 10
|
||||||
|
halfMaxY = moduleIntvlHor / 10
|
||||||
|
|
||||||
|
if (currentModuleTpCd !== neighborModuleTpCd) {
|
||||||
|
maxX = currentHeight / 2 + neighborHeight / 2 + moduleIntvlVer / 10
|
||||||
|
maxY = currentWidth / 2 + neighborWidth / 2 + moduleIntvlHor / 10
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.abs(m1X - m2X) < 1) {
|
||||||
|
return Math.abs(Math.abs(m1Y - m2Y) - maxX) < 1
|
||||||
|
} else if (Math.abs(m1Y - m2Y) < 1) {
|
||||||
|
return Math.abs(Math.abs(m1X - m2X) - maxY) < 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
(Math.abs(m1X - m2X) <= maxY - moduleIntvlVer / 10 && Math.abs(m1Y - m2Y) <= maxX - moduleIntvlHor / 10) ||
|
||||||
|
(Math.abs(Math.abs(m1X - m2X) - maxY / 2) < halfMaxY + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxX) < halfMaxX + 1) ||
|
||||||
|
(Math.abs(Math.abs(m1X - m2X) - maxY) < halfMaxY + 1 && Math.abs(Math.abs(m1Y - m2Y) - maxX / 2) < halfMaxX + 1)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 25-04-02 추가
|
||||||
|
// 그룹화
|
||||||
|
function groupPoints(modules, surface) {
|
||||||
|
const groups = []
|
||||||
|
const visited = new Set()
|
||||||
|
|
||||||
|
for (const point of modules) {
|
||||||
|
const { x: pointX, y: pointY } = point.getCenterPoint()
|
||||||
|
const key = `${pointX},${pointY}`
|
||||||
|
if (visited.has(key)) continue
|
||||||
|
|
||||||
|
const queue = [point]
|
||||||
|
const group = []
|
||||||
|
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const current = queue.shift()
|
||||||
|
const { x: currentX, y: currentY } = current.getCenterPoint()
|
||||||
|
const currentKey = `${currentX},${currentY}`
|
||||||
|
if (visited.has(currentKey)) continue
|
||||||
|
|
||||||
|
visited.add(currentKey)
|
||||||
|
group.push(current)
|
||||||
|
|
||||||
|
for (const neighbor of modules) {
|
||||||
|
const { x: neighborX, y: neighborY } = neighbor.getCenterPoint()
|
||||||
|
const neighborKey = `${neighborX},${neighborY}`
|
||||||
|
if (!visited.has(neighborKey) && areConnected(current, neighbor, surface)) {
|
||||||
|
queue.push(neighbor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groups.push(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
|
||||||
// 각도에 따른 길이 반환
|
// 각도에 따른 길이 반환
|
||||||
function getTrestleLength(length, degree) {
|
function getTrestleLength(length, degree) {
|
||||||
if (roofSizeSet !== 1) {
|
if (roofSizeSet !== 1) {
|
||||||
@ -2864,5 +3046,82 @@ export const useTrestle = () => {
|
|||||||
return surfaces.every((surface) => surface.isComplete)
|
return surfaces.every((surface) => surface.isComplete)
|
||||||
}
|
}
|
||||||
|
|
||||||
return { apply, getTrestleParams, clear, setViewCircuitNumberTexts, getEstimateData, setAllModuleSurfaceIsComplete, isAllComplete }
|
const groupByType = (originArr = []) => {
|
||||||
|
const grouped = {}
|
||||||
|
const newArr = [...originArr]
|
||||||
|
|
||||||
|
// 타입별로 객체들을 분류
|
||||||
|
for (const item of newArr) {
|
||||||
|
if (!grouped[item.circuitNumber]) {
|
||||||
|
grouped[item.circuitNumber] = []
|
||||||
|
}
|
||||||
|
grouped[item.circuitNumber].push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 객체를 배열로 변환
|
||||||
|
return Object.values(grouped)
|
||||||
|
}
|
||||||
|
|
||||||
|
function groupByCircuitAndSurface(arr) {
|
||||||
|
const circuitGroups = {}
|
||||||
|
|
||||||
|
for (const item of arr) {
|
||||||
|
const { circuitNumber, surfaceId } = item
|
||||||
|
if (!circuitGroups[circuitNumber]) {
|
||||||
|
circuitGroups[circuitNumber] = new Map()
|
||||||
|
}
|
||||||
|
|
||||||
|
const surfaceMap = circuitGroups[circuitNumber]
|
||||||
|
const key = surfaceId
|
||||||
|
|
||||||
|
if (!surfaceMap.has(key)) {
|
||||||
|
surfaceMap.set(key, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
surfaceMap.get(key).push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 결과: circuitNumber별 surface 그룹 수
|
||||||
|
const result = {}
|
||||||
|
for (const [circuit, surfaceMap] of Object.entries(circuitGroups)) {
|
||||||
|
result[circuit] = surfaceMap.size
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// 양단 케이블 구하는 공식
|
||||||
|
const getTotalConnectCableCnt = () => {
|
||||||
|
let cnt = 0
|
||||||
|
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
|
surfaces.forEach((surface) => {
|
||||||
|
const modules = surface.modules
|
||||||
|
const groups = groupByType(modules)
|
||||||
|
groups.forEach((group) => {
|
||||||
|
const result = groupPoints(group, surface)
|
||||||
|
cnt += result.length - 1
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const groupByCircuitAndSurfaceCnt = groupByCircuitAndSurface(modules)
|
||||||
|
|
||||||
|
Object.keys(groupByCircuitAndSurfaceCnt).forEach((key) => {
|
||||||
|
cnt += groupByCircuitAndSurfaceCnt[key] - 1
|
||||||
|
})
|
||||||
|
|
||||||
|
return cnt
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
apply,
|
||||||
|
getTrestleParams,
|
||||||
|
clear,
|
||||||
|
setViewCircuitNumberTexts,
|
||||||
|
getEstimateData,
|
||||||
|
setAllModuleSurfaceIsComplete,
|
||||||
|
isAllComplete,
|
||||||
|
groupCoordinates,
|
||||||
|
groupPoints,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -123,6 +123,7 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */
|
const resetModuleSelectionData = useResetRecoilState(moduleSelectionDataState) /* 다음으로 넘어가는 최종 데이터 */
|
||||||
const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */
|
const resetSelectedModules = useResetRecoilState(selectedModuleState) /* 선택된 모듈 */
|
||||||
|
|
||||||
|
const { trigger: orientationTrigger } = useCanvasPopupStatusController(1)
|
||||||
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||||
|
|
||||||
const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */
|
const [raftCodes, setRaftCodes] = useState([]) /* 서까래 정보 */
|
||||||
@ -526,7 +527,10 @@ export function useCanvasSetting(executeEffect = true) {
|
|||||||
|
|
||||||
/** 모듈 선택 데이터 초기화 */
|
/** 모듈 선택 데이터 초기화 */
|
||||||
resetModuleSelectionData()
|
resetModuleSelectionData()
|
||||||
moduleSelectedDataTrigger({ common: {}, module: {}, roofConstructions: [] })
|
//1번 초기화
|
||||||
|
orientationTrigger({ compasDeg: 0, common: {}, module: {} })
|
||||||
|
//2번 초기화
|
||||||
|
moduleSelectedDataTrigger({ roofConstructions: [] })
|
||||||
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
const isModuleExist = canvas.getObjects().some((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||||
if (!isModuleExist) {
|
if (!isModuleExist) {
|
||||||
resetSelectedModules()
|
resetSelectedModules()
|
||||||
|
|||||||
@ -5,16 +5,6 @@ import { useEvent } from '@/hooks/useEvent'
|
|||||||
import { useMouse } from '@/hooks/useMouse'
|
import { useMouse } from '@/hooks/useMouse'
|
||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
import {
|
|
||||||
outerLineAngle1State,
|
|
||||||
outerLineAngle2State,
|
|
||||||
outerLineArrow1State,
|
|
||||||
outerLineArrow2State,
|
|
||||||
outerLineDiagonalState,
|
|
||||||
outerLineLength1State,
|
|
||||||
outerLineLength2State,
|
|
||||||
outerLineTypeState,
|
|
||||||
} from '@/store/outerLineAtom'
|
|
||||||
import { calculateIntersection, distanceBetweenPoints, findClosestPoint, isPointOnLine } from '@/util/canvas-util'
|
import { calculateIntersection, distanceBetweenPoints, findClosestPoint, isPointOnLine } from '@/util/canvas-util'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
||||||
@ -23,6 +13,16 @@ import { usePopup } from '@/hooks/usePopup'
|
|||||||
import { calculateAngle, isSamePoint } from '@/util/qpolygon-utils'
|
import { calculateAngle, isSamePoint } from '@/util/qpolygon-utils'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { useMessage } from '../useMessage'
|
import { useMessage } from '../useMessage'
|
||||||
|
import {
|
||||||
|
auxiliaryLineAngle1State,
|
||||||
|
auxiliaryLineAngle2State,
|
||||||
|
auxiliaryLineArrow1State,
|
||||||
|
auxiliaryLineArrow2State,
|
||||||
|
auxiliaryLineDiagonalState,
|
||||||
|
auxiliaryLineLength1State,
|
||||||
|
auxiliaryLineLength2State,
|
||||||
|
auxiliaryLineTypeState,
|
||||||
|
} from '@/store/auxiliaryLineAtom'
|
||||||
|
|
||||||
// 보조선 작성
|
// 보조선 작성
|
||||||
export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
||||||
@ -49,20 +49,20 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
const length2Ref = useRef(0)
|
const length2Ref = useRef(0)
|
||||||
const angle1Ref = useRef('')
|
const angle1Ref = useRef('')
|
||||||
const angle2Ref = useRef('')
|
const angle2Ref = useRef('')
|
||||||
const [length1, setLength1] = useRecoilState(outerLineLength1State)
|
const [length1, setLength1] = useRecoilState(auxiliaryLineLength1State)
|
||||||
const [length2, setLength2] = useRecoilState(outerLineLength2State)
|
const [length2, setLength2] = useRecoilState(auxiliaryLineLength2State)
|
||||||
const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
|
const [arrow1, setArrow1] = useRecoilState(auxiliaryLineArrow1State)
|
||||||
const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
|
const [arrow2, setArrow2] = useRecoilState(auxiliaryLineArrow2State)
|
||||||
const [type, setType] = useRecoilState(outerLineTypeState)
|
const [type, setType] = useRecoilState(auxiliaryLineTypeState)
|
||||||
const [angle1, setAngle1] = useRecoilState(outerLineAngle1State)
|
const [angle1, setAngle1] = useRecoilState(auxiliaryLineAngle1State)
|
||||||
const [angle2, setAngle2] = useRecoilState(outerLineAngle2State)
|
const [angle2, setAngle2] = useRecoilState(auxiliaryLineAngle2State)
|
||||||
const [outerLineDiagonalLength, setOuterLineDiagonalLength] = useRecoilState(outerLineDiagonalState)
|
const [auxiliaryLineDiagonalLength, setAuxiliaryLineDiagonalLength] = useRecoilState(auxiliaryLineDiagonalState)
|
||||||
const arrow1Ref = useRef(arrow1)
|
const arrow1Ref = useRef(arrow1)
|
||||||
const arrow2Ref = useRef(arrow2)
|
const arrow2Ref = useRef(arrow2)
|
||||||
|
|
||||||
const typeRef = useRef(type)
|
const typeRef = useRef(type)
|
||||||
|
|
||||||
const outerLineDiagonalLengthRef = useRef(0)
|
const auxiliaryLineDiagonalLengthRef = useRef(0)
|
||||||
const intersectionPoints = useRef([])
|
const intersectionPoints = useRef([])
|
||||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
// innerLines가 있을경우 삭제
|
// innerLines가 있을경우 삭제
|
||||||
const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
if (roofs.length === 0) {
|
if (roofs.length === 0) {
|
||||||
swalFire({ text: '지붕형상이 없습니다.' })
|
swalFire({ text: getMessage('roof.line.not.found') })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
setAngle1(0)
|
setAngle1(0)
|
||||||
setAngle2(0)
|
setAngle2(0)
|
||||||
|
|
||||||
setOuterLineDiagonalLength(0)
|
setAuxiliaryLineDiagonalLength(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const move = (object, x, y) => {
|
const move = (object, x, y) => {
|
||||||
@ -408,7 +408,7 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
//대각선 완료될 경우 확인
|
//대각선 완료될 경우 확인
|
||||||
const checkDiagonal = (direction) => {
|
const checkDiagonal = (direction) => {
|
||||||
const activeElem = document.activeElement
|
const activeElem = document.activeElement
|
||||||
const diagonalLength = outerLineDiagonalLengthRef.current.value // 대각선 길이
|
const diagonalLength = auxiliaryLineDiagonalLengthRef.current.value // 대각선 길이
|
||||||
|
|
||||||
const length1Value = length1Ref.current.value
|
const length1Value = length1Ref.current.value
|
||||||
|
|
||||||
@ -913,9 +913,9 @@ export function useAuxiliaryDrawing(id, isUseEffect = true) {
|
|||||||
angle2,
|
angle2,
|
||||||
setAngle2,
|
setAngle2,
|
||||||
angle2Ref,
|
angle2Ref,
|
||||||
outerLineDiagonalLength,
|
auxiliaryLineDiagonalLength,
|
||||||
setOuterLineDiagonalLength,
|
setAuxiliaryLineDiagonalLength,
|
||||||
outerLineDiagonalLengthRef,
|
auxiliaryLineDiagonalLengthRef,
|
||||||
type,
|
type,
|
||||||
setType,
|
setType,
|
||||||
handleFix,
|
handleFix,
|
||||||
|
|||||||
@ -52,7 +52,7 @@ export function useEavesGableEdit(id) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
if (!outerLineFix || outerLines.length === 0) {
|
if (!outerLineFix || outerLines.length === 0) {
|
||||||
swalFire({ text: '외벽선이 없습니다.' })
|
swalFire({ text: getMessage('wall.line.not.found') })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|||||||
@ -32,6 +32,7 @@ import { outlineDisplaySelector } from '@/store/settingAtom'
|
|||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting'
|
import PropertiesSetting from '@/components/floor-plan/modal/outerlinesetting/PropertiesSetting'
|
||||||
import Big from 'big.js'
|
import Big from 'big.js'
|
||||||
|
import RoofShapeSetting from '@/components/floor-plan/modal/roofShape/RoofShapeSetting'
|
||||||
|
|
||||||
//외벽선 그리기
|
//외벽선 그리기
|
||||||
export function useOuterLineWall(id, propertiesId) {
|
export function useOuterLineWall(id, propertiesId) {
|
||||||
@ -256,7 +257,7 @@ export function useOuterLineWall(id, propertiesId) {
|
|||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
setOuterLineFix(true)
|
setOuterLineFix(true)
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
addPopup(propertiesId, 1, <PropertiesSetting id={propertiesId} pos={{ x: 50, y: 230 }} />)
|
addPopup(propertiesId, 1, <RoofShapeSetting id={propertiesId} pos={{ x: 50, y: 230 }} />)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (points.length < 3) {
|
if (points.length < 3) {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||||
import { canvasState, currentAngleTypeSelector, currentMenuState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasState, currentAngleTypeSelector, currentMenuState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useContext, useEffect, useRef, useState } from 'react'
|
||||||
import { useAxios } from '@/hooks/useAxios'
|
import { useAxios } from '@/hooks/useAxios'
|
||||||
import { useSwal } from '@/hooks/useSwal'
|
import { useSwal } from '@/hooks/useSwal'
|
||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
@ -11,6 +11,8 @@ import {
|
|||||||
roofDisplaySelector,
|
roofDisplaySelector,
|
||||||
roofMaterialsSelector,
|
roofMaterialsSelector,
|
||||||
selectedRoofMaterialSelector,
|
selectedRoofMaterialSelector,
|
||||||
|
settingModalFirstOptionsState,
|
||||||
|
corridorDimensionSelector,
|
||||||
} from '@/store/settingAtom'
|
} from '@/store/settingAtom'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
@ -26,6 +28,9 @@ import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
|
|||||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||||
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
|
import { roofsState } from '@/store/roofAtom'
|
||||||
|
|
||||||
export function useRoofAllocationSetting(id) {
|
export function useRoofAllocationSetting(id) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
@ -49,11 +54,13 @@ export function useRoofAllocationSetting(id) {
|
|||||||
const { get, post } = useAxios(globalLocaleState)
|
const { get, post } = useAxios(globalLocaleState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
const { swalFire } = useSwal()
|
const { swalFire } = useSwal()
|
||||||
|
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||||
const { setSurfaceShapePattern } = useRoofFn()
|
const { setSurfaceShapePattern } = useRoofFn()
|
||||||
|
const { saveCanvas } = usePlan()
|
||||||
|
const [roofsStore, setRoofsStore] = useRecoilState(roofsState)
|
||||||
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
||||||
const resetPoints = useResetRecoilState(outerLinePointsState)
|
const resetPoints = useResetRecoilState(outerLinePointsState)
|
||||||
|
const [corridorDimension, setCorridorDimension] = useRecoilState(corridorDimensionSelector)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
/** 배치면 초기설정에서 선택한 지붕재 배열 설정 */
|
/** 배치면 초기설정에서 선택한 지붕재 배열 설정 */
|
||||||
@ -68,30 +75,19 @@ export function useRoofAllocationSetting(id) {
|
|||||||
roof.innerLines.forEach((line) => {
|
roof.innerLines.forEach((line) => {
|
||||||
/** 실측값이 없는 경우 라인 두께 4로 설정 */
|
/** 실측값이 없는 경우 라인 두께 4로 설정 */
|
||||||
if (!line.attributes.actualSize || line.attributes?.actualSize === 0) {
|
if (!line.attributes.actualSize || line.attributes?.actualSize === 0) {
|
||||||
line.set({
|
line.set({ strokeWidth: 4, stroke: 'black', selectable: true })
|
||||||
strokeWidth: 4,
|
|
||||||
stroke: 'black',
|
|
||||||
selectable: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 현재 선택된 라인인 경우 라인 두께 2로 설정 */
|
/** 현재 선택된 라인인 경우 라인 두께 2로 설정 */
|
||||||
if (editingLines.includes(line)) {
|
if (editingLines.includes(line)) {
|
||||||
line.set({
|
line.set({ strokeWidth: 2, stroke: 'black', selectable: true })
|
||||||
strokeWidth: 2,
|
|
||||||
stroke: 'black',
|
|
||||||
selectable: true,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/** 현재 선택된 객체가 보조라인, 피라미드, 힙인 경우 두께 4로 설정 */
|
/** 현재 선택된 객체가 보조라인, 피라미드, 힙인 경우 두께 4로 설정 */
|
||||||
if (currentObject && currentObject.name && ['auxiliaryLine', 'ridge', 'hip'].includes(currentObject.name)) {
|
if (currentObject && currentObject.name && ['auxiliaryLine', 'ridge', 'hip'].includes(currentObject.name)) {
|
||||||
currentObject.set({
|
currentObject.set({ strokeWidth: 4, stroke: '#EA10AC' })
|
||||||
strokeWidth: 4,
|
|
||||||
stroke: '#EA10AC',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}, [currentObject])
|
}, [currentObject])
|
||||||
|
|
||||||
@ -99,7 +95,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
/** 현재 선택된 객체가 보조라인, 피라미드, 힙인 경우 두께 4로 설정 */
|
/** 현재 선택된 객체가 보조라인, 피라미드, 힙인 경우 두께 4로 설정 */
|
||||||
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
if (roofBases.length === 0) {
|
if (roofBases.length === 0) {
|
||||||
swalFire({ text: '할당할 지붕이 없습니다.' })
|
swalFire({ text: getMessage('roofAllocation.not.found'), icon: 'warning' })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,9 +108,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
*/
|
*/
|
||||||
const fetchBasicSettings = async (planNo) => {
|
const fetchBasicSettings = async (planNo) => {
|
||||||
try {
|
try {
|
||||||
await get({
|
await get({ url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}` }).then((res) => {
|
||||||
url: `/api/canvas-management/canvas-basic-settings/by-object/${correntObjectNo}/${planNo}`,
|
|
||||||
}).then((res) => {
|
|
||||||
let roofsArray = {}
|
let roofsArray = {}
|
||||||
|
|
||||||
if (res.length > 0) {
|
if (res.length > 0) {
|
||||||
@ -184,11 +178,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
selectedRoofMaterial: selectRoofs.find((roof) => roof.selected),
|
selectedRoofMaterial: selectRoofs.find((roof) => roof.selected),
|
||||||
})
|
})
|
||||||
|
|
||||||
setBasicInfo({
|
setBasicInfo({ planNo: '' + res[0].planNo, roofSizeSet: '' + res[0].roofSizeSet, roofAngleSet: '' + res[0].roofAngleSet })
|
||||||
planNo: '' + res[0].planNo,
|
|
||||||
roofSizeSet: '' + res[0].roofSizeSet,
|
|
||||||
roofAngleSet: '' + res[0].roofAngleSet,
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Data fetching error:', error)
|
console.error('Data fetching error:', error)
|
||||||
@ -200,6 +190,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
*/
|
*/
|
||||||
const basicSettingSave = async () => {
|
const basicSettingSave = async () => {
|
||||||
try {
|
try {
|
||||||
|
setIsGlobalLoading(true)
|
||||||
const patternData = {
|
const patternData = {
|
||||||
objectNo: correntObjectNo,
|
objectNo: correntObjectNo,
|
||||||
planNo: Number(basicSetting.planNo),
|
planNo: Number(basicSetting.planNo),
|
||||||
@ -222,6 +213,8 @@ export function useRoofAllocationSetting(id) {
|
|||||||
|
|
||||||
await post({ url: `/api/canvas-management/roof-allocation-settings`, data: patternData }).then((res) => {
|
await post({ url: `/api/canvas-management/roof-allocation-settings`, data: patternData }).then((res) => {
|
||||||
swalFire({ text: getMessage(res.returnMessage) })
|
swalFire({ text: getMessage(res.returnMessage) })
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
saveCanvas(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
//Recoil 설정
|
//Recoil 설정
|
||||||
@ -242,36 +235,48 @@ export function useRoofAllocationSetting(id) {
|
|||||||
swalFire({ type: 'alert', icon: 'error', text: getMessage('roof.exceed.count') })
|
swalFire({ type: 'alert', icon: 'error', text: getMessage('roof.exceed.count') })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setCurrentRoofList([
|
|
||||||
...currentRoofList,
|
const originCurrentRoofList = currentRoofList.map((roof) => {
|
||||||
{
|
return { ...roof, selected: false }
|
||||||
...currentRoofMaterial,
|
})
|
||||||
selected: false,
|
originCurrentRoofList.push({
|
||||||
id: currentRoofMaterial.roofMatlCd,
|
...currentRoofMaterial,
|
||||||
name: currentRoofMaterial.roofMatlNm,
|
selected: true,
|
||||||
index: currentRoofList.length,
|
id: currentRoofMaterial.roofMatlCd,
|
||||||
},
|
name: currentRoofMaterial.roofMatlNm,
|
||||||
])
|
index: currentRoofList.length,
|
||||||
|
})
|
||||||
|
|
||||||
|
setCurrentRoofList(originCurrentRoofList)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 지붕재 삭제
|
* 지붕재 삭제
|
||||||
*/
|
*/
|
||||||
const onDeleteRoofMaterial = (idx) => {
|
const onDeleteRoofMaterial = (idx) => {
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
|
||||||
|
for (let i = 0; i < roofs.length; i++) {
|
||||||
|
if (roofs[i].roofMaterial?.index === idx) {
|
||||||
|
swalFire({ type: 'alert', icon: 'error', text: getMessage('roof.material.can.not.delete') })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const isSelected = currentRoofList[idx].selected
|
const isSelected = currentRoofList[idx].selected
|
||||||
const newRoofList = JSON.parse(JSON.stringify(currentRoofList)).filter((_, index) => index !== idx)
|
const newRoofList = JSON.parse(JSON.stringify(currentRoofList)).filter((_, index) => index !== idx)
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
newRoofList[0].selected = true
|
newRoofList[0].selected = true
|
||||||
}
|
}
|
||||||
setCurrentRoofList(newRoofList)
|
setCurrentRoofList(newRoofList)
|
||||||
|
setRoofsStore(newRoofList)
|
||||||
|
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 선택한 지붕재로 할당
|
* 선택한 지붕재로 할당
|
||||||
*/
|
*/
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
basicSettingSave()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 모두 actualSize 있으면 바로 적용 없으면 actualSize 설정
|
* 모두 actualSize 있으면 바로 적용 없으면 actualSize 설정
|
||||||
*/
|
*/
|
||||||
@ -280,6 +285,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
} else {
|
} else {
|
||||||
apply()
|
apply()
|
||||||
resetPoints()
|
resetPoints()
|
||||||
|
basicSettingSave()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,23 +293,47 @@ export function useRoofAllocationSetting(id) {
|
|||||||
* 지붕재 오른쪽 마우스 클릭 후 단일로 지붕재 변경 필요한 경우
|
* 지붕재 오른쪽 마우스 클릭 후 단일로 지붕재 변경 필요한 경우
|
||||||
*/
|
*/
|
||||||
const handleSaveContext = () => {
|
const handleSaveContext = () => {
|
||||||
basicSettingSave()
|
|
||||||
const newRoofList = currentRoofList.map((roof, idx) => {
|
const newRoofList = currentRoofList.map((roof, idx) => {
|
||||||
|
if (roof.index !== idx) {
|
||||||
|
// 기존 저장된 지붕재의 index 수정
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF && obj.roofMaterial?.index === roof.index)
|
||||||
|
roofs.forEach((roof) => {
|
||||||
|
setSurfaceShapePattern(roof, roofDisplay.column, false, { ...roof, index: idx }, true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return { ...roof, index: idx, raft: roof.raft ? roof.raft : roof.raftBaseCd }
|
return { ...roof, index: idx, raft: roof.raft ? roof.raft : roof.raftBaseCd }
|
||||||
})
|
})
|
||||||
|
|
||||||
setBasicSetting((prev) => {
|
setBasicSetting((prev) => {
|
||||||
return {
|
return { ...prev, selectedRoofMaterial: newRoofList.find((roof) => roof.selected) }
|
||||||
...prev,
|
|
||||||
selectedRoofMaterial: newRoofList.find((roof) => roof.selected),
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
setRoofList(newRoofList)
|
setRoofList(newRoofList)
|
||||||
|
setRoofMaterials(newRoofList)
|
||||||
|
setRoofsStore(newRoofList)
|
||||||
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
|
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
|
||||||
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial, true)
|
||||||
drawDirectionArrow(currentObject)
|
drawDirectionArrow(currentObject)
|
||||||
modifyModuleSelectionData()
|
modifyModuleSelectionData()
|
||||||
closeAll()
|
closeAll()
|
||||||
|
basicSettingSave()
|
||||||
|
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 기존 세팅된 지붕에 지붕재 내용을 바뀐 내용으로 수정
|
||||||
|
* @param newRoofMaterials
|
||||||
|
*/
|
||||||
|
const setRoofMaterials = (newRoofMaterials) => {
|
||||||
|
const roofs = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
newRoofMaterials.forEach((roofMaterial) => {
|
||||||
|
const index = roofMaterial.index
|
||||||
|
const tempRoofs = roofs.filter((roof) => roof.roofMaterial?.index === index)
|
||||||
|
tempRoofs.forEach((roof) => {
|
||||||
|
setSurfaceShapePattern(roof, roofDisplay.column, false, roofMaterial)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -313,11 +343,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
if (!checkInnerLines()) {
|
if (!checkInnerLines()) {
|
||||||
apply()
|
apply()
|
||||||
} else {
|
} else {
|
||||||
swalFire({
|
swalFire({ type: 'alert', icon: 'error', text: getMessage('실제치수를 입력해 주세요.') })
|
||||||
type: 'alert',
|
|
||||||
icon: 'error',
|
|
||||||
text: getMessage('실제치수를 입력해 주세요.'),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,11 +358,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
if (roof.separatePolygon.length === 0) {
|
if (roof.separatePolygon.length === 0) {
|
||||||
roof.innerLines.forEach((line) => {
|
roof.innerLines.forEach((line) => {
|
||||||
if (!line.attributes.actualSize || line.attributes?.actualSize === 0) {
|
if (!line.attributes.actualSize || line.attributes?.actualSize === 0) {
|
||||||
line.set({
|
line.set({ strokeWidth: 4, stroke: 'black', selectable: true })
|
||||||
strokeWidth: 4,
|
|
||||||
stroke: 'black',
|
|
||||||
selectable: true,
|
|
||||||
})
|
|
||||||
result = true
|
result = true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -361,6 +383,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
splitPolygonWithLines(roofBase)
|
splitPolygonWithLines(roofBase)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,10 +406,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
setBasicSetting((prev) => {
|
setBasicSetting((prev) => {
|
||||||
return {
|
return { ...prev, selectedRoofMaterial: newRoofList.find((roof) => roof.selected) }
|
||||||
...prev,
|
|
||||||
selectedRoofMaterial: newRoofList.find((roof) => roof.selected),
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
setRoofList(newRoofList)
|
setRoofList(newRoofList)
|
||||||
|
|
||||||
@ -394,9 +414,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
|
|
||||||
roofs.forEach((roof) => {
|
roofs.forEach((roof) => {
|
||||||
if (roof.isFixed) return
|
if (roof.isFixed) return
|
||||||
roof.set({
|
roof.set({ isFixed: true })
|
||||||
isFixed: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
/** 모양 패턴 설정 */
|
/** 모양 패턴 설정 */
|
||||||
setSurfaceShapePattern(
|
setSurfaceShapePattern(
|
||||||
@ -408,6 +426,8 @@ export function useRoofAllocationSetting(id) {
|
|||||||
drawDirectionArrow(roof)
|
drawDirectionArrow(roof)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
setRoofMaterials(newRoofList)
|
||||||
|
setRoofsStore(newRoofList)
|
||||||
/** 외곽선 삭제 */
|
/** 외곽선 삭제 */
|
||||||
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
|
const removeTargets = canvas.getObjects().filter((obj) => obj.name === 'outerLinePoint' || obj.name === 'outerLine')
|
||||||
removeTargets.forEach((obj) => {
|
removeTargets.forEach((obj) => {
|
||||||
@ -416,9 +436,12 @@ export function useRoofAllocationSetting(id) {
|
|||||||
setEditingLines([])
|
setEditingLines([])
|
||||||
closeAll()
|
closeAll()
|
||||||
setSelectedMenu('surface')
|
setSelectedMenu('surface')
|
||||||
|
//지붕면 완성 후 실측치 로 보이도록 수정
|
||||||
|
setCorridorDimension(1)
|
||||||
|
|
||||||
/** 모듈 선택 데이터 초기화 */
|
/** 모듈 선택 데이터 초기화 */
|
||||||
modifyModuleSelectionData()
|
// modifyModuleSelectionData()
|
||||||
|
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: newRoofList })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -431,10 +454,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
if (id === line.id) {
|
if (id === line.id) {
|
||||||
setEditingLines([...editingLines.filter((editLine) => editLine.id !== line.id), line])
|
setEditingLines([...editingLines.filter((editLine) => editLine.id !== line.id), line])
|
||||||
line.attributes.actualSize = size
|
line.attributes.actualSize = size
|
||||||
line.set({
|
line.set({ strokeWidth: 2, stroke: 'black' })
|
||||||
strokeWidth: 2,
|
|
||||||
stroke: 'black',
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -449,7 +469,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value.id)
|
const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value.id)
|
||||||
const newRoofList = currentRoofList.map((roof, idx) => {
|
const newRoofList = currentRoofList.map((roof, idx) => {
|
||||||
if (idx === index) {
|
if (idx === index) {
|
||||||
return { ...selectedRoofMaterial, selected: roof.selected }
|
return { ...selectedRoofMaterial, selected: roof.selected, index }
|
||||||
}
|
}
|
||||||
return roof
|
return roof
|
||||||
})
|
})
|
||||||
@ -539,7 +559,7 @@ export function useRoofAllocationSetting(id) {
|
|||||||
* 모듈 선택에서 선택한 데이터 초기화
|
* 모듈 선택에서 선택한 데이터 초기화
|
||||||
*/
|
*/
|
||||||
const modifyModuleSelectionData = () => {
|
const modifyModuleSelectionData = () => {
|
||||||
if (moduleSelectionData.roofConstructions.length > 0) {
|
if (moduleSelectionData.roofConstructions?.length > 0) {
|
||||||
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: [] })
|
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: [] })
|
||||||
moduleSelectedDataTrigger({ ...moduleSelectionData, roofConstructions: [] })
|
moduleSelectedDataTrigger({ ...moduleSelectionData, roofConstructions: [] })
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export function useRoofShapePassivitySetting(id) {
|
|||||||
const { addCanvasMouseEventListener, initEvent } = useEvent()
|
const { addCanvasMouseEventListener, initEvent } = useEvent()
|
||||||
// const { addCanvasMouseEventListener, initEvent } = useContext(EventContext)
|
// const { addCanvasMouseEventListener, initEvent } = useContext(EventContext)
|
||||||
const { drawRoofPolygon } = useMode()
|
const { drawRoofPolygon } = useMode()
|
||||||
const { addPolygonByLines } = usePolygon()
|
const { addPolygonByLines, addLengthText } = usePolygon()
|
||||||
const currentObject = useRecoilValue(currentObjectState)
|
const currentObject = useRecoilValue(currentObjectState)
|
||||||
const offsetRef = useRef(null)
|
const offsetRef = useRef(null)
|
||||||
const pitchRef = useRef(null)
|
const pitchRef = useRef(null)
|
||||||
@ -51,7 +51,7 @@ export function useRoofShapePassivitySetting(id) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
if (!outerLineFix || outerLines.length === 0) {
|
if (!outerLineFix || outerLines.length === 0) {
|
||||||
swalFire({ text: '외벽선이 없습니다.' })
|
swalFire({ text: getMessage('wall.line.not.found') })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -248,6 +248,7 @@ export function useRoofShapePassivitySetting(id) {
|
|||||||
// 완료 한 경우에는 지붕까지 그려줌
|
// 완료 한 경우에는 지붕까지 그려줌
|
||||||
addPitchTextsByOuterLines()
|
addPitchTextsByOuterLines()
|
||||||
const roof = drawRoofPolygon(wall)
|
const roof = drawRoofPolygon(wall)
|
||||||
|
addLengthText(roof)
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
|
|||||||
@ -191,7 +191,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
let direction
|
let direction
|
||||||
|
|
||||||
if (outerLines.length < 2) {
|
if (outerLines.length < 2) {
|
||||||
swalFire({ text: '외벽선이 없습니다.', icon: 'error' })
|
swalFire({ text: getMessage('wall.line.not.found') })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,6 +231,21 @@ export function useRoofShapeSetting(id) {
|
|||||||
pitch: pitchRef.current,
|
pitch: pitchRef.current,
|
||||||
onlyOffset: true,
|
onlyOffset: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (line.direction) {
|
||||||
|
case 'bottom':
|
||||||
|
direction = 'east'
|
||||||
|
break
|
||||||
|
case 'top':
|
||||||
|
direction = 'west'
|
||||||
|
break
|
||||||
|
case 'left':
|
||||||
|
direction = 'south'
|
||||||
|
break
|
||||||
|
case 'right':
|
||||||
|
direction = 'north'
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -716,6 +731,7 @@ export function useRoofShapeSetting(id) {
|
|||||||
type: LINE_TYPE.WALLLINE.SHED,
|
type: LINE_TYPE.WALLLINE.SHED,
|
||||||
pitch: shedPitchRef.current,
|
pitch: shedPitchRef.current,
|
||||||
width: shedWidth / 10,
|
width: shedWidth / 10,
|
||||||
|
offset: shedWidth / 10,
|
||||||
}
|
}
|
||||||
selectedLine.attributes = { ...attributes, isFixed: true }
|
selectedLine.attributes = { ...attributes, isFixed: true }
|
||||||
addPitchText(currentObject)
|
addPitchText(currentObject)
|
||||||
|
|||||||
@ -60,7 +60,7 @@ export function useWallLineOffsetSetting(id) {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||||
if (outerLines.length === 0) {
|
if (outerLines.length === 0) {
|
||||||
swalFire({ text: '외벽선이 없습니다.' })
|
swalFire({ text: getMessage('wall.line.not.found') })
|
||||||
closePopup(id)
|
closePopup(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { useMouse } from '@/hooks/useMouse'
|
|||||||
import { useLine } from '@/hooks/useLine'
|
import { useLine } from '@/hooks/useLine'
|
||||||
import { useTempGrid } from '@/hooks/useTempGrid'
|
import { useTempGrid } from '@/hooks/useTempGrid'
|
||||||
import { useEffect, useRef } from 'react'
|
import { useEffect, useRef } from 'react'
|
||||||
import { distanceBetweenPoints } from '@/util/canvas-util'
|
import { calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util'
|
||||||
import { fabric } from 'fabric'
|
import { fabric } from 'fabric'
|
||||||
import { calculateAngle } from '@/util/qpolygon-utils'
|
import { calculateAngle } from '@/util/qpolygon-utils'
|
||||||
import {
|
import {
|
||||||
@ -32,16 +32,18 @@ import {
|
|||||||
import { usePolygon } from '@/hooks/usePolygon'
|
import { usePolygon } from '@/hooks/usePolygon'
|
||||||
import { POLYGON_TYPE } from '@/common/common'
|
import { POLYGON_TYPE } from '@/common/common'
|
||||||
import { usePopup } from '@/hooks/usePopup'
|
import { usePopup } from '@/hooks/usePopup'
|
||||||
|
import { useSurfaceShapeBatch } from './useSurfaceShapeBatch'
|
||||||
|
|
||||||
import { roofDisplaySelector } from '@/store/settingAtom'
|
import { roofDisplaySelector } from '@/store/settingAtom'
|
||||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||||
import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
|
import PlacementSurfaceLineProperty from '@/components/floor-plan/modal/placementShape/PlacementSurfaceLineProperty'
|
||||||
|
import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint'
|
||||||
|
|
||||||
// 배치면 그리기
|
// 배치면 그리기
|
||||||
export function usePlacementShapeDrawing(id) {
|
export function usePlacementShapeDrawing(id) {
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||||
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
|
const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseLine } =
|
||||||
useEvent()
|
useEvent()
|
||||||
// const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
|
// const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } =
|
||||||
// useContext(EventContext)
|
// useContext(EventContext)
|
||||||
@ -50,6 +52,8 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
const { addPolygonByLines, drawDirectionArrow } = usePolygon()
|
const { addPolygonByLines, drawDirectionArrow } = usePolygon()
|
||||||
const { tempGridMode } = useTempGrid()
|
const { tempGridMode } = useTempGrid()
|
||||||
const { setSurfaceShapePattern } = useRoofFn()
|
const { setSurfaceShapePattern } = useRoofFn()
|
||||||
|
const { changeSurfaceLineType } = useSurfaceShapeBatch({})
|
||||||
|
|
||||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||||
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
|
||||||
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
|
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)
|
||||||
@ -115,6 +119,7 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
}, [type])
|
}, [type])
|
||||||
|
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
|
addCanvasMouseEventListener('mouse:move', mouseMove)
|
||||||
setLength1(0)
|
setLength1(0)
|
||||||
setLength2(0)
|
setLength2(0)
|
||||||
|
|
||||||
@ -170,6 +175,80 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
mouseMove
|
||||||
|
*/
|
||||||
|
const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||||
|
const roofAdsorptionPoints = useRef([])
|
||||||
|
const intersectionPoints = useRef([])
|
||||||
|
const { getAdsorptionPoints } = useAdsorptionPoint()
|
||||||
|
|
||||||
|
const mouseMove = (e) => {
|
||||||
|
removeMouseLine();
|
||||||
|
const pointer = canvas.getPointer(e.e)
|
||||||
|
const roofsPoints = roofs.map((roof) => roof.points).flat()
|
||||||
|
roofAdsorptionPoints.current = [...roofsPoints]
|
||||||
|
|
||||||
|
const auxiliaryLines = canvas.getObjects().filter((obj) => obj.name === 'auxiliaryLine' && !obj.isFixed)
|
||||||
|
const otherAdsorptionPoints = []
|
||||||
|
|
||||||
|
auxiliaryLines.forEach((line1) => {
|
||||||
|
auxiliaryLines.forEach((line2) => {
|
||||||
|
if (line1 === line2) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const intersectionPoint = calculateIntersection(line1, line2)
|
||||||
|
if (!intersectionPoint || intersectionPoints.current.some((point) => point.x === intersectionPoint.x && point.y === intersectionPoint.y)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
otherAdsorptionPoints.push(intersectionPoint)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
let innerLinePoints = []
|
||||||
|
canvas
|
||||||
|
.getObjects()
|
||||||
|
.filter((obj) => obj.innerLines)
|
||||||
|
.forEach((polygon) => {
|
||||||
|
polygon.innerLines.forEach((line) => {
|
||||||
|
innerLinePoints.push({ x: line.x1, y: line.y1 })
|
||||||
|
innerLinePoints.push({ x: line.x2, y: line.y2 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const adsorptionPoints = [
|
||||||
|
...getAdsorptionPoints(),
|
||||||
|
...roofAdsorptionPoints.current,
|
||||||
|
...otherAdsorptionPoints,
|
||||||
|
...intersectionPoints.current,
|
||||||
|
...innerLinePoints,
|
||||||
|
]
|
||||||
|
|
||||||
|
let arrivalPoint = { x: pointer.x, y: pointer.y }
|
||||||
|
let adsorptionPoint = findClosestPoint(pointer, adsorptionPoints)
|
||||||
|
|
||||||
|
if (adsorptionPoint && distanceBetweenPoints(pointer, adsorptionPoint) <= adsorptionRange) {
|
||||||
|
arrivalPoint = { ...adsorptionPoint }
|
||||||
|
}
|
||||||
|
const horizontalLine = new fabric.Line([-1 * canvas.width, arrivalPoint.y, 2 * canvas.width, arrivalPoint.y], {
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'mouseLine',
|
||||||
|
})
|
||||||
|
|
||||||
|
const verticalLine = new fabric.Line([arrivalPoint.x, -1 * canvas.height, arrivalPoint.x, 2 * canvas.height], {
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 1,
|
||||||
|
selectable: false,
|
||||||
|
name: 'mouseLine',
|
||||||
|
})
|
||||||
|
canvas?.add(horizontalLine, verticalLine)
|
||||||
|
canvas?.renderAll()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
canvas
|
canvas
|
||||||
?.getObjects()
|
?.getObjects()
|
||||||
@ -253,11 +332,14 @@ export function usePlacementShapeDrawing(id) {
|
|||||||
setPoints([])
|
setPoints([])
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
|
|
||||||
if (+canvasSetting?.roofSizeSet === 3) {
|
// if (+canvasSetting?.roofSizeSet === 3) {
|
||||||
closePopup(id)
|
// closePopup(id)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
addPopup(id, 1, <PlacementSurfaceLineProperty id={id} roof={roof} />, false)
|
// addPopup(id, 1, <PlacementSurfaceLineProperty id={id} roof={roof} />, false)
|
||||||
|
|
||||||
|
changeSurfaceLineType(roof)
|
||||||
|
closePopup(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (points.length < 3) {
|
if (points.length < 3) {
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||||
import { canvasSettingState, canvasState, currentCanvasPlanState, globalPitchState } from '@/store/canvasAtom'
|
import { canvasSettingState, canvasState, currentCanvasPlanState, globalPitchState } from '@/store/canvasAtom'
|
||||||
import { MENU, POLYGON_TYPE } from '@/common/common'
|
import { MENU, POLYGON_TYPE, LINE_TYPE } from '@/common/common'
|
||||||
import { getIntersectionPoint, toFixedWithoutRounding } from '@/util/canvas-util'
|
import { getIntersectionPoint, toFixedWithoutRounding } from '@/util/canvas-util'
|
||||||
import { degreesToRadians } from '@turf/turf'
|
import { degreesToRadians } from '@turf/turf'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
@ -111,7 +111,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
lockScalingX: true, // X 축 크기 조정 잠금
|
lockScalingX: true, // X 축 크기 조정 잠금
|
||||||
lockScalingY: true, // Y 축 크기 조정 잠금
|
lockScalingY: true, // Y 축 크기 조정 잠금
|
||||||
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
|
name: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH_TEMP,
|
||||||
flipX: xInversion !== yInversion,
|
// flipX: xInversion !== yInversion,
|
||||||
// angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
|
// angle: xInversion && yInversion ? Math.abs((rotate + 180) % 360) : Math.abs(rotate),
|
||||||
// angle: rotate,
|
// angle: rotate,
|
||||||
originX: 'center',
|
originX: 'center',
|
||||||
@ -120,6 +120,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
obj = new QPolygon(points, options)
|
obj = new QPolygon(points, options)
|
||||||
|
|
||||||
let imageRotate = 0
|
let imageRotate = 0
|
||||||
if (xInversion && !yInversion) {
|
if (xInversion && !yInversion) {
|
||||||
if (rotate % 180 === 0 || rotate < 0) {
|
if (rotate % 180 === 0 || rotate < 0) {
|
||||||
@ -148,7 +149,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
} else {
|
} else {
|
||||||
imageRotate = (rotate + 360) % 360
|
imageRotate = (rotate + 360) % 360
|
||||||
}
|
}
|
||||||
obj.set({ angle: imageRotate })
|
obj.set({ angle: imageRotate, flipX: xInversion !== yInversion })
|
||||||
obj.setCoords() //좌표 변경 적용
|
obj.setCoords() //좌표 변경 적용
|
||||||
|
|
||||||
canvas?.add(obj)
|
canvas?.add(obj)
|
||||||
@ -158,6 +159,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
addCanvasMouseEventListener('mouse:down', (e) => {
|
addCanvasMouseEventListener('mouse:down', (e) => {
|
||||||
isDrawing = false
|
isDrawing = false
|
||||||
|
|
||||||
|
const { xInversion, yInversion } = surfaceRefs
|
||||||
canvas?.remove(obj)
|
canvas?.remove(obj)
|
||||||
|
|
||||||
//각도 추가
|
//각도 추가
|
||||||
@ -178,6 +180,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//회전, flip등이 먹은 기준으로 새로생성
|
//회전, flip등이 먹은 기준으로 새로생성
|
||||||
|
// const batchSurface = addPolygon(reorderedPoints, {
|
||||||
const batchSurface = addPolygon(obj.getCurrentPoints(), {
|
const batchSurface = addPolygon(obj.getCurrentPoints(), {
|
||||||
fill: 'transparent',
|
fill: 'transparent',
|
||||||
stroke: 'red',
|
stroke: 'red',
|
||||||
@ -196,18 +199,25 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
pitch: globalPitch,
|
pitch: globalPitch,
|
||||||
surfaceId: surfaceId,
|
surfaceId: surfaceId,
|
||||||
direction: direction,
|
direction: direction,
|
||||||
|
isXInversion: xInversion,
|
||||||
|
isYInversion: yInversion,
|
||||||
})
|
})
|
||||||
canvas.setActiveObject(batchSurface)
|
canvas.setActiveObject(batchSurface)
|
||||||
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
setSurfaceShapePattern(batchSurface, roofDisplay.column)
|
||||||
drawDirectionArrow(batchSurface)
|
drawDirectionArrow(batchSurface)
|
||||||
|
|
||||||
// if (setIsHidden) setIsHidden(false)
|
|
||||||
|
|
||||||
// closePopup(id)
|
// closePopup(id)
|
||||||
initEvent()
|
initEvent()
|
||||||
if (+canvasSetting?.roofSizeSet === 3) return
|
// if (+canvasSetting?.roofSizeSet === 3) return
|
||||||
const popupId = uuidv4()
|
// const popupId = uuidv4()
|
||||||
addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
// addPopup(popupId, 2, <PlacementSurfaceLineProperty roof={batchSurface} id={popupId} setIsHidden={setIsHidden} />)
|
||||||
|
|
||||||
|
// console.log('xInversion', xInversion) //상하반전
|
||||||
|
// console.log('yInversion', yInversion) //좌우반전
|
||||||
|
|
||||||
|
changeSurfaceLineType(batchSurface)
|
||||||
|
|
||||||
|
if (setIsHidden) setIsHidden(false)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (setIsHidden) setIsHidden(false)
|
if (setIsHidden) setIsHidden(false)
|
||||||
@ -488,18 +498,18 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
case 10: {
|
case 10: {
|
||||||
points = [
|
points = [
|
||||||
{ x: pointer.x + length1 / 2, y: pointer.y + length4 / 2 },
|
|
||||||
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 },
|
|
||||||
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 - length5 },
|
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 - length5 },
|
||||||
{ x: pointer.x + length1 / 2 - length1 + length2, y: pointer.y + length4 / 2 - length5 },
|
{ x: pointer.x + length1 / 2 - length1, y: pointer.y + length4 / 2 },
|
||||||
{
|
{ x: pointer.x + length1 / 2, y: pointer.y + length4 / 2 },
|
||||||
x: pointer.x + length1 / 2 - length1 + length2,
|
|
||||||
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
x: pointer.x + length1 / 2 - length1 + length2 + length3,
|
x: pointer.x + length1 / 2 - length1 + length2 + length3,
|
||||||
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
x: pointer.x + length1 / 2 - length1 + length2,
|
||||||
|
y: pointer.y + length4 / 2 - length5 - (length4 - length5),
|
||||||
|
},
|
||||||
|
{ x: pointer.x + length1 / 2 - length1 + length2, y: pointer.y + length4 / 2 - length5 },
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -613,27 +623,27 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
}
|
}
|
||||||
case 14: {
|
case 14: {
|
||||||
points = [
|
points = [
|
||||||
{ x: pointer.x - length1 / 2 + length2, y: pointer.y + length4 / 2 },
|
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
|
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 - length4 },
|
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 - length4 },
|
||||||
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 },
|
{ x: pointer.x - length1 / 2, y: pointer.y + length4 / 2 },
|
||||||
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 + length4 },
|
{ x: pointer.x - length1 / 2 + length2, y: pointer.y + length4 / 2 },
|
||||||
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 + length4 },
|
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length2 + (length1 - length2 - length3) / 2,
|
x: pointer.x - length1 / 2 + length2 + (length1 - length2 - length3) / 2,
|
||||||
y: pointer.y + length4 / 2 - length4 + length5,
|
y: pointer.y + length4 / 2 - length4 + length5,
|
||||||
},
|
},
|
||||||
|
{ x: pointer.x - length1 / 2 + length1 - length3, y: pointer.y + length4 / 2 - length4 + length4 },
|
||||||
|
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 + length4 },
|
||||||
|
{ x: pointer.x - length1 / 2 + length1, y: pointer.y + length4 / 2 - length4 },
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case 15: {
|
case 15: {
|
||||||
points = [
|
points = [
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 },
|
|
||||||
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
||||||
{ x: pointer.x, y: pointer.y + length2 - length2 / 2 - length3 - (length2 - length3) },
|
{ x: pointer.x - length1 / 2, y: pointer.y + length2 - length2 / 2 },
|
||||||
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
|
||||||
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 + length3 },
|
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 + length3 },
|
||||||
|
{ x: pointer.x + length1 / 2, y: pointer.y + length2 - length2 / 2 - length3 },
|
||||||
|
{ x: pointer.x, y: pointer.y + length2 - length2 / 2 - length3 - (length2 - length3) },
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -641,28 +651,28 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
case 16: {
|
case 16: {
|
||||||
points = [
|
points = [
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
||||||
y: pointer.y + length3 / 2,
|
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4),
|
y: pointer.y + length3 / 2 - (length3 - length4),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2,
|
x: pointer.x - length1 / 2,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
y: pointer.y + length3 / 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
x: pointer.x - length1 / 2 + length1,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
y: pointer.y + length3 / 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
||||||
y: pointer.y + length3 / 2 - (length3 - length4) - length4 + length4,
|
y: pointer.y + length3 / 2 - (length3 - length4) - length4 + length4,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length1,
|
x: pointer.x - length1 / 2 + (length1 - length2) / 2 + length2,
|
||||||
y: pointer.y + length3 / 2,
|
y: pointer.y + length3 / 2 - (length3 - length4) - length4,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
@ -673,25 +683,25 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
const topL = (length1 - length2) / 2 / Math.cos((angle * Math.PI) / 180) // 꺽이는부분 윗쪽 길이
|
const topL = (length1 - length2) / 2 / Math.cos((angle * Math.PI) / 180) // 꺽이는부분 윗쪽 길이
|
||||||
|
|
||||||
points = [
|
points = [
|
||||||
{
|
|
||||||
x: pointer.x - length1 / 2 + length1,
|
|
||||||
y: pointer.y + length3 / 2,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2,
|
x: pointer.x - length1 / 2,
|
||||||
y: pointer.y + length3 / 2,
|
y: pointer.y + length3 / 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)),
|
x: pointer.x - length1 / 2 + length1,
|
||||||
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
y: pointer.y + length3 / 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2 + topL * Math.cos(degreesToRadians(angle)),
|
||||||
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)) + topL * Math.sin(degreesToRadians(angle)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2,
|
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2,
|
||||||
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)) + length2 + topL * Math.cos(degreesToRadians(angle)),
|
x: pointer.x - length1 / 2 + length4 * Math.cos(degreesToRadians(angle)),
|
||||||
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)) + topL * Math.sin(degreesToRadians(angle)),
|
y: pointer.y + length3 / 2 - length4 * Math.sin(degreesToRadians(angle)),
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
break
|
break
|
||||||
@ -1066,45 +1076,294 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateFlippedPoints = (polygon) => {
|
/**
|
||||||
if (!(polygon instanceof fabric.Polygon)) {
|
* 면형상 작도시 라인 속성 넣는 로직
|
||||||
console.error('The object is not a Polygon.')
|
* 폴리곤으로 보면 직선방향에 따라 아래쪽인지 윗쪽인지 판단이 가능하다고 생각하여
|
||||||
return
|
* south -> 밑면은 무조건 right direction이라 가정하고 작업함 좌우반전시 반대로 그려지는 경우도 생기지만 그럴땐 흐름방향에 따라 최대값(최소값)을 찾아
|
||||||
}
|
* 해당 하는 흐름에 맞게 변경함
|
||||||
|
* @param { } polygon
|
||||||
|
*/
|
||||||
|
|
||||||
const { flipX, flipY, width, height, points, left, top, scaleX, scaleY } = polygon
|
//폴리곤, 상하반전, 좌우반전
|
||||||
|
const changeSurfaceLineType = (polygon) => {
|
||||||
|
const { isXInversion, isYInversion } = polygon //상하반전, 좌우반전
|
||||||
|
|
||||||
// 현재 points의 사본 가져오기
|
polygon.lines.forEach((line) => {
|
||||||
const newPoints = points.map((point) => {
|
line.attributes.type = LINE_TYPE.WALLLINE.GABLE
|
||||||
let x = point.x
|
|
||||||
let y = point.y
|
|
||||||
|
|
||||||
// flipX 적용
|
|
||||||
if (flipX) {
|
|
||||||
x = width - x
|
|
||||||
}
|
|
||||||
|
|
||||||
// flipY 적용
|
|
||||||
if (flipY) {
|
|
||||||
y = height - y
|
|
||||||
}
|
|
||||||
|
|
||||||
// 스케일 및 전역 좌표 고려
|
|
||||||
x = (x - width / 2) * scaleX + width / 2
|
|
||||||
y = (y - height / 2) * scaleY + height / 2
|
|
||||||
|
|
||||||
return { x, y }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// flipX, flipY를 초기화
|
const directionConfig = {
|
||||||
polygon.flipX = false
|
south: { evaesDirection: 'right', ridgeDirection: 'left', coord1: 'y1', coord2: 'y2' },
|
||||||
polygon.flipY = false
|
north: { evaesDirection: 'left', ridgeDirection: 'right', coord1: 'y1', coord2: 'y2' },
|
||||||
|
east: { evaesDirection: 'top', ridgeDirection: 'bottom', coord1: 'x1', coord2: 'x2' },
|
||||||
|
west: { evaesDirection: 'bottom', ridgeDirection: 'top', coord1: 'x1', coord2: 'x2' },
|
||||||
|
}
|
||||||
|
|
||||||
// points 업데이트
|
const { evaesDirection, ridgeDirection, coord1, coord2 } = directionConfig[polygon.direction] || directionConfig.west
|
||||||
polygon.set({ points: newPoints })
|
|
||||||
polygon.setCoords()
|
|
||||||
|
|
||||||
return polygon
|
polygon.lines.forEach((line) => {
|
||||||
|
if (line[coord1] === line[coord2]) {
|
||||||
|
if (line.direction === evaesDirection) {
|
||||||
|
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
|
} else if (line.direction === ridgeDirection) {
|
||||||
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 진짜 처마 라인인지 확인하는 로직 -> 특정 모양에 따라 처마가 없는 경우가 있는데 위에 로직으로는
|
||||||
|
* 용마루도 처마로 만들어서 재보정
|
||||||
|
*/
|
||||||
|
//직선 찾는 로직
|
||||||
|
const maxLine = polygon.lines.filter((line) => line[coord1] === line[coord2])
|
||||||
|
|
||||||
|
if (maxLine.length > 0) {
|
||||||
|
const maxLineSorted = maxLine.reduce((a, b) => {
|
||||||
|
return (polygon.direction === 'south' || polygon.direction === 'east' ? b : a)[coord1] >
|
||||||
|
(polygon.direction === 'south' || polygon.direction === 'east' ? a : b)[coord1]
|
||||||
|
? b
|
||||||
|
: a
|
||||||
|
})
|
||||||
|
|
||||||
|
//정렬된 폴리곤이 아니면(대각선이 존재하는 폴리곤일때)
|
||||||
|
if (!polygon.isSortedPoints) {
|
||||||
|
//좌우 반전을 했으면 반대로 정의함
|
||||||
|
if (isYInversion || isXInversion) {
|
||||||
|
polygon.lines.forEach((line) => {
|
||||||
|
if (line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||||
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
} else if (line.attributes.type === LINE_TYPE.SUBLINE.RIDGE) {
|
||||||
|
line.attributes.type = LINE_TYPE.WALLLINE.EAVES
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxLine.length === 1) {
|
||||||
|
const maxLineCoord = polygon.lines.reduce((a, b) => {
|
||||||
|
return (polygon.direction === 'south' || polygon.direction === 'east' ? b : a)[coord1] >
|
||||||
|
(polygon.direction === 'south' || polygon.direction === 'east' ? a : b)[coord1]
|
||||||
|
? b
|
||||||
|
: a
|
||||||
|
})
|
||||||
|
|
||||||
|
const isRealEavesLine = polygon.lines.filter((line) => line.attributes.type === LINE_TYPE.WALLLINE.EAVES)
|
||||||
|
if (isRealEavesLine.length > 0) {
|
||||||
|
isRealEavesLine.forEach((line) => {
|
||||||
|
if (polygon.direction === 'south' || polygon.direction === 'north') {
|
||||||
|
const targetCoord =
|
||||||
|
polygon.direction === 'south' ? Math.max(maxLineCoord.y1, maxLineCoord.y2) : Math.min(maxLineCoord.y1, maxLineCoord.y2)
|
||||||
|
const realLineCoord = polygon.direction === 'south' ? Math.max(line.y1, line.y2) : Math.min(line.y1, line.y2)
|
||||||
|
|
||||||
|
if (targetCoord !== realLineCoord) {
|
||||||
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
}
|
||||||
|
} else if (polygon.direction === 'east' || polygon.direction === 'west') {
|
||||||
|
const targetCoord =
|
||||||
|
polygon.direction === 'east' ? Math.max(maxLineCoord.x1, maxLineCoord.x2) : Math.min(maxLineCoord.x1, maxLineCoord.x2)
|
||||||
|
const realLineCoord = polygon.direction === 'east' ? Math.max(line.x1, line.x2) : Math.min(line.x1, line.x2)
|
||||||
|
|
||||||
|
if (targetCoord !== realLineCoord) {
|
||||||
|
line.attributes.type = LINE_TYPE.SUBLINE.RIDGE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function findCentroid(points) {
|
||||||
|
let sumX = 0,
|
||||||
|
sumY = 0
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
sumX += points[i].x
|
||||||
|
sumY += points[i].y
|
||||||
|
}
|
||||||
|
return { x: sumX / points.length, y: sumY / points.length }
|
||||||
|
}
|
||||||
|
|
||||||
|
// 도형의 포인트를 왼쪽부터 반시계 방향으로 정렬하는 함수
|
||||||
|
/**
|
||||||
|
* 다각형의 점들을 시계 반대 방향으로 정렬하는 함수
|
||||||
|
* @param {Array} points - {x, y} 좌표 객체 배열
|
||||||
|
* @param {Object} startPoint - 시작점 (제공되지 않으면 가장 왼쪽 아래 점을 사용)
|
||||||
|
* @returns {Array} 시계 반대 방향으로 정렬된 점들의 배열
|
||||||
|
*/
|
||||||
|
function orderPointsCounterClockwise(points, startPoint = null) {
|
||||||
|
if (points.length <= 3) {
|
||||||
|
return points // 점이 3개 이하면 이미 다각형의 모든 점이므로 그대로 반환
|
||||||
|
}
|
||||||
|
|
||||||
|
// 시작점이 제공되지 않았다면 가장 왼쪽 아래 점을 찾음
|
||||||
|
let start = startPoint
|
||||||
|
if (!start) {
|
||||||
|
start = points[0]
|
||||||
|
for (let i = 1; i < points.length; i++) {
|
||||||
|
if (points[i].x < start.x || (points[i].x === start.x && points[i].y < start.y)) {
|
||||||
|
start = points[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 다각형의 중심점 계산
|
||||||
|
let centerX = 0,
|
||||||
|
centerY = 0
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
centerX += points[i].x
|
||||||
|
centerY += points[i].y
|
||||||
|
}
|
||||||
|
centerX /= points.length
|
||||||
|
centerY /= points.length
|
||||||
|
|
||||||
|
// 시작점에서 시계 반대 방향으로 각도 계산
|
||||||
|
let angles = []
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
// 시작점은 제외
|
||||||
|
if (points[i] === start) continue
|
||||||
|
|
||||||
|
// 시작점을 기준으로 각 점의 각도 계산
|
||||||
|
let angle = Math.atan2(points[i].y - start.y, points[i].x - start.x)
|
||||||
|
|
||||||
|
// 각도가 음수면 2π를 더해 0~2π 범위로 변환
|
||||||
|
if (angle < 0) angle += 2 * Math.PI
|
||||||
|
|
||||||
|
angles.push({
|
||||||
|
point: points[i],
|
||||||
|
angle: angle,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 각도에 따라 정렬 (시계 반대 방향)
|
||||||
|
angles.sort((a, b) => a.angle - b.angle)
|
||||||
|
|
||||||
|
// 정렬된 배열 생성 (시작점을 첫 번째로)
|
||||||
|
let orderedPoints = [start]
|
||||||
|
for (let i = 0; i < angles.length; i++) {
|
||||||
|
orderedPoints.push(angles[i].point)
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedPoints
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 특정 점에서 시작하여 시계 반대 방향으로 다음 점을 찾는 함수
|
||||||
|
* @param {Object} currentPoint - 현재 점 {x, y}
|
||||||
|
* @param {Array} points - 모든 점들의 배열
|
||||||
|
* @param {Array} visited - 방문한 점들의 인덱스 배열
|
||||||
|
* @param {Object} prevVector - 이전 벡터 방향 (첫 호출에서는 null)
|
||||||
|
* @returns {Object} 다음 점의 인덱스와 객체
|
||||||
|
*/
|
||||||
|
function findNextCounterClockwisePoint(currentPoint, points, visited, prevVector = null) {
|
||||||
|
let minAngle = Infinity
|
||||||
|
let nextIndex = -1
|
||||||
|
|
||||||
|
// 이전 벡터가 없으면 (첫 점인 경우) 아래쪽을 향하는 벡터 사용
|
||||||
|
if (!prevVector) {
|
||||||
|
prevVector = { x: 0, y: -1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
// 이미 방문했거나 현재 점이면 건너뜀
|
||||||
|
if (visited.includes(i) || (points[i].x === currentPoint.x && points[i].y === currentPoint.y)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 현재 점에서 다음 후보 점으로의 벡터
|
||||||
|
let vector = {
|
||||||
|
x: points[i].x - currentPoint.x,
|
||||||
|
y: points[i].y - currentPoint.y,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 벡터의 크기
|
||||||
|
let magnitude = Math.sqrt(vector.x * vector.x + vector.y * vector.y)
|
||||||
|
|
||||||
|
// 단위 벡터로 정규화
|
||||||
|
vector.x /= magnitude
|
||||||
|
vector.y /= magnitude
|
||||||
|
|
||||||
|
// 이전 벡터와 현재 벡터 사이의 각도 계산 (내적 사용)
|
||||||
|
let dotProduct = prevVector.x * vector.x + prevVector.y * vector.y
|
||||||
|
let crossProduct = prevVector.x * vector.y - prevVector.y * vector.x
|
||||||
|
|
||||||
|
// 각도 계산 (atan2 사용)
|
||||||
|
let angle = Math.atan2(crossProduct, dotProduct)
|
||||||
|
|
||||||
|
// 시계 반대 방향으로 가장 작은 각도를 가진 점 찾기
|
||||||
|
// 각도가 음수면 2π를 더해 0~2π 범위로 변환
|
||||||
|
if (angle < 0) angle += 2 * Math.PI
|
||||||
|
|
||||||
|
if (angle < minAngle) {
|
||||||
|
minAngle = angle
|
||||||
|
nextIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nextIndex !== -1 ? { index: nextIndex, point: points[nextIndex] } : null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 다각형의 점들을 시계 반대 방향으로 추적하는 함수
|
||||||
|
* @param {Array} points - {x, y} 좌표 객체 배열
|
||||||
|
* @param {Object} startPoint - 시작점 (제공되지 않으면 가장 왼쪽 아래 점을 사용)
|
||||||
|
* @returns {Array} 시계 반대 방향으로 정렬된 점들의 배열
|
||||||
|
*/
|
||||||
|
function tracePolygonCounterClockwise(points, startPoint = null) {
|
||||||
|
if (points.length <= 3) {
|
||||||
|
return orderPointsCounterClockwise(points, startPoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 시작점이 제공되지 않았다면 가장 왼쪽 아래 점을 찾음
|
||||||
|
let startIndex = 0
|
||||||
|
if (!startPoint) {
|
||||||
|
for (let i = 1; i < points.length; i++) {
|
||||||
|
if (points[i].x < points[startIndex].x || (points[i].x === points[startIndex].x && points[i].y < points[startIndex].y)) {
|
||||||
|
startIndex = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startPoint = points[startIndex]
|
||||||
|
} else {
|
||||||
|
// 시작점이 제공된 경우 해당 점의 인덱스 찾기
|
||||||
|
for (let i = 0; i < points.length; i++) {
|
||||||
|
if (points[i].x === startPoint.x && points[i].y === startPoint.y) {
|
||||||
|
startIndex = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 결과 배열 초기화
|
||||||
|
let orderedPoints = [startPoint]
|
||||||
|
let visited = [startIndex]
|
||||||
|
|
||||||
|
let currentPoint = startPoint
|
||||||
|
let prevVector = null
|
||||||
|
|
||||||
|
// 모든 점을 방문할 때까지 반복
|
||||||
|
while (visited.length < points.length) {
|
||||||
|
let next = findNextCounterClockwisePoint(currentPoint, points, visited, prevVector)
|
||||||
|
|
||||||
|
if (!next) break // 더 이상 찾을 점이 없으면 종료
|
||||||
|
|
||||||
|
orderedPoints.push(next.point)
|
||||||
|
visited.push(next.index)
|
||||||
|
|
||||||
|
// 이전 벡터 업데이트 (현재 점에서 다음 점으로의 벡터)
|
||||||
|
prevVector = {
|
||||||
|
x: next.point.x - currentPoint.x,
|
||||||
|
y: next.point.y - currentPoint.y,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 벡터 정규화
|
||||||
|
let magnitude = Math.sqrt(prevVector.x * prevVector.x + prevVector.y * prevVector.y)
|
||||||
|
prevVector.x /= magnitude
|
||||||
|
prevVector.y /= magnitude
|
||||||
|
|
||||||
|
currentPoint = next.point
|
||||||
|
}
|
||||||
|
|
||||||
|
return orderedPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -1115,5 +1374,6 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
|||||||
changeSurfaceLinePropertyEvent,
|
changeSurfaceLinePropertyEvent,
|
||||||
changeSurfaceLineProperty,
|
changeSurfaceLineProperty,
|
||||||
changeSurfaceLinePropertyReset,
|
changeSurfaceLinePropertyReset,
|
||||||
|
changeSurfaceLineType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,10 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import { canvasSizeState, canvasState, canvasZoomState, currentObjectState } from '@/store/canvasAtom'
|
import { canvasSizeState, canvasState, canvasZoomState, currentMenuState, currentObjectState } from '@/store/canvasAtom'
|
||||||
import { QPolygon } from '@/components/fabric/QPolygon'
|
import { QPolygon } from '@/components/fabric/QPolygon'
|
||||||
import { fontSelector } from '@/store/fontAtom'
|
import { fontSelector } from '@/store/fontAtom'
|
||||||
|
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||||
|
|
||||||
// 캔버스에 필요한 이벤트
|
// 캔버스에 필요한 이벤트
|
||||||
export function useCanvasEvent() {
|
export function useCanvasEvent() {
|
||||||
@ -13,11 +14,16 @@ export function useCanvasEvent() {
|
|||||||
const canvasSize = useRecoilValue(canvasSizeState)
|
const canvasSize = useRecoilValue(canvasSizeState)
|
||||||
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
|
||||||
const lengthTextOption = useRecoilValue(fontSelector('lengthText'))
|
const lengthTextOption = useRecoilValue(fontSelector('lengthText'))
|
||||||
|
const currentMenu = useRecoilValue(currentMenuState)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
canvas?.setZoom(canvasZoom / 100)
|
canvas?.setZoom(canvasZoom / 100)
|
||||||
}, [canvasZoom])
|
}, [canvasZoom])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
attachDefaultEventOnCanvas()
|
||||||
|
}, [currentMenu])
|
||||||
|
|
||||||
// 기본적인 이벤트 필요시 추가
|
// 기본적인 이벤트 필요시 추가
|
||||||
const attachDefaultEventOnCanvas = () => {
|
const attachDefaultEventOnCanvas = () => {
|
||||||
removeEventOnCanvas()
|
removeEventOnCanvas()
|
||||||
@ -198,8 +204,20 @@ export function useCanvasEvent() {
|
|||||||
|
|
||||||
if (selected?.length > 0) {
|
if (selected?.length > 0) {
|
||||||
selected.forEach((obj) => {
|
selected.forEach((obj) => {
|
||||||
if (obj.type === 'QPolygon' && obj.name !== 'module') {
|
// if (obj.type === 'QPolygon' && currentMenu !== MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING) {
|
||||||
|
if (obj.type === 'QPolygon') {
|
||||||
|
const originStroke = obj.stroke
|
||||||
obj.set({ stroke: 'red' })
|
obj.set({ stroke: 'red' })
|
||||||
|
|
||||||
|
if (currentMenu === MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING) {
|
||||||
|
if (obj.name === POLYGON_TYPE.MODULE) {
|
||||||
|
obj.set({ strokeWidth: 3 })
|
||||||
|
}
|
||||||
|
if (obj.name === POLYGON_TYPE.ROOF) {
|
||||||
|
canvas.discardActiveObject()
|
||||||
|
obj.set({ stroke: originStroke })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
@ -215,6 +233,9 @@ export function useCanvasEvent() {
|
|||||||
if (obj.name !== 'moduleSetupSurface') {
|
if (obj.name !== 'moduleSetupSurface') {
|
||||||
obj.set({ stroke: 'black' })
|
obj.set({ stroke: 'black' })
|
||||||
}
|
}
|
||||||
|
if (obj.name === POLYGON_TYPE.MODULE && currentMenu === MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING) {
|
||||||
|
obj.set({ strokeWidth: 0.3 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -229,14 +250,22 @@ export function useCanvasEvent() {
|
|||||||
deselected.forEach((obj) => {
|
deselected.forEach((obj) => {
|
||||||
if (obj.type === 'QPolygon') {
|
if (obj.type === 'QPolygon') {
|
||||||
obj.set({ stroke: 'black' })
|
obj.set({ stroke: 'black' })
|
||||||
|
if (obj.name === POLYGON_TYPE.MODULE && currentMenu === MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING) {
|
||||||
|
//모듈 미선택시 라인 두께 변경
|
||||||
|
obj.set({ strokeWidth: 0.3 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selected?.length > 0) {
|
if (selected?.length > 0) {
|
||||||
selected.forEach((obj) => {
|
selected.forEach((obj) => {
|
||||||
if (obj.type === 'QPolygon' && obj.name !== 'module') {
|
if (obj.type === 'QPolygon') {
|
||||||
obj.set({ stroke: 'red' })
|
obj.set({ stroke: 'red' })
|
||||||
|
if (obj.name === POLYGON_TYPE.MODULE && currentMenu === MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING) {
|
||||||
|
//모듈 선택시 라인 두께 변경
|
||||||
|
obj.set({ strokeWidth: 3 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,14 +24,14 @@ export function useCircuitTrestle(executeEffect = false) {
|
|||||||
const [selectedModels, setSelectedModels] = useRecoilState(selectedModelsState)
|
const [selectedModels, setSelectedModels] = useRecoilState(selectedModelsState)
|
||||||
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
||||||
const selectedModules = useRecoilValue(selectedModuleState)
|
const selectedModules = useRecoilValue(selectedModuleState)
|
||||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
const { managementState } = useContext(GlobalDataContext)
|
||||||
const canvas = useRecoilValue(canvasState)
|
const canvas = useRecoilValue(canvasState)
|
||||||
const setModuleStatistics = useSetRecoilState(moduleStatisticsState)
|
const setModuleStatistics = useSetRecoilState(moduleStatisticsState)
|
||||||
const resetModuleStatistics = useResetRecoilState(moduleStatisticsState)
|
const resetModuleStatistics = useResetRecoilState(moduleStatisticsState)
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Object.keys(selectedModules).length > 0 && executeEffect) setModuleStatisticsData()
|
if (selectedModules && Object.keys(selectedModules).length > 0 && executeEffect) setModuleStatisticsData()
|
||||||
}, [selectedModules])
|
}, [selectedModules])
|
||||||
|
|
||||||
const getOptYn = () => {
|
const getOptYn = () => {
|
||||||
|
|||||||
@ -81,9 +81,9 @@ export function useContextMenu() {
|
|||||||
switch (selectedMenu) {
|
switch (selectedMenu) {
|
||||||
case 'outline':
|
case 'outline':
|
||||||
break
|
break
|
||||||
default:
|
// default:
|
||||||
setContextMenu([])
|
// setContextMenu([])
|
||||||
break
|
// break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { useTrestle } from '@/hooks/module/useTrestle'
|
|||||||
import { usePlan } from '@/hooks/usePlan'
|
import { usePlan } from '@/hooks/usePlan'
|
||||||
|
|
||||||
export function useEstimate() {
|
export function useEstimate() {
|
||||||
const { managementStateLoaded } = useContext(GlobalDataContext)
|
const { managementState } = useContext(GlobalDataContext)
|
||||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const loginUserState = useRecoilValue(loginUserStore)
|
const loginUserState = useRecoilValue(loginUserStore)
|
||||||
@ -31,16 +31,18 @@ export function useEstimate() {
|
|||||||
* @param {Object} estimateParam - 견적서 저장 데이터
|
* @param {Object} estimateParam - 견적서 저장 데이터
|
||||||
*/
|
*/
|
||||||
const saveEstimate = async (estimateParam) => {
|
const saveEstimate = async (estimateParam) => {
|
||||||
|
console.log('managementState', managementState)
|
||||||
|
|
||||||
const userId = loginUserState.userId
|
const userId = loginUserState.userId
|
||||||
const saleStoreId = managementStateLoaded.saleStoreId
|
const saleStoreId = managementState.saleStoreId
|
||||||
const objectNo = currentCanvasPlan.objectNo
|
const objectNo = currentCanvasPlan.objectNo
|
||||||
const planNo = currentCanvasPlan.planNo
|
const planNo = currentCanvasPlan.planNo
|
||||||
const slope = estimateParam.roofSurfaceList[0].slope
|
const slope = estimateParam.roofSurfaceList[0].slope
|
||||||
const angle = estimateParam.roofSurfaceList[0].angle
|
const angle = estimateParam.roofSurfaceList[0].angle
|
||||||
const surfaceType = managementStateLoaded.surfaceType
|
const surfaceType = managementState.surfaceType
|
||||||
const setupHeight = managementStateLoaded.installHeight
|
const setupHeight = managementState.installHeight
|
||||||
const standardWindSpeedId = managementStateLoaded.standardWindSpeedId
|
const standardWindSpeedId = managementState.standardWindSpeedId
|
||||||
const snowfall = managementStateLoaded.verticalSnowCover
|
const snowfall = managementState.verticalSnowCover
|
||||||
const drawingFlg = '1'
|
const drawingFlg = '1'
|
||||||
|
|
||||||
const saveEstimateData = {
|
const saveEstimateData = {
|
||||||
|
|||||||
@ -77,7 +77,10 @@ export function useEvent() {
|
|||||||
setCanvasZoom(Number((zoom * 100).toFixed(0)))
|
setCanvasZoom(Number((zoom * 100).toFixed(0)))
|
||||||
|
|
||||||
// 마우스 위치 기준으로 확대/축소
|
// 마우스 위치 기준으로 확대/축소
|
||||||
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom)
|
canvas.zoomToPoint(new fabric.Point(opt.e.offsetX, opt.e.offsetY), zoom)
|
||||||
|
canvas.calcOffset()
|
||||||
|
canvas.setViewportTransform(canvas.viewportTransform)
|
||||||
|
canvas.requestRenderAll()
|
||||||
|
|
||||||
// 이벤트의 기본 동작 방지 (스크롤 방지)
|
// 이벤트의 기본 동작 방지 (스크롤 방지)
|
||||||
opt.e.preventDefault()
|
opt.e.preventDefault()
|
||||||
@ -104,6 +107,10 @@ export function useEvent() {
|
|||||||
const horizonLines = canvas.getObjects().filter((obj) => obj.name === 'lineGrid' && obj.direction === 'horizontal')
|
const horizonLines = canvas.getObjects().filter((obj) => obj.name === 'lineGrid' && obj.direction === 'horizontal')
|
||||||
const verticalLines = canvas.getObjects().filter((obj) => obj.name === 'lineGrid' && obj.direction === 'vertical')
|
const verticalLines = canvas.getObjects().filter((obj) => obj.name === 'lineGrid' && obj.direction === 'vertical')
|
||||||
|
|
||||||
|
if (!horizonLines || !verticalLines) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const closestHorizontalLine = horizonLines.reduce((prev, curr) => {
|
const closestHorizontalLine = horizonLines.reduce((prev, curr) => {
|
||||||
const prevDistance = calculateDistance(pointer, prev)
|
const prevDistance = calculateDistance(pointer, prev)
|
||||||
const currDistance = calculateDistance(pointer, curr)
|
const currDistance = calculateDistance(pointer, curr)
|
||||||
|
|||||||
@ -53,8 +53,8 @@ export const useLine = () => {
|
|||||||
})
|
})
|
||||||
canvas
|
canvas
|
||||||
?.getObjects()
|
?.getObjects()
|
||||||
.find((obj) => obj.parentId === line.id)
|
?.find((obj) => obj.parentId === line.id)
|
||||||
.set({
|
?.set({
|
||||||
visible: true,
|
visible: true,
|
||||||
})
|
})
|
||||||
canvas?.renderAll()
|
canvas?.renderAll()
|
||||||
|
|||||||
@ -20,6 +20,8 @@ import { compasDegAtom } from '@/store/orientationAtom'
|
|||||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||||
import { useCanvasPopupStatusController } from './common/useCanvasPopupStatusController'
|
import { useCanvasPopupStatusController } from './common/useCanvasPopupStatusController'
|
||||||
import { useCanvasMenu } from './common/useCanvasMenu'
|
import { useCanvasMenu } from './common/useCanvasMenu'
|
||||||
|
import { QcastContext } from '@/app/QcastProvider'
|
||||||
|
import { unescapeString } from '@/util/common-utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 플랜 처리 훅
|
* 플랜 처리 훅
|
||||||
@ -52,6 +54,9 @@ export function usePlan(params = {}) {
|
|||||||
const { fetchBasicSettings, basicSettingCopySave } = useCanvasSetting()
|
const { fetchBasicSettings, basicSettingCopySave } = useCanvasSetting()
|
||||||
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
|
||||||
|
|
||||||
|
/** 전역 로딩바 컨텍스트 */
|
||||||
|
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 플랜 복사 시 모듈이 있을경우 모듈 데이터 복사하기 위한 처리
|
* 플랜 복사 시 모듈이 있을경우 모듈 데이터 복사하기 위한 처리
|
||||||
*/
|
*/
|
||||||
@ -260,7 +265,7 @@ export function usePlan(params = {}) {
|
|||||||
objectNo,
|
objectNo,
|
||||||
planNo: parseInt(newPlan.planNo),
|
planNo: parseInt(newPlan.planNo),
|
||||||
popupType: 1,
|
popupType: 1,
|
||||||
popupStatus: sourceDegree.popupStatus,
|
popupStatus: unescapeString(sourceDegree.popupStatus),
|
||||||
}
|
}
|
||||||
console.log('🚀 ~ postObjectPlan ~ degreeData:', degreeData)
|
console.log('🚀 ~ postObjectPlan ~ degreeData:', degreeData)
|
||||||
await post({ url: `/api/v1/canvas-popup-status`, data: degreeData })
|
await post({ url: `/api/v1/canvas-popup-status`, data: degreeData })
|
||||||
@ -402,19 +407,28 @@ export function usePlan(params = {}) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if (!currentCanvasPlan || currentCanvasPlan.id !== newCurrentId) {
|
swalFire({
|
||||||
await saveCanvas(true)
|
text: getMessage('plan.message.confirm.save'),
|
||||||
clearRecoilState()
|
type: 'confirm',
|
||||||
}
|
confirmFn: async () => {
|
||||||
setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
|
//저장 전에 플랜이 이동되어 state가 변경되는 이슈가 있음
|
||||||
setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
|
await saveCanvas(true)
|
||||||
|
clearRecoilState()
|
||||||
|
setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
|
||||||
|
setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
|
||||||
|
},
|
||||||
|
denyFn: async () => {
|
||||||
|
setCurrentCanvasPlan(plans.find((plan) => plan.id === newCurrentId))
|
||||||
|
setPlans((plans) => plans.map((plan) => ({ ...plan, isCurrent: plan.id === newCurrentId })))
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedPlan(currentCanvasPlan)
|
setSelectedPlan(currentCanvasPlan)
|
||||||
handleCurrentPlanUrl()
|
handleCurrentPlanUrl()
|
||||||
resetCurrentObject()
|
// resetCurrentObject()
|
||||||
resetModuleSetupSurface()
|
resetModuleSetupSurface()
|
||||||
}, [currentCanvasPlan])
|
}, [currentCanvasPlan])
|
||||||
|
|
||||||
@ -442,23 +456,46 @@ export function usePlan(params = {}) {
|
|||||||
* @param {string} objectNo - 물건번호
|
* @param {string} objectNo - 물건번호
|
||||||
*/
|
*/
|
||||||
const handleAddPlan = async (userId, objectNo) => {
|
const handleAddPlan = async (userId, objectNo) => {
|
||||||
|
let isSelected = false
|
||||||
|
|
||||||
if (currentCanvasPlan?.id) {
|
if (currentCanvasPlan?.id) {
|
||||||
await saveCanvas(false)
|
swalFire({
|
||||||
|
text: getMessage('plan.message.confirm.save'),
|
||||||
|
type: 'confirm',
|
||||||
|
confirmFn: async () => {
|
||||||
|
//저장 전에 플랜이 이동되어 state가 변경되는 이슈가 있음
|
||||||
|
await saveCanvas(true)
|
||||||
|
handleAddPlanCopyConfirm(userId, objectNo)
|
||||||
|
},
|
||||||
|
denyFn: async () => {
|
||||||
|
handleAddPlanCopyConfirm(userId, objectNo)
|
||||||
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
JSON.parse(currentCanvasData()).objects.length > 0
|
|
||||||
? swalFire({
|
|
||||||
text: `Plan ${currentCanvasPlan.planNo} ` + getMessage('plan.message.confirm.copy'),
|
|
||||||
type: 'confirm',
|
|
||||||
confirmFn: async () => {
|
|
||||||
await postObjectPlan(userId, objectNo, true, false)
|
|
||||||
},
|
|
||||||
denyFn: async () => {
|
|
||||||
await postObjectPlan(userId, objectNo, false, false)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
: await postObjectPlan(userId, objectNo, false, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleAddPlanCopyConfirm = async (userId, objectNo) => {
|
||||||
|
if (JSON.parse(currentCanvasData()).objects.length > 0) {
|
||||||
|
swalFire({
|
||||||
|
text: `Plan ${currentCanvasPlan.planNo} ` + getMessage('plan.message.confirm.copy'),
|
||||||
|
type: 'confirm',
|
||||||
|
confirmFn: async () => {
|
||||||
|
setIsGlobalLoading(true)
|
||||||
|
await postObjectPlan(userId, objectNo, true, false)
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
},
|
||||||
|
denyFn: async () => {
|
||||||
|
setIsGlobalLoading(true)
|
||||||
|
await postObjectPlan(userId, objectNo, false, false)
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
setIsGlobalLoading(true)
|
||||||
|
await postObjectPlan(userId, objectNo, false, false)
|
||||||
|
setIsGlobalLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* 물건번호(object) plan 삭제 (canvas 삭제 전 planNo 삭제)
|
* 물건번호(object) plan 삭제 (canvas 삭제 전 planNo 삭제)
|
||||||
*
|
*
|
||||||
|
|||||||
@ -176,6 +176,10 @@ export const usePolygon = () => {
|
|||||||
* @param showDirectionText
|
* @param showDirectionText
|
||||||
*/
|
*/
|
||||||
const drawDirectionArrow = (polygon, showDirectionText = true) => {
|
const drawDirectionArrow = (polygon, showDirectionText = true) => {
|
||||||
|
if (!polygon) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (polygon.points.length < 3) {
|
if (polygon.points.length < 3) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -767,7 +771,7 @@ export const usePolygon = () => {
|
|||||||
obj.type === 'QLine' &&
|
obj.type === 'QLine' &&
|
||||||
obj.attributes?.type !== 'pitchSizeLine' &&
|
obj.attributes?.type !== 'pitchSizeLine' &&
|
||||||
obj.attributes?.roofId === polygon.id &&
|
obj.attributes?.roofId === polygon.id &&
|
||||||
(innerLineTypes.includes(obj.name) || !obj.name),
|
innerLineTypes.includes(obj.name),
|
||||||
)
|
)
|
||||||
|
|
||||||
innerLines = [...polygon.innerLines]
|
innerLines = [...polygon.innerLines]
|
||||||
|
|||||||
@ -48,6 +48,7 @@ export async function setSession(data) {
|
|||||||
session.pwdInitYn = data.pwdInitYn
|
session.pwdInitYn = data.pwdInitYn
|
||||||
session.custCd = data.custCd
|
session.custCd = data.custCd
|
||||||
session.isLoggedIn = true
|
session.isLoggedIn = true
|
||||||
|
session.builderNo = data.builderNo
|
||||||
|
|
||||||
await session.save()
|
await session.save()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"welcome": "ようこそ。 {0}さん",
|
"welcome": "ようこそ。 {0}さん",
|
||||||
"header.menus.home": "ホーム",
|
"header.menus.home": "ホーム",
|
||||||
"header.menus.management": "見積書管理画面",
|
"header.menus.management": "見積書管理画面",
|
||||||
"header.menus.management.newStuff": "新規見積登録",
|
"header.menus.management.newStuff": "新規物件登録",
|
||||||
"header.menus.management.detail": "物件詳細",
|
"header.menus.management.detail": "物件詳細",
|
||||||
"header.menus.management.stuffList": "物件検索",
|
"header.menus.management.stuffList": "物件検索",
|
||||||
"header.menus.community": "コミュニティ",
|
"header.menus.community": "コミュニティ",
|
||||||
@ -18,6 +18,7 @@
|
|||||||
"plan.menu.placement.surface.initial.setting": "配置面初期設定",
|
"plan.menu.placement.surface.initial.setting": "配置面初期設定",
|
||||||
"modal.placement.initial.setting.plan.drawing": "図面の作成方法",
|
"modal.placement.initial.setting.plan.drawing": "図面の作成方法",
|
||||||
"modal.placement.initial.setting.plan.drawing.size.stuff": "寸法入力による物件作成",
|
"modal.placement.initial.setting.plan.drawing.size.stuff": "寸法入力による物件作成",
|
||||||
|
"modal.placement.initial.setting.plan.drawing.size.info": "※数字は[半角]入力のみ可能です。",
|
||||||
"modal.placement.initial.setting.size": "寸法入力方法",
|
"modal.placement.initial.setting.size": "寸法入力方法",
|
||||||
"modal.placement.initial.setting.size.info": "寸法入力方法案内",
|
"modal.placement.initial.setting.size.info": "寸法入力方法案内",
|
||||||
"modal.placement.initial.setting.size.roof": "伏図入力",
|
"modal.placement.initial.setting.size.roof": "伏図入力",
|
||||||
@ -36,8 +37,8 @@
|
|||||||
"modal.roof.shape.setting.ridge": "棟",
|
"modal.roof.shape.setting.ridge": "棟",
|
||||||
"modal.roof.shape.setting.patten.a": "Aパターン",
|
"modal.roof.shape.setting.patten.a": "Aパターン",
|
||||||
"modal.roof.shape.setting.patten.b": "Bパターン",
|
"modal.roof.shape.setting.patten.b": "Bパターン",
|
||||||
"modal.roof.shape.setting.side": "別に設定",
|
"modal.roof.shape.setting.side": "個別に設定",
|
||||||
"plan.menu.roof.cover": "屋根作図",
|
"plan.menu.roof.cover": "伏せ図入力",
|
||||||
"plan.menu.roof.cover.outline.drawing": "外壁線を描く",
|
"plan.menu.roof.cover.outline.drawing": "外壁線を描く",
|
||||||
"plan.menu.roof.cover.roof.shape.setting": "屋根形状の設定",
|
"plan.menu.roof.cover.roof.shape.setting": "屋根形状の設定",
|
||||||
"plan.menu.roof.cover.roof.shape.passivity.setting": "屋根形状の手動設定",
|
"plan.menu.roof.cover.roof.shape.passivity.setting": "屋根形状の手動設定",
|
||||||
@ -72,7 +73,7 @@
|
|||||||
"common.setting.rollback": "前に戻る",
|
"common.setting.rollback": "前に戻る",
|
||||||
"modal.cover.outline.remove": "外壁の取り外し",
|
"modal.cover.outline.remove": "外壁の取り外し",
|
||||||
"modal.cover.outline.select.move": "外壁選択の移動",
|
"modal.cover.outline.select.move": "外壁選択の移動",
|
||||||
"plan.menu.placement.surface": "配置面",
|
"plan.menu.placement.surface": "実測値入力",
|
||||||
"plan.menu.placement.surface.slope.setting": "傾斜設定",
|
"plan.menu.placement.surface.slope.setting": "傾斜設定",
|
||||||
"plan.menu.placement.surface.drawing": "配置面の描画",
|
"plan.menu.placement.surface.drawing": "配置面の描画",
|
||||||
"modal.placement.surface.drawing.straight.line": "直線",
|
"modal.placement.surface.drawing.straight.line": "直線",
|
||||||
@ -88,13 +89,20 @@
|
|||||||
"plan.menu.module.circuit.setting.default": "モジュール/架台設定",
|
"plan.menu.module.circuit.setting.default": "モジュール/架台設定",
|
||||||
"modal.module.basic.setting.orientation.setting": "方位設定",
|
"modal.module.basic.setting.orientation.setting": "方位設定",
|
||||||
"modal.module.basic.setting.orientation.setting.info": "※シミュレーション計算用方位を指定します。南の方位を設定してください。",
|
"modal.module.basic.setting.orientation.setting.info": "※シミュレーション計算用方位を指定します。南の方位を設定してください。",
|
||||||
"modal.module.basic.setting.orientation.setting.angle.passivity": "勾配を直接入力",
|
"modal.module.basic.setting.orientation.setting.angle.passivity": "角度変更",
|
||||||
"modal.module.basic.setting.module.roof.material": "屋根材",
|
"modal.module.basic.setting.module.roof.material": "屋根材",
|
||||||
"modal.module.basic.setting.module.trestle.maker": "架台メーカー",
|
"modal.module.basic.setting.module.trestle.maker": "架台メーカー",
|
||||||
"modal.module.basic.setting.module.rafter.margin": "垂木の間隔",
|
"modal.module.basic.setting.module.rafter.margin": "垂木の間隔",
|
||||||
"modal.module.basic.setting.module.construction.method": "工法",
|
"modal.module.basic.setting.module.construction.method": "工法",
|
||||||
"modal.module.basic.setting.module.under.roof": "屋根の下",
|
"modal.module.basic.setting.module.under.roof": "屋根下地",
|
||||||
"modal.module.basic.setting.module.setting": "モジュールの選択",
|
"modal.module.basic.setting.module.setting": "モジュールの選択",
|
||||||
|
"modal.module.basic.setting.module.placement.area": "モジュール配置領域",
|
||||||
|
"modal.module.basic.setting.module.placement.margin": "モジュール間の間隙",
|
||||||
|
"modal.module.basic.setting.module.placement.area.eaves": "軒側",
|
||||||
|
"modal.module.basic.setting.module.placement.area.ridge": "棟側",
|
||||||
|
"modal.module.basic.setting.module.placement.area.keraba": "けらぱ",
|
||||||
|
"modal.module.basic.setting.module.placement.margin.horizontal": "左右",
|
||||||
|
"modal.module.basic.setting.module.placement.margin.vertical": "上下",
|
||||||
"modal.module.basic.setting.module.hajebichi": "ハゼピッチ",
|
"modal.module.basic.setting.module.hajebichi": "ハゼピッチ",
|
||||||
"modal.module.basic.setting.module.setting.info1": "※勾配の範囲には制限があります。屋根傾斜が2.5値未満10値を超える場合は、施工が可能かどうか施工マニュアルを確認してください。",
|
"modal.module.basic.setting.module.setting.info1": "※勾配の範囲には制限があります。屋根傾斜が2.5値未満10値を超える場合は、施工が可能かどうか施工マニュアルを確認してください。",
|
||||||
"modal.module.basic.setting.module.setting.info2": "※モジュール配置時は、施工マニュアルに記載されている<モジュール配置条件>を必ずご確認ください。",
|
"modal.module.basic.setting.module.setting.info2": "※モジュール配置時は、施工マニュアルに記載されている<モジュール配置条件>を必ずご確認ください。",
|
||||||
@ -105,32 +113,50 @@
|
|||||||
"modal.module.basic.setting.module.standard.snowfall.amount": "積雪量",
|
"modal.module.basic.setting.module.standard.snowfall.amount": "積雪量",
|
||||||
"modal.module.basic.setting.module.standard.construction": "標準施工",
|
"modal.module.basic.setting.module.standard.construction": "標準施工",
|
||||||
"modal.module.basic.setting.module.enforce.construction": "強化施工",
|
"modal.module.basic.setting.module.enforce.construction": "強化施工",
|
||||||
"modal.module.basic.setting.module.multiple.construction": "多設施工",
|
"modal.module.basic.setting.module.multiple.construction": "多雪施工",
|
||||||
"modal.module.basic.setting.module.eaves.bar.fitting": "軒カバーの設置",
|
"modal.module.basic.setting.module.eaves.bar.fitting": "軒カバーの設置",
|
||||||
"modal.module.basic.setting.module.blind.metal.fitting": "落雪防止金具設置",
|
"modal.module.basic.setting.module.blind.metal.fitting": "落雪防止金具設置",
|
||||||
"modal.module.basic.setting.module.select": "モジュール/架台選択",
|
"modal.module.basic.setting.module.select": "モジュール/架台選択",
|
||||||
|
"modal.module.basic.settting.module.error1": "架台メーカーを選択してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error2": "工法を選択してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error3": "屋根の下を選択してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error4": "設置可能な施工条件がないので設置条件を変更してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error5": "L を選択してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error6": "垂木の間隔を入力してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error7": "下在ビーチを入力してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error8": "モジュール配置領域の値を入力してください。\n(屋根材: {0})",
|
||||||
|
"modal.module.basic.settting.module.error9": "軒側の値は{0} mm以上でなければなりません。\n(屋根材: {1})",
|
||||||
|
"modal.module.basic.settting.module.error10": "吊下側の値は{0} mm以上でなければなりません。\n(屋根材: {1})",
|
||||||
|
"modal.module.basic.settting.module.error11": "ケラバ側の値は{0} mm以上でなければなりません。\n(屋根材: {1})",
|
||||||
|
"modal.module.basic.settting.module.error12": "施工方法を選択してください。\n(屋根材: {0})",
|
||||||
"modal.module.basic.setting.module.placement": "モジュールの配置",
|
"modal.module.basic.setting.module.placement": "モジュールの配置",
|
||||||
"modal.module.basic.setting.module.placement.select.fitting.type": "設置形態を選択してください。",
|
"modal.module.basic.setting.module.placement.select.fitting.type": "設置形態を選択してください。",
|
||||||
"modal.module.basic.setting.module.placement.waterfowl.arrangement": "千鳥配置",
|
"modal.module.basic.setting.module.placement.waterfowl.arrangement": "千鳥配置",
|
||||||
|
"modal.module.basic.setting.module.placement.max.row.amount": "Max段数",
|
||||||
|
"modal.module.basic.setting.module.placement.mix.max.row.amount": "混合Max段数",
|
||||||
|
"modal.module.basic.setting.module.placement.row.amount": "段数",
|
||||||
|
"modal.module.basic.setting.module.placement.column.amount": "列数",
|
||||||
"modal.module.basic.setting.module.placement.do": "する",
|
"modal.module.basic.setting.module.placement.do": "する",
|
||||||
"modal.module.basic.setting.module.placement.do.not": "しない",
|
"modal.module.basic.setting.module.placement.do.not": "しない",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard": "配置基準",
|
"modal.module.basic.setting.module.placement.arrangement.standard": "配置基準",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard.center": "中央",
|
"modal.module.basic.setting.module.placement.arrangement.standard.center": "中央",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard.eaves": "軒",
|
"modal.module.basic.setting.module.placement.arrangement.standard.eaves": "軒側",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard.ridge": "棟",
|
"modal.module.basic.setting.module.placement.arrangement.standard.ridge": "棟側",
|
||||||
"modal.module.basic.setting.module.placement.maximum": "最大配置",
|
"modal.module.basic.setting.module.placement.maximum": "最大配置",
|
||||||
"modal.module.basic.setting.pitch.module.placement.standard.setting": "配置基準設定",
|
"modal.module.basic.setting.pitch.module.placement.standard.setting": "配置基準の設定",
|
||||||
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "南向き設置",
|
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "南向きに設置す",
|
||||||
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "指定した辺を基準に設置",
|
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "指定した辺を基準に設置する",
|
||||||
"modal.module.basic.setting.pitch.module.allocation.setting": "割り当て設定",
|
"modal.module.basic.setting.pitch.module.allocation.setting": "割り当て設定",
|
||||||
"modal.module.basic.setting.pitch.module.allocation.setting.info": "※配置パネルの種類が1種類の場合のみ使用できます。",
|
"modal.module.basic.setting.pitch.module.allocation.setting.info": "※配置パネルの種類が1種類の場合のみ使用できます。",
|
||||||
"modal.module.basic.setting.pitch.module.row.amount": "単数",
|
"modal.module.basic.setting.pitch.module.row.amount": "単数",
|
||||||
"modal.module.basic.setting.pitch.module.row.margin": "上下間隔",
|
"modal.module.basic.setting.pitch.module.row.margin": "上下間隔",
|
||||||
"modal.module.basic.setting.pitch.module.column.amount": "列数",
|
"modal.module.basic.setting.pitch.module.column.amount": "列数",
|
||||||
"modal.module.basic.setting.pitch.module.column.margin": "左右間隔",
|
"modal.module.basic.setting.pitch.module.column.margin": "左右間隔",
|
||||||
"modal.module.basic.setting.prev": "移転",
|
"modal.module.basic.setting.prev": "前に戻る",
|
||||||
|
"modal.module.basic.setting.row.batch": "レイアウト指定",
|
||||||
"modal.module.basic.setting.passivity.placement": "手動配置",
|
"modal.module.basic.setting.passivity.placement": "手動配置",
|
||||||
"modal.module.basic.setting.auto.placement": "設定値に自動配置",
|
"modal.module.basic.setting.auto.placement": "自動配置",
|
||||||
|
"modal.module.basic.setting.auto.row.batch": "自動レイアウト指定",
|
||||||
"plan.menu.module.circuit.setting.circuit.trestle.setting": "回路設定",
|
"plan.menu.module.circuit.setting.circuit.trestle.setting": "回路設定",
|
||||||
"modal.circuit.trestle.setting": "回路設定",
|
"modal.circuit.trestle.setting": "回路設定",
|
||||||
"modal.circuit.trestle.setting.alloc.trestle": "架台配置",
|
"modal.circuit.trestle.setting.alloc.trestle": "架台配置",
|
||||||
@ -142,7 +168,7 @@
|
|||||||
"modal.circuit.trestle.setting.power.conditional.select.max.connection": "標準枚数",
|
"modal.circuit.trestle.setting.power.conditional.select.max.connection": "標準枚数",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.max.overload": "最大枚数",
|
"modal.circuit.trestle.setting.power.conditional.select.max.overload": "最大枚数",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.output.current": "出力電流",
|
"modal.circuit.trestle.setting.power.conditional.select.output.current": "出力電流",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.check1": "同じ傾斜同じ方向の面積ケース同じ面として回路分ける。",
|
"modal.circuit.trestle.setting.power.conditional.select.check1": "同一勾配・同一方面の面である場合、同じ面として回路分けを行う",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.check2": "MAX接続(過積)で回路を分ける。",
|
"modal.circuit.trestle.setting.power.conditional.select.check2": "MAX接続(過積)で回路を分ける。",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation": "回路割り当て",
|
"modal.circuit.trestle.setting.circuit.allocation": "回路割り当て",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.auto": "自動回路割り当て",
|
"modal.circuit.trestle.setting.circuit.allocation.auto": "自動回路割り当て",
|
||||||
@ -153,7 +179,7 @@
|
|||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.info": "同じ回路のモジュールを選択状態にした後、[番号確定]ボタンを押すと番号が割り当てられます。",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.info": "同じ回路のモジュールを選択状態にした後、[番号確定]ボタンを押すと番号が割り当てられます。",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional": "選択したパワーコンディショナー",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional": "選択したパワーコンディショナー",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num": "設定する回路番号(1~)",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num": "設定する回路番号(1~)",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info": "標準回路{0}章~{1}章",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info": "標準回路{0}~{1}直",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset": "選択したパワーコンディショナーの回路番号の初期化",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset": "選択したパワーコンディショナーの回路番号の初期化",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info": "選択したパワーコンディショナーの回路割り当てを初期化します。",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info": "選択したパワーコンディショナーの回路割り当てを初期化します。",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset": "すべての回路番号の初期化",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset": "すべての回路番号の初期化",
|
||||||
@ -162,7 +188,7 @@
|
|||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.validation.error02": "シリーズを選択してください。",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.validation.error02": "シリーズを選択してください。",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix": "番号確定",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix": "番号確定",
|
||||||
"modal.circuit.trestle.setting.step.up.allocation": "昇圧設定",
|
"modal.circuit.trestle.setting.step.up.allocation": "昇圧設定",
|
||||||
"modal.circuit.trestle.setting.step.up.allocation.serial.amount": "シリアル枚数",
|
"modal.circuit.trestle.setting.step.up.allocation.serial.amount": "直列枚数",
|
||||||
"modal.circuit.trestle.setting.step.up.allocation.total.amount": "総回路数",
|
"modal.circuit.trestle.setting.step.up.allocation.total.amount": "総回路数",
|
||||||
"modal.circuit.trestle.setting.step.up.allocation.connected": "接続する",
|
"modal.circuit.trestle.setting.step.up.allocation.connected": "接続する",
|
||||||
"modal.circuit.trestle.setting.step.up.allocation.circuit.amount": "昇圧回路数",
|
"modal.circuit.trestle.setting.step.up.allocation.circuit.amount": "昇圧回路数",
|
||||||
@ -178,7 +204,7 @@
|
|||||||
"modal.roof.alloc.select.parallel": "筋配置",
|
"modal.roof.alloc.select.parallel": "筋配置",
|
||||||
"modal.roof.alloc.select.stairs": "千鳥配置",
|
"modal.roof.alloc.select.stairs": "千鳥配置",
|
||||||
"modal.roof.alloc.apply": "選択した屋根材として割り当て",
|
"modal.roof.alloc.apply": "選択した屋根材として割り当て",
|
||||||
"plan.menu.estimate.docDown": "各種資料ダウンロード",
|
"plan.menu.estimate.docDownload": "見積書出力",
|
||||||
"plan.menu.estimate.save": "保存",
|
"plan.menu.estimate.save": "保存",
|
||||||
"plan.menu.estimate.reset": "初期化",
|
"plan.menu.estimate.reset": "初期化",
|
||||||
"plan.menu.estimate.copy": "見積書のコピー",
|
"plan.menu.estimate.copy": "見積書のコピー",
|
||||||
@ -299,7 +325,7 @@
|
|||||||
"modal.object.setting.offset.width": "幅の出幅",
|
"modal.object.setting.offset.width": "幅の出幅",
|
||||||
"modal.object.setting.offset.slope": "勾配",
|
"modal.object.setting.offset.slope": "勾配",
|
||||||
"modal.object.setting.direction.select": "方向の選択",
|
"modal.object.setting.direction.select": "方向の選択",
|
||||||
"modal.placement.surface.setting.info": "ⓘ①の長さ入力後、対角線長を入力すると②の長さを自動計算します。",
|
"modal.placement.surface.setting.info": "①の長さを入力後、③の長さを入力すると②の長さを自動計算します。",
|
||||||
"modal.placement.surface.setting.diagonal.length": "斜めの長さ",
|
"modal.placement.surface.setting.diagonal.length": "斜めの長さ",
|
||||||
"modal.color.picker.title": "色設定",
|
"modal.color.picker.title": "色設定",
|
||||||
"modal.color.picker.default.color": "基本色",
|
"modal.color.picker.default.color": "基本色",
|
||||||
@ -549,7 +575,7 @@
|
|||||||
"color.pink": "ピンク",
|
"color.pink": "ピンク",
|
||||||
"color.gold": "黄金色",
|
"color.gold": "黄金色",
|
||||||
"color.darkblue": "藍色",
|
"color.darkblue": "藍色",
|
||||||
"site.name": "HANASYS設計",
|
"site.name": "HANASYS DESIGN",
|
||||||
"site.sub_name": "太陽光発電システム図面管理サイト",
|
"site.sub_name": "太陽光発電システム図面管理サイト",
|
||||||
"site.header.link1": "選択してください。",
|
"site.header.link1": "選択してください。",
|
||||||
"site.header.link2": "オンライン保証システム",
|
"site.header.link2": "オンライン保証システム",
|
||||||
@ -558,7 +584,7 @@
|
|||||||
"board.faq.title": "FAQ",
|
"board.faq.title": "FAQ",
|
||||||
"board.faq.sub.title": "FAQリスト",
|
"board.faq.sub.title": "FAQリスト",
|
||||||
"board.archive.title": "各種資料ダウンロード",
|
"board.archive.title": "各種資料ダウンロード",
|
||||||
"board.archive.sub.title": "見積書一覧",
|
"board.archive.sub.title": "掲載資料一覧",
|
||||||
"board.list.header.rownum": "番号",
|
"board.list.header.rownum": "番号",
|
||||||
"board.list.header.title": "タイトル",
|
"board.list.header.title": "タイトル",
|
||||||
"board.list.header.regDt": "登録日",
|
"board.list.header.regDt": "登録日",
|
||||||
@ -594,6 +620,7 @@
|
|||||||
"myinfo.message.password.error": "パスワードが間違っています。",
|
"myinfo.message.password.error": "パスワードが間違っています。",
|
||||||
"login": "ログイン",
|
"login": "ログイン",
|
||||||
"login.auto.page.text": "自動ログイン中です。",
|
"login.auto.page.text": "自動ログイン中です。",
|
||||||
|
"login.fail": "계정이 없거나 비밀번호가 잘못되었습니다.",
|
||||||
"login.id.save": "ID保存",
|
"login.id.save": "ID保存",
|
||||||
"login.id.placeholder": "IDを入力してください。",
|
"login.id.placeholder": "IDを入力してください。",
|
||||||
"login.password.placeholder": "パスワードを入力してください。",
|
"login.password.placeholder": "パスワードを入力してください。",
|
||||||
@ -841,7 +868,7 @@
|
|||||||
"has.not.sleeve": "袖なし",
|
"has.not.sleeve": "袖なし",
|
||||||
"jerkinhead.width": "半切妻幅",
|
"jerkinhead.width": "半切妻幅",
|
||||||
"jerkinhead.slope": "半切妻傾斜",
|
"jerkinhead.slope": "半切妻傾斜",
|
||||||
"shed.width": "片流幅",
|
"shed.width": "片流れの出幅",
|
||||||
"windage": "片流れ",
|
"windage": "片流れ",
|
||||||
"windage.width": "片流れの出幅",
|
"windage.width": "片流れの出幅",
|
||||||
"write": "作成",
|
"write": "作成",
|
||||||
@ -886,7 +913,7 @@
|
|||||||
"estimate.detail.drawingEstimateCreateDate": "登録日",
|
"estimate.detail.drawingEstimateCreateDate": "登録日",
|
||||||
"estimate.detail.lastEditDatetime": "変更日時",
|
"estimate.detail.lastEditDatetime": "変更日時",
|
||||||
"estimate.detail.saleStoreId": "一次販売店名",
|
"estimate.detail.saleStoreId": "一次販売店名",
|
||||||
"estimate.detail.estimateDate": "見積日",
|
"estimate.detail.estimateDate": "見積作成日",
|
||||||
"estimate.detail.otherSaleStoreId": "二次販売店名",
|
"estimate.detail.otherSaleStoreId": "二次販売店名",
|
||||||
"estimate.detail.noOtherSaleStoreId": "二次店なし",
|
"estimate.detail.noOtherSaleStoreId": "二次店なし",
|
||||||
"estimate.detail.receiveUser": "担当者",
|
"estimate.detail.receiveUser": "担当者",
|
||||||
@ -895,6 +922,7 @@
|
|||||||
"estimate.detail.estimateType": "注文分類",
|
"estimate.detail.estimateType": "注文分類",
|
||||||
"estimate.detail.estimateType.yjss": "住宅PKG",
|
"estimate.detail.estimateType.yjss": "住宅PKG",
|
||||||
"estimate.detail.estimateType.yjod": "積上げ(YJOD)",
|
"estimate.detail.estimateType.yjod": "積上げ(YJOD)",
|
||||||
|
"estimate.detail.agency": "2次店名",
|
||||||
"estimate.detail.roofCns": "屋根材・施工区分",
|
"estimate.detail.roofCns": "屋根材・施工区分",
|
||||||
"estimate.detail.remarks": "備考",
|
"estimate.detail.remarks": "備考",
|
||||||
"estimate.detail.fileFlg": "後日資料提出",
|
"estimate.detail.fileFlg": "後日資料提出",
|
||||||
@ -918,6 +946,7 @@
|
|||||||
"estimate.detail.header.unitPrice": "定価",
|
"estimate.detail.header.unitPrice": "定価",
|
||||||
"estimate.detail.showPrice.pricingBtn": "Pricing",
|
"estimate.detail.showPrice.pricingBtn": "Pricing",
|
||||||
"estimate.detail.showPrice.pricingBtn.noItemId": "Pricingが欠落しているアイテムがあります。 Pricingを進めてください。",
|
"estimate.detail.showPrice.pricingBtn.noItemId": "Pricingが欠落しているアイテムがあります。 Pricingを進めてください。",
|
||||||
|
"estimate.detail.showPrice.pricingBtn.confirm": "価格登録初期化されますがよろしいですか?",
|
||||||
"estimate.detail.showPrice.description1": "製品価格OPEN",
|
"estimate.detail.showPrice.description1": "製品価格OPEN",
|
||||||
"estimate.detail.showPrice.description2": "追加の変更品目",
|
"estimate.detail.showPrice.description2": "追加の変更品目",
|
||||||
"estimate.detail.showPrice.description3": "添付必須",
|
"estimate.detail.showPrice.description3": "添付必須",
|
||||||
@ -957,6 +986,7 @@
|
|||||||
"estimate.detail.estimateCopyPopup.close": "閉じる",
|
"estimate.detail.estimateCopyPopup.close": "閉じる",
|
||||||
"estimate.detail.estimateCopyPopup.copyBtn": "見積コピー",
|
"estimate.detail.estimateCopyPopup.copyBtn": "見積コピー",
|
||||||
"estimate.detail.estimateCopyPopup.copy.alertMessage": "見積書がコピーされました。コピーした見積情報に移動します。",
|
"estimate.detail.estimateCopyPopup.copy.alertMessage": "見積書がコピーされました。コピーした見積情報に移動します。",
|
||||||
|
"estimate.detail.estimateCopyPopup.copy.alertMessageError": "キャンバスのコピー中にエラーが発生しました.",
|
||||||
"estimate.detail.productFeaturesPopup.title": "製品特異事項",
|
"estimate.detail.productFeaturesPopup.title": "製品特異事項",
|
||||||
"estimate.detail.productFeaturesPopup.close": "閉じる",
|
"estimate.detail.productFeaturesPopup.close": "閉じる",
|
||||||
"estimate.detail.productFeaturesPopup.requiredStoreId": "一次販売店は必須です。",
|
"estimate.detail.productFeaturesPopup.requiredStoreId": "一次販売店は必須です。",
|
||||||
@ -997,7 +1027,7 @@
|
|||||||
"simulator.table.sub5": "枚数",
|
"simulator.table.sub5": "枚数",
|
||||||
"simulator.table.sub6": "合計",
|
"simulator.table.sub6": "合計",
|
||||||
"simulator.table.sub7": "パワーコンディショナー",
|
"simulator.table.sub7": "パワーコンディショナー",
|
||||||
"simulator.table.sub8": "ティーン",
|
"simulator.table.sub8": "台",
|
||||||
"simulator.table.sub9": "予測発電量(kWh)",
|
"simulator.table.sub9": "予測発電量(kWh)",
|
||||||
"simulator.notice.sub1": "ハンファジャパン年間発電量",
|
"simulator.notice.sub1": "ハンファジャパン年間発電量",
|
||||||
"simulator.notice.sub2": "シミュレーションガイド",
|
"simulator.notice.sub2": "シミュレーションガイド",
|
||||||
@ -1034,5 +1064,20 @@
|
|||||||
"roof.exceed.count": "屋根材は4つまで選択可能です。",
|
"roof.exceed.count": "屋根材は4つまで選択可能です。",
|
||||||
"outerLine.property.fix": "外壁線の属性設定 を完了しますか?",
|
"outerLine.property.fix": "外壁線の属性設定 を完了しますか?",
|
||||||
"outerLine.property.close": "外壁線の属性設定 を終了しますか?",
|
"outerLine.property.close": "外壁線の属性設定 を終了しますか?",
|
||||||
"want.to.complete.auxiliary.creation": "보補助線の作成を完了しますか?"
|
"want.to.complete.auxiliary.creation": "補助線の作成を完了しますか?",
|
||||||
|
"module.layout.setup.has.zero.value": "モジュールの列数、段数を入力して下さい。",
|
||||||
|
"modal.placement.initial.setting.plan.drawing.only.number": "(※数字は[半角]入力のみ可能です。)",
|
||||||
|
"wall.line.not.found": "外壁がありません",
|
||||||
|
"roof.line.not.found": "屋根形状がありません",
|
||||||
|
"roof.material.can.not.delete": "割り当てられた配置面があります。",
|
||||||
|
"chidory.can.not.install": "千鳥配置できない工法です。",
|
||||||
|
"module.layout.setup.max.count": "モジュールの単体での最大段数は{0}、最大列数は{1}です。 (JA)",
|
||||||
|
"module.layout.setup.max.count.multiple": "モジュール{0}の単体での最大段数は{1}、最大列数は{2}です。 (JA)",
|
||||||
|
"roofAllocation.not.found": "割り当てる屋根がありません。 (JA)",
|
||||||
|
"modal.module.basic.setting.module.placement.max.size.check": "屋根材別モジュールの単体の単体での最大段数、2種混合の段数を確認して下さい",
|
||||||
|
"modal.module.basic.setting.module.placement.max.row": "単体で\rの最大段数",
|
||||||
|
"modal.module.basic.setting.module.placement.max.rows.multiple": "2種混合時\rの最大段数",
|
||||||
|
"modal.module.basic.setting.module.placement.mix.asg.yn.error": "混合インストール不可能なモジュールです。 (JA)",
|
||||||
|
"modal.module.basic.setting.module.placement.mix.asg.yn": "混合",
|
||||||
|
"modal.module.basic.setting.module.placement.over.max.row": "{0} 最大段数超過しました。最大段数表を参考にしてください。"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"plan.menu.placement.surface.initial.setting": "배치면 초기설정",
|
"plan.menu.placement.surface.initial.setting": "배치면 초기설정",
|
||||||
"modal.placement.initial.setting.plan.drawing": "도면 작성방법",
|
"modal.placement.initial.setting.plan.drawing": "도면 작성방법",
|
||||||
"modal.placement.initial.setting.plan.drawing.size.stuff": "치수 입력에 의한 물건 작성",
|
"modal.placement.initial.setting.plan.drawing.size.stuff": "치수 입력에 의한 물건 작성",
|
||||||
|
"modal.placement.initial.setting.plan.drawing.size.info": "※숫자는 [반각] 입력만 가능합니다.",
|
||||||
"modal.placement.initial.setting.size": "치수 입력방법",
|
"modal.placement.initial.setting.size": "치수 입력방법",
|
||||||
"modal.placement.initial.setting.size.info": "치수 입력방법 안내",
|
"modal.placement.initial.setting.size.info": "치수 입력방법 안내",
|
||||||
"modal.placement.initial.setting.size.roof": "복시도 입력",
|
"modal.placement.initial.setting.size.roof": "복시도 입력",
|
||||||
@ -88,13 +89,20 @@
|
|||||||
"plan.menu.module.circuit.setting.default": "모듈/가대설정",
|
"plan.menu.module.circuit.setting.default": "모듈/가대설정",
|
||||||
"modal.module.basic.setting.orientation.setting": "방위 설정",
|
"modal.module.basic.setting.orientation.setting": "방위 설정",
|
||||||
"modal.module.basic.setting.orientation.setting.info": "※시뮬레이션 계산용 방위를 지정합니다. 남쪽의 방위를 설정해주세요.",
|
"modal.module.basic.setting.orientation.setting.info": "※시뮬레이션 계산용 방위를 지정합니다. 남쪽의 방위를 설정해주세요.",
|
||||||
"modal.module.basic.setting.orientation.setting.angle.passivity": "각도를 직접 입력",
|
"modal.module.basic.setting.orientation.setting.angle.passivity": "각도 입력",
|
||||||
"modal.module.basic.setting.module.roof.material": "지붕재",
|
"modal.module.basic.setting.module.roof.material": "지붕재",
|
||||||
"modal.module.basic.setting.module.trestle.maker": "가대메이커",
|
"modal.module.basic.setting.module.trestle.maker": "가대메이커",
|
||||||
"modal.module.basic.setting.module.rafter.margin": "서까래 간격",
|
"modal.module.basic.setting.module.rafter.margin": "서까래 간격",
|
||||||
"modal.module.basic.setting.module.construction.method": "공법",
|
"modal.module.basic.setting.module.construction.method": "공법",
|
||||||
"modal.module.basic.setting.module.under.roof": "지붕밑바탕",
|
"modal.module.basic.setting.module.under.roof": "지붕밑바탕",
|
||||||
"modal.module.basic.setting.module.setting": "모듈 선택",
|
"modal.module.basic.setting.module.setting": "모듈 선택",
|
||||||
|
"modal.module.basic.setting.module.placement.area": "모듈 배치 영역",
|
||||||
|
"modal.module.basic.setting.module.placement.margin": "모듈 배치 간격",
|
||||||
|
"modal.module.basic.setting.module.placement.area.eaves": "처마쪽",
|
||||||
|
"modal.module.basic.setting.module.placement.area.ridge": "용마루쪽",
|
||||||
|
"modal.module.basic.setting.module.placement.area.keraba": "케라바쪽",
|
||||||
|
"modal.module.basic.setting.module.placement.margin.horizontal": "좌우",
|
||||||
|
"modal.module.basic.setting.module.placement.margin.vertical": "상하",
|
||||||
"modal.module.basic.setting.module.hajebichi": "망둥어 피치",
|
"modal.module.basic.setting.module.hajebichi": "망둥어 피치",
|
||||||
"modal.module.basic.setting.module.setting.info1": "※ 구배의 범위에는 제한이 있습니다. 지붕경사가 2.5치 미만 10치를 초과하는 경우에는 시공이 가능한지 시공 매뉴얼을 확인해주십시오.",
|
"modal.module.basic.setting.module.setting.info1": "※ 구배의 범위에는 제한이 있습니다. 지붕경사가 2.5치 미만 10치를 초과하는 경우에는 시공이 가능한지 시공 매뉴얼을 확인해주십시오.",
|
||||||
"modal.module.basic.setting.module.setting.info2": "※ 모듈 배치 시에는 시공 매뉴얼에 기재된 <모듈 배치 조건>을 반드시 확인해주십시오.",
|
"modal.module.basic.setting.module.setting.info2": "※ 모듈 배치 시에는 시공 매뉴얼에 기재된 <모듈 배치 조건>을 반드시 확인해주십시오.",
|
||||||
@ -109,16 +117,33 @@
|
|||||||
"modal.module.basic.setting.module.eaves.bar.fitting": "처마커버설치",
|
"modal.module.basic.setting.module.eaves.bar.fitting": "처마커버설치",
|
||||||
"modal.module.basic.setting.module.blind.metal.fitting": "적설방지금구설치",
|
"modal.module.basic.setting.module.blind.metal.fitting": "적설방지금구설치",
|
||||||
"modal.module.basic.setting.module.select": "모듈/가대 선택",
|
"modal.module.basic.setting.module.select": "모듈/가대 선택",
|
||||||
|
"modal.module.basic.settting.module.error1": "가대메이커를 선택해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error2": "공법를 선택해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error3": "지붕밑바탕을 선택해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error4": "설치 조건이 없으므로 설치 조건을 변경하십시오.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error5": "L 을 입력해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error6": "서까래 간격을 입력해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error7": "하제비치를 입력해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error8": "모듈 배치 영역 값을 입력해주세요.\n(지붕재: {0})",
|
||||||
|
"modal.module.basic.settting.module.error9": "처마쪽 값은 {0}mm 이상이어야 합니다.\n(지붕재: {1})",
|
||||||
|
"modal.module.basic.settting.module.error10": "용마루쪽 값은 {0}mm 이상이어야 합니다.\n(지붕재: {1})",
|
||||||
|
"modal.module.basic.settting.module.error11": "케라바쪽 값은 {0}mm 이상이어야 합니다.\n(지붕재: {1})",
|
||||||
|
"modal.module.basic.settting.module.error12": "시공법을 선택해주세요.\n(지붕재: {0})",
|
||||||
"modal.module.basic.setting.module.placement": "모듈 배치",
|
"modal.module.basic.setting.module.placement": "모듈 배치",
|
||||||
"modal.module.basic.setting.module.placement.select.fitting.type": "설치형태를 선택합니다.",
|
"modal.module.basic.setting.module.placement.select.fitting.type": "설치형태를 선택합니다.",
|
||||||
"modal.module.basic.setting.module.placement.waterfowl.arrangement": "물떼새 배치",
|
"modal.module.basic.setting.module.placement.waterfowl.arrangement": "물떼새 배치",
|
||||||
|
"modal.module.basic.setting.module.placement.max.row.amount": "Max 단수",
|
||||||
|
"modal.module.basic.setting.module.placement.mix.max.row.amount": "혼합Max 단수",
|
||||||
|
"modal.module.basic.setting.module.placement.row.amount": "단수",
|
||||||
|
"modal.module.basic.setting.module.placement.column.amount": "열수",
|
||||||
"modal.module.basic.setting.module.placement.do": "한다",
|
"modal.module.basic.setting.module.placement.do": "한다",
|
||||||
"modal.module.basic.setting.module.placement.do.not": "하지 않는다",
|
"modal.module.basic.setting.module.placement.do.not": "하지 않는다",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard": "배치 기준",
|
"modal.module.basic.setting.module.placement.arrangement.standard": "배치 기준",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard.center": "중앙",
|
"modal.module.basic.setting.module.placement.arrangement.standard.center": "중앙",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard.eaves": "처마",
|
"modal.module.basic.setting.module.placement.arrangement.standard.eaves": "처마쪽",
|
||||||
"modal.module.basic.setting.module.placement.arrangement.standard.ridge": "용마루",
|
"modal.module.basic.setting.module.placement.arrangement.standard.ridge": "용마루쪽",
|
||||||
"modal.module.basic.setting.module.placement.maximum": "최대배치",
|
"modal.module.basic.setting.module.placement.maximum": "최대배치",
|
||||||
|
"modal.module.basic.setting.module.placement.margin.check1": "가대메이커를 선택해주세요.",
|
||||||
"modal.module.basic.setting.pitch.module.placement.standard.setting": "배치기준 설정",
|
"modal.module.basic.setting.pitch.module.placement.standard.setting": "배치기준 설정",
|
||||||
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "남향설치",
|
"modal.module.basic.setting.pitch.module.placement.standard.setting.south": "남향설치",
|
||||||
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "지정한 변을 기준으로 설치",
|
"modal.module.basic.setting.pitch.module.placement.standard.setting.select": "지정한 변을 기준으로 설치",
|
||||||
@ -129,8 +154,10 @@
|
|||||||
"modal.module.basic.setting.pitch.module.column.amount": "열수",
|
"modal.module.basic.setting.pitch.module.column.amount": "열수",
|
||||||
"modal.module.basic.setting.pitch.module.column.margin": "좌우간격",
|
"modal.module.basic.setting.pitch.module.column.margin": "좌우간격",
|
||||||
"modal.module.basic.setting.prev": "이전",
|
"modal.module.basic.setting.prev": "이전",
|
||||||
|
"modal.module.basic.setting.row.batch": "단·열수 지정 배치",
|
||||||
"modal.module.basic.setting.passivity.placement": "수동 배치",
|
"modal.module.basic.setting.passivity.placement": "수동 배치",
|
||||||
"modal.module.basic.setting.auto.placement": "설정값으로 자동 배치",
|
"modal.module.basic.setting.auto.placement": "자동 배치",
|
||||||
|
"modal.module.basic.setting.auto.row.batch": "자동 단·열수 지정 배치 ",
|
||||||
"plan.menu.module.circuit.setting.circuit.trestle.setting": "회로설정",
|
"plan.menu.module.circuit.setting.circuit.trestle.setting": "회로설정",
|
||||||
"modal.circuit.trestle.setting": "회로설정",
|
"modal.circuit.trestle.setting": "회로설정",
|
||||||
"modal.circuit.trestle.setting.alloc.trestle": "가대할당",
|
"modal.circuit.trestle.setting.alloc.trestle": "가대할당",
|
||||||
@ -142,7 +169,7 @@
|
|||||||
"modal.circuit.trestle.setting.power.conditional.select.max.connection": "표준매수",
|
"modal.circuit.trestle.setting.power.conditional.select.max.connection": "표준매수",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.max.overload": "최대매수",
|
"modal.circuit.trestle.setting.power.conditional.select.max.overload": "최대매수",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.output.current": "출력전류",
|
"modal.circuit.trestle.setting.power.conditional.select.output.current": "출력전류",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.check1": "동일경사 동일방면의 면적인 경우 같은 면으로서 회로를 나눈다.",
|
"modal.circuit.trestle.setting.power.conditional.select.check1": "동일 구배·동일 방면의 면인 경우, 같은 면으로서 회로를 나눈다",
|
||||||
"modal.circuit.trestle.setting.power.conditional.select.check2": "MAX 접속(과적)으로 회로를 나눈다.",
|
"modal.circuit.trestle.setting.power.conditional.select.check2": "MAX 접속(과적)으로 회로를 나눈다.",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation": "회로 할당",
|
"modal.circuit.trestle.setting.circuit.allocation": "회로 할당",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.auto": "자동회로 할당",
|
"modal.circuit.trestle.setting.circuit.allocation.auto": "자동회로 할당",
|
||||||
@ -153,7 +180,7 @@
|
|||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.info": "동일한 회로의 모듈을 선택 상태로 만든 후 [번호 확정] 버튼을 누르면 번호가 할당됩니다.",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.info": "동일한 회로의 모듈을 선택 상태로 만든 후 [번호 확정] 버튼을 누르면 번호가 할당됩니다.",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional": "선택된 파워컨디셔너",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional": "선택된 파워컨디셔너",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num": "설정할 회로번호(1~)",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num": "설정할 회로번호(1~)",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info": "표준회로{0}장~{1}장",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info": "표준회로{0}~{1}직",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset": "선택된 파워컨디셔너의 회로번호 초기화",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset": "선택된 파워컨디셔너의 회로번호 초기화",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info": "선택된 파워 컨디셔너의 회로할당을 초기화합니다.",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset.info": "선택된 파워 컨디셔너의 회로할당을 초기화합니다.",
|
||||||
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset": "모든 회로번호 초기화",
|
"modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset": "모든 회로번호 초기화",
|
||||||
@ -178,7 +205,7 @@
|
|||||||
"modal.roof.alloc.select.parallel": "병렬식",
|
"modal.roof.alloc.select.parallel": "병렬식",
|
||||||
"modal.roof.alloc.select.stairs": "계단식",
|
"modal.roof.alloc.select.stairs": "계단식",
|
||||||
"modal.roof.alloc.apply": "선택한 지붕재로 할당",
|
"modal.roof.alloc.apply": "선택한 지붕재로 할당",
|
||||||
"plan.menu.estimate.docDown": "문서 다운로드",
|
"plan.menu.estimate.docDownload": "문서 다운로드",
|
||||||
"plan.menu.estimate.save": "저장",
|
"plan.menu.estimate.save": "저장",
|
||||||
"plan.menu.estimate.reset": "초기화",
|
"plan.menu.estimate.reset": "초기화",
|
||||||
"plan.menu.estimate.copy": "견적서 복사",
|
"plan.menu.estimate.copy": "견적서 복사",
|
||||||
@ -594,6 +621,7 @@
|
|||||||
"myinfo.message.password.error": "비밀번호가 틀렸습니다.",
|
"myinfo.message.password.error": "비밀번호가 틀렸습니다.",
|
||||||
"login": "로그인",
|
"login": "로그인",
|
||||||
"login.auto.page.text": "자동로그인 중 입니다.",
|
"login.auto.page.text": "자동로그인 중 입니다.",
|
||||||
|
"login.fail": "계정이 없거나 비밀번호가 잘못되었습니다.",
|
||||||
"login.id.save": "ID Save",
|
"login.id.save": "ID Save",
|
||||||
"login.id.placeholder": "아이디를 입력해주세요.",
|
"login.id.placeholder": "아이디를 입력해주세요.",
|
||||||
"login.password.placeholder": "비밀번호를 입력해주세요.",
|
"login.password.placeholder": "비밀번호를 입력해주세요.",
|
||||||
@ -886,7 +914,7 @@
|
|||||||
"estimate.detail.drawingEstimateCreateDate": "등록일",
|
"estimate.detail.drawingEstimateCreateDate": "등록일",
|
||||||
"estimate.detail.lastEditDatetime": "변경일시",
|
"estimate.detail.lastEditDatetime": "변경일시",
|
||||||
"estimate.detail.saleStoreId": "1차 판매점명",
|
"estimate.detail.saleStoreId": "1차 판매점명",
|
||||||
"estimate.detail.estimateDate": "견적일",
|
"estimate.detail.estimateDate": "견적작성일",
|
||||||
"estimate.detail.otherSaleStoreId": "2차 판매점명",
|
"estimate.detail.otherSaleStoreId": "2차 판매점명",
|
||||||
"estimate.detail.noOtherSaleStoreId": "2차점 없음",
|
"estimate.detail.noOtherSaleStoreId": "2차점 없음",
|
||||||
"estimate.detail.receiveUser": "담당자",
|
"estimate.detail.receiveUser": "담당자",
|
||||||
@ -895,6 +923,7 @@
|
|||||||
"estimate.detail.estimateType": "주문분류",
|
"estimate.detail.estimateType": "주문분류",
|
||||||
"estimate.detail.estimateType.yjss": "住宅PKG",
|
"estimate.detail.estimateType.yjss": "住宅PKG",
|
||||||
"estimate.detail.estimateType.yjod": "積上げ( YJOD )",
|
"estimate.detail.estimateType.yjod": "積上げ( YJOD )",
|
||||||
|
"estimate.detail.agency": "2차점명",
|
||||||
"estimate.detail.roofCns": "지붕재・사양시공",
|
"estimate.detail.roofCns": "지붕재・사양시공",
|
||||||
"estimate.detail.remarks": "비고",
|
"estimate.detail.remarks": "비고",
|
||||||
"estimate.detail.fileFlg": "후일자료제출",
|
"estimate.detail.fileFlg": "후일자료제출",
|
||||||
@ -918,6 +947,7 @@
|
|||||||
"estimate.detail.header.unitPrice": "정가",
|
"estimate.detail.header.unitPrice": "정가",
|
||||||
"estimate.detail.showPrice.pricingBtn": "Pricing",
|
"estimate.detail.showPrice.pricingBtn": "Pricing",
|
||||||
"estimate.detail.showPrice.pricingBtn.noItemId": "Pricing이 누락된 아이템이 있습니다. 제품 선택 후 Pricing을 진행해주세요.",
|
"estimate.detail.showPrice.pricingBtn.noItemId": "Pricing이 누락된 아이템이 있습니다. 제품 선택 후 Pricing을 진행해주세요.",
|
||||||
|
"estimate.detail.showPrice.pricingBtn.confirm": "가격등록을 초기화 하시겠습니까?",
|
||||||
"estimate.detail.showPrice.description1": "제품 가격 OPEN",
|
"estimate.detail.showPrice.description1": "제품 가격 OPEN",
|
||||||
"estimate.detail.showPrice.description2": "추가 변경 자재",
|
"estimate.detail.showPrice.description2": "추가 변경 자재",
|
||||||
"estimate.detail.showPrice.description3": "첨부필수",
|
"estimate.detail.showPrice.description3": "첨부필수",
|
||||||
@ -957,6 +987,7 @@
|
|||||||
"estimate.detail.estimateCopyPopup.close": "닫기",
|
"estimate.detail.estimateCopyPopup.close": "닫기",
|
||||||
"estimate.detail.estimateCopyPopup.copyBtn": "견적복사",
|
"estimate.detail.estimateCopyPopup.copyBtn": "견적복사",
|
||||||
"estimate.detail.estimateCopyPopup.copy.alertMessage": "견적서가 복사되었습니다. 복사된 물건정보로 이동합니다.",
|
"estimate.detail.estimateCopyPopup.copy.alertMessage": "견적서가 복사되었습니다. 복사된 물건정보로 이동합니다.",
|
||||||
|
"estimate.detail.estimateCopyPopup.copy.alertMessageError": "캔버스 복사 중 오류 발생.",
|
||||||
"estimate.detail.productFeaturesPopup.title": "제품특이사항",
|
"estimate.detail.productFeaturesPopup.title": "제품특이사항",
|
||||||
"estimate.detail.productFeaturesPopup.close": "닫기",
|
"estimate.detail.productFeaturesPopup.close": "닫기",
|
||||||
"estimate.detail.productFeaturesPopup.requiredStoreId": "1차 판매점은 필수값 입니다.",
|
"estimate.detail.productFeaturesPopup.requiredStoreId": "1차 판매점은 필수값 입니다.",
|
||||||
@ -1034,5 +1065,20 @@
|
|||||||
"roof.exceed.count": "지붕재는 4개까지 선택 가능합니다.",
|
"roof.exceed.count": "지붕재는 4개까지 선택 가능합니다.",
|
||||||
"outerLine.property.fix": "외벽선 속성 설정을 완료하시겠습니까?",
|
"outerLine.property.fix": "외벽선 속성 설정을 완료하시겠습니까?",
|
||||||
"outerLine.property.close": "외벽선 속성 설정을 종료하시겠습니까?",
|
"outerLine.property.close": "외벽선 속성 설정을 종료하시겠습니까?",
|
||||||
"want.to.complete.auxiliary.creation": "보조선 작성을 완료하시겠습니까?"
|
"want.to.complete.auxiliary.creation": "보조선 작성을 완료하시겠습니까?",
|
||||||
|
"module.layout.setup.has.zero.value": "모듈의 열수, 단수를 입력해 주세요.",
|
||||||
|
"modal.placement.initial.setting.plan.drawing.only.number": "(※ 숫자는 [반각]입력만 가능합니다.)",
|
||||||
|
"wall.line.not.found": "외벽선이 없습니다.",
|
||||||
|
"roof.line.not.found": "지붕형상이 없습니다.",
|
||||||
|
"roof.material.can.not.delete": "할당된 배치면이 있습니다.",
|
||||||
|
"chidory.can.not.install": "치조 불가 공법입니다.",
|
||||||
|
"module.layout.setup.max.count": "모듈의 최대 단수는 {0}, 최대 열수는 {1} 입니다.",
|
||||||
|
"module.layout.setup.max.count.multiple": "모듈 {0}번의 최대 단수는 {1}, 최대 열수는 {2} 입니다.",
|
||||||
|
"roofAllocation.not.found": "할당할 지붕이 없습니다.",
|
||||||
|
"modal.module.basic.setting.module.placement.max.size.check": "지붕재별 모듈 단체의 최대 단수, 2종 혼합 단수를 확인하십시오.",
|
||||||
|
"modal.module.basic.setting.module.placement.max.row": "최대 단수",
|
||||||
|
"modal.module.basic.setting.module.placement.max.rows.multiple": "2종 혼합 최대단수",
|
||||||
|
"modal.module.basic.setting.module.placement.mix.asg.yn.error": "혼합 설치 불가능한 모듈입니다.",
|
||||||
|
"modal.module.basic.setting.module.placement.mix.asg.yn": "혼합",
|
||||||
|
"modal.module.basic.setting.module.placement.over.max.row": "{0}의 최대단수를 초과했습니다. 최대단수표를 참고해 주세요."
|
||||||
}
|
}
|
||||||
|
|||||||
71
src/store/auxiliaryLineAtom.js
Normal file
71
src/store/auxiliaryLineAtom.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { atom } from 'recoil'
|
||||||
|
|
||||||
|
// 보조선 타입
|
||||||
|
export const AUXILIARY_LINE_TYPE = {
|
||||||
|
OUTER_LINE: 'outerLine', // 외벽선
|
||||||
|
RIGHT_ANGLE: 'rightAngle', // 직각
|
||||||
|
DOUBLE_PITCH: 'doublePitch',
|
||||||
|
ANGLE: 'angle', // 각도
|
||||||
|
DIAGONAL_LINE: 'diagonalLine', // 대각선
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 보조선 작성에서 사용하는 recoilState
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const auxiliaryLineLength1State = atom({
|
||||||
|
//길이1
|
||||||
|
key: 'auxiliaryLineLength1State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineLength2State = atom({
|
||||||
|
// 길이2
|
||||||
|
key: 'auxiliaryLineLength2State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineArrow1State = atom({
|
||||||
|
// 방향1
|
||||||
|
key: 'auxiliaryLineArrow1State',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineArrow2State = atom({
|
||||||
|
// 방향2
|
||||||
|
key: 'auxiliaryLineArrow2State',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineAngle1State = atom({
|
||||||
|
// 각도1
|
||||||
|
key: 'auxiliaryLineAngle1State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineAngle2State = atom({
|
||||||
|
// 각도2
|
||||||
|
key: 'auxiliaryLineAngle2State',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineDiagonalState = atom({
|
||||||
|
// 대각선
|
||||||
|
key: 'auxiliaryLineDiagonalState',
|
||||||
|
default: 0,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineTypeState = atom({
|
||||||
|
key: 'auxiliaryLineTypeState',
|
||||||
|
default: AUXILIARY_LINE_TYPE.OUTER_LINE,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLinePointsState = atom({
|
||||||
|
key: 'auxiliaryLinePointsState',
|
||||||
|
default: [],
|
||||||
|
})
|
||||||
|
|
||||||
|
export const auxiliaryLineFixState = atom({
|
||||||
|
key: 'auxiliaryLineFixState',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
@ -384,3 +384,27 @@ export const isManualModuleSetupState = atom({
|
|||||||
key: 'isManualModuleSetupState',
|
key: 'isManualModuleSetupState',
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const isManualModuleLayoutSetupState = atom({
|
||||||
|
key: 'isManualModuleLayoutSetupState',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
|
|
||||||
|
export const moduleSetupOptionState = atom({
|
||||||
|
key: 'moduleSetupOptionState',
|
||||||
|
default: {
|
||||||
|
isChidori: false, //치조 안함
|
||||||
|
setupLocation: 'eaves', //처마
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const toggleManualSetupModeState = atom({
|
||||||
|
key: 'toggleManualSetupModeState',
|
||||||
|
default: '',
|
||||||
|
})
|
||||||
|
|
||||||
|
export const moduleRowColArrayState = atom({
|
||||||
|
key: 'moduleRowColArrayState',
|
||||||
|
default: [],
|
||||||
|
dangerouslyAllowMutability: true,
|
||||||
|
})
|
||||||
|
|||||||
6
src/store/hotkeyAtom.js
Normal file
6
src/store/hotkeyAtom.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { atom } from 'recoil'
|
||||||
|
|
||||||
|
export const hotkeyStore = atom({
|
||||||
|
key: 'hotkeyState',
|
||||||
|
default: [],
|
||||||
|
})
|
||||||
7
src/store/roofAtom.js
Normal file
7
src/store/roofAtom.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import { atom } from 'recoil'
|
||||||
|
|
||||||
|
export const roofsState = atom({
|
||||||
|
key: 'roofs',
|
||||||
|
default: null,
|
||||||
|
dangerouslyAllowMutability: true,
|
||||||
|
})
|
||||||
@ -2,7 +2,7 @@ import { atom } from 'recoil'
|
|||||||
|
|
||||||
export const selectedModuleState = atom({
|
export const selectedModuleState = atom({
|
||||||
key: 'selectedModuleState',
|
key: 'selectedModuleState',
|
||||||
default: [],
|
default: null,
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -221,6 +221,22 @@ export const corridorDimensionSelector = selector({
|
|||||||
const settingModalFirstOptions = get(settingModalFirstOptionsState)
|
const settingModalFirstOptions = get(settingModalFirstOptionsState)
|
||||||
return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected)
|
return settingModalFirstOptions.dimensionDisplay.find((option) => option.selected)
|
||||||
},
|
},
|
||||||
|
set: ({ set }, newValue) => {
|
||||||
|
//0 : 복도치수 , 1 : 실제치수
|
||||||
|
|
||||||
|
set(settingModalFirstOptionsState, (prev) => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
dimensionDisplay: prev.dimensionDisplay.map((item, index) => {
|
||||||
|
if (index === newValue) {
|
||||||
|
return { ...item, selected: true }
|
||||||
|
} else {
|
||||||
|
return { ...item, selected: false }
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
dangerouslyAllowMutability: true,
|
dangerouslyAllowMutability: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -340,6 +340,14 @@
|
|||||||
&.active{
|
&.active{
|
||||||
top: calc(92.8px + 50px);
|
top: calc(92.8px + 50px);
|
||||||
}
|
}
|
||||||
|
.canvas-id{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 9.6px 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #1083E3;
|
||||||
|
}
|
||||||
.canvas-plane-wrap{
|
.canvas-plane-wrap{
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -798,28 +806,28 @@
|
|||||||
color: #45576F;
|
color: #45576F;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
.drag-file-box{
|
.btn-area{
|
||||||
padding: 10px;
|
padding-bottom: 15px;
|
||||||
.btn-area{
|
border-bottom: 1px solid #ECF0F4;
|
||||||
padding-bottom: 15px;
|
.file-upload{
|
||||||
border-bottom: 1px solid #ECF0F4;
|
display: inline-block;
|
||||||
.file-upload{
|
height: 30px;
|
||||||
display: inline-block;
|
background-color: #94A0AD;
|
||||||
height: 30px;
|
padding: 0 10px;
|
||||||
background-color: #94A0AD;
|
border-radius: 2px;
|
||||||
padding: 0 10px;
|
font-size: 13px;
|
||||||
border-radius: 2px;
|
line-height: 30px;
|
||||||
font-size: 13px;
|
color: #fff;
|
||||||
line-height: 30px;
|
font-weight: 500;
|
||||||
color: #fff;
|
cursor: pointer;
|
||||||
font-weight: 500;
|
transition: background .15s ease-in-out;
|
||||||
cursor: pointer;
|
&:hover{
|
||||||
transition: background .15s ease-in-out;
|
background-color: #607F9A;
|
||||||
&:hover{
|
|
||||||
background-color: #607F9A;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.drag-file-box{
|
||||||
|
padding: 10px;
|
||||||
.drag-file-area{
|
.drag-file-area{
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
|
|||||||
@ -24,6 +24,10 @@
|
|||||||
.ag-header-cell{
|
.ag-header-cell{
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
border-right: 1px solid #738596;
|
||||||
|
&:last-child{
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.ag-header-cell-label{
|
.ag-header-cell-label{
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
@ -279,10 +279,11 @@ $alert-color: #101010;
|
|||||||
border-bottom: 1px solid #424242;
|
border-bottom: 1px solid #424242;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.grid-check-form-block{
|
.grid-check-form-flex{
|
||||||
display: block;
|
display: flex;
|
||||||
> div{
|
gap: 10px;
|
||||||
margin-bottom: 10px;
|
.d-check-box{
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.grid-option-overflow{
|
.grid-option-overflow{
|
||||||
@ -1313,13 +1314,13 @@ $alert-color: #101010;
|
|||||||
|
|
||||||
.circle {
|
.circle {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 12px;
|
width: 10px;
|
||||||
height: 12px;
|
height: 10px;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
top: 95%;
|
top: 88%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform-origin: 0 -90px; /* 중심에서 반지름 거리만큼 떨어져 위치 */
|
transform-origin: 0 -76px; /* 중심에서 반지름 거리만큼 떨어져 위치 */
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
/* 0번을 180도 위치(아래)에, 13번을 0도 위치(위)에 배치 */
|
/* 0번을 180도 위치(아래)에, 13번을 0도 위치(위)에 배치 */
|
||||||
@ -1366,8 +1367,8 @@ $alert-color: #101010;
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 5px;
|
width: 4px;
|
||||||
height: 5px;
|
height: 4px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
@ -1381,15 +1382,15 @@ $alert-color: #101010;
|
|||||||
top: 50%;
|
top: 50%;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
width: 148px;
|
width: 121px;
|
||||||
height: 148px;
|
height: 121px;
|
||||||
border: 4px solid #fff;
|
border: 4px solid #fff;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
.compas-arr{
|
.compas-arr{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: url(../../public/static/images/canvas/compas.svg)no-repeat center;
|
background: url(../../public/static/images/canvas/compas.svg)no-repeat center;
|
||||||
background-size: 122px 122px;
|
background-size: 100px 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1441,10 +1442,10 @@ $alert-color: #101010;
|
|||||||
.roof-module-compas{
|
.roof-module-compas{
|
||||||
margin-bottom: 24px;
|
margin-bottom: 24px;
|
||||||
.compas-box-inner{
|
.compas-box-inner{
|
||||||
width: 280px;
|
width: 235px;
|
||||||
height: 253px;
|
height: 215px;
|
||||||
.circle{
|
.circle{
|
||||||
top: 86%;
|
top: 85%;
|
||||||
// &:nth-child(1),
|
// &:nth-child(1),
|
||||||
// &:nth-child(7),
|
// &:nth-child(7),
|
||||||
// &:nth-child(13),
|
// &:nth-child(13),
|
||||||
@ -1461,7 +1462,7 @@ $alert-color: #101010;
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
i{
|
i{
|
||||||
top: 22px;
|
top: 19px;
|
||||||
}
|
}
|
||||||
&.act{
|
&.act{
|
||||||
i{color: #8B8B8B;}
|
i{color: #8B8B8B;}
|
||||||
@ -1482,6 +1483,10 @@ $alert-color: #101010;
|
|||||||
.outline-form{
|
.outline-form{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
.non-flex{
|
||||||
|
min-width: 300px;
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.module-box-tab{
|
.module-box-tab{
|
||||||
@ -2172,31 +2177,46 @@ $alert-color: #101010;
|
|||||||
&.tab2{
|
&.tab2{
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
gap: 15px;
|
gap: 15px;
|
||||||
|
.eaves-keraba-table{
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.module-flex-item{
|
.module-flex-item{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
.module-flex-item-tit{
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #fff;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
border-bottom: 1px solid #4D4D4D;
|
|
||||||
}
|
|
||||||
.flex-item-btn-wrap{
|
.flex-item-btn-wrap{
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 24px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
&.non-flex{
|
&.non-flex{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex: none;
|
flex: none;
|
||||||
padding-top: 27.5px;
|
width: 340px;
|
||||||
width: 260px;
|
|
||||||
}
|
}
|
||||||
|
.flex-item-button{
|
||||||
|
margin-top: 10px;
|
||||||
|
button{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.module-flex-item-tit-wrap{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #4D4D4D;
|
||||||
|
.module-flex-item-tit{
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
button{
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2278,3 +2298,142 @@ $alert-color: #101010;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.roof-module-inner{
|
||||||
|
display: flex;
|
||||||
|
.compas-wrapper{
|
||||||
|
position: relative;
|
||||||
|
flex: none;
|
||||||
|
width: 300px;
|
||||||
|
padding-right: 15px;
|
||||||
|
&:before{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 10px;
|
||||||
|
width: 1px;
|
||||||
|
height: 100%;
|
||||||
|
background-color: #424242;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.compas-table-wrap{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
.compas-table-box{
|
||||||
|
background-color: #3D3D3D;
|
||||||
|
padding: 10px;
|
||||||
|
.outline-form{
|
||||||
|
span{
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.compas-grid-table{
|
||||||
|
display: grid;
|
||||||
|
gap: 10px;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
.outline-form{
|
||||||
|
span{
|
||||||
|
width: 65px;
|
||||||
|
&.thin{
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.module-table-block-wrap{
|
||||||
|
.roof-module-table{
|
||||||
|
&.self{
|
||||||
|
table{
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.self-table-radio{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.placement-name-guide{
|
||||||
|
font-size: 11px;
|
||||||
|
margin-left: 10px;
|
||||||
|
color: #53a7eb;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hexagonal-flex-wrap{
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
.non-flex{
|
||||||
|
flex: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.hexagonal-radio-wrap{
|
||||||
|
padding: 17px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-check-guide{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
margin-top: 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
.arr{
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
margin-left: 10px;
|
||||||
|
background: url(../../public/static/images/canvas/hide-check-arr.svg) no-repeat center;
|
||||||
|
background-size: contain;
|
||||||
|
transform: rotate(180deg);
|
||||||
|
&.act{
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.module-table-box{
|
||||||
|
&.hide{
|
||||||
|
overflow: hidden;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2025-05-07 지붕모듈
|
||||||
|
.module-input-area{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
.module-area-title{
|
||||||
|
flex: none;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
.module-input-wrap{
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
.outline-form{
|
||||||
|
width: calc(33.333% - 10px);
|
||||||
|
margin-right: 15px;
|
||||||
|
&:last-child{
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.input-grid{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -222,15 +222,16 @@ button{
|
|||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
font-family: 'Noto Sans JP', sans-serif;
|
font-family: 'Noto Sans JP', sans-serif;
|
||||||
background-color: transparent;
|
background-color: #353535;
|
||||||
border: 1px solid #484848;
|
border: 1px solid #484848;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
&.blue{
|
&.blue{
|
||||||
background-color: #4C6FBF;
|
background-color: #4C6FBF;
|
||||||
border: 1px solid #4C6FBF;
|
border: 1px solid #4C6FBF;
|
||||||
&:hover{
|
&:hover{
|
||||||
background-color: #414E6C;
|
background-color: #4C6FBF;
|
||||||
border: 1px solid #414E6C;
|
border: 1px solid #4C6FBF;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.white{
|
&.white{
|
||||||
@ -241,13 +242,14 @@ button{
|
|||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
color: #101010;
|
color: #101010;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover{
|
&:hover{
|
||||||
font-weight: 400;
|
background-color: #353535;
|
||||||
background-color: transparent;
|
|
||||||
border: 1px solid #484848;
|
border: 1px solid #484848;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.self{
|
&.self{
|
||||||
@ -375,13 +377,14 @@ button{
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
&:hover{
|
&:hover{
|
||||||
background-color: #2C2C2C;
|
background-color: #2C2C2C;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
width: 2px;
|
width: 5px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1022,3 +1025,22 @@ input:checked + .slider {
|
|||||||
.swal2-container{
|
.swal2-container{
|
||||||
z-index: 120000;
|
z-index: 120000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// textarea
|
||||||
|
.textarea-form{
|
||||||
|
width: 100%;
|
||||||
|
outline: none;
|
||||||
|
resize: none;
|
||||||
|
border: none;
|
||||||
|
border: 1px solid #eee;
|
||||||
|
min-height: 150px;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #45576F;
|
||||||
|
border-radius: 2px;
|
||||||
|
font-family: "Noto Sans JP", sans-serif;
|
||||||
|
transition: border .15s ease-in-out;
|
||||||
|
&:focus{
|
||||||
|
border-color: #94a0ad;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -288,55 +288,56 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 커뮤니티
|
// 커뮤니티
|
||||||
.community_detail{
|
.community_detail-tit{
|
||||||
.community_detail-tit{
|
font-size: 16px;
|
||||||
font-size: 16px;
|
color: #101010;
|
||||||
color: #101010;
|
font-weight: 600;
|
||||||
font-weight: 600;
|
padding-bottom: 14px;
|
||||||
padding-bottom: 14px;
|
border-bottom: 2px solid #101010;
|
||||||
border-bottom: 2px solid #101010;
|
}
|
||||||
}
|
.community_detail-file-wrap{
|
||||||
.community_detail-file-wrap{
|
padding: 24px 0;
|
||||||
padding: 24px 0;
|
border-bottom: 1px solid #E5E5E5;
|
||||||
border-bottom: 1px solid #E5E5E5;
|
dt{
|
||||||
dt{
|
|
||||||
font-size: 13px;
|
|
||||||
color: #101010;
|
|
||||||
font-weight: 500;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
dd{
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
color: #344356;
|
|
||||||
&:last-child{
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.community_detail-inner{
|
|
||||||
max-height: 300px;
|
|
||||||
overflow-y: auto;
|
|
||||||
margin-top: 20px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
color: #101010;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
dd{
|
||||||
|
font-size: 12px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #45576F;
|
margin-bottom: 3px;
|
||||||
line-height: 26px;
|
color: #344356;
|
||||||
word-break: keep-all;
|
&:nth-child(2){
|
||||||
&::-webkit-scrollbar {
|
margin-top: 15px;
|
||||||
width: 4px;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
}
|
||||||
&::-webkit-scrollbar-thumb {
|
&:last-child{
|
||||||
background-color: #C1CCD7;
|
margin-bottom: 0;
|
||||||
}
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.community_detail-inner{
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #45576F;
|
||||||
|
line-height: 26px;
|
||||||
|
word-break: keep-all;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
width: 4px;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #C1CCD7;
|
||||||
|
}
|
||||||
|
&::-webkit-scrollbar-track {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 견적 복사
|
// 견적 복사
|
||||||
.estimate-copy-info-item{
|
.estimate-copy-info-item{
|
||||||
@ -369,3 +370,116 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 1:1문의
|
||||||
|
.one-on-one{
|
||||||
|
.select-wrap{
|
||||||
|
width: 250px;
|
||||||
|
}
|
||||||
|
.input-wrap{
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
&.btn-area{
|
||||||
|
padding-bottom: 0;
|
||||||
|
border: none;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
&.drag-file-box{
|
||||||
|
border: 1px solid #eee;
|
||||||
|
.drag-file-area{
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.oneonone-header-wrap{
|
||||||
|
padding-bottom: 14px;
|
||||||
|
border-bottom: 2px solid #101010;
|
||||||
|
.oneonone-title{
|
||||||
|
font-size: 16px;
|
||||||
|
color: #101010;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.oneonone-infor{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.profile{
|
||||||
|
position: relative;
|
||||||
|
padding-left: 26px;
|
||||||
|
padding-right: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #101010;
|
||||||
|
&::before{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
background: url(./../../public/static/images/sub/oneonone_profile_icon.svg)no-repeat center;
|
||||||
|
}
|
||||||
|
&::after{
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 0;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
width: 1px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #CCCCCC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.date{
|
||||||
|
padding-left: 8px;
|
||||||
|
font-size: 13px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #101010;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.oneonone-detail{
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #101010;
|
||||||
|
border-top: none;
|
||||||
|
.community_detail-file-wrap{
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
.community_detail-inner{
|
||||||
|
max-height: 110px;
|
||||||
|
margin-top: 24px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.oneonone-answer{
|
||||||
|
margin-top: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #101010;
|
||||||
|
.community_detail-inner{
|
||||||
|
max-height: 110px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.community_detail-file-wrap{
|
||||||
|
border-top: 1px solid #D4DCE7;
|
||||||
|
padding: 16px 0 0 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.answer-title-wrap{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 14px;
|
||||||
|
border-bottom: 1px solid #D4DCE7;
|
||||||
|
.answer-title{
|
||||||
|
font-size: 14px;
|
||||||
|
color: #101010;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.oneonone-infor{
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -47,6 +47,16 @@ table{
|
|||||||
}
|
}
|
||||||
.form-flex-wrap{
|
.form-flex-wrap{
|
||||||
@include flexbox;
|
@include flexbox;
|
||||||
|
.form-flex-select{
|
||||||
|
@include flexbox;
|
||||||
|
label{
|
||||||
|
flex: none;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.form-select{
|
||||||
|
min-width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.date-picker-wrap{
|
.date-picker-wrap{
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -236,6 +246,16 @@ table{
|
|||||||
.d-check-box{
|
.d-check-box{
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
.color-wrap{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.color-box{
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbody{
|
tbody{
|
||||||
|
|||||||
@ -348,15 +348,15 @@ export const calculateIntersection = (line1, line2) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Determine the min and max for line1 and line2 for both x and y
|
// Determine the min and max for line1 and line2 for both x and y
|
||||||
const line1MinX = Math.min(line1.x1, line1.x2)
|
const line1MinX = Math.min(line1.x1, line1.x2) - 5
|
||||||
const line1MaxX = Math.max(line1.x1, line1.x2)
|
const line1MaxX = Math.max(line1.x1, line1.x2) + 5
|
||||||
const line2MinX = Math.min(line2.x1, line2.x2)
|
const line2MinX = Math.min(line2.x1, line2.x2) - 5
|
||||||
const line2MaxX = Math.max(line2.x1, line2.x2)
|
const line2MaxX = Math.max(line2.x1, line2.x2) + 5
|
||||||
|
|
||||||
const line1MinY = Math.min(line1.y1, line1.y2)
|
const line1MinY = Math.min(line1.y1, line1.y2) - 5
|
||||||
const line1MaxY = Math.max(line1.y1, line1.y2)
|
const line1MaxY = Math.max(line1.y1, line1.y2) + 5
|
||||||
const line2MinY = Math.min(line2.y1, line2.y2)
|
const line2MinY = Math.min(line2.y1, line2.y2) - 5
|
||||||
const line2MaxY = Math.max(line2.y1, line2.y2)
|
const line2MaxY = Math.max(line2.y1, line2.y2) + 5
|
||||||
|
|
||||||
// Check if the intersection X and Y are within the range of both lines
|
// Check if the intersection X and Y are within the range of both lines
|
||||||
if (
|
if (
|
||||||
@ -518,14 +518,23 @@ export const sortedPointLessEightPoint = (points) => {
|
|||||||
*/
|
*/
|
||||||
// 직선의 방정식.
|
// 직선의 방정식.
|
||||||
// 방정식은 ax + by + c = 0이며, 점의 좌표를 대입하여 계산된 값은 직선과 점 사이의 관계를 나타낸다.
|
// 방정식은 ax + by + c = 0이며, 점의 좌표를 대입하여 계산된 값은 직선과 점 사이의 관계를 나타낸다.
|
||||||
export function isPointOnLine(line, point) {
|
export function isPointOnLine({ x1, y1, x2, y2 }, { x, y }) {
|
||||||
const a = line.y2 - line.y1
|
/*const a = line.y2 - line.y1
|
||||||
const b = line.x1 - line.x2
|
const b = line.x1 - line.x2
|
||||||
const c = line.x2 * line.y1 - line.x1 * line.y2
|
const c = line.x2 * line.y1 - line.x1 * line.y2
|
||||||
const result = Math.abs(a * point.x + b * point.y + c) / 100
|
const result = Math.abs(a * point.x + b * point.y + c) / 100
|
||||||
|
|
||||||
// 점이 선 위에 있는지 확인
|
// 점이 선 위에 있는지 확인
|
||||||
return result <= 10
|
return result <= 10*/
|
||||||
|
// 직선 방정식 만족 여부 확인
|
||||||
|
const crossProduct = (y - y1) * (x2 - x1) - (x - x1) * (y2 - y1)
|
||||||
|
if (Math.abs(crossProduct) > 5) return false // 작은 오차 허용
|
||||||
|
|
||||||
|
// 점이 선분의 범위 내에 있는지 확인
|
||||||
|
const withinXRange = Math.min(x1, x2) <= x && x <= Math.max(x1, x2)
|
||||||
|
const withinYRange = Math.min(y1, y2) <= y && y <= Math.max(y1, y2)
|
||||||
|
|
||||||
|
return withinXRange && withinYRange
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 점과 가까운 line 찾기
|
* 점과 가까운 line 찾기
|
||||||
|
|||||||
@ -145,9 +145,19 @@ export const unescapeString = (str) => {
|
|||||||
''': "'",
|
''': "'",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
1. 한번 변환은 {" 로 변환됨 : 에러 발생 => while 변경
|
||||||
|
2. 변환할 내용이 없으면 리턴값이 undefined
|
||||||
|
|
||||||
if (regex.test(str)) {
|
if (regex.test(str)) {
|
||||||
return str.replace(regex, (matched) => chars[matched] || matched)
|
return str.replace(regex, (matched) => chars[matched] || matched)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (regex.test(str)) {
|
||||||
|
str = str.replace(regex, (matched) => chars[matched] || matched);
|
||||||
|
}
|
||||||
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isNullOrUndefined = (value) => {
|
export const isNullOrUndefined = (value) => {
|
||||||
|
|||||||
@ -305,6 +305,9 @@ export function removeDuplicatePolygons(polygons) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const isSamePoint = (a, b) => {
|
export const isSamePoint = (a, b) => {
|
||||||
|
if (!a || !b) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2
|
return Math.abs(Math.round(a.x) - Math.round(b.x)) <= 2 && Math.abs(Math.round(a.y) - Math.round(b.y)) <= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3524,7 +3527,7 @@ export const calcLinePlaneSize = (points) => {
|
|||||||
* @param degree
|
* @param degree
|
||||||
* @returns number
|
* @returns number
|
||||||
*/
|
*/
|
||||||
export const calcLineActualSize = (points, degree) => {
|
export const calcLineActualSize = (points, degree = 0) => {
|
||||||
const { x1, y1, x2, y2 } = points
|
const { x1, y1, x2, y2 } = points
|
||||||
const planeSize = calcLinePlaneSize(points)
|
const planeSize = calcLinePlaneSize(points)
|
||||||
let height = Big(Math.tan(Big(degree).times(Math.PI / 180))).times(planeSize)
|
let height = Big(Math.tan(Big(degree).times(Math.PI / 180))).times(planeSize)
|
||||||
|
|||||||
2
startscript-3000.js
Normal file
2
startscript-3000.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('yarn dev -p 3000', { windowsHide: true })
|
||||||
@ -1,2 +1,2 @@
|
|||||||
var exec = require('child_process').exec
|
var exec = require('child_process').exec
|
||||||
exec('yarn start', { windowsHide: true })
|
exec('yarn dev -p 5000', { windowsHide: true })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user