Merge branch 'dev' into feature/jaeyoung
# Conflicts: # src/hooks/useContextMenu.js
This commit is contained in:
commit
5ef8ccfc40
@ -3,17 +3,32 @@
|
||||
import { createContext, useEffect, useState } from 'react'
|
||||
import { useLocalStorage } from 'usehooks-ts'
|
||||
|
||||
export const GlobalDataContext = createContext({
|
||||
managementState: {},
|
||||
setManagementState: () => {},
|
||||
managementStateLoaded: null,
|
||||
})
|
||||
// export const GlobalDataContext = createContext({
|
||||
// managementState: {},
|
||||
// setManagementState: () => {},
|
||||
// managementStateLoaded: null,
|
||||
// })
|
||||
export const GlobalDataContext = createContext(null)
|
||||
|
||||
const GlobalDataProvider = ({ children }) => {
|
||||
const [managementState, setManagementState] = useState(null)
|
||||
// TODO: 임시 조치이며 개발 완료시 삭제 예정 -> 잊지말기...
|
||||
const [managementStateLoaded, setManagementStateLoaded] = useLocalStorage('managementStateLoaded', null)
|
||||
|
||||
// const pathname = usePathname()
|
||||
// const setCorrentObjectNo = useSetRecoilState(correntObjectNoState)
|
||||
// const searchParams = useSearchParams()
|
||||
// const objectNo = searchParams.get('objectNo')
|
||||
// const pid = searchParams.get('pid')
|
||||
// useEffect(() => {
|
||||
// if (pathname === '/floor-plan') {
|
||||
// if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) {
|
||||
// notFound()
|
||||
// }
|
||||
// setCorrentObjectNo(objectNo)
|
||||
// }
|
||||
// }, [pathname])
|
||||
|
||||
useEffect(() => {
|
||||
if (managementState !== null) {
|
||||
setManagementStateLoaded(managementState)
|
||||
|
||||
11
src/app/GlobalLoadingProvider.js
Normal file
11
src/app/GlobalLoadingProvider.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import { useContext } from 'react'
|
||||
import { QcastContext } from './QcastProvider'
|
||||
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
||||
|
||||
export default function GlobalLoadingProvider() {
|
||||
const { isGlobalLoading } = useContext(QcastContext)
|
||||
|
||||
return <>{isGlobalLoading && <GlobalSpinner />}</>
|
||||
}
|
||||
@ -6,7 +6,6 @@ import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import ServerError from './error'
|
||||
|
||||
import '@/styles/common.scss'
|
||||
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
||||
|
||||
export const QcastContext = createContext({
|
||||
qcastState: {},
|
||||
@ -17,7 +16,7 @@ export const QcastContext = createContext({
|
||||
|
||||
export const QcastProvider = ({ children }) => {
|
||||
const [planSave, setPlanSave] = useState(false)
|
||||
const [isGlobalLoading, setIsGlobalLoading] = useState(false)
|
||||
const [isGlobalLoading, setIsGlobalLoading] = useState(true)
|
||||
const { commonCode, findCommonCode } = useCommonCode()
|
||||
|
||||
const [qcastState, setQcastState] = useState({
|
||||
@ -35,11 +34,6 @@ export const QcastProvider = ({ children }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{isGlobalLoading && (
|
||||
<div className="fixed inset-0 bg-white z-50 flex items-center justify-center">
|
||||
<GlobalSpinner />
|
||||
</div>
|
||||
)}
|
||||
<QcastContext.Provider value={{ qcastState, setQcastState, isGlobalLoading, setIsGlobalLoading }}>
|
||||
<ErrorBoundary fallback={<ServerError />}>{children}</ErrorBoundary>
|
||||
</QcastContext.Provider>
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
'ues client'
|
||||
|
||||
import { correntObjectNoState } from '@/store/settingAtom'
|
||||
// import { correntObjectNoState } from '@/store/settingAtom'
|
||||
import { notFound, usePathname, useSearchParams } from 'next/navigation'
|
||||
import { createContext, useReducer, useState, useEffect } from 'react'
|
||||
import { useSetRecoilState } from 'recoil'
|
||||
// import { useSetRecoilState } from 'recoil'
|
||||
|
||||
const reducer = (prevState, nextState) => {
|
||||
return { ...prevState, ...nextState }
|
||||
@ -27,12 +27,12 @@ const defaultEstimateData = {
|
||||
* 모듈,회로 구성 상태 데이터
|
||||
* 각 설정 팝업 상태를 저장하는 데이터
|
||||
*/
|
||||
const defaultProcessStep = {
|
||||
gnbStep: 0,
|
||||
processStep: 0,
|
||||
moduleCofigureData: {},
|
||||
pcsConfigureData: {},
|
||||
}
|
||||
// const defaultProcessStep = {
|
||||
// gnbStep: 0,
|
||||
// processStep: 0,
|
||||
// moduleCofigureData: {},
|
||||
// pcsConfigureData: {},
|
||||
// }
|
||||
|
||||
export const FloorPlanContext = createContext({
|
||||
floorPlanState: {},
|
||||
@ -42,20 +42,29 @@ export const FloorPlanContext = createContext({
|
||||
})
|
||||
|
||||
const FloorPlanProvider = ({ children }) => {
|
||||
const pathname = usePathname()
|
||||
const setCurrentObjectNo = useSetRecoilState(correntObjectNoState)
|
||||
// const pathname = usePathname()
|
||||
// const setCorrentObjectNo = useSetRecoilState(correntObjectNoState)
|
||||
const searchParams = useSearchParams()
|
||||
const objectNo = searchParams.get('objectNo')
|
||||
const pid = searchParams.get('pid')
|
||||
// useEffect(() => {
|
||||
// console.log('🚀 ~ useEffect ~ objectNo:')
|
||||
// if (pathname === '/floor-plan') {
|
||||
// if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) {
|
||||
// notFound()
|
||||
// }
|
||||
// setCorrentObjectNo(objectNo)
|
||||
// }
|
||||
// }, [])
|
||||
|
||||
useEffect(() => { // 오류 발생으로 useEffect 사용
|
||||
if (pathname === '/floor-plan') {
|
||||
if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) {
|
||||
notFound()
|
||||
}
|
||||
setCurrentObjectNo(objectNo)
|
||||
}
|
||||
}, [pid, objectNo])
|
||||
//useEffect(() => { // 오류 발생으로 useEffect 사용
|
||||
// if (pathname === '/floor-plan') {
|
||||
// if (pid === undefined || pid === '' || pid === null || objectNo === undefined || objectNo === '' || objectNo === null) {
|
||||
// notFound()
|
||||
// }
|
||||
// setCurrentObjectNo(objectNo)
|
||||
// }
|
||||
//}, [pid, objectNo])
|
||||
|
||||
const [floorPlanState, setFloorPlanState] = useState({
|
||||
// 플랜 파일 업로드 모달 오픈 제어
|
||||
@ -70,12 +79,10 @@ const FloorPlanProvider = ({ children }) => {
|
||||
|
||||
const [estimateContextState, setEstimateContextState] = useReducer(reducer, defaultEstimateData)
|
||||
|
||||
const [processStepState, setProcessStepState] = useReducer(reducer, defaultProcessStep)
|
||||
// const [processStepState, setProcessStepState] = useReducer(reducer, defaultProcessStep)
|
||||
|
||||
return (
|
||||
<FloorPlanContext.Provider
|
||||
value={{ floorPlanState, setFloorPlanState, estimateContextState, setEstimateContextState, processStepState, setProcessStepState }}
|
||||
>
|
||||
<FloorPlanContext.Provider value={{ floorPlanState, setFloorPlanState, estimateContextState, setEstimateContextState }}>
|
||||
{children}
|
||||
</FloorPlanContext.Provider>
|
||||
)
|
||||
|
||||
@ -1,31 +1,22 @@
|
||||
'use client'
|
||||
|
||||
import { usePathname } from 'next/navigation'
|
||||
import FloorPlanProvider from './FloorPlanProvider'
|
||||
import FloorPlan from '@/components/floor-plan/FloorPlan'
|
||||
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
|
||||
import { Suspense } from 'react'
|
||||
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
||||
|
||||
export default function FloorPlanLayout({ children }) {
|
||||
console.log('🚀 ~ FloorPlanLayout ~ FloorPlanLayout:')
|
||||
const pathname = usePathname()
|
||||
console.log('🚀 ~ FloorPlanLayout ~ pathname:', pathname)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Suspense fallback={<GlobalSpinner />}>
|
||||
<FloorPlanProvider>
|
||||
<FloorPlan>
|
||||
{/* {pathname.includes('estimate') || pathname.includes('simulator') ? (
|
||||
<FloorPlanProvider>
|
||||
<FloorPlan>
|
||||
{/* {pathname.includes('estimate') || pathname.includes('simulator') ? (
|
||||
<div className="canvas-layout">{children}</div>
|
||||
) : (
|
||||
<CanvasLayout>{children}</CanvasLayout>
|
||||
)} */}
|
||||
<CanvasLayout>{children}</CanvasLayout>
|
||||
</FloorPlan>
|
||||
</FloorPlanProvider>
|
||||
</Suspense>
|
||||
<CanvasLayout>{children}</CanvasLayout>
|
||||
</FloorPlan>
|
||||
</FloorPlanProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -8,15 +8,13 @@ import SessionProvider from './SessionProvider'
|
||||
import GlobalDataProvider from './GlobalDataProvider'
|
||||
import Header from '@/components/header/Header'
|
||||
import QModal from '@/components/common/modal/QModal'
|
||||
import Dimmed from '@/components/ui/Dimmed'
|
||||
import PopupManager from '@/components/common/popupManager/PopupManager'
|
||||
|
||||
import './globals.css'
|
||||
import '../styles/style.scss'
|
||||
import '../styles/contents.scss'
|
||||
import Footer from '@/components/footer/Footer'
|
||||
import { Suspense } from 'react'
|
||||
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
||||
import GlobalLoadingProvider from './GlobalLoadingProvider'
|
||||
|
||||
export const metadata = {
|
||||
title: 'Create Next App',
|
||||
@ -66,24 +64,22 @@ export default async function RootLayout({ children }) {
|
||||
<GlobalDataProvider>
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Suspense fallback={<GlobalSpinner />}>
|
||||
{headerPathname === '/login' || headerPathname === '/join' ? (
|
||||
<QcastProvider>{children}</QcastProvider>
|
||||
) : (
|
||||
<QcastProvider>
|
||||
<div className="wrap">
|
||||
<Header userSession={sessionProps} />
|
||||
<div className="content">
|
||||
<Dimmed />
|
||||
<SessionProvider useSession={sessionProps}>{children}</SessionProvider>
|
||||
</div>
|
||||
<Footer />
|
||||
{headerPathname === '/login' || headerPathname === '/join' ? (
|
||||
<QcastProvider>{children}</QcastProvider>
|
||||
) : (
|
||||
<QcastProvider>
|
||||
<GlobalLoadingProvider />
|
||||
<div className="wrap">
|
||||
<Header userSession={sessionProps} />
|
||||
<div className="content">
|
||||
<SessionProvider useSession={sessionProps}>{children}</SessionProvider>
|
||||
</div>
|
||||
</QcastProvider>
|
||||
)}
|
||||
<QModal />
|
||||
<PopupManager />
|
||||
</Suspense>
|
||||
<Footer />
|
||||
</div>
|
||||
</QcastProvider>
|
||||
)}
|
||||
<QModal />
|
||||
<PopupManager />
|
||||
</body>
|
||||
</html>
|
||||
</GlobalDataProvider>
|
||||
|
||||
@ -12,7 +12,8 @@ const ManagementProvider = ({ children }) => {
|
||||
// }, [managementState])
|
||||
|
||||
// return <ManagementContext.Provider value={{ managementState, setManagementState }}>{children}</ManagementContext.Provider>
|
||||
return <ManagementContext.Provider>{children}</ManagementContext.Provider>
|
||||
// return <ManagementContext.Provider>{children}</ManagementContext.Provider>
|
||||
return <>{children}</>
|
||||
}
|
||||
|
||||
export default ManagementProvider
|
||||
|
||||
@ -113,6 +113,7 @@ export const POLYGON_TYPE = {
|
||||
TRESTLE: 'trestle',
|
||||
MODULE_SETUP_SURFACE: 'moduleSetupSurface',
|
||||
MODULE: 'module',
|
||||
OBJECT_SURFACE: 'objectOffset',
|
||||
}
|
||||
|
||||
export const SAVE_KEY = [
|
||||
@ -170,6 +171,12 @@ export const SAVE_KEY = [
|
||||
'supFitIntvlPct',
|
||||
'rackLen',
|
||||
'trestleDetail',
|
||||
'turfPoints',
|
||||
'tempIndex',
|
||||
'surfaceId',
|
||||
'moduleRowsTotCnt',
|
||||
'seq',
|
||||
'smartRackId',
|
||||
]
|
||||
|
||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype]
|
||||
|
||||
@ -27,6 +27,7 @@ import useSWR from 'swr'
|
||||
import useSWRMutation from 'swr/mutation'
|
||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||
import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
|
||||
import { moduleSelectionDataPlanListState } from '@/store/selectedModuleOptions'
|
||||
|
||||
export default function Playground() {
|
||||
const [useCadFile, setUseCadFile] = useRecoilState(useCadFileState)
|
||||
@ -256,25 +257,25 @@ export default function Playground() {
|
||||
})
|
||||
}
|
||||
|
||||
const [callFlag, setCallFlag] = useState(false)
|
||||
// const [callFlag, setCallFlag] = useState(false)
|
||||
// const { data: tutoData, error, isLoading } = useSWR('http://localhost:8080/api/tutorial', getFetcher)
|
||||
const { data: tutoData, error, isLoading } = useSWR(callFlag ? 'http://localhost:8080/api/tutorial' : null, getFetcher)
|
||||
const { trigger, isMutating } = useSWRMutation('http://localhost:8080/api/tutorial', postFetcher)
|
||||
// const { data: tutoData, error, isLoading } = useSWR(callFlag ? 'http://localhost:8080/api/tutorial' : null, getFetcher)
|
||||
// const { trigger, isMutating } = useSWRMutation('http://localhost:8080/api/tutorial', postFetcher)
|
||||
|
||||
if (isLoading) {
|
||||
return <div>Loading...</div>
|
||||
}
|
||||
// if (isLoading) {
|
||||
// return <div>Loading...</div>
|
||||
// }
|
||||
|
||||
if (error) {
|
||||
return <div>Error...</div>
|
||||
}
|
||||
// if (error) {
|
||||
// return <div>Error...</div>
|
||||
// }
|
||||
|
||||
useCanvasPopupStatusController(1)
|
||||
// const [moduleSelectionDataPlanListStore, setModuleSelectionDataPlanListStore] = useRecoilState(moduleSelectionDataPlanListState)
|
||||
// useEffect(() => {
|
||||
// console.log('🚀 ~ Playground ~ moduleSelectionDataPlanListStore:', moduleSelectionDataPlanListStore)
|
||||
// }, [moduleSelectionDataPlanListStore])
|
||||
// const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController({ objectNo: 'R201T01241120001', planNo: 2, popupType: 2 })
|
||||
|
||||
const [canvasPopupStatusState, setCanvasPopupStatusState] = useRecoilState(canvasPopupStatusStore)
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ Playground ~ canvasPopupStatusState:', canvasPopupStatusState)
|
||||
}, [canvasPopupStatusState])
|
||||
return (
|
||||
<>
|
||||
<div className="container mx-auto p-4 m-4 border">
|
||||
@ -579,7 +580,7 @@ export default function Playground() {
|
||||
Sweetalert - alert
|
||||
</Button>
|
||||
</div>
|
||||
<div className="my-2">
|
||||
{/* <div className="my-2">
|
||||
{tutoData &&
|
||||
tutoData.map((item) => (
|
||||
<div key={item.id}>
|
||||
@ -594,6 +595,301 @@ export default function Playground() {
|
||||
<Button disabled={isMutating} onClick={() => trigger({ id: 3, name: 'seulda kim', email: 'seulda.kim@interplug.co.kr' })}>
|
||||
insert data
|
||||
</Button>
|
||||
</div> */}
|
||||
<div className="my-2">
|
||||
<Button
|
||||
onClick={() => {
|
||||
canvasPopupStatusTrigger({
|
||||
common: {
|
||||
illuminationTp: '3',
|
||||
instHt: '10',
|
||||
stdWindSpeed: 'WL_32',
|
||||
stdSnowLd: '5',
|
||||
moduleTpCd: 'A1',
|
||||
moduleItemId: '106796',
|
||||
},
|
||||
roofConstructions: [
|
||||
{
|
||||
roofIndex: 0,
|
||||
addRoof: {
|
||||
roofMatlCd: 'ROOF_ID_WA_53A',
|
||||
roofMatlNm: '일본기와 A',
|
||||
roofMatlNmJp: '和瓦A',
|
||||
widAuth: 'R',
|
||||
widBase: '265.000',
|
||||
lenAuth: 'R',
|
||||
lenBase: '235.000',
|
||||
roofPchAuth: null,
|
||||
roofPchBase: null,
|
||||
raftAuth: 'C',
|
||||
raftBaseCd: 'HEI_455',
|
||||
id: 'ROOF_ID_WA_53A',
|
||||
name: '일본기와 A',
|
||||
selected: true,
|
||||
index: 0,
|
||||
nameJp: '和瓦A',
|
||||
length: 235,
|
||||
width: 265,
|
||||
raft: 'HEI_455',
|
||||
layout: 'P',
|
||||
hajebichi: 0,
|
||||
pitch: 7,
|
||||
angle: 21.8,
|
||||
roofSizeSet: '1',
|
||||
roofAngleSet: 'slope',
|
||||
},
|
||||
trestle: {
|
||||
moduleTpCd: 'A1',
|
||||
moduleTpCdNm: 'A1type',
|
||||
moduleTpCdJp: 'A1type',
|
||||
roofMatlCd: 'ROOF_ID_WA_53A',
|
||||
roofMatlCdNm: '일본기와 A',
|
||||
roofMatlCdJp: '和瓦A',
|
||||
trestleMkrCd: 'ROOF_TECHRI',
|
||||
trestleMkrCdNm: '지붕 기술 연구소',
|
||||
trestleMkrCdJp: '屋根技術研究所',
|
||||
constMthdCd: 'CST026',
|
||||
constMthdCdNm: 'YG 앵커 랙 있음',
|
||||
constMthdCdJp: 'YGアンカー ラック有り',
|
||||
roofBaseCd: 'RFB001',
|
||||
roofBaseCdNm: '구조용 합판 9mm 이상',
|
||||
roofBaseCdJp: '構造用合板9mm以上',
|
||||
rackYn: null,
|
||||
priority: 1,
|
||||
},
|
||||
construction: {
|
||||
constTp: 'WORK_LV_ID_1',
|
||||
constTpNm: '표준 시공',
|
||||
constTpJp: '標準施工',
|
||||
constPossYn: 'Y',
|
||||
plvrYn: 'Y',
|
||||
cvrYn: 'Y',
|
||||
cvrLmtRow: 9999,
|
||||
snowGdPossYn: 'Y',
|
||||
roofIndex: 0,
|
||||
setupCover: true,
|
||||
setupSnowCover: true,
|
||||
selectedIndex: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
roofIndex: 1,
|
||||
addRoof: {
|
||||
roofMatlCd: 'ROOF_ID_WA_53B',
|
||||
roofMatlNm: '일본기와 B',
|
||||
roofMatlNmJp: '和瓦B',
|
||||
widAuth: 'R',
|
||||
widBase: '275.000',
|
||||
lenAuth: 'R',
|
||||
lenBase: '225.000',
|
||||
roofPchAuth: null,
|
||||
roofPchBase: null,
|
||||
raftAuth: 'C',
|
||||
raftBaseCd: 'HEI_455',
|
||||
id: 'ROOF_ID_WA_53B',
|
||||
name: '일본기와 B',
|
||||
selected: true,
|
||||
index: 1,
|
||||
nameJp: '和瓦B',
|
||||
length: 225,
|
||||
width: 275,
|
||||
raft: 'HEI_455',
|
||||
layout: 'P',
|
||||
hajebichi: 0,
|
||||
pitch: 5,
|
||||
angle: 21.8,
|
||||
roofSizeSet: '1',
|
||||
roofAngleSet: 'slope',
|
||||
},
|
||||
trestle: {
|
||||
moduleTpCd: 'A1',
|
||||
moduleTpCdNm: 'A1type',
|
||||
moduleTpCdJp: 'A1type',
|
||||
roofMatlCd: 'ROOF_ID_WA_53B',
|
||||
roofMatlCdNm: '일본기와 B',
|
||||
roofMatlCdJp: '和瓦B',
|
||||
trestleMkrCd: 'DAIDO HUNT',
|
||||
trestleMkrCdNm: '다이도 헌트',
|
||||
trestleMkrCdJp: 'ダイドーハント',
|
||||
constMthdCd: 'CST016',
|
||||
constMthdCdNm: '지지 기와Ⅱ-B 랙 있음',
|
||||
constMthdCdJp: '支持瓦Ⅱ-B ラック有り',
|
||||
roofBaseCd: 'RFB002',
|
||||
roofBaseCdNm: 'OSB12mm 이상',
|
||||
roofBaseCdJp: 'OSB12mm以上',
|
||||
rackYn: null,
|
||||
priority: 95,
|
||||
},
|
||||
construction: {
|
||||
constTp: 'WORK_LV_ID_1',
|
||||
constTpNm: '표준 시공',
|
||||
constTpJp: '標準施工',
|
||||
constPossYn: 'Y',
|
||||
plvrYn: 'Y',
|
||||
cvrYn: 'Y',
|
||||
cvrLmtRow: 9999,
|
||||
snowGdPossYn: 'Y',
|
||||
roofIndex: 1,
|
||||
setupCover: false,
|
||||
setupSnowCover: true,
|
||||
selectedIndex: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
roofIndex: 2,
|
||||
addRoof: {
|
||||
roofMatlCd: 'ROOF_ID_HIRA_C',
|
||||
roofMatlNm: '평판기와 C',
|
||||
roofMatlNmJp: '平板瓦C',
|
||||
widAuth: 'R',
|
||||
widBase: '305.000',
|
||||
lenAuth: 'R',
|
||||
lenBase: '280.000',
|
||||
roofPchAuth: null,
|
||||
roofPchBase: null,
|
||||
raftAuth: 'C',
|
||||
raftBaseCd: 'HEI_455',
|
||||
id: 'ROOF_ID_HIRA_C',
|
||||
name: '평판기와 C',
|
||||
selected: true,
|
||||
index: 2,
|
||||
nameJp: '平板瓦C',
|
||||
length: 280,
|
||||
width: 305,
|
||||
raft: 'HEI_455',
|
||||
layout: 'P',
|
||||
hajebichi: 0,
|
||||
pitch: 4,
|
||||
angle: 21.8,
|
||||
roofSizeSet: '1',
|
||||
roofAngleSet: 'slope',
|
||||
},
|
||||
trestle: {
|
||||
moduleTpCd: 'A1',
|
||||
moduleTpCdNm: 'A1type',
|
||||
moduleTpCdJp: 'A1type',
|
||||
roofMatlCd: 'ROOF_ID_HIRA_C',
|
||||
roofMatlCdNm: '평판기와 C',
|
||||
roofMatlCdJp: '平板瓦C',
|
||||
trestleMkrCd: 'ROOF_TECHRI',
|
||||
trestleMkrCdNm: '지붕 기술 연구소',
|
||||
trestleMkrCdJp: '屋根技術研究所',
|
||||
constMthdCd: 'CST034',
|
||||
constMthdCdNm: '지지 기와 C 랙 있음',
|
||||
constMthdCdJp: '支持瓦C ラック有り',
|
||||
roofBaseCd: 'RFB001',
|
||||
roofBaseCdNm: '구조용 합판 9mm 이상',
|
||||
roofBaseCdJp: '構造用合板9mm以上',
|
||||
rackYn: null,
|
||||
priority: 122,
|
||||
},
|
||||
construction: {
|
||||
constTp: 'WORK_LV_ID_1',
|
||||
constTpNm: '표준 시공',
|
||||
constTpJp: '標準施工',
|
||||
constPossYn: 'Y',
|
||||
plvrYn: 'Y',
|
||||
cvrYn: 'Y',
|
||||
cvrLmtRow: 9999,
|
||||
snowGdPossYn: 'Y',
|
||||
roofIndex: 2,
|
||||
setupCover: false,
|
||||
setupSnowCover: false,
|
||||
selectedIndex: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
roofIndex: 3,
|
||||
addRoof: {
|
||||
roofMatlCd: 'ROOF_ID_HIRA_D',
|
||||
roofMatlNm: '평판기와 D',
|
||||
roofMatlNmJp: '平板瓦D',
|
||||
widAuth: 'R',
|
||||
widBase: '305.000',
|
||||
lenAuth: 'R',
|
||||
lenBase: '280.000',
|
||||
roofPchAuth: null,
|
||||
roofPchBase: null,
|
||||
raftAuth: 'C',
|
||||
raftBaseCd: 'HEI_455',
|
||||
id: 'ROOF_ID_HIRA_D',
|
||||
name: '평판기와 D',
|
||||
selected: true,
|
||||
index: 3,
|
||||
nameJp: '平板瓦D',
|
||||
length: 280,
|
||||
width: 305,
|
||||
raft: 'HEI_455',
|
||||
layout: 'P',
|
||||
hajebichi: 0,
|
||||
pitch: 8,
|
||||
angle: 21.8,
|
||||
roofSizeSet: '1',
|
||||
roofAngleSet: 'slope',
|
||||
},
|
||||
trestle: {
|
||||
moduleTpCd: 'A1',
|
||||
moduleTpCdNm: 'A1type',
|
||||
moduleTpCdJp: 'A1type',
|
||||
roofMatlCd: 'ROOF_ID_HIRA_D',
|
||||
roofMatlCdNm: '평판기와 D',
|
||||
roofMatlCdJp: '平板瓦D',
|
||||
trestleMkrCd: 'DAIDO HUNT',
|
||||
trestleMkrCdNm: '다이도 헌트',
|
||||
trestleMkrCdJp: 'ダイドーハント',
|
||||
constMthdCd: 'CST018',
|
||||
constMthdCdNm: '지지 기와Ⅱ-D 랙 있음',
|
||||
constMthdCdJp: '支持瓦Ⅱ-D ラック有り',
|
||||
roofBaseCd: 'RFB002',
|
||||
roofBaseCdNm: 'OSB12mm 이상',
|
||||
roofBaseCdJp: 'OSB12mm以上',
|
||||
rackYn: null,
|
||||
priority: 203,
|
||||
},
|
||||
construction: {
|
||||
constTp: 'WORK_LV_ID_3',
|
||||
constTpNm: '강화 시공',
|
||||
constTpJp: '強化施工',
|
||||
constPossYn: 'Y',
|
||||
plvrYn: 'Y',
|
||||
cvrYn: 'Y',
|
||||
cvrLmtRow: 9999,
|
||||
snowGdPossYn: 'Y',
|
||||
roofIndex: 3,
|
||||
setupCover: false,
|
||||
setupSnowCover: false,
|
||||
selectedIndex: 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
module: {
|
||||
itemId: '106796',
|
||||
itemNm: 'Q.TRON M-G2.4+ 430',
|
||||
goodsNo: 'Q.TRON M-G2.4+ 430',
|
||||
itemTp: 'A1',
|
||||
mixMatlNo: null,
|
||||
mixItemTpYn: 'N',
|
||||
itemList: [
|
||||
{
|
||||
itemId: '106796',
|
||||
itemNm: 'Q.TRON M-G2.4+ 430',
|
||||
goodsNo: 'Q.TRON M-G2.4+ 430',
|
||||
itemTp: 'A1',
|
||||
color: '#BEF781',
|
||||
longAxis: '1722.000',
|
||||
shortAxis: '1134.000',
|
||||
thickness: '30.000',
|
||||
wpOut: '430',
|
||||
mixMatlNo: null,
|
||||
},
|
||||
],
|
||||
name: 'Q.TRON M-G2.4+ 430',
|
||||
},
|
||||
})
|
||||
}}
|
||||
>
|
||||
Test Data insert
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { useRef } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
@ -8,7 +8,11 @@ import Cookies from 'js-cookie'
|
||||
|
||||
import { isObjectNotEmpty, inputTelNumberCheck, inputNumberCheck } from '@/util/common-utils'
|
||||
|
||||
import GlobalSpinner from '@/components/common/spinner/GlobalSpinner'
|
||||
|
||||
export default function Join() {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const { getMessage } = useMessage()
|
||||
const { promisePost } = useAxios()
|
||||
const router = useRouter()
|
||||
@ -152,6 +156,8 @@ export default function Join() {
|
||||
},
|
||||
}
|
||||
|
||||
setIsLoading(true)
|
||||
|
||||
await promisePost({ url: '/api/login/v1.0/user/join', data: param })
|
||||
.then((res) => {
|
||||
if (res) {
|
||||
@ -162,8 +168,10 @@ export default function Join() {
|
||||
alert(res.data.result.resultMsg)
|
||||
}
|
||||
}
|
||||
setIsLoading(false)
|
||||
})
|
||||
.catch((error) => {
|
||||
setIsLoading(false)
|
||||
alert(error.response.data.message)
|
||||
})
|
||||
}
|
||||
@ -171,277 +179,280 @@ export default function Join() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="center-page-wrap">
|
||||
<div className="center-page-inner">
|
||||
<form onSubmit={joinProcess}>
|
||||
<div className="center-page-tit">{getMessage('join.title')}</div>
|
||||
<div className="sub-table-box signup">
|
||||
<div className="table-box-title-wrap">
|
||||
<div className="title-wrap">
|
||||
<h3>
|
||||
{getMessage('join.sub1.title')} <span className="important">(*{getMessage('common.require')})</span>
|
||||
</h3>
|
||||
<span className="option">{getMessage('join.sub1.comment')}</span>
|
||||
<>
|
||||
{isLoading && <GlobalSpinner />}
|
||||
<div className="center-page-wrap">
|
||||
<div className="center-page-inner">
|
||||
<form onSubmit={joinProcess}>
|
||||
<div className="center-page-tit">{getMessage('join.title')}</div>
|
||||
<div className="sub-table-box signup">
|
||||
<div className="table-box-title-wrap">
|
||||
<div className="title-wrap">
|
||||
<h3>
|
||||
{getMessage('join.sub1.title')} <span className="important">(*{getMessage('common.require')})</span>
|
||||
</h3>
|
||||
<span className="option">{getMessage('join.sub1.comment')}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="common-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '180px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{/* 판매대리점명 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.storeQcastNm')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '700px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="storeQcastNm"
|
||||
name="storeQcastNm"
|
||||
alt={getMessage('join.sub1.storeQcastNm')}
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.storeQcastNm_placeholder')}
|
||||
maxLength={30}
|
||||
ref={storeQcastNmRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 판매대리점명 후리가나 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.storeQcastNmKana')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '700px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="storeQcastNmKana"
|
||||
name="storeQcastNmKana"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.storeQcastNmKana_placeholder')}
|
||||
maxLength={30}
|
||||
ref={storeQcastNmKanaRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 우편번호/주소 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr5" style={{ width: '200px' }}>
|
||||
<div className="common-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '180px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{/* 판매대리점명 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.storeQcastNm')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '700px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="postCd"
|
||||
name="postCd"
|
||||
id="storeQcastNm"
|
||||
name="storeQcastNm"
|
||||
alt={getMessage('join.sub1.storeQcastNm')}
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.postCd_placeholder')}
|
||||
onChange={inputNumberCheck}
|
||||
maxLength={7}
|
||||
ref={postCdRef}
|
||||
placeholder={getMessage('join.sub1.storeQcastNm_placeholder')}
|
||||
maxLength={30}
|
||||
ref={storeQcastNmRef}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '495px' }}>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 판매대리점명 후리가나 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.storeQcastNmKana')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '700px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="addr"
|
||||
name="addr"
|
||||
id="storeQcastNmKana"
|
||||
name="storeQcastNmKana"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.addr_placeholder')}
|
||||
maxLength={50}
|
||||
ref={addrRef}
|
||||
placeholder={getMessage('join.sub1.storeQcastNmKana_placeholder')}
|
||||
maxLength={30}
|
||||
ref={storeQcastNmKanaRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 전화번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.telNo')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="telNo"
|
||||
name="telNo"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={telNoRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* FAX 번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.fax')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="fax"
|
||||
name="fax"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={faxRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 법인번호 */}
|
||||
<tr>
|
||||
<th>{getMessage('join.sub1.bizNo')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="bizNo" name="bizNo" className="input-light" maxLength={15} onChange={inputTelNumberCheck} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sub-table-box signup">
|
||||
<div className="table-box-title-wrap">
|
||||
<div className="title-wrap">
|
||||
<h3>
|
||||
{getMessage('join.sub2.title')} <span className="important">(*{getMessage('common.require')})</span>
|
||||
</h3>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 우편번호/주소 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.postCd')}/{getMessage('join.sub1.addr')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr5" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="postCd"
|
||||
name="postCd"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.postCd_placeholder')}
|
||||
onChange={inputNumberCheck}
|
||||
maxLength={7}
|
||||
ref={postCdRef}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '495px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="addr"
|
||||
name="addr"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.addr_placeholder')}
|
||||
maxLength={50}
|
||||
ref={addrRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 전화번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.telNo')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="telNo"
|
||||
name="telNo"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.telNo_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={telNoRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* FAX 번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub1.fax')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="fax"
|
||||
name="fax"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={faxRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 법인번호 */}
|
||||
<tr>
|
||||
<th>{getMessage('join.sub1.bizNo')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="bizNo" name="bizNo" className="input-light" maxLength={15} onChange={inputTelNumberCheck} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="common-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '180px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{/* 담당자명 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.userNm')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="userNm" name="userNm" className="input-light" maxLength={20} ref={userNmRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 담당자명 후리가나 */}
|
||||
<tr>
|
||||
<th>{getMessage('join.sub2.userNmKana')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="userNmKana" name="userNmKana" maxLength={20} className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 신청 ID */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.userId')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="userId" name="userId" className="input-light" maxLength={20} ref={userIdRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 이메일 주소 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.email')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="email" name="email" className="input-light" maxLength={30} ref={emailRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 전화번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.telNo')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="userTelNo"
|
||||
name="userTelNo"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub2.telNo_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={userTelNoRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* FAX 번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.fax')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="userFax"
|
||||
name="userFax"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={userFaxRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 부서명 */}
|
||||
<tr>
|
||||
<th>{getMessage('join.sub2.category')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="category" name="category" className="input-light" maxLength={20} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div className="sub-table-box signup">
|
||||
<div className="table-box-title-wrap">
|
||||
<div className="title-wrap">
|
||||
<h3>
|
||||
{getMessage('join.sub2.title')} <span className="important">(*{getMessage('common.require')})</span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div className="common-table">
|
||||
<table>
|
||||
<colgroup>
|
||||
<col style={{ width: '180px' }} />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{/* 담당자명 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.userNm')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="userNm" name="userNm" className="input-light" maxLength={20} ref={userNmRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 담당자명 후리가나 */}
|
||||
<tr>
|
||||
<th>{getMessage('join.sub2.userNmKana')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="userNmKana" name="userNmKana" maxLength={20} className="input-light" />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 신청 ID */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.userId')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="userId" name="userId" className="input-light" maxLength={20} ref={userIdRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 이메일 주소 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.email')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="email" name="email" className="input-light" maxLength={30} ref={emailRef} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 전화번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.telNo')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="userTelNo"
|
||||
name="userTelNo"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub2.telNo_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={userTelNoRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* FAX 번호 */}
|
||||
<tr>
|
||||
<th>
|
||||
{getMessage('join.sub2.fax')} <span className="important">*</span>
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
id="userFax"
|
||||
name="userFax"
|
||||
className="input-light"
|
||||
placeholder={getMessage('join.sub1.fax_placeholder')}
|
||||
maxLength={15}
|
||||
onChange={inputTelNumberCheck}
|
||||
ref={userFaxRef}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* 부서명 */}
|
||||
<tr>
|
||||
<th>{getMessage('join.sub2.category')}</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '200px' }}>
|
||||
<input type="text" id="category" name="category" className="input-light" maxLength={20} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="sign-up-btn-wrap">
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey mr5"
|
||||
onClick={() => {
|
||||
router.push('/login')
|
||||
}}
|
||||
>
|
||||
{getMessage('join.btn.login_page')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy">
|
||||
{getMessage('join.btn.approval_request')}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div className="sign-up-btn-wrap">
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey mr5"
|
||||
onClick={() => {
|
||||
router.push('/login')
|
||||
}}
|
||||
>
|
||||
{getMessage('join.btn.login_page')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy">
|
||||
{getMessage('join.btn.approval_request')}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -33,9 +33,9 @@ export default function ColorPickerModal(props) {
|
||||
}, [isShow])
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos ?? ''}>
|
||||
<WithDraggable isShow={true} pos={pos ?? ''} handle=".modal-handle">
|
||||
<div className={`modal-pop-wrap lr mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.color.picker.title')}</h1>
|
||||
<button
|
||||
className="modal-close"
|
||||
@ -78,6 +78,7 @@ export default function ColorPickerModal(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -20,7 +20,7 @@ export default function WithDraggable({ isShow, children, pos = { x: 0, y: 0 },
|
||||
<Draggable
|
||||
position={{ x: position.x, y: position.y }}
|
||||
onDrag={(e, data) => handleOnDrag(e, data)}
|
||||
handle={handle === '' ? '.modal-head' : handle}
|
||||
handle={handle === '' ? '.modal-handle' : handle}
|
||||
>
|
||||
{children}
|
||||
</Draggable>
|
||||
|
||||
@ -67,9 +67,9 @@ export default function FontSetting(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<WithDraggable isShow={true} pos={pos} handle=".modal-handle">
|
||||
<div className={`modal-pop-wrap lrr mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.font')}</h1>
|
||||
<button
|
||||
className="modal-close"
|
||||
@ -133,6 +133,7 @@ export default function FontSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -59,8 +59,6 @@ export default function QSelectBox({
|
||||
const ref = useRef(null)
|
||||
|
||||
const handleClickSelectOption = (option) => {
|
||||
console.log('🚀 ~ handleClickSelectOption ~ option:', option)
|
||||
|
||||
setSelected(showKey !== '' ? option[showKey] : option.name)
|
||||
onChange?.(option, params)
|
||||
}
|
||||
@ -77,7 +75,11 @@ export default function QSelectBox({
|
||||
useOnClickOutside(ref, handleClose)
|
||||
|
||||
return (
|
||||
<div className={`sort-select ${openSelect ? 'active' : ''}`} ref={ref} onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}>
|
||||
<div
|
||||
className={`sort-select ${openSelect ? 'active' : ''} ${disabled ? 'disabled' : ''}`}
|
||||
ref={ref}
|
||||
onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}
|
||||
>
|
||||
<p>{selected}</p>
|
||||
<ul className="select-item-wrap">
|
||||
{options?.length > 0 &&
|
||||
|
||||
@ -54,31 +54,6 @@ export default function ArchiveTable({ clsCode }) {
|
||||
fetchData()
|
||||
}, [search.searchValue, search.searchFlag])
|
||||
|
||||
// 상세 파일 목록 조회
|
||||
const handleDetailFileListDown = async (noticeNo) => {
|
||||
const url = `/api/board/detail`
|
||||
const params = new URLSearchParams({
|
||||
noticeNo: noticeNo,
|
||||
})
|
||||
const apiUrl = `${url}?${params.toString()}`
|
||||
|
||||
const resultData = await get({ url: apiUrl })
|
||||
|
||||
if (resultData) {
|
||||
if (resultData.result.code === 200) {
|
||||
const boardDetailFileList = resultData.data.listFile
|
||||
|
||||
if (boardDetailFileList && Array.isArray(boardDetailFileList)) {
|
||||
boardDetailFileList.forEach((boardFile) => {
|
||||
handleFileDown(boardFile)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
alert(resultData.result.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{boardList.length > 0 ? (
|
||||
@ -101,7 +76,7 @@ export default function ArchiveTable({ clsCode }) {
|
||||
</div>
|
||||
<div className="file-down-box">
|
||||
{/* 첨부파일 */}
|
||||
<button type="button" className="file-down-btn" onClick={() => handleDetailFileListDown(board.noticeNo)}></button>
|
||||
<button type="button" className="file-down-btn" onClick={() => handleFileDown(board.noticeNo, 'Y')}></button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@ -41,6 +41,7 @@ export default function Table({ clsCode }) {
|
||||
schTitle: search.searchValue ? search.searchValue : '',
|
||||
startRow: startRow,
|
||||
endRow: endRow,
|
||||
schMainYn: 'N',
|
||||
})
|
||||
const apiUrl = `${url}?${params.toString()}`
|
||||
|
||||
|
||||
@ -61,7 +61,7 @@ export default function BoardDetailModal({ noticeNo, setOpen }) {
|
||||
<dt>{getMessage('board.sub.fileList')}</dt>
|
||||
{boardDetail.listFile.map((boardFile) => (
|
||||
<dd key={boardFile.encodeFileNo}>
|
||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile)}>
|
||||
<button type="button" className="down" onClick={() => handleFileDown(boardFile.fileNo, 'N')}>
|
||||
{boardFile.srcFileNm}
|
||||
</button>
|
||||
</dd>
|
||||
|
||||
@ -99,7 +99,9 @@ export default function Estimate({}) {
|
||||
|
||||
const initEstimate = (currPid = currentPid) => {
|
||||
console.log('🚀 ~ initEstimate ~ currPid:', currPid)
|
||||
closeAll()
|
||||
setMenuNumber(5)
|
||||
|
||||
setObjectNo(objectRecoil.floorPlanObjectNo)
|
||||
|
||||
setPlanNo(currPid)
|
||||
@ -133,11 +135,10 @@ export default function Estimate({}) {
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ Estimate ~ selectedPlan:', selectedPlan)
|
||||
if (selectedPlan) initEstimate(selectedPlan.ordering)
|
||||
if (selectedPlan) initEstimate(selectedPlan.planNo)
|
||||
}, [selectedPlan])
|
||||
|
||||
useEffect(() => {
|
||||
closeAll()
|
||||
initEstimate()
|
||||
}, [])
|
||||
|
||||
@ -619,7 +620,7 @@ export default function Estimate({}) {
|
||||
updates.partAdd = '0'
|
||||
updates.saleTotPrice = (Number(amount.replaceAll(',', '')) * estimateContextState.itemList[index].salePrice.replaceAll(',', '')).toLocaleString()
|
||||
updates.showSaleTotPrice = (
|
||||
Number(amount.replaceAll(',', '')) * estimateContextState.itemList[index].showSalePrice?.replaceAll(',', '')
|
||||
Number(amount.replaceAll(',', '')) * estimateContextState.itemList[index].salePrice?.replaceAll(',', '')
|
||||
).toLocaleString()
|
||||
|
||||
updateList = estimateContextState.itemList.map((item) => {
|
||||
@ -681,7 +682,6 @@ export default function Estimate({}) {
|
||||
let updateList = []
|
||||
let updates = {}
|
||||
get({ url: apiUrl }).then((res) => {
|
||||
// console.log('아이템디테일::::::::', res)
|
||||
updates.objectNo = objectNo
|
||||
updates.planNo = planNo
|
||||
updates.itemId = res.itemId
|
||||
@ -706,7 +706,6 @@ export default function Estimate({}) {
|
||||
updates.openFlg = res.openFlg
|
||||
|
||||
if (estimateContextState.estimateType === 'YJSS') {
|
||||
// console.log('YJSS:::,', res.pkgMaterialFlg)
|
||||
if (res.pkgMaterialFlg === '0') {
|
||||
updates.showSalePrice = '0'
|
||||
updates.showSaleTotPrice = '0'
|
||||
@ -721,14 +720,19 @@ export default function Estimate({}) {
|
||||
//104671
|
||||
let bomList = res.itemBomList
|
||||
|
||||
// console.log('updates::', updates)
|
||||
updateList = estimateContextState.itemList.map((item) => {
|
||||
if (item.dispOrder === dispOrder) {
|
||||
if (item?.addFlg) {
|
||||
return { ...item, ...updates, saleTotPrice: '' }
|
||||
} else {
|
||||
if (estimateContextState.estimateType === 'YJSS') {
|
||||
return { ...item, ...updates, salePrice: '', saleTotPrice: '' }
|
||||
// return { ...item, ...updates, salePrice: '', saleTotPrice: '' }
|
||||
//확인
|
||||
if (updates.pkgMaterialFlg === '1') {
|
||||
return { ...item, ...updates, showSalePrice: updates.salePrice }
|
||||
} else {
|
||||
return { ...item, ...updates, salePrice: '', saleTotPrice: '' }
|
||||
}
|
||||
} else {
|
||||
return { ...item, ...updates }
|
||||
}
|
||||
@ -739,7 +743,6 @@ export default function Estimate({}) {
|
||||
return item
|
||||
}
|
||||
})
|
||||
|
||||
//paDispOrder
|
||||
if (bomList) {
|
||||
bomList.map((bomItem, index) => {
|
||||
@ -879,7 +882,6 @@ export default function Estimate({}) {
|
||||
}
|
||||
|
||||
const calculateYJSSTotals = (itemList) => {
|
||||
// console.log(':::itemList::', itemList)
|
||||
itemList.sort((a, b) => a.dispOrder - b.dispOrder)
|
||||
makeUniqueSpecialNoteCd(itemList)
|
||||
itemList.forEach((item) => {
|
||||
@ -918,7 +920,6 @@ export default function Estimate({}) {
|
||||
}
|
||||
}
|
||||
})
|
||||
// console.log('itemList::', itemList)
|
||||
let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0
|
||||
|
||||
totals.pkgTotPrice = pkgAsp * totals.totVolKw * 1000
|
||||
@ -949,30 +950,138 @@ export default function Estimate({}) {
|
||||
|
||||
setItemChangeYn(false)
|
||||
} else {
|
||||
estimateContextState.itemList.forEach((item) => {
|
||||
if (estimateContextState.estimateType === 'YJSS' && !item.paDispOrder && item.pkgMaterialFlg === '0') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (estimateContextState.estimateType === 'YJSS' && item.openFlg === '1') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (estimateContextState.estimateType === 'YJSS' && item.paDispOrder) {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
})
|
||||
estimateContextState.itemList.forEach((item) => {
|
||||
if (estimateContextState.estimateType === 'YJOD' && item.openFlg === '1') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (estimateContextState.estimateType === 'YJOD' && item.paDispOrder) {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
})
|
||||
let totals = {
|
||||
totAmount: 0,
|
||||
totVolKw: 0,
|
||||
supplyPrice: 0,
|
||||
vatPrice: 0,
|
||||
totPrice: 0,
|
||||
addSupplyPrice: 0,
|
||||
pkgTotPrice: 0,
|
||||
}
|
||||
estimateContextState.itemList.sort((a, b) => a.dispOrder - b.dispOrder)
|
||||
makeUniqueSpecialNoteCd(estimateContextState.itemList)
|
||||
|
||||
if (estimateContextState.estimateType === 'YJSS') {
|
||||
estimateContextState.itemList.forEach((item) => {
|
||||
if (estimateContextState.estimateType === 'YJSS' && !item.paDispOrder && item.pkgMaterialFlg === '0') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (estimateContextState.estimateType === 'YJSS' && item.openFlg === '1') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (estimateContextState.estimateType === 'YJSS' && item.paDispOrder) {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
})
|
||||
|
||||
estimateContextState.itemList.forEach((item) => {
|
||||
if (item.delFlg === '0') {
|
||||
let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0
|
||||
let salePrice
|
||||
if (item.moduleFlg === '1') {
|
||||
const volKw = (item.pnowW * amount) / 1000
|
||||
totals.totVolKw += volKw
|
||||
}
|
||||
if (amount === 0) {
|
||||
salePrice = 0
|
||||
} else {
|
||||
salePrice = Number(item.salePrice?.replaceAll(',', '')) || 0
|
||||
}
|
||||
|
||||
totals.totAmount += amount
|
||||
if (item.pkgMaterialFlg === '1') {
|
||||
const saleTotPrice = amount * salePrice
|
||||
totals.addSupplyPrice += saleTotPrice
|
||||
}
|
||||
|
||||
if (!item.paDispOrder) {
|
||||
if (item.pkgMaterialFlg === '0') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
} else {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
|
||||
if (item.openFlg === '1') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
}
|
||||
})
|
||||
let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0
|
||||
|
||||
totals.pkgTotPrice = pkgAsp * totals.totVolKw * 1000
|
||||
totals.supplyPrice = totals.addSupplyPrice + totals.pkgTotPrice
|
||||
totals.vatPrice = totals.supplyPrice * 0.1
|
||||
totals.totPrice = totals.supplyPrice + totals.vatPrice
|
||||
|
||||
setEstimateContextState({
|
||||
pkgTotPrice: totals.pkgTotPrice,
|
||||
totAmount: totals.totAmount,
|
||||
totVolKw: totals.totVolKw.toFixed(2),
|
||||
supplyPrice: totals.supplyPrice.toFixed(0), //소수첫자리에서 반올림
|
||||
vatPrice: totals.vatPrice.toFixed(0), //소수첫자리에서 반올림
|
||||
totPrice: totals.totPrice.toFixed(0), //소수첫자리에서 반올림
|
||||
})
|
||||
} else {
|
||||
estimateContextState.itemList.forEach((item) => {
|
||||
if (estimateContextState.estimateType === 'YJOD' && item.openFlg === '1') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (estimateContextState.estimateType === 'YJOD' && item.paDispOrder) {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
})
|
||||
|
||||
estimateContextState.itemList.forEach((item) => {
|
||||
delete item.showSalePrice
|
||||
delete item.showSaleTotPrice
|
||||
if (item.delFlg === '0') {
|
||||
let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0
|
||||
let price
|
||||
if (amount === 0) {
|
||||
price = 0
|
||||
} else {
|
||||
price = Number(item.saleTotPrice?.replaceAll(',', '')) || 0
|
||||
}
|
||||
|
||||
if (item.moduleFlg === '1') {
|
||||
const volKw = (item.pnowW * amount) / 1000
|
||||
totals.totVolKw += volKw
|
||||
}
|
||||
totals.supplyPrice += price
|
||||
totals.totAmount += amount
|
||||
|
||||
if (item.paDispOrder) {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
if (item.openFlg === '1') {
|
||||
item.showSalePrice = '0'
|
||||
item.showSaleTotPrice = '0'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
totals.vatPrice = totals.supplyPrice * 0.1
|
||||
totals.totPrice = totals.supplyPrice + totals.vatPrice
|
||||
|
||||
setEstimateContextState({
|
||||
totAmount: totals.totAmount,
|
||||
totVolKw: totals.totVolKw.toFixed(2),
|
||||
supplyPrice: totals.supplyPrice.toFixed(0), //소수첫자리에서 반올림
|
||||
vatPrice: totals.vatPrice.toFixed(0), //소수첫자리에서 반올림
|
||||
totPrice: totals.totPrice.toFixed(0), //소수첫자리에서 반올림
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [itemChangeYn, estimateContextState.itemList])
|
||||
|
||||
@ -1006,7 +1115,7 @@ export default function Estimate({}) {
|
||||
<div className="estimate-tit">{getMessage('estimate.detail.objectNo')}</div>
|
||||
<div className="estimate-name">
|
||||
{/* {objectNo} (Plan No: {estimateContextState.planNo}) */}
|
||||
{objectNo} (Plan No: {planNo})
|
||||
{currentObjectNo} (Plan No: {planNo})
|
||||
</div>
|
||||
</div>
|
||||
<div className="estimate-box">
|
||||
@ -1076,7 +1185,6 @@ export default function Estimate({}) {
|
||||
</th>
|
||||
<td>
|
||||
<div className="input-wrap" style={{ width: '350px' }}>
|
||||
{/* <input type="text" className="input-light" defaultValue={estimateContextState?.charger} onBlur={handleBlurCharger} /> */}
|
||||
<input
|
||||
type="text"
|
||||
className="input-light"
|
||||
@ -1095,7 +1203,6 @@ export default function Estimate({}) {
|
||||
<td colSpan={3}>
|
||||
<div className="form-flex-wrap">
|
||||
<div className="input-wrap mr5" style={{ width: '610px' }}>
|
||||
{/* <input type="text" className="input-light" defaultValue={estimateContextState?.objectName} onBlur={handleBlurObjectName} /> */}
|
||||
<input
|
||||
type="text"
|
||||
className="input-light"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { useContext, useEffect, useRef } from 'react'
|
||||
|
||||
import { useRecoilValue } from 'recoil'
|
||||
|
||||
@ -14,21 +14,25 @@ import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitial
|
||||
import { currentMenuState } from '@/store/canvasAtom'
|
||||
import { totalDisplaySelector } from '@/store/settingAtom'
|
||||
import { MENU } from '@/common/common'
|
||||
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
export default function CanvasFrame() {
|
||||
const canvasRef = useRef(null)
|
||||
const { canvas } = useCanvas('canvas')
|
||||
const { canvasLoadInit, gridInit } = useCanvasConfigInitialize()
|
||||
const currentMenu = useRecoilValue(currentMenuState)
|
||||
const { floorPlanState } = useContext(FloorPlanContext)
|
||||
const { contextMenu, handleClick } = useContextMenu()
|
||||
const { selectedPlan } = usePlan()
|
||||
const { currentCanvasPlan } = usePlan()
|
||||
const totalDisplay = useRecoilValue(totalDisplaySelector) // 집계표 표시 여부
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
|
||||
const loadCanvas = () => {
|
||||
if (canvas) {
|
||||
canvas?.clear() // 캔버스를 초기화합니다.
|
||||
if (selectedPlan?.canvasStatus) {
|
||||
canvas?.loadFromJSON(JSON.parse(selectedPlan.canvasStatus), function () {
|
||||
if (currentCanvasPlan?.canvasStatus && floorPlanState.objectNo === currentCanvasPlan.objectNo) {
|
||||
canvas?.loadFromJSON(JSON.parse(currentCanvasPlan.canvasStatus), function () {
|
||||
canvasLoadInit() //config된 상태로 캔버스 객체를 그린다
|
||||
canvas?.renderAll() // 캔버스를 다시 그립니다.
|
||||
})
|
||||
@ -39,7 +43,11 @@ export default function CanvasFrame() {
|
||||
|
||||
useEffect(() => {
|
||||
loadCanvas()
|
||||
}, [selectedPlan, canvas])
|
||||
}, [currentCanvasPlan, canvas])
|
||||
|
||||
useEffect(() => {
|
||||
setIsGlobalLoading(false)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="canvas-frame">
|
||||
|
||||
@ -30,22 +30,22 @@ export default function CanvasLayout({ children }) {
|
||||
<div className="canvas-layout">
|
||||
<div className={`canvas-page-list ${menuNumber === 2 || menuNumber === 3 || menuNumber === 4 ? 'active' : ''}`}>
|
||||
<div className="canvas-plane-wrap">
|
||||
{plans.map((plan) => (
|
||||
{plans.map((plan, index) => (
|
||||
<button
|
||||
key={`plan-${plan.id}`}
|
||||
className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`}
|
||||
onClick={() => handleCurrentPlan(plan.id)}
|
||||
>
|
||||
<span>{`Plan ${plan.ordering}`}</span>
|
||||
{plan.ordering !== 1 && (
|
||||
<span>{`Plan ${plan.planNo}`}</span>
|
||||
{index !== 0 && (
|
||||
<i
|
||||
className="close"
|
||||
onClick={(e) =>
|
||||
swalFire({
|
||||
text: `Plan ${plan.ordering} ` + getMessage('plan.message.confirm.delete'),
|
||||
text: `Plan ${plan.planNo} ` + getMessage('plan.message.confirm.delete'),
|
||||
type: 'confirm',
|
||||
confirmFn: () => {
|
||||
handleDeletePlan(e, plan.id)
|
||||
handleDeletePlan(e, plan)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -41,9 +41,10 @@ import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
import KO from '@/locales/ko.json'
|
||||
import JA from '@/locales/ja.json'
|
||||
|
||||
import { MENU } from '@/common/common'
|
||||
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
export default function CanvasMenu(props) {
|
||||
const { menuNumber, setMenuNumber } = props
|
||||
const pathname = usePathname()
|
||||
@ -101,6 +102,8 @@ export default function CanvasMenu(props) {
|
||||
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
|
||||
//임시
|
||||
const { selectedPlan } = usePlan()
|
||||
const handleExcelPdfFileDown = async (donwloadType, drawingFlg) => {
|
||||
const url = '/api/estimate/excel-download'
|
||||
|
||||
@ -164,18 +167,23 @@ export default function CanvasMenu(props) {
|
||||
setType('surface')
|
||||
break
|
||||
case 4:
|
||||
setType('module')
|
||||
if (!checkMenuAndCanvasState()) {
|
||||
swalFire({ text: getMessage('menu.validation.canvas.roof') })
|
||||
return
|
||||
} else {
|
||||
setType('module')
|
||||
}
|
||||
break
|
||||
case 5:
|
||||
// let pid = urlParams.get('pid')
|
||||
promiseGet({ url: `/api/estimate/${objectNo}/${pid}/detail` }).then((res) => {
|
||||
promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan.planNo}/detail` }).then((res) => {
|
||||
if (res.status === 200) {
|
||||
const estimateDetail = res.data
|
||||
if (estimateDetail.docNo) {
|
||||
if (estimateDetail.tempFlg === '0' && estimateDetail.estimateDate !== null) {
|
||||
setMenuNumber(menu.index)
|
||||
setCurrentMenu(menu.title)
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
||||
router.push(`/floor-plan/estimate/5?pid=${pid}&objectNo=${objectNo}`)
|
||||
router.push(`/floor-plan/estimate/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
||||
} else {
|
||||
swalFire({ text: getMessage('estimate.menu.move.valid1') })
|
||||
}
|
||||
@ -183,13 +191,13 @@ export default function CanvasMenu(props) {
|
||||
})
|
||||
break
|
||||
case 6:
|
||||
promiseGet({ url: `/api/estimate/${objectNo}/${pid}/detail` }).then((res) => {
|
||||
promiseGet({ url: `/api/estimate/${objectNo}/${selectedPlan.planNo}/detail` }).then((res) => {
|
||||
if (res.status === 200) {
|
||||
const estimateDetail = res.data
|
||||
if (estimateDetail.docNo) {
|
||||
if (estimateDetail.tempFlg === '0') {
|
||||
setMenuNumber(menu.index)
|
||||
setCurrentMenu(menu.title)
|
||||
router.push(`/floor-plan/simulator/${menu.index}?pid=${pid}&objectNo=${objectNo}`)
|
||||
router.push(`/floor-plan/simulator/${menu.index}?pid=${selectedPlan.planNo}&objectNo=${objectNo}`)
|
||||
} else {
|
||||
swalFire({ text: getMessage('simulator.menu.move.valid1') })
|
||||
}
|
||||
@ -203,8 +211,10 @@ export default function CanvasMenu(props) {
|
||||
setCurrentMenu(menu.title)
|
||||
}
|
||||
|
||||
if (pathname !== '/floor-plan' && pathname !== '/floor-plan/estimate/5' && pathname !== '/floor-plan/simulator/6') {
|
||||
router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`)
|
||||
if (pathname !== '/floor-plan') {
|
||||
if (menu.index !== 0) {
|
||||
router.push(`/floor-plan?pid=${pid}&objectNo=${objectNo}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,6 +245,20 @@ export default function CanvasMenu(props) {
|
||||
await saveCanvas()
|
||||
}
|
||||
|
||||
// 나가기 버튼 클릭
|
||||
const handleLeaveCanvas = () => {
|
||||
swalFire({
|
||||
text: getMessage('plan.message.leave'),
|
||||
type: 'confirm',
|
||||
confirmButtonText: getMessage('plan.message.corfirm.yes'),
|
||||
cancelButtonText: getMessage('plan.message.confirm.no'),
|
||||
confirmFn: async () => {
|
||||
await handleSaveCanvas()
|
||||
router.push(`/management/stuff`)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const [placementInitialId, setPlacementInitialId] = useState(uuidv4())
|
||||
const placementInitialProps = {
|
||||
id: placementInitialId,
|
||||
@ -323,6 +347,14 @@ export default function CanvasMenu(props) {
|
||||
return (['2', '3'].includes(canvasSetting?.roofSizeSet) && menu.index === 2) || (menuNumber === 4 && menu.index === 2)
|
||||
}
|
||||
|
||||
const checkMenuAndCanvasState = () => {
|
||||
const roofs = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF)
|
||||
// 지붕면 할당이 끝난 지붕이 하나라도 있는지 체크
|
||||
const isExist = roofs?.some((roof) => roof.roofMaterial)
|
||||
console.log('🚀 ~ checkMenuAndCanvasState ~ isExist:', isExist)
|
||||
return isExist
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(estimateRecoilState)) {
|
||||
if (estimateRecoilState?.createUser === 'T01') {
|
||||
@ -368,7 +400,9 @@ export default function CanvasMenu(props) {
|
||||
*/
|
||||
const handleEstimateLockController = (estimateRecoilState) => {
|
||||
swalFire({
|
||||
text: estimateRecoilState.lockFlg === '0' ? getMessage('estimate.detail.lock.alertMsg') : getMessage('estimate.detail.unlock.alertMsg'),
|
||||
// text: estimateRecoilState.lockFlg === '0' ? getMessage('estimate.detail.lock.alertMsg') : getMessage('estimate.detail.unlock.alertMsg'),
|
||||
html: estimateRecoilState.lockFlg === '0' ? getMessage('estimate.detail.lock.alertMsg') : getMessage('estimate.detail.unlock.alertMsg'),
|
||||
confirmButtonText: estimateRecoilState.lockFlg === '1' ? getMessage('estimate.detail.unlock.confirmBtnName') : '',
|
||||
type: 'confirm',
|
||||
confirmFn: async () => {
|
||||
setIsGlobalLoading(true)
|
||||
@ -511,7 +545,7 @@ export default function CanvasMenu(props) {
|
||||
</div>
|
||||
<div className="btn-from">
|
||||
<button className="btn08" onClick={handleSaveCanvas}></button>
|
||||
<button className="btn09"></button>
|
||||
<button className="btn09" onClick={handleLeaveCanvas}></button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -1,37 +1,53 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
//import { useRecoilState } from 'recoil'
|
||||
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
|
||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
//import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
||||
//import { correntObjectNoState } from '@/store/settingAtom'
|
||||
import '@/styles/contents.scss'
|
||||
import { notFound, useSearchParams } from 'next/navigation'
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { correntObjectNoState } from '@/store/settingAtom'
|
||||
|
||||
export default function FloorPlan({ children }) {
|
||||
//const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext)
|
||||
//const [correntObjectNo, setCorrentObjectNo] = useRecoilState(correntObjectNoState)
|
||||
const [correntObjectNo, setCurrentObjectNo] = useRecoilState(correntObjectNoState)
|
||||
const searchParams = useSearchParams()
|
||||
const objectNo = searchParams.get('objectNo')
|
||||
const pid = searchParams.get('pid')
|
||||
|
||||
const { closeAll } = usePopup()
|
||||
const { menuNumber, setMenuNumber } = useCanvasMenu()
|
||||
const { fetchSettings } = useCanvasSetting()
|
||||
const { fetchSettings, fetchBasicSettings } = useCanvasSetting()
|
||||
|
||||
// URL 파라미터에서 objectNo 설정
|
||||
useEffect(() => {
|
||||
if (!objectNo) {
|
||||
notFound()
|
||||
}
|
||||
setCurrentObjectNo(objectNo)
|
||||
}, [objectNo, setCurrentObjectNo])
|
||||
|
||||
// 설정 데이터 fetch
|
||||
useEffect(() => {
|
||||
if (!correntObjectNo) return // correntObjectNo가 없으면 실행하지 않음
|
||||
|
||||
if(menuNumber === null) {
|
||||
setMenuNumber(1)
|
||||
}
|
||||
fetchSettings()
|
||||
fetchBasicSettings()
|
||||
|
||||
return () => {
|
||||
closeAll()
|
||||
}
|
||||
}, [correntObjectNo])
|
||||
|
||||
const modalProps = {
|
||||
menuNumber,
|
||||
setMenuNumber,
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
///setCorrentObjectNo(floorPlanState.objectNo)
|
||||
//console.log('FloorPlan objectNo ', floorPlanState.objectNo, correntObjectNo)
|
||||
setMenuNumber(1)
|
||||
fetchSettings()
|
||||
return () => {
|
||||
closeAll()
|
||||
}
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="canvas-wrap">
|
||||
|
||||
@ -15,7 +15,7 @@ export default function Slope({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xxxm`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.placement.surface.slope.setting')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -45,6 +45,7 @@ export default function Slope({ id, pos = { x: 50, y: 230 } }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -126,7 +126,7 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.auxiliary.drawing')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -160,6 +160,7 @@ export default function AuxiliaryDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -46,7 +46,7 @@ export default function AuxiliaryEdit(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage(type === 'copy' ? 'modal.auxiliary.copy' : 'modal.auxiliary.move')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -111,6 +111,7 @@ export default function AuxiliaryEdit(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -14,7 +14,7 @@ export default function AuxiliarySize(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.auxiliary.size.edit')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -63,6 +63,7 @@ export default function AuxiliarySize(props) {
|
||||
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -11,6 +11,11 @@ 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 } from '@/store/selectedModuleOptions'
|
||||
import { addedRoofsState } from '@/store/settingAtom'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
import Swal from 'sweetalert2'
|
||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||
|
||||
export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
const { getMessage } = useMessage()
|
||||
@ -20,13 +25,32 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
const orientationRef = useRef(null)
|
||||
const { initEvent } = useEvent()
|
||||
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
|
||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState)
|
||||
const addedRoofs = useRecoilValue(addedRoofsState)
|
||||
|
||||
// const { initEvent } = useContext(EventContext)
|
||||
const { manualModuleSetup, autoModuleSetup, manualFlatroofModuleSetup, autoFlatroofModuleSetup } = useModuleBasicSetting()
|
||||
const handleBtnNextStep = () => {
|
||||
if (tabNum === 1) {
|
||||
orientationRef.current.handleNextStep()
|
||||
} else if (tabNum === 2) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
setTabNum(tabNum + 1)
|
||||
}
|
||||
|
||||
@ -51,7 +75,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap lx-2`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.module.circuit.setting.default')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -115,6 +139,7 @@ export default function BasicSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -1,28 +1,31 @@
|
||||
import { useEffect, useState, useReducer } from 'react'
|
||||
import { useEffect, useState, useReducer, useRef } from 'react'
|
||||
import { useRecoilValue, useRecoilState } from 'recoil'
|
||||
import { addedRoofsState } from '@/store/settingAtom'
|
||||
import { canvasSettingState, pitchSelector } from '@/store/canvasAtom'
|
||||
import { currentCanvasPlanState } from '@/store/canvasAtom'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||
import { useModuleSelection } from '@/hooks/module/useModuleSelection'
|
||||
import ModuleTabContents from './ModuleTabContents'
|
||||
import { useDebounceCallback, useDebounceValue } from 'usehooks-ts'
|
||||
import { useDebounceValue } from 'usehooks-ts'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
|
||||
export default function Module({ setTabNum }) {
|
||||
const { getMessage } = useMessage()
|
||||
const addedRoofs = useRecoilValue(addedRoofsState) //지붕재 선택
|
||||
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState) //지붕재 선택
|
||||
const [roofTab, setRoofTab] = useState(0) //지붕재 탭
|
||||
|
||||
const {
|
||||
moduleSelectionInitParams,
|
||||
selectedModules,
|
||||
raftCodes,
|
||||
roughnessCodes,
|
||||
windSpeedCodes,
|
||||
managementState,
|
||||
moduleList,
|
||||
selectedSurfaceType,
|
||||
installHeight,
|
||||
standardWindSpeed,
|
||||
verticalSnowCover,
|
||||
handleChangeModule,
|
||||
handleChangeSurfaceType,
|
||||
@ -31,8 +34,8 @@ export default function Module({ setTabNum }) {
|
||||
handleChangeVerticalSnowCover,
|
||||
} = useModuleSelection({ addedRoofs })
|
||||
|
||||
const [inputInstallHeight, setInputInstallHeight] = useState(installHeight)
|
||||
const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState(verticalSnowCover)
|
||||
const [inputInstallHeight, setInputInstallHeight] = useState()
|
||||
const [inputVerticalSnowCover, setInputVerticalSnowCover] = useState()
|
||||
|
||||
const [debouncedInstallHeight] = useDebounceValue(inputInstallHeight, 500)
|
||||
const [debouncedVerticalSnowCover] = useDebounceValue(inputVerticalSnowCover, 500)
|
||||
@ -44,18 +47,38 @@ export default function Module({ setTabNum }) {
|
||||
}, moduleSelectionData)
|
||||
|
||||
useEffect(() => {
|
||||
handleChangeInstallHeight(debouncedInstallHeight)
|
||||
if (installHeight) {
|
||||
setInputInstallHeight(installHeight)
|
||||
}
|
||||
if (verticalSnowCover) {
|
||||
setInputVerticalSnowCover(verticalSnowCover)
|
||||
}
|
||||
}, [installHeight, verticalSnowCover])
|
||||
|
||||
useEffect(() => {
|
||||
if (tempModuleSelectionData.roofConstructions.length > 0) {
|
||||
if (tempModuleSelectionData.common.moduleItemId && isObjectNotEmpty(tempModuleSelectionData.module)) {
|
||||
//저장된 temp데이터가 지붕재(addedRoofs) 개수와 같으면 모듈 선택 저장
|
||||
if (tempModuleSelectionData.roofConstructions.length === addedRoofs.length) {
|
||||
setModuleSelectionData(tempModuleSelectionData)
|
||||
moduleSelectedDataTrigger(tempModuleSelectionData)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [tempModuleSelectionData])
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedInstallHeight) {
|
||||
handleChangeInstallHeight(debouncedInstallHeight)
|
||||
}
|
||||
}, [debouncedInstallHeight])
|
||||
|
||||
useEffect(() => {
|
||||
handleChangeVerticalSnowCover(debouncedVerticalSnowCover)
|
||||
if (debouncedVerticalSnowCover) {
|
||||
handleChangeVerticalSnowCover(debouncedVerticalSnowCover)
|
||||
}
|
||||
}, [debouncedVerticalSnowCover])
|
||||
|
||||
useEffect(() => {
|
||||
setInputInstallHeight(installHeight)
|
||||
setInputVerticalSnowCover(verticalSnowCover)
|
||||
}, [installHeight, verticalSnowCover])
|
||||
|
||||
const moduleData = {
|
||||
header: [
|
||||
{ name: getMessage('module'), width: 150, prop: 'module', type: 'color-box' },
|
||||
@ -69,16 +92,12 @@ export default function Module({ setTabNum }) {
|
||||
rows: [],
|
||||
}
|
||||
|
||||
useEffect(() => {}, [roofTab])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('moduleSelectionData', moduleSelectionData)
|
||||
}, [])
|
||||
|
||||
const handleRoofTab = (tab) => {
|
||||
setRoofTab(tab)
|
||||
}
|
||||
|
||||
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="roof-module-tab2-overflow">
|
||||
@ -114,21 +133,20 @@ export default function Module({ setTabNum }) {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{selectedModules.itemList &&
|
||||
selectedModules.itemList.map((row) => (
|
||||
<>
|
||||
<tr>
|
||||
<td>
|
||||
<div className="color-wrap">
|
||||
<span className="color-box" style={{ backgroundColor: row.color }}></span>
|
||||
<span className="name">{row.itemNm}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="al-r">{Number(row.shortAxis).toFixed(0)}</td>
|
||||
<td className="al-r">{Number(row.longAxis).toFixed(0)}</td>
|
||||
<td className="al-r">{Number(row.wpOut).toFixed(0)}</td>
|
||||
</tr>
|
||||
</>
|
||||
{selectedModules &&
|
||||
selectedModules.itemList &&
|
||||
selectedModules.itemList.map((row, index) => (
|
||||
<tr key={index}>
|
||||
<td>
|
||||
<div className="color-wrap">
|
||||
<span className="color-box" style={{ backgroundColor: row.color }}></span>
|
||||
<span className="name">{row.itemNm}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="al-r">{Number(row.shortAxis).toFixed(0)}</td>
|
||||
<td className="al-r">{Number(row.longAxis).toFixed(0)}</td>
|
||||
<td className="al-r">{Number(row.wpOut).toFixed(0)}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
@ -232,11 +250,10 @@ export default function Module({ setTabNum }) {
|
||||
<div style={{ display: roofTab === index ? 'block' : 'none' }} key={index}>
|
||||
<ModuleTabContents
|
||||
key={index}
|
||||
index={index}
|
||||
tabIndex={index}
|
||||
addRoof={roof}
|
||||
roofTab={index}
|
||||
moduleConstructionSelectionData={moduleSelectionData.roofConstructions[index]}
|
||||
setModuleSelectionData={setModuleSelectionData}
|
||||
setAddedRoofs={setAddedRoofs}
|
||||
roofTab={roofTab}
|
||||
tempModuleSelectionData={tempModuleSelectionData}
|
||||
setTempModuleSelectionData={setTempModuleSelectionData}
|
||||
/>
|
||||
|
||||
@ -1,288 +1,42 @@
|
||||
import { useEffect, useState, useRef } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { pitchTextSelector } from '@/store/canvasAtom'
|
||||
import { useState } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import { moduleSelectionInitParamsState } from '@/store/selectedModuleOptions'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||
import { useModuleTabContents } from '@/hooks/module/useModuleTabContents'
|
||||
|
||||
export default function ModuleTabContents({
|
||||
addRoof,
|
||||
roofTab,
|
||||
moduleConstructionSelectionData,
|
||||
setModuleSelectionData,
|
||||
tempModuleSelectionData,
|
||||
setTempModuleSelectionData,
|
||||
}) {
|
||||
export default function ModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
|
||||
const { getMessage } = useMessage()
|
||||
const [roofMaterial, setRoofMaterial] = useState(addRoof) //지붕재`
|
||||
const globalPitchText = useRecoilValue(pitchTextSelector) //피치 텍스트
|
||||
|
||||
const { findCommonCode } = useCommonCode()
|
||||
const [raftCodes, setRaftCodes] = useState([]) //가대 목록
|
||||
const [trestleList, setTrestleList] = useState([])
|
||||
const [constMthdList, setConstMthdList] = useState([])
|
||||
const [roofBaseList, setRoofBaseList] = useState([])
|
||||
const [constructionList, setConstructionList] = useState([{}]) //공법 목록
|
||||
|
||||
const [selectedRaftBase, setSelectedRaftBase] = useState({}) //선택된 가대
|
||||
const [selectedTrestle, setSelectedTrestle] = useState({}) //선택된 가대
|
||||
const [selectedConstMthd, setSelectedConstMthd] = useState({}) //선택된 공법
|
||||
const [selectedRoofBase, setSelectedRoofBase] = useState({}) //선택된 지붕밑바탕
|
||||
const [selectedConstruction, setSelectedConstruction] = useState({}) //선택된 공법
|
||||
const [constructionListParams, setConstructionListParams] = useState({})
|
||||
|
||||
const [trestleParams, setTrestleParams] = useState({}) //서까래, 가대메이커,공법,지붕밑바탕 관련 api호출 파라메터
|
||||
const [constructionParams, setConstructionParams] = useState({}) //공법 관련 api호출 파라메터
|
||||
const [roofBaseParams, setRoofBaseParams] = useState({}) //지붕밑바탕 관련 api호출 파라메터
|
||||
|
||||
const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
|
||||
|
||||
const { getTrestleList, getConstructionList } = useMasterController()
|
||||
|
||||
const constructionRef = useRef([])
|
||||
const [cvrYn, setCvrYn] = useState('N')
|
||||
const [snowGdPossYn, setSnowGdPossYn] = useState('N')
|
||||
|
||||
const [cvrChecked, setCvrChecked] = useState(false)
|
||||
const [snowGdChecked, setSnowGdChecked] = useState(false)
|
||||
|
||||
const [isExistData, setIsExistData] = useState(false)
|
||||
|
||||
//서까래간격 변경
|
||||
const handleChangeRaftBase = (option) => {
|
||||
setSelectedRaftBase(option)
|
||||
setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode })
|
||||
|
||||
setTrestleList([]) //가대메이커
|
||||
setConstMthdList([]) //공법 초기화
|
||||
setRoofBaseList([]) //지붕밑바탕 초기화
|
||||
setConstructionList([]) //공법 초기화
|
||||
}
|
||||
|
||||
//가대메이커 변경
|
||||
const handleChangeTrestle = (option) => {
|
||||
setSelectedTrestle(option) //선택값 저장
|
||||
setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' })
|
||||
setConstMthdList([]) //공법 초기화
|
||||
setRoofBaseList([]) //지붕밑바탕 초기화
|
||||
setConstructionList([]) //공법 초기화
|
||||
}
|
||||
|
||||
//공법 변경
|
||||
const handleChangeConstMthd = (option) => {
|
||||
setSelectedConstMthd(option) //선택된값 저장
|
||||
setRoofBaseParams({ ...trestleParams, trestleMkrCd: selectedTrestle.trestleMkrCd, constMthdCd: option.constMthdCd, roofBaseCd: '' })
|
||||
setConstructionList([]) //공법 초기화
|
||||
}
|
||||
|
||||
//지붕밑바탕변경
|
||||
const handleChangeRoofBase = (option) => {
|
||||
// if (option) {
|
||||
setConstructionListParams({
|
||||
...moduleSelectionInitParams,
|
||||
...roofBaseParams,
|
||||
roofBaseCd: option.roofBaseCd,
|
||||
inclCd: addRoof.pitch,
|
||||
})
|
||||
setSelectedRoofBase(option)
|
||||
}
|
||||
|
||||
const getModuleOptionsListData = async (params) => {
|
||||
const optionsList = await getTrestleList(params)
|
||||
|
||||
if (optionsList.data.length > 0) {
|
||||
if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd === null) {
|
||||
setTrestleList(optionsList.data)
|
||||
if (isExistData) {
|
||||
setSelectedTrestle({ ...moduleConstructionSelectionData.trestle })
|
||||
} else {
|
||||
setConstMthdList([])
|
||||
setRoofBaseList([])
|
||||
}
|
||||
}
|
||||
|
||||
if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd === null) {
|
||||
setConstMthdList(optionsList.data)
|
||||
if (isExistData) {
|
||||
setSelectedConstMthd({ ...moduleConstructionSelectionData.trestle })
|
||||
} else {
|
||||
setRoofBaseList([])
|
||||
}
|
||||
}
|
||||
|
||||
if (optionsList.data[0].trestleMkrCd && optionsList.data[0].constMthdCd && optionsList.data[0].roofBaseCd) {
|
||||
setRoofBaseList(optionsList.data)
|
||||
if (isExistData) {
|
||||
setSelectedRoofBase({ ...moduleConstructionSelectionData.trestle })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const getConstructionListData = async (params) => {
|
||||
if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
|
||||
const optionsList = await getConstructionList(params)
|
||||
setConstructionList(optionsList.data)
|
||||
}
|
||||
}
|
||||
|
||||
const handleConstruction = (index) => {
|
||||
if (index > -1) {
|
||||
const isPossibleIndex = constructionRef.current
|
||||
.map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1))
|
||||
.filter((index) => index !== -1)
|
||||
|
||||
isPossibleIndex.forEach((index) => {
|
||||
if (constructionRef.current[index].classList.contains('blue')) {
|
||||
constructionRef.current[index].classList.remove('blue')
|
||||
constructionRef.current[index].classList.add('white')
|
||||
}
|
||||
})
|
||||
constructionRef.current[index].classList.remove('white')
|
||||
constructionRef.current[index].classList.add('blue')
|
||||
|
||||
const selectedConstruction = constructionList[index]
|
||||
selectedConstruction.roofIndex = roofTab
|
||||
selectedConstruction.setupCover = false //처마력바 설치 여부
|
||||
selectedConstruction.setupSnowCover = false //눈막이금구 설치 여부
|
||||
selectedConstruction.selectedIndex = index
|
||||
|
||||
setCvrYn(selectedConstruction.cvrYn)
|
||||
setSnowGdPossYn(selectedConstruction.snowGdPossYn)
|
||||
setSelectedConstruction(selectedConstruction)
|
||||
} else {
|
||||
constructionRef.current.forEach((ref) => {
|
||||
ref.classList.remove('blue')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
|
||||
const newRoofConstructions = {
|
||||
roofIndex: roofTab,
|
||||
addRoof: addRoof,
|
||||
trestle: selectedRoofBase,
|
||||
construction: selectedConstruction,
|
||||
}
|
||||
const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === roofTab)
|
||||
|
||||
if (index > -1) {
|
||||
const newArray = [
|
||||
...tempModuleSelectionData.roofConstructions.slice(0, index),
|
||||
newRoofConstructions,
|
||||
...tempModuleSelectionData.roofConstructions.slice(index + 1),
|
||||
]
|
||||
setTempModuleSelectionData({ roofConstructions: newArray })
|
||||
} else {
|
||||
setTempModuleSelectionData({ roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }] })
|
||||
}
|
||||
}
|
||||
}, [selectedConstruction])
|
||||
|
||||
const handleCvrChecked = () => {
|
||||
setCvrChecked(!cvrChecked)
|
||||
}
|
||||
|
||||
const handleSnowGdChecked = () => {
|
||||
setSnowGdChecked(!snowGdChecked)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedConstruction({ ...selectedConstruction, setupCover: cvrChecked })
|
||||
}, [cvrChecked])
|
||||
|
||||
useEffect(() => {
|
||||
setSelectedConstruction({ ...selectedConstruction, setupSnowCover: snowGdChecked })
|
||||
}, [snowGdChecked])
|
||||
|
||||
useEffect(() => {
|
||||
if (isExistData) {
|
||||
setConstructionListParams({
|
||||
...moduleSelectionInitParams,
|
||||
...roofBaseParams,
|
||||
roofBaseCd: selectedRoofBase.roofBaseCd,
|
||||
inclCd: addRoof.pitch,
|
||||
})
|
||||
}
|
||||
}, [selectedRoofBase])
|
||||
|
||||
useEffect(() => {
|
||||
if (isExistData && constructionList.length > 0) {
|
||||
const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
|
||||
handleConstruction(selectedIndex)
|
||||
}
|
||||
}, [constructionList])
|
||||
|
||||
useEffect(() => {
|
||||
// 202600 경사도
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
//서까래 코드
|
||||
raftCodeList.forEach((obj) => {
|
||||
obj.name = obj.clCodeNm
|
||||
obj.id = obj.clCode
|
||||
})
|
||||
setRaftCodes(raftCodeList)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
//물건 상세의 데이터를 가지고 초기화 데이터를 만든다
|
||||
if (
|
||||
moduleSelectionInitParams.illuminationTp &&
|
||||
moduleSelectionInitParams.instHt &&
|
||||
moduleSelectionInitParams.stdSnowLd &&
|
||||
moduleSelectionInitParams.stdWindSpeed
|
||||
) {
|
||||
const isModuleLoaded = moduleSelectionInitParams.hasOwnProperty('moduleTpCd') //모듈컬럼이 있으면 모듈을 변경했다는 내용
|
||||
if (isModuleLoaded) {
|
||||
setTrestleParams({ moduleTpCd: moduleSelectionInitParams.moduleTpCd, roofMatlCd: addRoof.roofMatlCd, raftBaseCd: addRoof.raftBaseCd })
|
||||
setConstructionList([])
|
||||
|
||||
if (isObjectNotEmpty(moduleConstructionSelectionData)) {
|
||||
setConstructionParams({ ...moduleConstructionSelectionData.trestle, constMthdCd: '', roofBaseCd: '' })
|
||||
setRoofBaseParams({ ...moduleConstructionSelectionData.trestle, roofBaseCd: '' })
|
||||
setCvrChecked(moduleConstructionSelectionData.construction.setupCover)
|
||||
setSnowGdChecked(moduleConstructionSelectionData.construction.setupSnowCover)
|
||||
setIsExistData(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setTempModuleSelectionData({ common: moduleSelectionInitParams })
|
||||
}, [moduleSelectionInitParams])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(trestleParams)) {
|
||||
getModuleOptionsListData(trestleParams)
|
||||
}
|
||||
}, [trestleParams])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(constructionParams)) {
|
||||
getModuleOptionsListData(constructionParams)
|
||||
}
|
||||
}, [constructionParams])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(roofBaseParams)) {
|
||||
getModuleOptionsListData(roofBaseParams)
|
||||
}
|
||||
}, [roofBaseParams])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(constructionListParams)) {
|
||||
getConstructionListData(constructionListParams)
|
||||
}
|
||||
}, [constructionListParams])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(tempModuleSelectionData)) {
|
||||
setModuleSelectionData(tempModuleSelectionData)
|
||||
}
|
||||
}, [tempModuleSelectionData])
|
||||
const {
|
||||
raftCodes,
|
||||
trestleList,
|
||||
constMthdList,
|
||||
roofBaseList,
|
||||
constructionList,
|
||||
globalPitchText,
|
||||
selectedTrestle,
|
||||
selectedConstMthd,
|
||||
selectedRoofBase,
|
||||
constructionRef,
|
||||
cvrYn,
|
||||
cvrChecked,
|
||||
snowGdPossYn,
|
||||
snowGdChecked,
|
||||
lengthBase,
|
||||
hajebichi,
|
||||
lengthRef,
|
||||
hajebichiRef,
|
||||
setLengthBase,
|
||||
setHajebichi,
|
||||
handleChangeRaftBase,
|
||||
handleChangeTrestle,
|
||||
handleChangeConstMthd,
|
||||
handleChangeRoofBase,
|
||||
handleConstruction,
|
||||
handleCvrChecked,
|
||||
handleSnowGdChecked,
|
||||
} = useModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData })
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -300,21 +54,21 @@ export default function ModuleTabContents({
|
||||
<>
|
||||
<div className="eaves-keraba-th">L</div>
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="keraba-flex">
|
||||
<div className="outline-form">
|
||||
<div className="grid-select">
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={roofMaterial.lenBase}
|
||||
disabled={roofMaterial.lenAuth === 'R' ? true : false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid-select">
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={lengthBase}
|
||||
onChange={(e) => setLengthBase(e.target.value)}
|
||||
disabled={roofMaterial.lenAuth === 'R' ? true : false}
|
||||
ref={lengthRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="eaves-keraba-item">
|
||||
{roofMaterial && ['C', 'R'].includes(roofMaterial.raftAuth) && (
|
||||
<>
|
||||
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.rafter.margin')}</div>
|
||||
@ -335,22 +89,21 @@ export default function ModuleTabContents({
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="eaves-keraba-item">
|
||||
{roofMaterial && ['C', 'R'].includes(roofMaterial.roofPchAuth) && (
|
||||
<>
|
||||
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.rafter.margin')}</div>
|
||||
<div className="eaves-keraba-th">{getMessage('modal.module.basic.setting.module.hajebichi')}</div>
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="keraba-flex">
|
||||
<div className="outline-form">
|
||||
<span>垂木の間隔</span>
|
||||
<div className="grid-select">
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={roofMaterial.hajebichi}
|
||||
disabled={roofMaterial.roofPchAuth === 'R' ? true : false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="grid-select">
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
disabled={roofMaterial.roofPchAuth === 'R' ? true : false}
|
||||
onChange={(e) => setHajebichi(e.target.value)}
|
||||
value={hajebichi}
|
||||
ref={hajebichiRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
@ -454,22 +207,22 @@ export default function ModuleTabContents({
|
||||
<div className="d-check-box pop">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`ch01_${roofTab}`}
|
||||
id={`ch01_${tabIndex}`}
|
||||
disabled={cvrYn === 'N' ? true : false}
|
||||
defaultChecked={cvrChecked}
|
||||
checked={cvrChecked || false}
|
||||
onChange={handleCvrChecked}
|
||||
/>
|
||||
<label htmlFor={`ch01_${roofTab}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
|
||||
<label htmlFor={`ch01_${tabIndex}`}>{getMessage('modal.module.basic.setting.module.eaves.bar.fitting')}</label>
|
||||
</div>
|
||||
<div className="d-check-box pop">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={`ch02_${roofTab}`}
|
||||
id={`ch02_${tabIndex}`}
|
||||
disabled={snowGdPossYn === 'N' ? true : false}
|
||||
defaultChecked={snowGdChecked}
|
||||
checked={snowGdChecked || false}
|
||||
onChange={handleSnowGdChecked}
|
||||
/>
|
||||
<label htmlFor={`ch02_${roofTab}`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
|
||||
<label htmlFor={`ch02_${tabIndex}`}>{getMessage('modal.module.basic.setting.module.blind.metal.fitting')}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
import { forwardRef, useImperativeHandle, useState } from 'react'
|
||||
import { forwardRef, useContext, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useOrientation } from '@/hooks/module/useOrientation'
|
||||
import { getDegreeInOrientation } from '@/util/canvas-util'
|
||||
import { numberCheck } from '@/util/common-utils'
|
||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||
|
||||
export const Orientation = forwardRef(({ tabNum }, ref) => {
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const { trigger: canvasPopupStatusTrigger } = useCanvasPopupStatusController(1)
|
||||
|
||||
const { nextStep, compasDeg, setCompasDeg } = useOrientation()
|
||||
|
||||
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
|
||||
@ -17,8 +20,13 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
|
||||
|
||||
const handleNextStep = () => {
|
||||
nextStep()
|
||||
canvasPopupStatusTrigger(compasDeg)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
checkDegree(compasDeg)
|
||||
}, [compasDeg])
|
||||
|
||||
const checkDegree = (e) => {
|
||||
if (numberCheck(Number(e)) && Number(e) >= -180 && Number(e) <= 180) {
|
||||
setCompasDeg(Number(e))
|
||||
@ -30,7 +38,6 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
|
||||
return (
|
||||
<>
|
||||
<div className="properties-setting-wrap">
|
||||
<div className="setting-tit">{getMessage('modal.module.basic.setting.orientation.setting')}</div>
|
||||
<div className="outline-wrap">
|
||||
<div className="guide">{getMessage('modal.module.basic.setting.orientation.setting.info')}</div>
|
||||
<div className="roof-module-compas">
|
||||
@ -64,7 +71,7 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
|
||||
</div>
|
||||
<div className="center-wrap">
|
||||
<div className="d-check-box pop">
|
||||
<input type="checkbox" id="ch99" checked={!hasAnglePassivity} onChange={() => setHasAnglePassivity(!hasAnglePassivity)} />
|
||||
<input type="checkbox" id="ch99" checked={hasAnglePassivity} onChange={() => setHasAnglePassivity(!hasAnglePassivity)} />
|
||||
<label htmlFor="ch99">{getMessage('modal.module.basic.setting.orientation.setting.angle.passivity')}(-180 〜 180)</label>
|
||||
</div>
|
||||
<div className="outline-form">
|
||||
@ -73,7 +80,7 @@ export const Orientation = forwardRef(({ tabNum }, ref) => {
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={compasDeg}
|
||||
readOnly={hasAnglePassivity}
|
||||
readOnly={!hasAnglePassivity}
|
||||
placeholder={0}
|
||||
onChange={
|
||||
(e) => checkDegree(e.target.value)
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
import { forwardRef, useEffect, useState } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting'
|
||||
import { checkedModuleState } from '@/store/canvasAtom'
|
||||
import { useRecoilValue, useRecoilState, useSetRecoilState } from 'recoil'
|
||||
import { selectedModuleState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { checkedModuleState, currentCanvasPlanState } from '@/store/canvasAtom'
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { useModulePlace } from '@/hooks/module/useModulePlace'
|
||||
|
||||
const Placement = forwardRef((props, refs) => {
|
||||
const { getMessage } = useMessage()
|
||||
const [isChidori, setIsChidori] = useState('false')
|
||||
const [isChidori, setIsChidori] = useState(false)
|
||||
const [isChidoriNotAble, setIsChidoriNotAble] = useState(false)
|
||||
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
||||
|
||||
const [setupLocation, setSetupLocation] = useState('center')
|
||||
const [isMaxSetup, setIsMaxSetup] = useState('false')
|
||||
const [selectedItems, setSelectedItems] = useState({})
|
||||
@ -21,9 +24,13 @@ const Placement = forwardRef((props, refs) => {
|
||||
|
||||
//모듈 배치면 생성
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ Placement ~ moduleSelectionData:', moduleSelectionData)
|
||||
console.log('🚀 ~ Placement ~ selectedModules:', selectedModules)
|
||||
makeModuleInstArea()
|
||||
if (moduleSelectionData) {
|
||||
//1개라도 치도리 불가가 있으면 치도리 불가
|
||||
const isChidroriValue = moduleSelectionData.roofConstructions.some((item) => item.construction.plvrYn === 'N')
|
||||
if (isChidroriValue) {
|
||||
setIsChidoriNotAble(true)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
//체크된 모듈 데이터
|
||||
@ -45,10 +52,15 @@ const Placement = forwardRef((props, refs) => {
|
||||
}
|
||||
|
||||
const handleChangeChidori = (e) => {
|
||||
setIsChidori(e.target.value)
|
||||
const bool = e.target.value === 'true' ? true : false
|
||||
setIsChidori(bool)
|
||||
refs.isChidori.current = e.target.value
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('isChidori', isChidori)
|
||||
}, [isChidori])
|
||||
|
||||
const handleSetupLocation = (e) => {
|
||||
setSetupLocation(e.target.value)
|
||||
refs.setupLocation.current = e.target.value
|
||||
@ -127,19 +139,19 @@ const Placement = forwardRef((props, refs) => {
|
||||
<div className="self-item-td">
|
||||
<div className="pop-form-radio">
|
||||
<div className="d-check-radio pop">
|
||||
<input type="radio" name="radio01" id="ra01" checked={isChidori === 'true'} value={'true'} onChange={handleChangeChidori} />
|
||||
<input
|
||||
type="radio"
|
||||
name="radio01"
|
||||
id="ra01"
|
||||
checked={isChidori}
|
||||
disabled={isChidoriNotAble}
|
||||
value={'true'}
|
||||
onChange={(e) => handleChangeChidori(e)}
|
||||
/>
|
||||
<label htmlFor="ra01">{getMessage('modal.module.basic.setting.module.placement.do')}</label>
|
||||
</div>
|
||||
<div className="d-check-radio pop">
|
||||
<input
|
||||
type="radio"
|
||||
name="radio02"
|
||||
id="ra02"
|
||||
value={'false'}
|
||||
defaultChecked
|
||||
checked={isChidori === 'false'}
|
||||
onChange={handleChangeChidori}
|
||||
/>
|
||||
<input type="radio" name="radio02" id="ra02" checked={!isChidori} value={'false'} onChange={(e) => handleChangeChidori(e)} />
|
||||
<label htmlFor="ra02">{getMessage('modal.module.basic.setting.module.placement.do.not')}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -6,20 +6,21 @@ import StepUp from '@/components/floor-plan/modal/circuitTrestle/step/StepUp'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
import PassivityCircuitAllocation from './step/type/PassivityCircuitAllocation'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { get } from 'react-hook-form'
|
||||
import { correntObjectNoState } from '@/store/settingAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { powerConditionalState } from '@/store/circuitTrestleAtom'
|
||||
import { makersState, modelsState, modelState, pcsCheckState, selectedMakerState, selectedModelsState, seriesState } from '@/store/circuitTrestleAtom'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
|
||||
import { useTrestle } from '@/hooks/module/useTrestle'
|
||||
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
import { stepUpListDataState } from '@/store/circuitTrestleAtom'
|
||||
|
||||
const ALLOCATION_TYPE = {
|
||||
AUTO: 'auto',
|
||||
@ -28,62 +29,455 @@ const ALLOCATION_TYPE = {
|
||||
export default function CircuitTrestleSetting({ id }) {
|
||||
const { getMessage } = useMessage()
|
||||
const { closePopup } = usePopup()
|
||||
// 탭 번호 1: 파워 컨디셔너 선택(+수동 설정)
|
||||
// 탭 번호 2: 회로 할당
|
||||
const { apply } = useTrestle()
|
||||
const { swalFire } = useSwal()
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
|
||||
const [makers, setMakers] = useRecoilState(makersState)
|
||||
const [selectedMaker, setSelectedMaker] = useRecoilState(selectedMakerState)
|
||||
const [series, setSeries] = useRecoilState(seriesState)
|
||||
const [models, setModels] = useRecoilState(modelsState)
|
||||
const [selectedModels, setSelectedModels] = useRecoilState(selectedModelsState)
|
||||
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
||||
|
||||
const [tabNum, setTabNum] = useState(1)
|
||||
const [allocationType, setAllocationType] = useState(ALLOCATION_TYPE.AUTO)
|
||||
|
||||
const [makers, setMakers] = useState([])
|
||||
const [series, setSeries] = useState([])
|
||||
const [models, setModels] = useState([])
|
||||
const [selectedMaker, setSelectedMaker] = useState(null)
|
||||
const [selectedModels, setSelectedModels] = useState(null)
|
||||
const [selectedSeries, setSelectedSeries] = useState(null)
|
||||
const correntObjectNo = useRecoilValue(correntObjectNoState)
|
||||
const { getPcsMakerList } = useMasterController()
|
||||
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
const { apply } = useTrestle()
|
||||
const selectedModules = useRecoilValue(selectedModuleState)
|
||||
const { getPcsAutoRecommendList, getPcsVoltageChk } = useMasterController()
|
||||
|
||||
// 회로할당(승합설정)에서 선택된 값들을 저장할 상태 추가
|
||||
const [selectedStepUpValues, setSelectedStepUpValues] = useState({})
|
||||
const [getStepUpSelections, setGetStepUpSelections] = useState(null)
|
||||
|
||||
const [stepUpListData, setStepUpListData] = useRecoilState(stepUpListDataState)
|
||||
|
||||
useEffect(() => {
|
||||
// console.log(canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE))
|
||||
// if (canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE).length === 0) {
|
||||
// swalFire({
|
||||
// title: '모듈을 배치해주세요.',
|
||||
// type: 'alert',
|
||||
// confirmFn: () => {
|
||||
// closePopup(id)
|
||||
// },
|
||||
// })
|
||||
// }
|
||||
if (!managementState) {
|
||||
setManagementState(managementStateLoaded)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log('🚀 ~ CircuitTrestleSetting ~ series:', series)
|
||||
// const selectedSeries = series.filter((s) => s.selectd).map((s) => s.pcsSerCd)
|
||||
// if (selectedSeries.length > 0) {
|
||||
// getPcsMakerList(selectedSeries).then((res) => {
|
||||
// setModels(res.data)
|
||||
// })
|
||||
// }
|
||||
// }, [series])
|
||||
// 회로 할당 유형
|
||||
const [circuitAllocationType, setCircuitAllocationType] = useState(1)
|
||||
useEffect(() => {
|
||||
if (allocationType === ALLOCATION_TYPE.PASSIVITY && tabNum === 2) {
|
||||
const notAllocationModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && !obj.circuit)
|
||||
canvas.remove(...notAllocationModules)
|
||||
canvas.renderAll()
|
||||
}
|
||||
}, [tabNum])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('stepUpListData >>> ', stepUpListData)
|
||||
}, [stepUpListData])
|
||||
|
||||
const onAutoRecommend = () => {
|
||||
if (series.filter((s) => s.selected).length === 0) {
|
||||
swalFire({
|
||||
title: '시리즈를 선택해 주세요.',
|
||||
type: 'alert',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const params = {
|
||||
...getOptYn(),
|
||||
useModuleItemList: getUseModuleItemList(),
|
||||
roofSurfaceList: getRoofSurfaceList(),
|
||||
pcsItemList: getPcsItemList(),
|
||||
}
|
||||
|
||||
if (selectedModels.length === 0) {
|
||||
getPcsAutoRecommendList(params).then((res) => {
|
||||
if (res.data?.pcsItemList) {
|
||||
const itemList = models.filter((model) => {
|
||||
return res.data?.pcsItemList.map((item) => item.itemId).includes(model.itemId)
|
||||
})
|
||||
const selectedModels = itemList.map((model) => {
|
||||
return {
|
||||
...model,
|
||||
id: uuidv4(),
|
||||
}
|
||||
})
|
||||
const pcsVoltageChkParams = {
|
||||
...getOptYn(),
|
||||
useModuleItemList: getUseModuleItemList(),
|
||||
roofSurfaceList: getRoofSurfaceList(),
|
||||
pcsItemList: getPcsItemList(),
|
||||
}
|
||||
setSelectedModels(selectedModels)
|
||||
getPcsVoltageChk(pcsVoltageChkParams).then((res) => {
|
||||
setTabNum(2)
|
||||
})
|
||||
} else {
|
||||
// 데이터가 없는 경우 오류 메시지 확인 필요
|
||||
if (res.result.resultCode === 'E') {
|
||||
swalFire({
|
||||
title: res.result.resultMsg,
|
||||
type: 'alert',
|
||||
})
|
||||
} else {
|
||||
swalFire({
|
||||
title: '파워컨디셔너를 추가해 주세요.',
|
||||
type: 'alert',
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
getPcsVoltageChk(params).then((res) => {
|
||||
setTabNum(2)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getOptYn = () => {
|
||||
return {
|
||||
maxConnYn: pcsCheck.max ? 'Y' : 'N',
|
||||
smpCirYn: pcsCheck.division ? 'Y' : 'N',
|
||||
coldZoneYn: managementState?.coldRegionFlg === '1' ? 'Y' : 'N',
|
||||
}
|
||||
}
|
||||
|
||||
const getPcsItemList = () => {
|
||||
return models.map((model) => {
|
||||
return {
|
||||
itemId: model.itemId,
|
||||
pcsMkrCd: model.pcsMkrCd,
|
||||
pcsSerCd: model.pcsSerCd,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getUseModuleItemList = () => {
|
||||
return selectedModules.itemList.map((m) => {
|
||||
return {
|
||||
itemId: m.itemId,
|
||||
mixMatlNo: m.mixMatlNo,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getRoofSurfaceList = () => {
|
||||
return canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||
.map((obj) => {
|
||||
getModuleList(obj)
|
||||
return {
|
||||
roofSurfaceId: obj.id,
|
||||
roofSurface: canvas
|
||||
.getObjects()
|
||||
.filter((o) => o.id === obj.parentId)[0]
|
||||
.directionText.replace(/[0-9]/g, ''),
|
||||
roofSurfaceIncl: canvas.getObjects().filter((o) => o.id === obj.parentId)[0].roofMaterial.pitch,
|
||||
moduleList: getModuleList(obj).map((module) => {
|
||||
return {
|
||||
itemId: module.moduleInfo.itemId,
|
||||
circuit: module.circuitNumber ? module.circuitNumber : null,
|
||||
pcsItemId: module.circuit ? module.circuit?.pcsItemId : null,
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getModuleList = (surface) => {
|
||||
let moduleList = []
|
||||
let [xObj, yObj] = [{}, {}]
|
||||
let [xPoints, yPoints] = [[], []]
|
||||
surface.modules.forEach((module) => {
|
||||
if (!xObj[module.left]) {
|
||||
xObj[module.left] = module.left
|
||||
xPoints.push(module.left)
|
||||
}
|
||||
if (!yObj[module.top]) {
|
||||
yObj[module.top] = module.top
|
||||
yPoints.push(module.top)
|
||||
}
|
||||
})
|
||||
switch (surface.direction) {
|
||||
case 'south':
|
||||
xPoints.sort((a, b) => a - b)
|
||||
yPoints.sort((a, b) => b - a)
|
||||
yPoints.forEach((y, index) => {
|
||||
let temp = surface.modules.filter((m) => m.top === y)
|
||||
if (index % 2 === 0) {
|
||||
temp.sort((a, b) => a.left - b.left)
|
||||
} else {
|
||||
temp.sort((a, b) => b.left - a.left)
|
||||
}
|
||||
moduleList = [...moduleList, ...temp]
|
||||
})
|
||||
break
|
||||
case 'north':
|
||||
xPoints.sort((a, b) => b - a)
|
||||
yPoints.sort((a, b) => a - b)
|
||||
yPoints.forEach((y, index) => {
|
||||
let temp = surface.modules.filter((m) => m.top === y)
|
||||
if (index % 2 === 0) {
|
||||
temp.sort((a, b) => b.left - a.left)
|
||||
} else {
|
||||
temp.sort((a, b) => a.left - b.left)
|
||||
}
|
||||
moduleList = [...moduleList, ...temp]
|
||||
})
|
||||
break
|
||||
case 'west':
|
||||
xPoints.sort((a, b) => a - b)
|
||||
yPoints.sort((a, b) => a - b)
|
||||
xPoints.forEach((x, index) => {
|
||||
let temp = surface.modules.filter((m) => m.left === x)
|
||||
if (index % 2 === 0) {
|
||||
temp.sort((a, b) => a.top - b.top)
|
||||
} else {
|
||||
temp.sort((a, b) => b.top - a.top)
|
||||
}
|
||||
moduleList = [...moduleList, ...temp]
|
||||
})
|
||||
break
|
||||
case 'east':
|
||||
xPoints.sort((a, b) => b - a)
|
||||
yPoints.sort((a, b) => b - a)
|
||||
xPoints.forEach((x, index) => {
|
||||
let temp = surface.modules.filter((m) => m.left === x)
|
||||
if (index % 2 === 0) {
|
||||
temp.sort((a, b) => b.top - a.top)
|
||||
} else {
|
||||
temp.sort((a, b) => a.top - b.top)
|
||||
}
|
||||
moduleList = [...moduleList, ...temp]
|
||||
})
|
||||
break
|
||||
default:
|
||||
return []
|
||||
}
|
||||
return moduleList
|
||||
}
|
||||
|
||||
const onAutoAllocation = () => {
|
||||
let moduleStdQty = 0
|
||||
let moduleMaxQty = 0
|
||||
const selectedModels = models.filter((m) => m.selected)
|
||||
|
||||
if (selectedModels.length === 0) {
|
||||
onAutoRecommend()
|
||||
} else {
|
||||
moduleStdQty = selectedModels.reduce((acc, model) => {
|
||||
return acc + parseInt(model.moduleStdQty)
|
||||
}, 0)
|
||||
moduleMaxQty = selectedModels.reduce((acc, model) => {
|
||||
return acc + parseInt(model.moduleMaxQty)
|
||||
}, 0)
|
||||
}
|
||||
// const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
|
||||
// const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
|
||||
// if (placementModules.length > target) {
|
||||
// swalFire({
|
||||
// title: '배치가능 매수를 초과합니다. 파워컨디셔너를 다시 선택해 주세요.',
|
||||
// type: 'alert',
|
||||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
// setAllocationType(ALLOCATION_TYPE.AUTO)
|
||||
// setTabNum(2)
|
||||
}
|
||||
|
||||
const onPassivityAllocation = () => {
|
||||
if (selectedModels.length === 0) {
|
||||
const params = {
|
||||
...getOptYn(),
|
||||
useModuleItemList: getUseModuleItemList(),
|
||||
roofSurfaceList: getRoofSurfaceList(),
|
||||
pcsItemList: getPcsItemList(),
|
||||
}
|
||||
|
||||
getPcsAutoRecommendList(params).then((res) => {
|
||||
if (res.data?.pcsItemList) {
|
||||
const itemList = models.filter((model) => {
|
||||
return res.data?.pcsItemList.map((item) => item.itemId).includes(model.itemId)
|
||||
})
|
||||
const selectedModels = itemList.map((model) => {
|
||||
return {
|
||||
...model,
|
||||
id: uuidv4(),
|
||||
}
|
||||
})
|
||||
const PcsVoltageChkParams = {
|
||||
...getOptYn(),
|
||||
useModuleItemList: getUseModuleItemList(),
|
||||
roofSurfaceList: getRoofSurfaceList(),
|
||||
pcsItemList: getPcsItemList(),
|
||||
}
|
||||
setSelectedModels(selectedModels)
|
||||
getPcsVoltageChk(PcsVoltageChkParams).then((res) => {})
|
||||
} else {
|
||||
swalFire({
|
||||
title: '파워컨디셔너를 추가해 주세요.',
|
||||
type: 'alert',
|
||||
})
|
||||
}
|
||||
})
|
||||
} else if (pcsCheck.max) {
|
||||
const moduleStdQty = selectedModels.reduce((acc, model) => {
|
||||
return acc + parseInt(model.moduleStdQty)
|
||||
}, 0)
|
||||
const moduleMaxQty = selectedModels.reduce((acc, model) => {
|
||||
return acc + parseInt(model.moduleMaxQty)
|
||||
}, 0)
|
||||
|
||||
const target = pcsCheck.max ? moduleMaxQty : moduleStdQty
|
||||
const placementModules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
|
||||
if (placementModules.length > target) {
|
||||
swalFire({
|
||||
title: '배치가능 매수를 초과합니다. 파워컨디셔너를 다시 선택해 주세요.',
|
||||
type: 'alert',
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
setAllocationType(ALLOCATION_TYPE.PASSIVITY)
|
||||
}
|
||||
|
||||
// StepUp에서 선택된 값들을 처리하는 함수 수정
|
||||
const handleStepUpValuesSelected = (selectionData) => {
|
||||
const { gooodsNo } = selectionData
|
||||
|
||||
setSelectedStepUpValues((prev) => ({
|
||||
...prev,
|
||||
[gooodsNo]: selectionData,
|
||||
}))
|
||||
}
|
||||
|
||||
// StepUp 컴포넌트 초기화 핸들러
|
||||
const handleStepUpInitialize = (getCurrentSelections) => {
|
||||
setGetStepUpSelections(() => getCurrentSelections)
|
||||
}
|
||||
|
||||
// apply 함수 수정
|
||||
const onApply = () => {
|
||||
// 현재 선택된 값들 가져오기
|
||||
const currentSelections = getStepUpSelections ? getStepUpSelections() : {}
|
||||
|
||||
console.log('currentSelections >>> ', currentSelections)
|
||||
|
||||
// 실제 선택된 값이 있는지 더 정확하게 확인
|
||||
const hasSelections = Object.values(currentSelections).some((stepUpConfig) => Object.values(stepUpConfig).length > 0)
|
||||
|
||||
console.log('hasSelections >>> ', hasSelections)
|
||||
|
||||
if (!hasSelections) {
|
||||
swalFire({
|
||||
title: '승압 설정값을 선택해주세요.1',
|
||||
type: 'alert',
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 선택된 값들 로그
|
||||
console.log('Applying StepUp configurations:', currentSelections)
|
||||
|
||||
// StepUp 컴포넌트로부터 stepUpListData 받아오기
|
||||
//const stepUpData = getStepUpSelections().stepUpListData
|
||||
//console.log('stepUpData >>> ', stepUpData)
|
||||
// stepUpListData를 Recoil state에 저장
|
||||
// setStepUpListData(stepUpData)
|
||||
|
||||
// 선택된 값들을 배열로 변환하여 처리
|
||||
const configurations = Object.values(currentSelections)
|
||||
.map((stepUpConfig) => {
|
||||
const firstConfig = Object.values(stepUpConfig)[0] // 첫 번째 설정만 사용
|
||||
return {
|
||||
pcsInfo: firstConfig.pcsInfo,
|
||||
allocation: firstConfig.allocation,
|
||||
}
|
||||
})
|
||||
.filter((config) => config.pcsInfo && config.allocation) // 유효한 설정만 필터링
|
||||
|
||||
console.log('Processed configurations:', configurations)
|
||||
|
||||
// stepUpListData를 Recoil state에 저장
|
||||
setStepUpListData(configurations)
|
||||
|
||||
// 기존 apply 로직 실행 전에 필요한 데이터가 모두 있는지 확인
|
||||
if (configurations.length > 0) {
|
||||
apply()
|
||||
} else {
|
||||
swalFire({
|
||||
title: '승압 설정값을 선택해주세요.2',
|
||||
type: 'alert',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const onClickPrev = () => {
|
||||
setAllocationType(ALLOCATION_TYPE.AUTO)
|
||||
swalFire({
|
||||
text: '할당한 회로 번호가 초기화됩니다.',
|
||||
type: 'alert',
|
||||
icon: 'warning',
|
||||
confirmFn: () => {
|
||||
const circuitModules = canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id))
|
||||
canvas.remove(...circuitModules.map((module) => module.circuit))
|
||||
circuitModules.forEach((obj) => {
|
||||
obj.circuit = null
|
||||
obj.pcsItemId = null
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const powerConditionalSelectProps = {
|
||||
tabNum,
|
||||
setTabNum,
|
||||
makers,
|
||||
setMakers,
|
||||
selectedMaker,
|
||||
setSelectedMaker,
|
||||
series,
|
||||
setSeries,
|
||||
models,
|
||||
setModels,
|
||||
selectedModels,
|
||||
setSelectedModels,
|
||||
managementState,
|
||||
}
|
||||
const circuitProps = {
|
||||
|
||||
const passivityProps = {
|
||||
tabNum,
|
||||
setTabNum,
|
||||
pcsCheck,
|
||||
selectedModels,
|
||||
setSelectedModels,
|
||||
getOptYn,
|
||||
getUseModuleItemList,
|
||||
getRoofSurfaceList,
|
||||
}
|
||||
|
||||
const stepUpProps = {
|
||||
tabNum,
|
||||
setTabNum,
|
||||
models,
|
||||
setModels,
|
||||
circuitAllocationType,
|
||||
setCircuitAllocationType,
|
||||
getOptYn, // 옵션 Y/N
|
||||
getUseModuleItemList, // 사용된 모듈아이템 List
|
||||
getRoofSurfaceList, // 지붕면 목록
|
||||
getPcsItemList, // PCS 아이템 목록
|
||||
onValuesSelected: handleStepUpValuesSelected, // 선택된 값들을 처리하는 함수
|
||||
}
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
||||
<div className={`modal-pop-wrap l-2`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.circuit.trestle.setting')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -98,14 +492,14 @@ export default function CircuitTrestleSetting({ id }) {
|
||||
</div>
|
||||
</div>
|
||||
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && <PowerConditionalSelect {...powerConditionalSelectProps} />}
|
||||
{tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && <PassivityCircuitAllocation {...powerConditionalSelectProps} />}
|
||||
{tabNum === 2 && <StepUp />}
|
||||
{tabNum === 1 && allocationType === ALLOCATION_TYPE.PASSIVITY && <PassivityCircuitAllocation {...passivityProps} />}
|
||||
{tabNum === 2 && <StepUp {...stepUpProps} onInitialize={handleStepUpInitialize} />}
|
||||
{tabNum === 1 && allocationType === ALLOCATION_TYPE.AUTO && (
|
||||
<div className="grid-btn-wrap">
|
||||
<button className="btn-frame modal mr5" onClick={() => setTabNum(2)}>
|
||||
<button className="btn-frame modal mr5" onClick={() => onAutoAllocation()}>
|
||||
{getMessage('modal.circuit.trestle.setting.circuit.allocation.auto')}
|
||||
</button>
|
||||
<button className="btn-frame modal act" onClick={() => setAllocationType(ALLOCATION_TYPE.PASSIVITY)}>
|
||||
<button className="btn-frame modal act" onClick={() => onPassivityAllocation()}>
|
||||
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}
|
||||
</button>
|
||||
</div>
|
||||
@ -125,12 +519,14 @@ export default function CircuitTrestleSetting({ id }) {
|
||||
<button className="btn-frame modal mr5" onClick={() => setTabNum(1)}>
|
||||
{getMessage('modal.common.prev')}
|
||||
</button>
|
||||
<button className="btn-frame modal act" onClick={() => apply()}>
|
||||
{/* <button className="btn-frame modal act" onClick={() => apply()}> */}
|
||||
<button className="btn-frame modal act" onClick={onApply}>
|
||||
{getMessage('modal.common.save')}({getMessage('modal.circuit.trestle.setting.circuit.allocation')})
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -1,36 +1,43 @@
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { makerState, modelState, seriesState } from '@/store/circuitTrestleAtom'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { pcsCheckState } from '@/store/circuitTrestleAtom'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { isNullOrUndefined } from '@/util/common-utils'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
|
||||
|
||||
export default function PowerConditionalSelect(props) {
|
||||
let { tabNum, setTabNum } = props
|
||||
const [makerData, setMakerData] = useRecoilState(makerState)
|
||||
const [makers, setMakers] = useState(makerData.makers)
|
||||
const [selectedMaker, setSelectedMaker] = useState(makerData.selectedMaker)
|
||||
const [series, setSeries] = useRecoilState(seriesState)
|
||||
const [seriesList, setSeriesList] = useState(series.series)
|
||||
const [selectedSeries, setSelectedSeries] = useState(series.selectedSeries)
|
||||
const model = useRecoilValue(modelState)
|
||||
const [models, setModels] = useState(model.models)
|
||||
const [selectedModels, setSelectedModels] = useState(model.selectedModels)
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
let {
|
||||
tabNum,
|
||||
setTabNum,
|
||||
makers,
|
||||
setMakers,
|
||||
selectedMaker,
|
||||
setSelectedMaker,
|
||||
series,
|
||||
setSeries,
|
||||
models,
|
||||
setModels,
|
||||
selectedModels,
|
||||
setSelectedModels,
|
||||
managementState,
|
||||
} = props
|
||||
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
||||
|
||||
const { getMessage } = useMessage()
|
||||
const [selectedRow, setSelectedRow] = useState(null)
|
||||
const globalLocale = useRecoilValue(globalLocaleStore)
|
||||
const { getPcsMakerList, getPcsModelList } = useMasterController()
|
||||
const selectedModules = useRecoilValue(selectedModuleState)
|
||||
const { swalFire } = useSwal()
|
||||
const modelHeader = [
|
||||
{ name: getMessage('시리즈'), width: '15%', prop: 'pcsSerNm', type: 'color-box' },
|
||||
{ name: getMessage('명칭'), width: '15%', prop: 'itemNm', type: 'color-box' },
|
||||
{
|
||||
name: `${getMessage('modal.circuit.trestle.setting.power.conditional.select.rated.output')} (kW)`,
|
||||
@ -57,86 +64,115 @@ export default function PowerConditionalSelect(props) {
|
||||
useEffect(() => {
|
||||
if (makers.length === 0) {
|
||||
getPcsMakerList().then((res) => {
|
||||
console.log('getPcsMakerList', res.data)
|
||||
setMakers(res.data)
|
||||
})
|
||||
}
|
||||
if (!managementState) {
|
||||
console.log('🚀 ~ useEffect ~ managementState:', managementState)
|
||||
setManagementState(managementStateLoaded)
|
||||
}
|
||||
// promiseGet({ url: `/api/object/${correntObjectNo}/detail` }).then((res) => {
|
||||
// console.log('🚀 ~ useEffect ~ /api/object/${correntObjectNo}/detail:', res)
|
||||
// // coldRegionFlg-한랭지사양, conType// 계약조건(잉여~,전량)
|
||||
// })
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ PowerConditionalSelect ~ selectedMaker:', selectedMaker)
|
||||
if (selectedMaker) {
|
||||
setSelectedModels([])
|
||||
getPcsMakerList(selectedMaker).then((res) => {
|
||||
setSeriesList(
|
||||
res.data.map((series) => {
|
||||
return { ...series, selected: false }
|
||||
}),
|
||||
)
|
||||
const checkValidation = () => {
|
||||
const checkedSeries = series.filter((s) => s.selected)
|
||||
if (checkedSeries.length === 0) {
|
||||
swalFire({
|
||||
title: 'PCS 시리즈를 선택해 주세요.',
|
||||
icon: 'warning',
|
||||
})
|
||||
return false
|
||||
} else if (checkedSeries.length === 1) {
|
||||
if (checkedSeries[0].pcsMkrMultiType === 'SINGLE-P' && checkedSeries[0].pcsSerParallelYn === 'Y') {
|
||||
swalFire({
|
||||
title: '병설은 단독으로 안 됨',
|
||||
icon: 'warning',
|
||||
})
|
||||
}
|
||||
return false
|
||||
}
|
||||
}, [selectedMaker])
|
||||
return true
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ useEffect ~ seriesList:', seriesList)
|
||||
if (seriesList.filter((series) => series.selected).length === 0) return
|
||||
const pcsMkrCd = seriesList.filter((series) => series.selected)[0]?.pcsMkrCd
|
||||
const pcsSerList = seriesList
|
||||
.filter((series) => series.selected)
|
||||
.map((series) => {
|
||||
return { pcsSerCd: series.pcsSerCd }
|
||||
})
|
||||
const onCheckSeries = (data) => {
|
||||
console.log('data', data)
|
||||
const copySeries = series.map((s) => {
|
||||
return {
|
||||
...s,
|
||||
selected: s.pcsSerCd === data.pcsSerCd ? !s.selected : s.selected,
|
||||
}
|
||||
})
|
||||
setSeries(copySeries)
|
||||
console.log('copySeries', copySeries)
|
||||
handleSetmodels(copySeries.filter((s) => s.selected))
|
||||
}
|
||||
|
||||
const handleSetmodels = (selectedSeries) => {
|
||||
console.log('series', selectedSeries)
|
||||
if (selectedSeries.length === 0) {
|
||||
setModels([])
|
||||
setSelectedModels([])
|
||||
return
|
||||
}
|
||||
const pcsMkrCd = selectedSeries[0]?.pcsMkrCd
|
||||
const pcsSerList = selectedSeries.map((series) => {
|
||||
return { pcsSerCd: series.pcsSerCd }
|
||||
})
|
||||
const moduleItemList = selectedModules.itemList?.map((module) => {
|
||||
return {
|
||||
itemId: module.itemId,
|
||||
mixMatlNo: module.mixMatlNo,
|
||||
}
|
||||
})
|
||||
console.log('🚀 ~ useEffect ~ moduleItemList:', selectedModules)
|
||||
getPcsModelList({ pcsMkrCd, pcsSerList, moduleItemList }).then((res) => {
|
||||
if (res?.result.code === 200) {
|
||||
console.log('🚀 ~ useEffect ~ res:', res.data)
|
||||
if (res?.result.code === 200 && res?.data) {
|
||||
setModels(
|
||||
res.data.map((model) => {
|
||||
return {
|
||||
...model,
|
||||
moduleStdQty: parseInt(model.moduleStdQty),
|
||||
moduleMaxQty: parseInt(model.moduleMaxQty),
|
||||
code: uuidv4(),
|
||||
selected: false,
|
||||
}
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
setModels([])
|
||||
setSelectedModels([])
|
||||
}
|
||||
})
|
||||
}, [seriesList])
|
||||
|
||||
const onCheckSeries = (series) => {
|
||||
setSeriesList((prev) => prev.map((s) => ({ ...s, selected: s.pcsSerCd === series.pcsSerCd ? !s.selected : s.selected })))
|
||||
}
|
||||
|
||||
const onAddSelectedModel = () => {
|
||||
setSelectedModels([...selectedModels, selectedRow])
|
||||
if (selectedRow === null) return
|
||||
if (selectedModels.length === 3) {
|
||||
swalFire({
|
||||
title: '최대 3개까지 선택할 수 있습니다.',
|
||||
icon: 'warning',
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
setSelectedModels([...selectedModels, { ...selectedRow, id: uuidv4() }])
|
||||
setSelectedRow(null)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const selectedModelsIds = selectedModels.map((model) => model.itemId)
|
||||
const onRemoveSelectedModel = (model) => {
|
||||
setSelectedModels(selectedModels.filter((m) => m.id !== model.id))
|
||||
}
|
||||
|
||||
const onChangeMaker = (option) => {
|
||||
if (option) {
|
||||
setModels([])
|
||||
setSelectedMaker(option)
|
||||
|
||||
getPcsMakerList(option).then((res) => {
|
||||
console.log('getPcsMakerList(series)', res.data)
|
||||
setSeries(
|
||||
res.data.map((series) => {
|
||||
return { ...series, selected: false }
|
||||
}),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
setModels(
|
||||
models.map((model) => {
|
||||
return {
|
||||
...model,
|
||||
selected: selectedModelsIds.includes(model.itemId) === selectedRow.itemId ? true : false,
|
||||
}
|
||||
}),
|
||||
)
|
||||
}, [selectedModels])
|
||||
return (
|
||||
<>
|
||||
<div className="outline-form mb15">
|
||||
@ -151,19 +187,19 @@ export default function PowerConditionalSelect(props) {
|
||||
sourceKey="pcsMkrCd"
|
||||
targetKey="pcsMkrCd"
|
||||
value={selectedMaker}
|
||||
onChange={(option) => setSelectedMaker(option)}
|
||||
onChange={(option) => onChangeMaker(option)}
|
||||
/>
|
||||
</div>
|
||||
{managementState?.conType === '1' && (
|
||||
{managementState?.coldRegionFlg === '1' && (
|
||||
<span className="thin">{getMessage('modal.circuit.trestle.setting.power.conditional.select.cold.region')}</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="module-table-box mb10">
|
||||
<div className="module-table-inner">
|
||||
<div className="circuit-check-inner overflow">
|
||||
{seriesList?.map((series, index) => (
|
||||
{series?.map((series, index) => (
|
||||
<div className="d-check-box pop sel">
|
||||
<input type="checkbox" id={`"ch0"${index}`} onClick={() => onCheckSeries(series)} checked={series.selected} />
|
||||
<input type="checkbox" id={`"ch0"${index}`} onChange={() => onCheckSeries(series)} checked={series.selected} />
|
||||
<label htmlFor={`"ch0"${index}`}>{globalLocale === 'ko' ? series.pcsSerNm : series.pcsSerNmJp}</label>
|
||||
</div>
|
||||
))}
|
||||
@ -185,15 +221,13 @@ export default function PowerConditionalSelect(props) {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{models
|
||||
?.filter((model) => !model.selected)
|
||||
.map((model, index) => (
|
||||
<tr key={index} onClick={() => setSelectedRow(model)} className={model === selectedRow ? 'on' : ''}>
|
||||
{modelHeader.map((header) => (
|
||||
<td>{model[header.prop]}</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
{models?.map((model, index) => (
|
||||
<tr key={index} onClick={() => setSelectedRow(model)} className={model === selectedRow ? 'on' : ''}>
|
||||
{modelHeader.map((header) => (
|
||||
<td>{model[header.prop]}</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -206,7 +240,7 @@ export default function PowerConditionalSelect(props) {
|
||||
<div className="circuit-data-form">
|
||||
{selectedModels?.map((model) => (
|
||||
<span className="normal-font">
|
||||
{model.itemNm} <button className="del"></button>
|
||||
{model.itemNm} <button className="del" onClick={() => onRemoveSelectedModel(model)}></button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
@ -214,11 +248,11 @@ export default function PowerConditionalSelect(props) {
|
||||
</div>
|
||||
<div className="slope-wrap">
|
||||
<div className="d-check-box pop mb15">
|
||||
<input type="checkbox" id="ch03" />
|
||||
<input type="checkbox" id="ch03" checked={pcsCheck.division} onChange={() => setPcsCheck({ ...pcsCheck, division: !pcsCheck.division })} />
|
||||
<label htmlFor="ch03">{getMessage('modal.circuit.trestle.setting.power.conditional.select.check1')}</label>
|
||||
</div>
|
||||
<div className="d-check-box pop">
|
||||
<input type="checkbox" id="ch04" />
|
||||
<input type="checkbox" id="ch04" checked={pcsCheck.max} onChange={() => setPcsCheck({ ...pcsCheck, max: !pcsCheck.max })} />
|
||||
<label className="red" htmlFor="ch04">
|
||||
{getMessage('modal.circuit.trestle.setting.power.conditional.select.check2')}
|
||||
</label>
|
||||
|
||||
@ -1,133 +1,416 @@
|
||||
import { useState } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { modelState, pcsCheckState } from '@/store/circuitTrestleAtom'
|
||||
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||
import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import QSelectBox from '@/components/common/select/QSelectBox'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
|
||||
const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
|
||||
|
||||
export default function StepUp({}) {
|
||||
export default function StepUp(props) {
|
||||
const { getMessage } = useMessage()
|
||||
const [moduleTab, setModuleTab] = useState(1)
|
||||
const [moduleTabs, setModuleTabs] = useState({})
|
||||
const [arrayLength, setArrayLength] = useState(3) //module-table-inner의 반복 개수
|
||||
const [pcsCheck, setPcsCheck] = useRecoilState(pcsCheckState)
|
||||
const { models } = props
|
||||
const { getPcsVoltageStepUpList, getPcsAutoRecommendList } = useMasterController()
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const selectedModules = useRecoilValue(selectedModuleState)
|
||||
const [stepUpListData, setStepUpListData] = useState([])
|
||||
const [optCodes, setOptCodes] = useState([])
|
||||
|
||||
useCanvasPopupStatusController(6)
|
||||
const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore)
|
||||
if (Object.keys(canvasPopupStatusState[6]).length !== 0) {
|
||||
const [selectedRows, setSelectedRows] = useState({})
|
||||
const [isManualSelection, setIsManualSelection] = useState({})
|
||||
|
||||
// 선택된 값들을 저장할 상태 추가
|
||||
const [selectedValues, setSelectedValues] = useState({})
|
||||
|
||||
// useCanvasPopupStatusController(6)
|
||||
// const canvasPopupStatusState = useRecoilValue(canvasPopupStatusStore)
|
||||
// if (Object.keys(canvasPopupStatusState[6]).length !== 0) {
|
||||
// console.log('🚀 ~ useEffect ~ canvasPopupStatusState :', canvasPopupStatusState)
|
||||
// }
|
||||
|
||||
useEffect(() => {
|
||||
// PCS 승압설정 정보 조회
|
||||
fetchStepUpData()
|
||||
}, [])
|
||||
|
||||
// PCS 승압설정 정보 조회
|
||||
const fetchStepUpData = async () => {
|
||||
try {
|
||||
const params = {
|
||||
useYn: props.getOptYn(), // 옵션 Y/N
|
||||
useModuleItemList: props.getUseModuleItemList(), // 사용된 모듈아이템 List
|
||||
roofSurfaceList: props.getRoofSurfaceList(), // 지붕면 목록
|
||||
pcsItemList: props.getPcsItemList(), // PCS 아이템 목록
|
||||
}
|
||||
|
||||
// PCS 승압설정 정보 조회
|
||||
const res = await getPcsVoltageStepUpList(params)
|
||||
|
||||
if (res?.result.code === 200 && res?.data) {
|
||||
const dataArray = Array.isArray(res.data) ? res.data : [res.data]
|
||||
const stepUpListData = formatStepUpListData(dataArray)
|
||||
|
||||
// PCS 승압설정 정보 SET
|
||||
setStepUpListData(stepUpListData)
|
||||
|
||||
// PCS 옵션 조회
|
||||
const formattedOptCodes = formatOptionCodes(res.data.optionList)
|
||||
setOptCodes(formattedOptCodes)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error fetching step up data:', error)
|
||||
}
|
||||
}
|
||||
|
||||
// PCS 옵션 조회
|
||||
const formatOptionCodes = (optionList = []) => {
|
||||
return optionList?.map((opt) => ({
|
||||
code: opt.pcsOptCd ? opt.pcsOptCd : '',
|
||||
name: opt.pcsOptNm ? opt.pcsOptNm : '',
|
||||
nameJp: opt.pcsOptNmJp ? opt.pcsOptNmJp : '',
|
||||
}))
|
||||
}
|
||||
|
||||
// // PCS 승압설정 정보 포맷
|
||||
// const formatStepUpListData = (dataArray = []) => {
|
||||
// return dataArray?.map((stepUps) => ({
|
||||
// ...stepUps,
|
||||
// optionList: formatOptionList(stepUps.optionList),
|
||||
// pcsItemList: formatPcsItemList(stepUps.pcsItemList),
|
||||
// selectedPcsItem: formatPcsItemList(stepUps.pcsItemList),
|
||||
// }))
|
||||
// }
|
||||
|
||||
// PCS 승압설정 정보 포맷 후 추천 값 저장
|
||||
const formatStepUpListData = (dataArray = []) => {
|
||||
const formattedData = dataArray?.map((stepUps) => ({
|
||||
...stepUps,
|
||||
optionList: formatOptionList(stepUps.optionList),
|
||||
pcsItemList: formatPcsItemList(stepUps.pcsItemList),
|
||||
selectedPcsItem: formatPcsItemList(stepUps.pcsItemList),
|
||||
}))
|
||||
|
||||
// 초기 추천 값들을 selectedValues에 저장
|
||||
const initialSelectedValues = {}
|
||||
formattedData.forEach((stepUp) => {
|
||||
stepUp.pcsItemList.forEach((pcsItem, pcsIdx) => {
|
||||
const pcsKey = `${stepUp.id}_${pcsIdx}`
|
||||
|
||||
// 추천 값(rmdYn === 'Y') 찾기
|
||||
const recommendedRow = pcsItem.serQtyList.find((item) => item.rmdYn === 'Y')
|
||||
if (recommendedRow) {
|
||||
const selectionData = {
|
||||
stepUpId: pcsItem.goodsNo,
|
||||
pcsInfo: {
|
||||
itemId: pcsItem.itemId,
|
||||
goodsNo: pcsItem.goodsNo,
|
||||
pcsMkrCd: pcsItem.pcsMkrCd,
|
||||
pcsSerCd: pcsItem.pcsSerCd,
|
||||
},
|
||||
allocation: {
|
||||
serQty: recommendedRow.serQty,
|
||||
paralQty: recommendedRow.paralQty,
|
||||
},
|
||||
}
|
||||
|
||||
initialSelectedValues[stepUp.id] = {
|
||||
...initialSelectedValues[stepUp.id],
|
||||
[pcsKey]: selectionData,
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
setSelectedValues(initialSelectedValues)
|
||||
|
||||
return formattedData
|
||||
}
|
||||
|
||||
// PCS 옵션 포맷
|
||||
const formatOptionList = (optionList = []) => {
|
||||
return optionList?.map((option) => ({
|
||||
pcsOptCd: option.pcsOptCd ? option.pcsOptCd : '',
|
||||
pcsOptNm: option.pcsOptNm ? option.pcsOptNm : '',
|
||||
pcsOptNmJp: option.pcsOptNmJp ? option.pcsOptNmJp : '',
|
||||
}))
|
||||
}
|
||||
|
||||
// PCS 아이템 포맷
|
||||
const formatPcsItemList = (pcsItemList = []) => {
|
||||
return pcsItemList?.map((item) => ({
|
||||
goodsNo: item.goodsNo ? item.goodsNo : '',
|
||||
itemId: item.itemId ? item.itemId : '',
|
||||
itemNm: item.itemNm ? item.itemNm : '',
|
||||
pcsMkrCd: item.pcsMkrCd ? item.pcsMkrCd : '',
|
||||
pcsSerCd: item.pcsSerCd ? item.pcsSerCd : '',
|
||||
connList: formatConnList(item.connList),
|
||||
serQtyList: formatSerQtyList(item.serQtyList),
|
||||
}))
|
||||
}
|
||||
|
||||
// PCS 연결 포맷
|
||||
const formatConnList = (connList = []) => {
|
||||
if (!connList) return [] // null인 경우 빈 배열 반환
|
||||
|
||||
return connList?.map((conn) => ({
|
||||
connAllowCur: conn.connAllowCur ? conn.connAllowCur : 0,
|
||||
connMaxParalCnt: conn.connMaxParalCnt ? conn.connMaxParalCnt : 0,
|
||||
goodsNo: conn.goodsNo ? conn.goodsNo : '',
|
||||
itemId: conn.itemId ? conn.itemId : '',
|
||||
itemNm: conn.itemNm ? conn.itemNm : '',
|
||||
vstuParalCnt: conn.vstuParalCnt ? conn.vstuParalCnt : 0,
|
||||
}))
|
||||
}
|
||||
|
||||
// PCS 시리즈 포맷
|
||||
const formatSerQtyList = (serQtyList = []) => {
|
||||
return serQtyList?.map((qty) => ({
|
||||
serQty: qty.serQty ? qty.serQty : 0,
|
||||
paralQty: qty.paralQty ? qty.paralQty : 0,
|
||||
rmdYn: qty.rmdYn ? qty.rmdYn : 'N',
|
||||
usePossYn: qty.usePossYn ? qty.usePossYn : 'Y',
|
||||
}))
|
||||
}
|
||||
|
||||
// 각 모듈의 탭을 변경하는 함수
|
||||
const handleTabChange = (goodsNo, idx, tabNumber) => {
|
||||
setModuleTabs((prev) => ({
|
||||
...prev,
|
||||
[`${goodsNo}_${idx}`]: tabNumber,
|
||||
}))
|
||||
}
|
||||
|
||||
// 행 선택 핸들러 함수 추가
|
||||
const handleRowClick = (goodsNo, pcsIdx, serQtyIdx, serQty, paralQty) => {
|
||||
const rowKey = `${goodsNo}_${pcsIdx}_${serQtyIdx}`
|
||||
const pcsKey = `${goodsNo}_${pcsIdx}`
|
||||
|
||||
console.log('goodsNo >> ', goodsNo, serQty, paralQty)
|
||||
|
||||
// 현재 선택된 PCS 아이템 정보 가져오기
|
||||
const pcsItem = stepUpListData.find((stepUp) => stepUp.pcsItemList.find((item) => item.goodsNo === goodsNo))?.pcsItemList[pcsIdx]
|
||||
|
||||
if (!pcsItem) {
|
||||
console.error('PCS item not found:', { goodsNo, pcsIdx })
|
||||
return
|
||||
}
|
||||
|
||||
// 선택된 값들 업데이트 - 더 자세한 정보 포함
|
||||
const selectionData = {
|
||||
goodsNo: goodsNo,
|
||||
pcsInfo: {
|
||||
itemId: pcsItem?.itemId,
|
||||
goodsNo: pcsItem?.goodsNo,
|
||||
pcsMkrCd: pcsItem?.pcsMkrCd,
|
||||
pcsSerCd: pcsItem?.pcsSerCd,
|
||||
},
|
||||
allocation: {
|
||||
serQty: serQty,
|
||||
paralQty: paralQty,
|
||||
},
|
||||
}
|
||||
|
||||
// 선택된 값들 업데이트
|
||||
setSelectedValues((prev) => ({
|
||||
...prev,
|
||||
[goodsNo]: {
|
||||
...prev[goodsNo],
|
||||
[pcsKey]: selectionData,
|
||||
},
|
||||
}))
|
||||
|
||||
// 부모 컴포넌트에 선택된 값들 전달
|
||||
if (props.onValuesSelected) {
|
||||
props.onValuesSelected(selectionData)
|
||||
}
|
||||
|
||||
setSelectedRows((prev) => {
|
||||
// 현재 stepUpId에 대한 선택 상태가 없으면 빈 객체로 초기화
|
||||
const currentStepUpSelections = prev[goodsNo] || {}
|
||||
|
||||
// 이미 선택된 행을 다시 클릭하는 경우, 선택을 해제하지 않음
|
||||
if (currentStepUpSelections[pcsKey] === rowKey) {
|
||||
return prev
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
[goodsNo]: {
|
||||
...currentStepUpSelections,
|
||||
[pcsKey]: rowKey,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
// 수동 선택 상태를 업데이트하되, 기존 추천 선택은 유지
|
||||
setIsManualSelection((prev) => ({
|
||||
...prev,
|
||||
[goodsNo]: {
|
||||
...prev[goodsNo],
|
||||
[pcsKey]: true,
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
// 현재 선택된 값들을 가져오는 함수 추가
|
||||
const getCurrentSelections = () => {
|
||||
return selectedValues
|
||||
}
|
||||
|
||||
// props로 getCurrentSelections 함수 전달
|
||||
useEffect(() => {
|
||||
if (props.onInitialize) {
|
||||
props.onInitialize(getCurrentSelections)
|
||||
}
|
||||
}, [])
|
||||
|
||||
// stepUpListData가 변경될 때마다 업데이트하는 useEffect
|
||||
useEffect(() => {
|
||||
if (props.onInitialize) {
|
||||
// onInitialize를 props에서 가져옴
|
||||
props.onInitialize(() => ({
|
||||
...getCurrentSelections(),
|
||||
stepUpListData, // stepUpListData를 포함하여 반환
|
||||
}))
|
||||
}
|
||||
}, [stepUpListData])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="properties-setting-wrap outer">
|
||||
<div className="circuit-overflow">
|
||||
{/* 3개일때 className = by-max */}
|
||||
<div className={`module-table-box ${arrayLength === 3 ? 'by-max' : ''}`}>
|
||||
{Array.from({ length: arrayLength }).map((_, idx) => (
|
||||
<div key={idx} className="module-table-inner">
|
||||
<div className="mb-box">
|
||||
<div className="circuit-table-tit">HQJP-KA55-5</div>
|
||||
<div className="roof-module-table overflow-y min">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.serial.amount')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.total.amount')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr className="on">
|
||||
<td className="al-r">10</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="al-r">10</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="al-r">10</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="al-r">10</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="al-r">10</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="al-r">10</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{stepUpListData.map((stepUp, index) => (
|
||||
<div key={index} className={`module-table-box ${stepUp.pcsItemList.length === 3 ? 'by-max' : ''}`}>
|
||||
{stepUp?.pcsItemList.map((_, idx) => (
|
||||
<div key={idx} className="module-table-inner">
|
||||
<div className="mb-box">
|
||||
<div className="circuit-table-tit">{stepUp.pcsItemList[idx].goodsNo}</div>
|
||||
<div className="roof-module-table overflow-y min">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.serial.amount')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.total.amount')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{stepUp.pcsItemList[idx].serQtyList.map((item, serQtyIdx) => {
|
||||
const rowKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}_${serQtyIdx}`
|
||||
const pcsKey = `${stepUp.pcsItemList[idx].goodsNo}_${idx}`
|
||||
return (
|
||||
<tr
|
||||
key={rowKey}
|
||||
className={`${
|
||||
(!isManualSelection[stepUp.pcsItemList[idx].goodsNo]?.[pcsKey] && item.rmdYn === 'Y') ||
|
||||
(selectedRows[stepUp.pcsItemList[idx].goodsNo] && selectedRows[stepUp.pcsItemList[idx].goodsNo][pcsKey] === rowKey)
|
||||
? 'on'
|
||||
: ''
|
||||
}`}
|
||||
onClick={() => handleRowClick(stepUp.pcsItemList[idx].goodsNo, idx, serQtyIdx, item.serQty, item.paralQty)}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<td className="al-r">{item.serQty}</td>
|
||||
<td className="al-r">{item.paralQty}</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div className="module-box-tab mb10">
|
||||
<button
|
||||
className={`module-btn ${(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 1 ? 'act' : ''}`}
|
||||
onClick={() => handleTabChange(stepUp.pcsItemList[idx].goodsNo, idx, 1)}
|
||||
>
|
||||
{getMessage('modal.circuit.trestle.setting.step.up.allocation.connected')}
|
||||
</button>
|
||||
<button
|
||||
className={`module-btn ${(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 2 ? 'act' : ''}`}
|
||||
onClick={() => handleTabChange(stepUp.pcsItemList[idx].goodsNo, idx, 2)}
|
||||
>
|
||||
{getMessage('modal.circuit.trestle.setting.step.up.allocation.option')}
|
||||
</button>
|
||||
</div>
|
||||
<div className="circuit-table-flx-wrap">
|
||||
{(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 1 && (
|
||||
<div className="circuit-table-flx-box">
|
||||
<div className="roof-module-table min mb10">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="al-c">
|
||||
{stepUp.pcsItemList[idx].connList?.[0]?.goodsNo ? stepUp.pcsItemList[idx].connList?.[0]?.goodsNo : '-'}
|
||||
</td>
|
||||
<td className="al-c">
|
||||
{stepUp.pcsItemList[idx].connList?.[0]?.connMaxParalCnt
|
||||
? (stepUp.pcsItemList[idx].connList?.[0]?.connMaxParalCnt ?? '-')
|
||||
: '-'}
|
||||
</td>
|
||||
<td className="al-c">
|
||||
{stepUp.pcsItemList[idx].connList?.[0]?.vstuParalCnt ? stepUp.pcsItemList[idx].connList?.[0]?.vstuParalCnt : '-'}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{(moduleTabs[`${stepUp.pcsItemList[idx].goodsNo}_${idx}`] || 1) === 2 && (
|
||||
<div className="circuit-table-flx-box">
|
||||
<div className="roof-module-table min mb10">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{/* <th>名称</th>
|
||||
<th>昇圧回路数</th> */}
|
||||
<th>{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="al-c">-</td>
|
||||
<td className="al-c">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="module-box-tab mb10">
|
||||
<button className={`module-btn ${moduleTab === 1 ? 'act' : ''}`} onClick={() => setModuleTab(1)}>
|
||||
{getMessage('modal.circuit.trestle.setting.step.up.allocation.connected')}
|
||||
</button>
|
||||
<button className={`module-btn ${moduleTab === 2 ? 'act' : ''}`} onClick={() => setModuleTab(2)}>
|
||||
{getMessage('modal.circuit.trestle.setting.step.up.allocation.option')}
|
||||
</button>
|
||||
</div>
|
||||
<div className="circuit-table-flx-wrap">
|
||||
{moduleTab === 1 && (
|
||||
<div className="circuit-table-flx-box">
|
||||
<div className="roof-module-table min mb10">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.power.conditional.select.name')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.power.conditional.select.circuit.amount')}</th>
|
||||
<th>{getMessage('modal.circuit.trestle.setting.step.up.allocation.circuit.amount')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="al-c">KTN-CBD4C</td>
|
||||
<td className="al-r">4</td>
|
||||
<td className="al-r">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{moduleTab === 2 && (
|
||||
<div className="circuit-table-flx-box">
|
||||
<div className="roof-module-table min mb10">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>名称</th>
|
||||
<th>昇圧回路数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="al-c">-</td>
|
||||
<td className="al-c">-</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="slope-wrap">
|
||||
<div className="outline-form">
|
||||
<span className="mr10" style={{ width: 'auto' }}>
|
||||
{getMessage('modal.circuit.trestle.setting.step.up.allocation.select.monitor')}
|
||||
</span>
|
||||
<div className="grid-select mr10">
|
||||
<QSelectBox title={'電力検出ユニット (モニター付き)'} options={SelectOption01} />
|
||||
</div>
|
||||
{optCodes.length > 0 && (
|
||||
<div className="grid-select mr10">
|
||||
{/* <QSelectBox title={'電力検出ユニット (モニター付き)'} /> */}
|
||||
<QSelectBox options={optCodes} title={optCodes[0].name} value={optCodes[0].name} sourceKey="code" targetKey="code" showKey="name" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,35 +1,449 @@
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
import { POLYGON_TYPE } from '@/common/common'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
|
||||
import { selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { useContext, useEffect, useState } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
|
||||
export default function PassivityCircuitAllocation() {
|
||||
export default function PassivityCircuitAllocation(props) {
|
||||
const {
|
||||
tabNum,
|
||||
setTabNum,
|
||||
selectedModels,
|
||||
getOptYn: getApiProps,
|
||||
getUseModuleItemList: getSelectedModuleList,
|
||||
getSelectModelList: getSelectModelList,
|
||||
getRoofSurfaceList,
|
||||
getModelList,
|
||||
} = props
|
||||
const { swalFire } = useSwal()
|
||||
const { getMessage } = useMessage()
|
||||
const moduleData = {
|
||||
header: [
|
||||
{ name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' },
|
||||
{ name: getMessage('modal.circuit.trestle.setting.circuit'), prop: 'circuit' },
|
||||
{
|
||||
name: getMessage('Q.TRON M-G2'),
|
||||
prop: 'moduleName',
|
||||
},
|
||||
{
|
||||
name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`,
|
||||
prop: 'powerGeneration',
|
||||
},
|
||||
],
|
||||
rows: [
|
||||
{
|
||||
roofShape: { name: 'M 1' },
|
||||
circuit: { name: 'M 1' },
|
||||
moduleName: { name: '8' },
|
||||
powerGeneration: { name: '3,400' },
|
||||
},
|
||||
{
|
||||
roofShape: { name: 'M 1' },
|
||||
circuit: { name: 'M 1' },
|
||||
moduleName: { name: '8' },
|
||||
powerGeneration: { name: '3,400' },
|
||||
},
|
||||
],
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
const selectedModules = useRecoilValue(selectedModuleState)
|
||||
const moduleStatistics = useRecoilValue(moduleStatisticsState)
|
||||
// const [totalWpout, setTotalWpout] = useState(0)
|
||||
const [selectedPcs, setSelectedPcs] = useState(selectedModels[0])
|
||||
// const { header, rows: row } = moduleStatistics
|
||||
const [header, setHeader] = useState(moduleStatistics.header)
|
||||
const [rows, setRows] = useState(moduleStatistics.rows)
|
||||
const [footer, setFooter] = useState(['합계'])
|
||||
const [circuitNumber, setCircuitNumber] = useState(1)
|
||||
const [targetModules, setTargetModules] = useState([])
|
||||
const { getPcsManualConfChk } = useMasterController()
|
||||
|
||||
useEffect(() => {
|
||||
console.log('header, rows', header, rows)
|
||||
console.log('selectedModels', selectedModels)
|
||||
// setSurfaceInfo()
|
||||
setTableData()
|
||||
if (!managementState) {
|
||||
setManagementState(managementStateLoaded)
|
||||
}
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
.forEach((obj) => {
|
||||
obj.on('mousedown', (e) => handleTargetModules(obj))
|
||||
})
|
||||
|
||||
return () => {
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE)
|
||||
.forEach((obj) => {
|
||||
obj.set({ strokeWidth: 0.3 })
|
||||
obj.off('mousedown')
|
||||
})
|
||||
canvas.renderAll()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleTargetModules = (obj) => {
|
||||
if (!Array.isArray(targetModules)) {
|
||||
setTargetModules([])
|
||||
return
|
||||
}
|
||||
|
||||
setTargetModules((prev) => {
|
||||
if (prev.includes(obj.id)) {
|
||||
obj.set({ strokeWidth: 0.3 })
|
||||
return prev.filter((o) => o !== obj.id)
|
||||
} else {
|
||||
obj.set({ strokeWidth: 2 })
|
||||
return [...prev, obj.id]
|
||||
}
|
||||
})
|
||||
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
const setSurfaceInfo = () => {
|
||||
const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
|
||||
// setHeaders([header[0], { name: '회로', prop: 'circuit' }, ...header.slice(1)])
|
||||
setRows(
|
||||
rows.map((row) => {
|
||||
return {
|
||||
...row,
|
||||
circuit: '',
|
||||
}
|
||||
}),
|
||||
)
|
||||
let totals = {}
|
||||
|
||||
rows.forEach((row) => {
|
||||
if (header.length === 4) {
|
||||
if (!totals[header[2].prop]) totals[header[2].prop] = 0
|
||||
totals[header[2].prop] += +row[header[2].prop]
|
||||
} else if (header.length === 5) {
|
||||
if (!totals[header[2].prop]) totals[header[2].prop] = 0
|
||||
totals[header[2].prop] += +row[header[2].prop]
|
||||
if (!totals[header[3].prop]) totals[header[3].prop] = 0
|
||||
totals[header[3]] += +row[header[3]]
|
||||
}
|
||||
})
|
||||
setFooter([
|
||||
...['합계', ''],
|
||||
...Object.keys(totals).map((key) => {
|
||||
return totals[key]
|
||||
}),
|
||||
Object.keys(totals).reduce((acc, key) => {
|
||||
return acc + totals[key]
|
||||
}, 0),
|
||||
])
|
||||
// let totalWpout = 0
|
||||
// const rows = surfaces.map((surface) => {
|
||||
// let wpOut = 0
|
||||
// let moduleInfo = {}
|
||||
// surface.modules.forEach((module) => {
|
||||
// wpOut += +module.moduleInfo.wpOut
|
||||
// if (!moduleInfo[module.moduleInfo.itemId]) moduleInfo[module.moduleInfo.itemId] = 0
|
||||
// moduleInfo[module.moduleInfo.itemId]++
|
||||
// })
|
||||
// totalWpout += wpOut
|
||||
// console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module)
|
||||
// return {
|
||||
// roofShape: DIRECTION[surface.direction],
|
||||
// powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
|
||||
// ...moduleInfo,
|
||||
// }
|
||||
// })
|
||||
|
||||
// setTotalWpout(totalWpout)
|
||||
// 지붕면 리스트 -> 지붕면에 있는 모듈 리스트 -> 발전량 총합 계산
|
||||
// wpOut
|
||||
|
||||
// setModuleData({
|
||||
// header: [
|
||||
// { name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'roofShape' },
|
||||
// { name: getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit'), prop: 'circuit' },
|
||||
// ...selectedModules.itemList.map((module) => {
|
||||
// return {
|
||||
// name: module.itemNm,
|
||||
// prop: module.itemId,
|
||||
// }
|
||||
// }),
|
||||
// {
|
||||
// name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`,
|
||||
// prop: 'powerGeneration',
|
||||
// },
|
||||
// ],
|
||||
// rows: rows,
|
||||
// })
|
||||
}
|
||||
|
||||
const handleCircuitNumberFix = () => {
|
||||
if (!circuitNumber || circuitNumber === 0) {
|
||||
swalFire({
|
||||
text: '회로번호를 1 이상입력해주세요.',
|
||||
type: 'alert',
|
||||
icon: 'warning',
|
||||
})
|
||||
return
|
||||
} else if (targetModules.length === 0) {
|
||||
swalFire({
|
||||
text: '모듈을 선택해주세요.',
|
||||
type: 'alert',
|
||||
icon: 'warning',
|
||||
})
|
||||
return
|
||||
} else if (selectedModels.length > 1) {
|
||||
const uniqueCircuitNumbers = [
|
||||
...new Set(
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.circuitNumber)
|
||||
.map((obj) => obj.circuitNumber),
|
||||
),
|
||||
]
|
||||
|
||||
let result = false
|
||||
uniqueCircuitNumbers.forEach((number) => {
|
||||
if (
|
||||
number.split('-')[1] === circuitNumber + ')' &&
|
||||
number.split('-')[0] !== '(' + (selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1)
|
||||
) {
|
||||
result = true
|
||||
}
|
||||
})
|
||||
if (result) {
|
||||
swalFire({
|
||||
text: '회로 번호가 같은 다른 파워 컨디셔너 모듈이 있습니다. 다른 회로 번호를 설정하십시오.',
|
||||
type: 'alert',
|
||||
icon: 'warning',
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
canvas.discardActiveObject()
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => targetModules.includes(obj.id))
|
||||
.forEach((obj) => {
|
||||
const moduleCircuitText = new fabric.Text(getCircuitNumber(), {
|
||||
left: obj.left + obj.width / 2,
|
||||
top: obj.top + obj.height / 2,
|
||||
fill: 'black',
|
||||
fontSize: 20,
|
||||
width: obj.width,
|
||||
height: obj.height,
|
||||
textAlign: 'center',
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
name: 'circuitNumber',
|
||||
parentId: obj.id,
|
||||
circuitInfo: selectedPcs,
|
||||
})
|
||||
obj.set({
|
||||
strokeWidth: 0.3,
|
||||
})
|
||||
obj.pcsItemId = selectedPcs.itemId
|
||||
obj.circuit = moduleCircuitText
|
||||
obj.circuitNumber = getCircuitNumber()
|
||||
canvas.add(moduleCircuitText)
|
||||
})
|
||||
|
||||
const roofSurfaceList = canvas
|
||||
.getObjects()
|
||||
.filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
|
||||
.map((surface) => {
|
||||
return {
|
||||
roofSurfaceId: surface.id,
|
||||
roofSurface: surface.direction,
|
||||
roofSurfaceIncl: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
|
||||
moduleList: surface.modules.map((module) => {
|
||||
return {
|
||||
itemId: module.moduleInfo.itemId,
|
||||
circuit: module.circuitNumber,
|
||||
pcsItemId: module.pcsItemId,
|
||||
}
|
||||
}),
|
||||
}
|
||||
})
|
||||
|
||||
const pcsItemList = selectedModels.map((model) => {
|
||||
return {
|
||||
pcsMkrCd: model.pcsMkrCd,
|
||||
pcsSerCd: model.pcsSerCd,
|
||||
itemId: model.itemId,
|
||||
itemNm: model.itemNm,
|
||||
goodsNo: model.goodsNo,
|
||||
serQtyList: [
|
||||
{
|
||||
serQty: 0,
|
||||
paralQty: 0,
|
||||
rmdYn: 'Y',
|
||||
usePossYn: 'Y',
|
||||
roofSurfaceList: roofSurfaceList,
|
||||
},
|
||||
],
|
||||
}
|
||||
})
|
||||
|
||||
const params = {
|
||||
...getApiProps(),
|
||||
useModuleItemList: getSelectedModuleList(),
|
||||
pcsItemList: pcsItemList,
|
||||
}
|
||||
|
||||
getPcsManualConfChk(params).then((res) => {
|
||||
if (res.resultCode === 'E') {
|
||||
swalFire({
|
||||
text: res.resultMsg,
|
||||
type: 'alert',
|
||||
icon: 'warning',
|
||||
confirmFn: () => {
|
||||
const circuitNumbers = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber' && targetModules.includes(obj.parentId))
|
||||
canvas.remove(...circuitNumbers)
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === 'module' && targetModules.includes(obj.id))
|
||||
.forEach((obj) => {
|
||||
obj.pcsItemId = null
|
||||
obj.circuit = null
|
||||
obj.circuitNumber = null
|
||||
})
|
||||
canvas.renderAll()
|
||||
},
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
setTargetModules([])
|
||||
setCircuitNumber(+circuitNumber + 1)
|
||||
setTableData()
|
||||
})
|
||||
}
|
||||
|
||||
const getCircuitNumber = () => {
|
||||
if (selectedModels.length === 1) {
|
||||
return `(${circuitNumber})`
|
||||
} else {
|
||||
return `(${selectedModels.findIndex((model) => model.id === selectedPcs.id) + 1}-${circuitNumber})`
|
||||
}
|
||||
}
|
||||
|
||||
const setTableData = () => {
|
||||
const tempHeader = [
|
||||
{ name: '지붕면', prop: 'name' },
|
||||
{ name: '회로', prop: 'circuit' },
|
||||
...selectedModules.itemList.map((module) => {
|
||||
return {
|
||||
name: module.itemNm,
|
||||
prop: module.itemId,
|
||||
}
|
||||
}),
|
||||
{ name: '발전량(kW)', prop: 'wpOut' },
|
||||
]
|
||||
|
||||
const surfaces = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||
const surfaceIds = surfaces.map((surface) => surface.parentId)
|
||||
const surfaceObjects = {}
|
||||
const rows = surfaces.map((surface) => {
|
||||
const moduleObject = {}
|
||||
surfaceObjects[surface.id] = {
|
||||
roofSurface: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].directionText,
|
||||
circuit: '-',
|
||||
amount: 0,
|
||||
wpOut: 0,
|
||||
circuits: {},
|
||||
}
|
||||
|
||||
surface.modules.forEach((module) => {
|
||||
if (!surfaceObjects[surface.id][module.moduleInfo.itemId]) {
|
||||
// 지붕면에 모듈 존재 여부
|
||||
surfaceObjects[surface.id][module.moduleInfo.itemId] = 0 // 모듈 초기화
|
||||
}
|
||||
|
||||
surfaceObjects[surface.id][module.moduleInfo.itemId]++
|
||||
surfaceObjects[surface.id].wpOut += +module.moduleInfo.wpOut
|
||||
if (module.circuit) {
|
||||
if (!surfaceObjects[surface.id].circuits[module.circuitNumber]) {
|
||||
surfaceObjects[surface.id].circuits[module.circuitNumber] = {
|
||||
circuit: module.circuitNumber,
|
||||
wpOut: 0,
|
||||
circuits: { wpOut: 0 },
|
||||
}
|
||||
|
||||
if (!surfaceObjects[surface.id].circuits[module.circuitNumber].circuits[module.moduleInfo.itemId]) {
|
||||
surfaceObjects[surface.id].circuits[module.circuitNumber].circuits[module.moduleInfo.itemId] = 0
|
||||
}
|
||||
}
|
||||
surfaceObjects[surface.id].circuits[module.circuitNumber].circuits[module.moduleInfo.itemId]++
|
||||
surfaceObjects[surface.id].circuits[module.circuitNumber].circuits.wpOut += +module.moduleInfo.wpOut
|
||||
surfaceObjects[surface.id].wpOut -= +module.moduleInfo.wpOut
|
||||
surfaceObjects[surface.id][module.moduleInfo.itemId]--
|
||||
}
|
||||
})
|
||||
})
|
||||
console.log('rows', rows)
|
||||
console.log('surfaceObjects', surfaceObjects)
|
||||
let tempRows = []
|
||||
Object.keys(surfaceObjects).forEach((key) => {
|
||||
let tempRow = {
|
||||
name: surfaceObjects[key].roofSurface,
|
||||
circuit: surfaceObjects[key].circuit,
|
||||
wpOut: surfaceObjects[key].wpOut,
|
||||
}
|
||||
selectedModules.itemList.forEach((module) => {
|
||||
tempRow[module.itemId] = surfaceObjects[key][module.itemId]
|
||||
})
|
||||
tempRows.push(tempRow)
|
||||
|
||||
Object.keys(surfaceObjects[key].circuits).forEach((circuit) => {
|
||||
let row = {
|
||||
name: surfaceObjects[key].roofSurface,
|
||||
circuit: surfaceObjects[key].circuits[circuit].circuit,
|
||||
wpOut: surfaceObjects[key].circuits[circuit].circuits.wpOut,
|
||||
}
|
||||
selectedModules.itemList.forEach((module) => {
|
||||
row[module.itemId] = surfaceObjects[key].circuits[circuit].circuits[module.itemId]
|
||||
})
|
||||
tempRows.push(row)
|
||||
})
|
||||
})
|
||||
const tempFooter = {
|
||||
name: '총합',
|
||||
circuit: '-',
|
||||
wpOut: tempRows.reduce((acc, row) => acc + row.wpOut, 0),
|
||||
}
|
||||
selectedModules.itemList.forEach((module) => {
|
||||
tempFooter[module.itemId] = tempRows.reduce((acc, row) => acc + row[module.itemId], 0)
|
||||
})
|
||||
console.log('tempHeader, tempRows, tempFooter', tempHeader, tempRows, tempFooter)
|
||||
setHeader(tempHeader)
|
||||
setRows(tempRows.filter((row) => row.wpOut !== 0))
|
||||
setFooter(tempFooter)
|
||||
}
|
||||
|
||||
const initSelectedPcsCircuitNumber = () => {
|
||||
swalFire({
|
||||
title: '선택된 파워 컨디셔너의 회로할당을 초기화합니다.',
|
||||
type: 'confirm',
|
||||
icon: 'warning',
|
||||
confirmFn: () => {
|
||||
const circuitModules = canvas.getObjects().filter((obj) => obj.name === 'module' && obj.circuit?.circuitInfo?.id === selectedPcs.id)
|
||||
canvas.remove(...circuitModules.map((module) => module.circuit))
|
||||
circuitModules.forEach((obj) => {
|
||||
obj.circuit = null
|
||||
obj.pcsItemId = null
|
||||
})
|
||||
setTargetModules([])
|
||||
|
||||
canvas.renderAll()
|
||||
canvas.discardActiveObject()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const initAllPcsCircuitNumber = () => {
|
||||
canvas.discardActiveObject()
|
||||
swalFire({
|
||||
title: '회로 할당의 설정을 초기화합니다.',
|
||||
type: 'confirm',
|
||||
icon: 'warning',
|
||||
confirmFn: () => {
|
||||
const circuitModules = canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.name === 'module' && selectedModels.map((model) => model.id).includes(obj.circuit?.circuitInfo?.id))
|
||||
canvas.remove(...circuitModules.map((module) => module.circuit))
|
||||
circuitModules.forEach((obj) => {
|
||||
obj.circuit = null
|
||||
obj.pcsItemId = null
|
||||
})
|
||||
setTargetModules([])
|
||||
|
||||
canvas.renderAll()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="properties-setting-wrap outer">
|
||||
@ -39,26 +453,35 @@ export default function PassivityCircuitAllocation() {
|
||||
<div className="bold-font mb10">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity')}</div>
|
||||
<div className="normal-font mb15">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.info')}</div>
|
||||
<div className="roof-module-table overflow-y">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{moduleData.header.map((header) => (
|
||||
<th key={header.prop}>{header.name}</th>
|
||||
{header && (
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
{header.map((header, index) => (
|
||||
<th key={'header' + index}>{header.name}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((row, index) => (
|
||||
<tr key={'row' + index}>
|
||||
{header.map((header, i) => (
|
||||
<td className="al-c" key={'rowcell' + i}>
|
||||
{row[header.prop]}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{moduleData.rows.map((row, index) => (
|
||||
<tr key={index}>
|
||||
{moduleData.header.map((header) => (
|
||||
<td className="al-c" key={header.prop}>
|
||||
{row[header.prop].name}
|
||||
<tr>
|
||||
{header.map((header, i) => (
|
||||
<td className="al-c" key={'footer' + i}>
|
||||
{footer[header.prop]}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -69,7 +492,27 @@ export default function PassivityCircuitAllocation() {
|
||||
<div className="bold-font">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional')}</div>
|
||||
</div>
|
||||
<div className="hexagonal-item">
|
||||
<div className="d-check-radio pop mb10">
|
||||
{selectedModels.map((model, index) => (
|
||||
<div className="d-check-radio pop mb10" key={'model' + index}>
|
||||
<input
|
||||
type="radio"
|
||||
name="radio01"
|
||||
id={`ra0${index + 1}`}
|
||||
value={model}
|
||||
checked={selectedPcs?.id === model.id}
|
||||
onChange={() => setSelectedPcs(model)}
|
||||
/>
|
||||
<label htmlFor={`ra0${index + 1}`}>
|
||||
{model.itemNm} (
|
||||
{getMessage(
|
||||
'modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.info',
|
||||
managementState?.coldRegionFlg === '1' ? [model.serMinQty, model.serColdZoneMaxQty] : [model.serMinQty, model.serMaxQty],
|
||||
)}
|
||||
)
|
||||
</label>
|
||||
</div>
|
||||
))}
|
||||
{/* <div className="d-check-radio pop mb10">
|
||||
<input type="radio" name="radio01" id="ra01" />
|
||||
<label htmlFor="ra01">HQJP-KA55-5 (標準回路2枚~10枚)</label>
|
||||
</div>
|
||||
@ -80,7 +523,7 @@ export default function PassivityCircuitAllocation() {
|
||||
<div className="d-check-radio pop">
|
||||
<input type="radio" name="radio01" id="ra03" />
|
||||
<label htmlFor="ra03">HQJP-KA55-5 (標準回路2枚~10枚)</label>
|
||||
</div>
|
||||
</div>*/}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -92,16 +535,25 @@ export default function PassivityCircuitAllocation() {
|
||||
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num')}
|
||||
</span>
|
||||
<div className="input-grid mr5" style={{ width: '70px' }}>
|
||||
<input type="text" className="input-origin block" />
|
||||
<input
|
||||
type="text"
|
||||
className="block input-origin"
|
||||
value={circuitNumber}
|
||||
min={1}
|
||||
max={99}
|
||||
onChange={(e) => setCircuitNumber(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<button className="btn-frame roof">{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix')}</button>
|
||||
<button className="btn-frame roof" onClick={() => handleCircuitNumberFix()}>
|
||||
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.circuit.num.fix')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="circuit-right-wrap">
|
||||
<button className="btn-frame roof mr5">
|
||||
<button className="btn-frame roof mr5" onClick={() => initSelectedPcsCircuitNumber()}>
|
||||
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.selected.power.conditional.reset')}
|
||||
</button>
|
||||
<button className="btn-frame roof mr5">
|
||||
<button className="btn-frame roof mr5" onClick={() => initAllPcsCircuitNumber()}>
|
||||
{getMessage('modal.circuit.trestle.setting.circuit.allocation.passivity.all.power.conditional.reset')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -85,7 +85,7 @@ export default function DimensionLineSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('contextmenu.display.edit')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -141,6 +141,7 @@ export default function DimensionLineSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -18,7 +18,7 @@ export default function Distance(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xxxm`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.distance')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -68,6 +68,7 @@ export default function Distance(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -40,7 +40,7 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.eaves.gable.edit')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -62,6 +62,7 @@ export default function EavesGableEdit({ id, pos = { x: 50, y: 230 } }) {
|
||||
{type === TYPES.SHED && <Shed {...shedProps} />}
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -65,7 +65,7 @@ export default function FlowDirectionSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap ml mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.shape.flow.direction.setting')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -176,6 +176,7 @@ export default function FlowDirectionSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -179,7 +179,7 @@ export default function DotLineGrid(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap ssm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.canvas.setting.grid.dot.line.setting')}</h1>
|
||||
<button
|
||||
className="modal-close"
|
||||
@ -293,6 +293,7 @@ export default function DotLineGrid(props) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</WithDraggable>
|
||||
)
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ export default function GridCopy(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.grid.copy')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -77,6 +77,7 @@ export default function GridCopy(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -75,7 +75,7 @@ export default function GridMove(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.grid.move')} </h1>
|
||||
<button className="modal-close" onClick={handleClose}>
|
||||
닫기
|
||||
@ -156,6 +156,7 @@ export default function GridMove(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -52,7 +52,7 @@ export default function LinePropertySetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('contextmenu.line.property.edit')} </h1>
|
||||
<button className="modal-close" onClick={() => handleClosePopup()}>
|
||||
닫기
|
||||
@ -91,6 +91,7 @@ export default function LinePropertySetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -18,7 +18,11 @@ export default function OuterLineWall({ props }) {
|
||||
className="input-origin block"
|
||||
value={length1}
|
||||
ref={length1Ref}
|
||||
onFocus={(e) => (length1Ref.current.value = '')}
|
||||
onFocus={(e) => {
|
||||
if (length1Ref.current.value === '0') {
|
||||
length1Ref.current.value = ''
|
||||
}
|
||||
}}
|
||||
onChange={(e) => onlyNumberInputChange(e, setLength1)}
|
||||
placeholder="3000"
|
||||
/>
|
||||
|
||||
@ -16,7 +16,7 @@ export default function CircuitNumberEdit(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title"> {getMessage('modal.module.circuit.number.edit')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -42,6 +42,7 @@ export default function CircuitNumberEdit(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -84,7 +84,7 @@ export default function PanelEdit(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">
|
||||
{getMessage([PANEL_EDIT_TYPE.MOVE, PANEL_EDIT_TYPE.COLUMN_MOVE].includes(type) ? 'modal.move.setting' : 'modal.copy.setting')}{' '}
|
||||
</h1>
|
||||
@ -139,6 +139,7 @@ export default function PanelEdit(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -26,7 +26,7 @@ export default function ColumnInsert(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.panel.column.insert')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -105,6 +105,7 @@ export default function ColumnInsert(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -29,7 +29,7 @@ export default function ColumnRemove(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.panel.column.remove')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -115,6 +115,7 @@ export default function ColumnRemove(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -26,7 +26,7 @@ export default function RowInsert(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.row.insert')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -105,6 +105,7 @@ export default function RowInsert(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -29,7 +29,7 @@ export default function RowRemove(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.row.remove')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -115,6 +115,7 @@ export default function RowRemove(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -18,7 +18,7 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.roof.cover.movement.shape.updown')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -33,7 +33,6 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
))}
|
||||
</div>
|
||||
<div className="properties-setting-wrap outer">
|
||||
<div className="setting-tit">{getMessage('setting')}</div>
|
||||
{type === TYPE.FLOW_LINE && <FlowLine {...flowLineProps} />}
|
||||
{type === TYPE.UP_DOWN && <Updown {...updownProps} />}
|
||||
</div>
|
||||
@ -43,6 +42,7 @@ export default function MovementSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -42,7 +42,7 @@ export default function DormerOffset(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{title}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -103,6 +103,7 @@ export default function DormerOffset(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -77,7 +77,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap lrr`} style={{ visibility: isHidden ? 'hidden' : 'visible' }}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.placement.surface.object')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -92,7 +92,6 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
))}
|
||||
</div>
|
||||
<div className="properties-setting-wrap outer">
|
||||
<div className="setting-tit">{getMessage('setting')}</div>
|
||||
{buttonAct === 1 && <OpenSpace ref={objectPlacement} />}
|
||||
{buttonAct === 2 && <Shadow ref={objectPlacement} />}
|
||||
{buttonAct === 3 && <TriangleDormer ref={dormerPlacement} />}
|
||||
@ -109,6 +108,7 @@ export default function ObjectSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -23,7 +23,7 @@ export default function RoofMaterialSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xxxm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.roof.material.edit')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -39,6 +39,7 @@ export default function RoofMaterialSetting(props) {
|
||||
<button className="btn-frame modal act">{getMessage('modal.common.save')}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -47,7 +47,7 @@ export default function SizeSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap ssm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.size.setting')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -95,6 +95,7 @@ export default function SizeSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -10,7 +10,7 @@ export default function PropertiesSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap ssm`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.canvas.setting.wallline.properties.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closeModal(id)}>
|
||||
닫기
|
||||
@ -38,6 +38,7 @@ export default function PropertiesSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -116,7 +116,7 @@ export default function WallLineSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={{ x: 50, y: 230 }}>
|
||||
<div className={`modal-pop-wrap r mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.cover.outline.drawing')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}></button>
|
||||
</div>
|
||||
@ -152,7 +152,6 @@ export default function WallLineSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
<div className="properties-setting-wrap outer">
|
||||
<div className="setting-tit">{getMessage('modal.cover.outline.setting')}</div>
|
||||
{type === OUTER_LINE_TYPE.OUTER_LINE ? (
|
||||
<OuterLineWall props={outerLineProps} />
|
||||
) : type === OUTER_LINE_TYPE.RIGHT_ANGLE ? (
|
||||
@ -184,6 +183,7 @@ export default function WallLineSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
import { useState } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import WithDraggable from '@/components/common/draggable/WithDraggable'
|
||||
import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
|
||||
import { useRecoilValue, useResetRecoilState } from 'recoil'
|
||||
|
||||
export default function PanelBatchStatistics() {
|
||||
const { getMessage } = useMessage()
|
||||
@ -11,6 +13,7 @@ export default function PanelBatchStatistics() {
|
||||
x: 0,
|
||||
y: 30,
|
||||
})
|
||||
const { header, rows, footer } = useRecoilValue(moduleStatisticsState)
|
||||
|
||||
return (
|
||||
<WithDraggable isShow={true} handle=".penal-wrap" pos={pos}>
|
||||
@ -21,14 +24,26 @@ export default function PanelBatchStatistics() {
|
||||
<table className="penal-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{getMessage('modal.panel.batch.statistic.roof.shape')}</th>
|
||||
<th>{getMessage('modal.panel.batch.statistic.power.generation.amount')} (kW)</th>
|
||||
{header.map((item, index) => (
|
||||
<th key={index}>{item.name}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((row, index) => (
|
||||
<tr key={index}>
|
||||
{header.map((item, i) => (
|
||||
<td key={index}>
|
||||
{typeof row[item.prop] === 'number' ? row[item.prop].toLocaleString('ko-KR', { maximumFractionDigits: 4 }) : row[item.prop]}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
<tr>
|
||||
<td>{getMessage('modal.panel.batch.statistic.total')}</td>
|
||||
<td className="al-r">0.000</td>
|
||||
{footer.map((item, index) => (
|
||||
<td key={index}>{typeof item === 'number' ? item.toLocaleString('ko-KR', { maximumFractionDigits: 4 }) : item}</td>
|
||||
// <td className="al-r">{item.amount}</td>
|
||||
))}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@ -123,7 +123,7 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.placement.surface.drawing')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -142,7 +142,6 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||
))}
|
||||
</div>
|
||||
<div className="properties-setting-wrap outer">
|
||||
<div className="setting-tit">{getMessage('setting')}</div>
|
||||
{buttonAct === 1 && <OuterLineWall props={outerLineProps} />}
|
||||
{buttonAct === 2 && <RightAngle props={rightAngleProps} />}
|
||||
{buttonAct === 3 && <DoublePitch props={doublePitchProps} />}
|
||||
@ -155,10 +154,11 @@ export default function PlacementShapeDrawing({ id, pos = { x: 50, y: 230 } }) {
|
||||
{getMessage('modal.cover.outline.rollback')}
|
||||
</button>
|
||||
<button className="btn-frame modal act" onClick={handleFix}>
|
||||
{getMessage('modal.cover.outline.fix')}
|
||||
{getMessage('modal.placement.surface.drawing.fix')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -56,20 +56,24 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
]
|
||||
|
||||
// 데이터를 최초 한 번만 조회
|
||||
useEffect(() => {
|
||||
if (!basicSetting || !currentRoof || Object.keys(currentRoof).length === 0 || Object.keys(basicSetting).length === 0) return
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
setRaftCodes(raftCodeList)
|
||||
// useEffect(() => {
|
||||
// if (!basicSetting || !currentRoof || Object.keys(currentRoof).length === 0 || Object.keys(basicSetting).length === 0) return
|
||||
// const raftCodeList = findCommonCode('203800')
|
||||
// setRaftCodes(raftCodeList)
|
||||
// console.log('🚀 ~ useEffect ~ >>>>>>>>>>>>> raftCodeList 11 :', raftCodeList)
|
||||
|
||||
if (addedRoofs[0].roofAngleSet && addedRoofs[0].roofAngleSet?.length > 0) {
|
||||
setCurrentRoof({ ...currentRoof, roofSizeSet: String(addedRoofs[0].roofSizeSet), roofAngleSet: addedRoofs[0].roofAngleSet })
|
||||
} else if (basicSetting.roofAngleSet && basicSetting.roofAngleSet?.length > 0) {
|
||||
setCurrentRoof({ ...currentRoof, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
|
||||
}
|
||||
}, [])
|
||||
// if (addedRoofs[0].roofAngleSet && addedRoofs[0].roofAngleSet?.length > 0) {
|
||||
// setCurrentRoof({ ...currentRoof, roofSizeSet: String(addedRoofs[0].roofSizeSet), roofAngleSet: addedRoofs[0].roofAngleSet })
|
||||
// } else if (basicSetting.roofAngleSet && basicSetting.roofAngleSet?.length > 0) {
|
||||
// setCurrentRoof({ ...currentRoof, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
|
||||
// }
|
||||
// }, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (addedRoofs.length > 0) {
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
setRaftCodes(raftCodeList)
|
||||
|
||||
setCurrentRoof({ ...addedRoofs[0] })
|
||||
}
|
||||
}, [addedRoofs])
|
||||
@ -155,20 +159,20 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
...roofInfo,
|
||||
},
|
||||
//roofs: addedRoofs,
|
||||
roofsData: {
|
||||
roofApply: true,
|
||||
roofSeq: 0,
|
||||
roofMatlCd: currentRoof.roofMatlCd,
|
||||
roofWidth: currentRoof.width,
|
||||
roofHeight: currentRoof.length,
|
||||
roofHajebichi: currentRoof.hajebichi,
|
||||
roofGap: currentRoof.raft,
|
||||
roofLayout: currentRoof.layout,
|
||||
roofSizeSet: currentRoof.roofSizeSet,
|
||||
roofAngleSet: currentRoof.roofAngleSet,
|
||||
roofPitch: currentRoof.pitch,
|
||||
roofAngle: currentRoof.angle,
|
||||
},
|
||||
// roofsData: {
|
||||
// roofApply: true,
|
||||
// roofSeq: 0,
|
||||
// roofMatlCd: currentRoof.roofMatlCd,
|
||||
// roofWidth: currentRoof.width,
|
||||
// roofHeight: currentRoof.length,
|
||||
// roofHajebichi: currentRoof.hajebichi,
|
||||
// roofGap: currentRoof.raft,
|
||||
// roofLayout: currentRoof.layout,
|
||||
// roofSizeSet: currentRoof.roofSizeSet,
|
||||
// roofAngleSet: currentRoof.roofAngleSet,
|
||||
// roofPitch: currentRoof.pitch,
|
||||
// roofAngle: currentRoof.angle,
|
||||
// },
|
||||
})
|
||||
|
||||
basicSettingSave()
|
||||
@ -177,7 +181,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap ll mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.placement.surface.initial.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -256,7 +260,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
title={
|
||||
currentRoof?.roofSizeSet === '3' ? getMessage('modal.placement.initial.setting.size.none.pitch') : currentRoof?.roofMatlNm
|
||||
}
|
||||
ref={roofRef.roofCd}
|
||||
//ref={roofRef.roofCd}
|
||||
options={roofMaterials.map((roof) => {
|
||||
return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp }
|
||||
})}
|
||||
@ -338,13 +342,14 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
{currentRoof && ['C', 'R'].includes(currentRoof.raftAuth) && (
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
|
||||
{raftCodes.length > 0 && (
|
||||
{raftCodes?.length > 0 && (
|
||||
<div className="select-wrap" style={{ width: '160px' }}>
|
||||
<QSelectBox
|
||||
options={raftCodes}
|
||||
ref={roofRef.rafter}
|
||||
//ref={roofRef.rafter}
|
||||
title={
|
||||
raftCodes.find((r) => r.clCode === (currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft)).clCodeNm
|
||||
raftCodes?.find((r) => r.clCode === (currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft))
|
||||
.clCodeNm
|
||||
}
|
||||
value={currentRoof?.raft === undefined ? currentRoof?.raftBaseCd : currentRoof?.raft}
|
||||
onChange={(e) => handleRafterChange(e.clCode)}
|
||||
@ -418,6 +423,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
|
||||
</div>
|
||||
{showSizeGuideModal && <SizeGuide setShowSizeGuidModal={setShowSizeGuidModal} />}
|
||||
{showMaterialGuideModal && <MaterialGuide setShowMaterialGuidModal={setShowMaterialGuidModal} />}
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -242,7 +242,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap lr-2`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.placement.surface.arrangement')} </h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -290,6 +290,7 @@ export default function PlacementSurfaceSetting({ id, pos = { x: 50, y: 230 } })
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -63,7 +63,7 @@ export default function ActualSizeSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap ssm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.actual.size.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -116,6 +116,7 @@ export default function ActualSizeSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -45,7 +45,7 @@ export default function ContextRoofAllocationSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap lr mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.estimate.roof.alloc')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -79,133 +79,134 @@ export default function ContextRoofAllocationSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
<div className="grid-option-wrap">
|
||||
{currentRoofList.map((roof, index) => {
|
||||
return (
|
||||
<div className="grid-option-box" key={index}>
|
||||
<div className="d-check-radio pop no-text">
|
||||
<input type="radio" name="radio01" checked={roof.selected && 'checked'} readOnly={true} />
|
||||
<label
|
||||
htmlFor="ra01"
|
||||
onClick={(e) => {
|
||||
handleDefaultRoofMaterial(index)
|
||||
}}
|
||||
></label>
|
||||
</div>
|
||||
<div className="grid-option-block-form">
|
||||
<div className="block-box">
|
||||
<div className="flex-ment">
|
||||
<div className="grid-select" style={{ width: '248px' }}>
|
||||
<QSelectBox
|
||||
options={roofMaterials}
|
||||
value={roof}
|
||||
showKey={'roofMatlNm'}
|
||||
sourceKey={'roofMatlCd'}
|
||||
targetKey={'roofMatlCd'}
|
||||
onChange={(e) => handleChangeRoofMaterial(e, index)}
|
||||
/>
|
||||
</div>
|
||||
{index === 0 && <span className="dec">{getMessage('modal.roof.alloc.default.roof.material')}</span>}
|
||||
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(index)}></button>}
|
||||
</div>
|
||||
{currentRoofList.length > 0 &&
|
||||
currentRoofList.map((roof, index) => {
|
||||
return (
|
||||
<div className="grid-option-box" key={index}>
|
||||
<div className="d-check-radio pop no-text">
|
||||
<input type="radio" name="radio01" checked={roof.selected && 'checked'} readOnly={true} />
|
||||
<label
|
||||
htmlFor="ra01"
|
||||
onClick={(e) => {
|
||||
handleDefaultRoofMaterial(index)
|
||||
}}
|
||||
></label>
|
||||
</div>
|
||||
<div className="block-box">
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('slope')}</span>
|
||||
<div className="input-grid" style={{ width: '214px' }}>
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
onChange={(e) => {
|
||||
handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index)
|
||||
}}
|
||||
defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle}
|
||||
/>
|
||||
<div className="grid-option-block-form">
|
||||
<div className="block-box">
|
||||
<div className="flex-ment">
|
||||
<div className="grid-select" style={{ width: '248px' }}>
|
||||
<QSelectBox
|
||||
options={roofMaterials}
|
||||
value={roof}
|
||||
showKey={'roofMatlNm'}
|
||||
sourceKey={'roofMatlCd'}
|
||||
targetKey={'roofMatlCd'}
|
||||
onChange={(e) => handleChangeRoofMaterial(e, index)}
|
||||
/>
|
||||
</div>
|
||||
{index === 0 && <span className="dec">{getMessage('modal.roof.alloc.default.roof.material')}</span>}
|
||||
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(index)}></button>}
|
||||
</div>
|
||||
<span>{pitchText}</span>
|
||||
</div>
|
||||
</div>
|
||||
{(roof.widAuth || roof.lenAuth) && (
|
||||
<div className="block-box">
|
||||
{roof.widAuth && (
|
||||
<div className="flex-ment">
|
||||
<span>W</span>
|
||||
<div className="input-grid" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" defaultValue={roof.width} readOnly={roof.widAuth === 'R'} />
|
||||
</div>
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('slope')}</span>
|
||||
<div className="input-grid" style={{ width: '214px' }}>
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
onChange={(e) => {
|
||||
handleChangeInput(e, currentAngleType === 'slope' ? 'pitch' : 'angle', index)
|
||||
}}
|
||||
defaultValue={currentAngleType === 'slope' ? roof.pitch : roof.angle}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{roof.lenAuth && (
|
||||
<div className="flex-ment">
|
||||
<span>L</span>
|
||||
<div className="input-grid" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" defaultValue={roof.length} readOnly={roof.lenAuth === 'R'} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<span>{pitchText}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{(roof.raftAuth || roof.roofPchAuth) && (
|
||||
<div className="block-box">
|
||||
{roof.raftAuth && (
|
||||
<div className="block-box">
|
||||
{(roof.widAuth || roof.lenAuth) && (
|
||||
<div className="block-box">
|
||||
{roof.widAuth && (
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
|
||||
{raftCodes.length > 0 && (
|
||||
<div className="grid-select" style={{ width: '160px' }}>
|
||||
<QSelectBox
|
||||
options={raftCodes}
|
||||
value={roof}
|
||||
showKey={'clCodeNm'}
|
||||
sourceKey={'clCode'}
|
||||
targetKey={roof.raft ? 'raft' : 'raftBaseCd'}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{roof.roofPchAuth && (
|
||||
<div className="block-box">
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('hajebichi')}</span>
|
||||
<div className="input-grid" style={{ width: '84px' }}>
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={parseInt(roof.hajebichi)}
|
||||
readOnly={roof.roofPchAuth === 'R'}
|
||||
/>
|
||||
<span>W</span>
|
||||
<div className="input-grid" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" defaultValue={roof.width} readOnly={roof.widAuth === 'R'} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="block-box">
|
||||
<div className="icon-btn-wrap">
|
||||
<button
|
||||
className={roof.layout === ROOF_MATERIAL_LAYOUT.PARALLEL ? 'act' : ''}
|
||||
onClick={() => {
|
||||
handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
|
||||
}}
|
||||
>
|
||||
{getMessage('modal.roof.alloc.select.parallel')}
|
||||
<i className="allocation01"></i>
|
||||
</button>
|
||||
<button
|
||||
className={roof.layout === ROOF_MATERIAL_LAYOUT.STAIRS ? 'act' : ''}
|
||||
onClick={() => {
|
||||
handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
|
||||
}}
|
||||
>
|
||||
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
|
||||
</button>
|
||||
)}
|
||||
{roof.lenAuth && (
|
||||
<div className="flex-ment">
|
||||
<span>L</span>
|
||||
<div className="input-grid" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" defaultValue={roof.length} readOnly={roof.lenAuth === 'R'} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{(roof.raftAuth || roof.roofPchAuth) && (
|
||||
<div className="block-box">
|
||||
{roof.raftAuth && (
|
||||
<div className="block-box">
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
|
||||
{raftCodes.length > 0 && (
|
||||
<div className="grid-select" style={{ width: '160px' }}>
|
||||
<QSelectBox
|
||||
options={raftCodes}
|
||||
value={roof}
|
||||
showKey={'clCodeNm'}
|
||||
sourceKey={'clCode'}
|
||||
targetKey={roof.raft ? 'raft' : 'raftBaseCd'}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{roof.roofPchAuth && (
|
||||
<div className="block-box">
|
||||
<div className="flex-ment">
|
||||
<span>{getMessage('hajebichi')}</span>
|
||||
<div className="input-grid" style={{ width: '84px' }}>
|
||||
<input
|
||||
type="text"
|
||||
className="input-origin block"
|
||||
value={parseInt(roof.hajebichi)}
|
||||
readOnly={roof.roofPchAuth === 'R'}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="block-box">
|
||||
<div className="icon-btn-wrap">
|
||||
<button
|
||||
className={roof.layout === ROOF_MATERIAL_LAYOUT.PARALLEL ? 'act' : ''}
|
||||
onClick={() => {
|
||||
handleChangeLayout(ROOF_MATERIAL_LAYOUT.PARALLEL, index)
|
||||
}}
|
||||
>
|
||||
{getMessage('modal.roof.alloc.select.parallel')}
|
||||
<i className="allocation01"></i>
|
||||
</button>
|
||||
<button
|
||||
className={roof.layout === ROOF_MATERIAL_LAYOUT.STAIRS ? 'act' : ''}
|
||||
onClick={() => {
|
||||
handleChangeLayout(ROOF_MATERIAL_LAYOUT.STAIRS, index)
|
||||
}}
|
||||
>
|
||||
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
<div className="grid-btn-wrap">
|
||||
<button className="btn-frame modal act" onClick={handleSaveContext}>
|
||||
@ -213,6 +214,7 @@ export default function ContextRoofAllocationSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -49,7 +49,7 @@ export default function RoofAllocationSetting(props) {
|
||||
<div className={`modal-pop-wrap lr mount`}>
|
||||
{currentRoofList && (
|
||||
<>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.estimate.roof.alloc')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -235,6 +235,7 @@ export default function RoofAllocationSetting(props) {
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -31,7 +31,7 @@ export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 }
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xxm`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('plan.menu.roof.cover.roof.shape.passivity.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -67,6 +67,7 @@ export default function RoofShapePassivitySetting({ id, pos = { x: 50, y: 230 }
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -90,7 +90,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap lr mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.roof.shape.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -108,7 +108,6 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
))}
|
||||
</div>
|
||||
<div className="properties-setting-wrap">
|
||||
<div className="setting-tit">{getMessage('setting')}</div>
|
||||
{shapeNum === 1 && <Ridge {...ridgeProps} />}
|
||||
{(shapeNum === 2 || shapeNum === 3) && <Pattern {...patternProps} />}
|
||||
{shapeNum === 4 && <Side {...sideProps} />}
|
||||
@ -120,6 +119,7 @@ export default function RoofShapeSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -75,7 +75,7 @@ export default function SettingModal01(props) {
|
||||
<>
|
||||
<WithDraggable isShow={true} pos={{ x: 1275, y: 180 }}>
|
||||
<div className={`modal-pop-wrap sm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.canvas.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id, true)}>
|
||||
닫기
|
||||
@ -100,6 +100,7 @@ export default function SettingModal01(props) {
|
||||
{buttonAct === 2 && <SecondOption {...secondProps} />}
|
||||
{buttonAct === 3 && <GridOption {...gridProps} />}
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
</>
|
||||
|
||||
@ -192,7 +192,7 @@ export default function DimensionLineSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xxxm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.canvas.setting.font.plan.absorption.dimension.line')} </h1>
|
||||
<button
|
||||
className="modal-close"
|
||||
@ -258,6 +258,7 @@ export default function DimensionLineSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -57,7 +57,7 @@ export default function PlanSizeSetting(props) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap xsm mount`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.canvas.setting.font.plan.absorption.plan.size.setting')}</h1>
|
||||
<button
|
||||
className="modal-close"
|
||||
@ -104,6 +104,7 @@ export default function PlanSizeSetting(props) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -41,7 +41,7 @@ export default function WallLineOffsetSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
return (
|
||||
<WithDraggable isShow={true} pos={pos}>
|
||||
<div className={`modal-pop-wrap r`}>
|
||||
<div className="modal-head">
|
||||
<div className="modal-head modal-handle">
|
||||
<h1 className="title">{getMessage('modal.wallline.offset.setting')}</h1>
|
||||
<button className="modal-close" onClick={() => closePopup(id)}>
|
||||
닫기
|
||||
@ -66,6 +66,7 @@ export default function WallLineOffsetSetting({ id, pos = { x: 50, y: 230 } }) {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-foot modal-handle"></div>
|
||||
</div>
|
||||
</WithDraggable>
|
||||
)
|
||||
|
||||
@ -221,7 +221,7 @@ export default function Header(props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isGlobalLoading && !(pathName.includes('login') || pathName.includes('join') || sessionState.pwdInitYn === 'N') && (
|
||||
{!(pathName.includes('login') || pathName.includes('join') || sessionState.pwdInitYn === 'N') && (
|
||||
<header className={isDimmed}>
|
||||
<div className="header-inner">
|
||||
<div className="header-right">
|
||||
|
||||
@ -10,12 +10,12 @@ import { useRecoilValue } from 'recoil'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { queryStringFormatter } from '@/util/common-utils'
|
||||
import MainSkeleton from '../ui/MainSkeleton'
|
||||
import { useMainContentsController } from '@/hooks/main/useMainContentsController'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
|
||||
import BoardDetailModal from '../community/modal/BoardDetailModal'
|
||||
import { handleFileDown } from '@/util/board-utils'
|
||||
|
||||
export default function MainContents() {
|
||||
const { swalFire } = useSwal()
|
||||
@ -23,26 +23,53 @@ export default function MainContents() {
|
||||
const { getMessage } = useMessage()
|
||||
const router = useRouter()
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
const { promiseGet } = useAxios(globalLocaleState)
|
||||
|
||||
const { promiseGet, get } = useAxios(globalLocaleState)
|
||||
//공지사항
|
||||
const [recentNoticeList, setRecentNoticeList] = useState([])
|
||||
|
||||
//FAQ
|
||||
const [recentFaqList, setRecentFaqList] = useState([])
|
||||
|
||||
const { qcastState } = useContext(QcastContext)
|
||||
const { qcastState, setIsGlobalLoading } = useContext(QcastContext)
|
||||
const { fetchObjectList, initObjectList } = useMainContentsController()
|
||||
|
||||
//첨부파일
|
||||
const [boardList, setBoardList] = useState([])
|
||||
useEffect(() => {
|
||||
fetchObjectList()
|
||||
fetchNoticeList()
|
||||
fetchFaqList()
|
||||
//첨부파일 목록 호출
|
||||
fetchArchiveList()
|
||||
return () => {
|
||||
initObjectList()
|
||||
}
|
||||
}, [])
|
||||
|
||||
//첨부파일 목록 호출
|
||||
const fetchArchiveList = async () => {
|
||||
const url = `/api/board/list`
|
||||
|
||||
const params = new URLSearchParams({
|
||||
schNoticeTpCd: 'QC',
|
||||
schNoticeClsCd: 'DOWN',
|
||||
startRow: 1,
|
||||
endRow: 2,
|
||||
schMainYn: 'Y',
|
||||
})
|
||||
|
||||
const apiUrl = `${url}?${params.toString()}`
|
||||
const resultData = await get({ url: apiUrl })
|
||||
|
||||
if (resultData) {
|
||||
if (resultData.result.code === 200) {
|
||||
setBoardList(resultData.data)
|
||||
} else {
|
||||
alert(resultData.result.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//공지사항 호출
|
||||
const fetchNoticeList = async () => {
|
||||
try {
|
||||
@ -105,6 +132,7 @@ export default function MainContents() {
|
||||
key={row.objectNo}
|
||||
className="recently-item"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
if (row.tempFlg === '0') {
|
||||
router.push(`/management/stuff/detail?objectNo=${row.objectNo.toString()}`, { scroll: false })
|
||||
} else {
|
||||
@ -114,7 +142,7 @@ export default function MainContents() {
|
||||
>
|
||||
<div className="item-inner">
|
||||
<span className="time">{dayjs(row.lastEditDatetime).format('YYYY.MM.DD HH:mm:ss')}</span>
|
||||
<span>{row.tempFlg === '0' ? row.objectNo : getMessage('stuff.gridData.tempObjectNo')}</span>
|
||||
<span className="product">{row.tempFlg === '0' ? row.objectNo : getMessage('stuff.gridData.tempObjectNo')}</span>
|
||||
<span>{row.objectName ? row.objectName : '-'}</span>
|
||||
<span>{row.saleStoreName}</span>
|
||||
</div>
|
||||
@ -183,14 +211,19 @@ export default function MainContents() {
|
||||
)}
|
||||
</ProductItem>
|
||||
<ProductItem num={4} name={'Data Download'}>
|
||||
<div className="data-download-wrap">
|
||||
<button className="data-down" type="button" onClick={() => swalFire({ text: getMessage('main.content.alert.noFile'), type: 'alert' })}>
|
||||
<span>{getMessage('main.content.download1')}</span>
|
||||
</button>
|
||||
<button className="data-down" type="button" onClick={() => swalFire({ text: getMessage('main.content.alert.noFile'), type: 'alert' })}>
|
||||
<span>{getMessage('main.content.download2')}</span>
|
||||
</button>
|
||||
</div>
|
||||
{boardList.length > 0 ? (
|
||||
<div className="data-download-wrap">
|
||||
{boardList?.map((board) => (
|
||||
<button type="button" key={board.noticeNo} className="data-down" onClick={() => handleFileDown(board.noticeNo, 'Y')}>
|
||||
<span>{board.title}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="file-down-nodata">
|
||||
<h3>{getMessage('common.message.no.data')}</h3>
|
||||
</div>
|
||||
)}
|
||||
</ProductItem>
|
||||
<ProductItem num={5} name={'Sales Contact info'}>
|
||||
<ul className="contact-info-list">
|
||||
|
||||
@ -15,12 +15,12 @@ import KO from '@/locales/ko.json'
|
||||
import JA from '@/locales/ja.json'
|
||||
import QPagination from '../common/pagination/QPagination'
|
||||
import { SessionContext } from '@/app/SessionProvider'
|
||||
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
export default function Stuff() {
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
|
||||
const { swalFire } = useSwal()
|
||||
const resetStuffRecoil = useResetRecoilState(stuffSearchState)
|
||||
const { session } = useContext(SessionContext)
|
||||
const setAppMessageState = useSetRecoilState(appMessageStore)
|
||||
@ -41,20 +41,18 @@ export default function Stuff() {
|
||||
|
||||
//그리드 내부 복사버튼
|
||||
const copyNo = async (value) => {
|
||||
// try {
|
||||
// await navigator.clipboard.writeText(value)
|
||||
// alert(getMessage('stuff.detail.header.successCopy'))
|
||||
// } catch (error) {
|
||||
// alert(getMessage('stuff.detail.header.failCopy'))
|
||||
// }
|
||||
// Navigator clipboard api needs a secure context (https)
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
console.log('trttt')
|
||||
await navigator.clipboard
|
||||
.writeText(value)
|
||||
.then(() => {
|
||||
alert(getMessage('stuff.detail.header.successCopy'))
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.header.successCopy'),
|
||||
type: 'alert',
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
.catch((e) => {
|
||||
console.log(e)
|
||||
alert(getMessage('stuff.detail.header.failCopy'))
|
||||
})
|
||||
} else {
|
||||
@ -71,7 +69,10 @@ export default function Stuff() {
|
||||
|
||||
try {
|
||||
document.execCommand('copy')
|
||||
alert(getMessage('stuff.detail.header.successCopy'))
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.header.successCopy'),
|
||||
type: 'alert',
|
||||
})
|
||||
} catch (err) {
|
||||
alert(getMessage('stuff.detail.header.failCopy'))
|
||||
} finally {
|
||||
@ -122,7 +123,7 @@ export default function Stuff() {
|
||||
type="button"
|
||||
className="copy_ico"
|
||||
onClick={() => {
|
||||
copyNo(params.value)
|
||||
copyNo(params?.value)
|
||||
}}
|
||||
></button>
|
||||
</>
|
||||
@ -219,6 +220,9 @@ export default function Stuff() {
|
||||
pageSize: stuffSearchParams?.pageSize ? stuffSearchParams.pageSize : 100,
|
||||
}
|
||||
|
||||
if (!params.saleStoreId) {
|
||||
params.saleStoreId = session.storeId
|
||||
}
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(params)}`
|
||||
await get({
|
||||
@ -271,6 +275,17 @@ export default function Stuff() {
|
||||
stuffSearchParams.schSortType = defaultSortType
|
||||
stuffSearchParams.pageNo = stuffSearchParams.pageNo
|
||||
|
||||
if (!stuffSearchParams.saleStoreId) {
|
||||
stuffSearchParams.saleStoreId = session.storeId
|
||||
}
|
||||
if (stuffSearchParams.schMyDataCheck) {
|
||||
if (session.storeLvl === '1') {
|
||||
//schOtherSelSaleStoreId 초기화 schSelSaleStoreId 에 saleStoreId 담아서 보내기
|
||||
stuffSearchParams.schOtherSelSaleStoreId = ''
|
||||
stuffSearchParams.schSelSaleStoreId = session.storeId
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(stuffSearchParams)}`
|
||||
await get({ url: apiUrl }).then((res) => {
|
||||
@ -301,6 +316,15 @@ export default function Stuff() {
|
||||
stuffSearchParams.schSortType = defaultSortType
|
||||
setPageNo(1)
|
||||
|
||||
if (!params.saleStoreId) {
|
||||
stuffSearchParams.saleStoreId = session.storeId
|
||||
}
|
||||
if (stuffSearchParams.schMyDataCheck) {
|
||||
//schOtherSelSaleStoreId 초기화 schSelSaleStoreId 에 saleStoreId 담아서 보내기
|
||||
stuffSearchParams.schOtherSelSaleStoreId = ''
|
||||
stuffSearchParams.schSelSaleStoreId = session.storeId
|
||||
}
|
||||
|
||||
async function fetchData() {
|
||||
const apiUrl = `/api/object/list?${queryStringFormatter(stuffSearchParams)}`
|
||||
await get({ url: apiUrl }).then((res) => {
|
||||
@ -336,6 +360,7 @@ export default function Stuff() {
|
||||
code: 'S',
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
schMyDataCheck: false,
|
||||
}
|
||||
|
||||
setStuffSearch({
|
||||
|
||||
@ -4,7 +4,6 @@ import { useState, useEffect, useRef, useContext } from 'react'
|
||||
import { useRouter, useSearchParams } from 'next/navigation'
|
||||
import { Button } from '@nextui-org/react'
|
||||
import Select, { components } from 'react-select'
|
||||
import Link from 'next/link'
|
||||
import { useAxios } from '@/hooks/useAxios'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
||||
@ -289,10 +288,12 @@ export default function StuffDetail() {
|
||||
display: 'none',
|
||||
}
|
||||
}
|
||||
// if (managementState?.createUser === 'T01' && session?.userId !== 'T01') {
|
||||
//createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기 적용할지 미정!!!!!!!!
|
||||
//buttonStyle = { display: 'none' }
|
||||
// }
|
||||
if (managementState?.createUser === 'T01') {
|
||||
if (session.userId !== 'T01') {
|
||||
// #474
|
||||
buttonStyle = { display: 'none' }
|
||||
}
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="grid-cell-btn">
|
||||
@ -301,9 +302,9 @@ export default function StuffDetail() {
|
||||
type="button"
|
||||
className="grid-btn"
|
||||
onClick={() => {
|
||||
//mid:5(견적서), /pid:플랜번호
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo })
|
||||
setIsGlobalLoading(true)
|
||||
setMenuNumber(5)
|
||||
router.push(`/floor-plan/estimate/5?pid=${params.data.planNo}&objectNo=${params.data.objectNo}`)
|
||||
}}
|
||||
>
|
||||
@ -349,6 +350,10 @@ export default function StuffDetail() {
|
||||
if (res?.data?.createUser === 'T01' && session?.userId !== 'T01') {
|
||||
//createUser가 T01인데 로그인사용자가 T01이 아니면 버튼숨기기
|
||||
setShowButton('none')
|
||||
} else {
|
||||
if (session.userId !== res?.data?.createUser) {
|
||||
setShowButton('none')
|
||||
}
|
||||
}
|
||||
if (isObjectNotEmpty(res.data)) {
|
||||
let surfaceTypeValue
|
||||
@ -357,7 +362,7 @@ export default function StuffDetail() {
|
||||
} else if (res.data.surfaceType === 'Ⅱ') {
|
||||
surfaceTypeValue = '2'
|
||||
}
|
||||
setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
|
||||
setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue, firstFlag: 'Y' })
|
||||
} else {
|
||||
setManagementState({})
|
||||
swalFire({
|
||||
@ -449,7 +454,6 @@ export default function StuffDetail() {
|
||||
firstList = res
|
||||
favList = res.filter((row) => row.priority !== 'B')
|
||||
otherList = res.filter((row) => row.firstAgentYn === 'N')
|
||||
|
||||
setSaleStoreList(firstList)
|
||||
setFavoriteStoreList(firstList)
|
||||
setShowSaleStoreList(firstList)
|
||||
@ -526,6 +530,11 @@ export default function StuffDetail() {
|
||||
get({ url: url }).then((res) => {
|
||||
if (!isEmptyArray(res)) {
|
||||
if (session?.storeId === 'T01') {
|
||||
//즐겨찾기 구분 추가
|
||||
res.map((row) => {
|
||||
row.value = row.saleStoreId
|
||||
row.label = row.saleStoreName
|
||||
})
|
||||
firstList = res.filter((row) => row.saleStoreLevel === '1')
|
||||
firstList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
|
||||
favList = firstList.filter((row) => row.saleStoreId === 'T01' || row.priority !== 'B')
|
||||
@ -648,7 +657,7 @@ export default function StuffDetail() {
|
||||
//염해지역용아이템사용 saltAreaFlg 1이면 true
|
||||
form.setValue('saltAreaFlg', managementState.saltAreaFlg === '1' ? true : false)
|
||||
//설치높이
|
||||
let installHeight = managementState.installHeight ? managementState.installHeight.split('.')[0] : '0'
|
||||
let installHeight = managementState.installHeight ? managementState.installHeight.split('.')[0] : ''
|
||||
form.setValue('installHeight', installHeight)
|
||||
//계약조건 null로 내려오면 0으로 디폴트셋팅
|
||||
if (managementState.conType === null) {
|
||||
@ -984,7 +993,7 @@ export default function StuffDetail() {
|
||||
form.setValue('saltAreaFlg', false)
|
||||
}
|
||||
|
||||
let installHeight = info.installHeight ? info.installHeight.split('.')[0] : '0'
|
||||
let installHeight = info.installHeight ? info.installHeight.split('.')[0] : ''
|
||||
|
||||
form.setValue('installHeight', installHeight)
|
||||
form.setValue('remarks', info.remarks)
|
||||
@ -1024,6 +1033,8 @@ export default function StuffDetail() {
|
||||
const _objectNameOmit = watch('objectNameOmit')
|
||||
// saleStoreId: '', //1차 판매점ID
|
||||
const _saleStoreId = watch('saleStoreId')
|
||||
// 2차 판매점명
|
||||
const _otherSaleStoreId = watch('otherSaleStoreId')
|
||||
// zipNo: '', //우편번호
|
||||
const _zipNo = watch('zipNo')
|
||||
// prefId: '', //도도부현
|
||||
@ -1042,6 +1053,7 @@ export default function StuffDetail() {
|
||||
useEffect(() => {
|
||||
if (editMode === 'NEW') {
|
||||
const formData = form.getValues()
|
||||
|
||||
let errors = {}
|
||||
if (!formData.receiveUser || formData.receiveUser.trim().length === 0) {
|
||||
errors.receiveUser = true
|
||||
@ -1056,6 +1068,12 @@ export default function StuffDetail() {
|
||||
errors.saleStoreId = true
|
||||
}
|
||||
|
||||
if (session?.storeLvl === '2') {
|
||||
if (!formData.otherSaleStoreId) {
|
||||
errors.otherSaleStoreId = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!formData.zipNo) {
|
||||
errors.zipNo = true
|
||||
}
|
||||
@ -1098,6 +1116,12 @@ export default function StuffDetail() {
|
||||
errors.saleStoreId = true
|
||||
}
|
||||
|
||||
if (session?.storeLvl === '2') {
|
||||
if (!formData.otherSaleStoreId) {
|
||||
errors.otherSaleStoreId = true
|
||||
}
|
||||
}
|
||||
|
||||
if (!formData.zipNo) {
|
||||
errors.zipNo = true
|
||||
}
|
||||
@ -1129,6 +1153,7 @@ export default function StuffDetail() {
|
||||
_objectName,
|
||||
_objectNameOmit,
|
||||
_saleStoreId,
|
||||
_otherSaleStoreId,
|
||||
_zipNo,
|
||||
_prefId,
|
||||
_address,
|
||||
@ -1357,7 +1382,7 @@ export default function StuffDetail() {
|
||||
//로그인이 2차점인데 otherSaleStoreId가 없으면 알럿
|
||||
if (session.storeLvl !== '1') {
|
||||
if (params.saleStoreLevel === '1') {
|
||||
return swalFire({ text: getMessage('stuff.detail.tempSave.message4'), type: 'alert' })
|
||||
return swalFire({ text: getMessage('stuff.detail.tempSave.message3'), type: 'alert' })
|
||||
}
|
||||
}
|
||||
|
||||
@ -1367,13 +1392,12 @@ export default function StuffDetail() {
|
||||
setIsGlobalLoading(true)
|
||||
//상세화면으로 전환
|
||||
if (res.status === 201) {
|
||||
setIsGlobalLoading(false)
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: objectNo })
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.save'),
|
||||
type: 'alert',
|
||||
confirmFn: () => {
|
||||
setIsGlobalLoading(false)
|
||||
|
||||
router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
|
||||
},
|
||||
})
|
||||
@ -1390,13 +1414,13 @@ export default function StuffDetail() {
|
||||
setIsGlobalLoading(true)
|
||||
|
||||
if (res.status === 201) {
|
||||
setIsGlobalLoading(false)
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: res.data.objectNo })
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.save'),
|
||||
type: 'alert',
|
||||
confirmFn: () => {
|
||||
setIsGlobalLoading(false)
|
||||
router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
|
||||
callDetailApi(objectNo)
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -1408,6 +1432,25 @@ export default function StuffDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
const callDetailApi = async (objectNo) => {
|
||||
await promiseGet({ url: `/api/object/${objectNo}/detail` }).then((res) => {
|
||||
if (res?.data?.createUser === 'T01' && session?.userId !== 'T01') {
|
||||
setShowButton('none')
|
||||
} else {
|
||||
if (session.userId !== res?.data?.createUser) {
|
||||
setShowButton('none')
|
||||
}
|
||||
}
|
||||
let surfaceTypeValue
|
||||
if (res.data.surfaceType === 'Ⅲ・Ⅳ') {
|
||||
surfaceTypeValue = '3'
|
||||
} else {
|
||||
surfaceTypeValue = '2'
|
||||
}
|
||||
setManagementState({ ...res.data, surfaceTypeValue: surfaceTypeValue })
|
||||
})
|
||||
}
|
||||
|
||||
// 임시저장
|
||||
const onTempSave = async () => {
|
||||
const formData = form.getValues()
|
||||
@ -1447,6 +1490,13 @@ export default function StuffDetail() {
|
||||
params.saleStoreLevel = session.storeLvl
|
||||
}
|
||||
|
||||
if (session.storeLvl !== '1') {
|
||||
//로그인이 1차점이 아닌데 2차점을 안골라서 saleStoreLevel = 1로 셋팅되어있으면 알럿
|
||||
if (params.saleStoreLevel === '1') {
|
||||
return swalFire({ text: getMessage('stuff.detail.tempSave.message3'), type: 'alert' })
|
||||
}
|
||||
}
|
||||
|
||||
// 담당자 자리수 체크
|
||||
if (params?.receiveUser !== '') {
|
||||
if (params?.receiveUser.trim().length > 10) {
|
||||
@ -1460,11 +1510,11 @@ export default function StuffDetail() {
|
||||
.then((res) => {
|
||||
setIsGlobalLoading(true)
|
||||
if (res.status === 201) {
|
||||
setIsGlobalLoading(false)
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.tempSave.message1'),
|
||||
type: 'alert',
|
||||
confirmFn: () => {
|
||||
setIsGlobalLoading(false)
|
||||
router.push(`/management/stuff/tempdetail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
|
||||
},
|
||||
})
|
||||
@ -1479,11 +1529,11 @@ export default function StuffDetail() {
|
||||
.then((res) => {
|
||||
setIsGlobalLoading(true)
|
||||
if (res.status === 201) {
|
||||
setIsGlobalLoading(false)
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.tempSave.message1'),
|
||||
type: 'alert',
|
||||
confirmFn: () => {
|
||||
setIsGlobalLoading(false)
|
||||
router.push(`/management/stuff/tempdetail?objectNo=${res.data.objectNo.toString()}`, { scroll: false })
|
||||
},
|
||||
})
|
||||
@ -1511,7 +1561,7 @@ export default function StuffDetail() {
|
||||
confirmFn: () => {
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: '' })
|
||||
del({ url: `/api/object/${objectNo}?${queryStringFormatter(delParams)}` })
|
||||
.then((res) => {
|
||||
.then(() => {
|
||||
setIsGlobalLoading(true)
|
||||
setFloorPlanObjectNo({ floorPlanObjectNo: '' })
|
||||
if (session.storeId === 'T01') {
|
||||
@ -1587,6 +1637,13 @@ export default function StuffDetail() {
|
||||
|
||||
// 그리드 더블 클릭 해당플랜의 도면작성 화면으로 이동
|
||||
const getCellDoubleClicked = (params) => {
|
||||
//#474정책
|
||||
if (managementState.createUser === 'T01') {
|
||||
if (session.userId !== 'T01') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if (params?.column?.colId !== 'estimateDate') {
|
||||
if (params?.data?.planNo && params?.data?.objectNo) {
|
||||
let objectNo = params?.data?.objectNo
|
||||
@ -1603,6 +1660,31 @@ export default function StuffDetail() {
|
||||
}
|
||||
}
|
||||
|
||||
const CustomOption = (props) => {
|
||||
const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
|
||||
const customClass = data.saleStoreId === 'T01' || data.priority !== 'B' ? 'special-option' : ''
|
||||
// 기본 선택/호버 상태 적용
|
||||
const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
|
||||
|
||||
return (
|
||||
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
|
||||
{data.label}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const CustomOption2 = (props) => {
|
||||
const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
|
||||
const customClass = data.priority !== 'B' ? 'special-option' : ''
|
||||
// 기본 선택/호버 상태 적용
|
||||
const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
|
||||
return (
|
||||
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
|
||||
{data.label}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{(editMode === 'NEW' && (
|
||||
@ -1623,11 +1705,21 @@ export default function StuffDetail() {
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</Button>
|
||||
)}
|
||||
<Link href="/management/stuff" scroll={false}>
|
||||
{/* <Link href="/management/stuff" scroll={false}>
|
||||
<button type="button" className="btn-origin grey">
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="infomation-table">
|
||||
@ -1760,6 +1852,7 @@ export default function StuffDetail() {
|
||||
value={saleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
components={{ Option: CustomOption }}
|
||||
></Select>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -1792,6 +1885,7 @@ export default function StuffDetail() {
|
||||
value={showSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
// components={{ Option: CustomOption }}
|
||||
></Select>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -1823,6 +1917,7 @@ export default function StuffDetail() {
|
||||
value={showSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
// components={{ Option: CustomOption }}
|
||||
></Select>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -1875,11 +1970,11 @@ export default function StuffDetail() {
|
||||
? true
|
||||
: false
|
||||
}
|
||||
// isDisabled={otherSaleStoreList != null && otherSaleStoreList.length === 1 ? true : false}
|
||||
isClearable={true}
|
||||
value={otherSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === otherSelOptions
|
||||
})}
|
||||
components={{ Option: CustomOption2 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -2123,11 +2218,21 @@ export default function StuffDetail() {
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</Button>
|
||||
)}
|
||||
<Link href="/management/stuff" scroll={false}>
|
||||
{/* <Link href="/management/stuff" scroll={false}>
|
||||
<button type="button" className="btn-origin grey">
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@ -2142,11 +2247,21 @@ export default function StuffDetail() {
|
||||
{managementState?.tempFlg === '0' ? (
|
||||
<>
|
||||
<div className="left-unit-box">
|
||||
<Link href="/management/stuff" scroll={false}>
|
||||
{/* <Link href="/management/stuff" scroll={false}>
|
||||
<button type="button" className="btn-origin grey mr5">
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey mr5"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
<Button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</Button>
|
||||
@ -2167,11 +2282,21 @@ export default function StuffDetail() {
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</Button>
|
||||
)}
|
||||
<Link href="/management/stuff" scroll={false}>
|
||||
{/* <Link href="/management/stuff" scroll={false}>
|
||||
<button type="button" className="btn-origin grey">
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
@ -2296,7 +2421,7 @@ export default function StuffDetail() {
|
||||
<>
|
||||
<div className="select-wrap mr5" style={{ width: '567px' }}>
|
||||
<Select
|
||||
menuPlacement={'auto'}
|
||||
// menuPlacement={'auto'}
|
||||
id="long-value-select1"
|
||||
instanceId="long-value-select1"
|
||||
className="react-select-custom"
|
||||
@ -2312,6 +2437,7 @@ export default function StuffDetail() {
|
||||
value={saleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
components={{ Option: CustomOption }}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -2352,6 +2478,7 @@ export default function StuffDetail() {
|
||||
value={showSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === selOptions
|
||||
})}
|
||||
// components={{ Option: CustomOption }}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -2386,6 +2513,7 @@ export default function StuffDetail() {
|
||||
return option.saleStoreId
|
||||
}
|
||||
})}
|
||||
// components={{ Option: CustomOption }}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -2425,19 +2553,22 @@ export default function StuffDetail() {
|
||||
onChange={onSelectionChange2}
|
||||
getOptionLabel={(x) => x.saleStoreName}
|
||||
getOptionValue={(x) => x.saleStoreId}
|
||||
// isDisabled={
|
||||
// managementState?.tempFlg === '0'
|
||||
// ? true
|
||||
// : session?.storeLvl === '1' && form.watch('saleStoreId') != ''
|
||||
// ? false
|
||||
// : false
|
||||
// }
|
||||
isDisabled={managementState?.tempFlg === '0' ? true : false}
|
||||
isDisabled={
|
||||
managementState?.tempFlg === '0'
|
||||
? true
|
||||
: session?.storeLvl === '1'
|
||||
? otherSaleStoreList.length > 0
|
||||
? false
|
||||
: true
|
||||
: otherSaleStoreList.length === 1
|
||||
? true
|
||||
: false
|
||||
}
|
||||
isClearable={managementState?.tempFlg === '0' ? false : true}
|
||||
// isClearable={managementState?.tempFlg === '0' ? false : session?.storeLvl === '1' ? true : true}
|
||||
value={otherSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === otherSelOptions
|
||||
})}
|
||||
// components={{ Option: CustomOption2 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="input-wrap" style={{ width: '216px' }}>
|
||||
@ -2721,11 +2852,21 @@ export default function StuffDetail() {
|
||||
</div>
|
||||
{/* 진짜R 플랜끝 */}
|
||||
<div className="sub-right-footer">
|
||||
<Link href="/management/stuff" scroll={false}>
|
||||
{/* <Link href="/management/stuff" scroll={false}>
|
||||
<button type="button" className="btn-origin grey mr5">
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey mr5"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
<Button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</Button>
|
||||
@ -2746,11 +2887,21 @@ export default function StuffDetail() {
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</Button>
|
||||
)}
|
||||
<Link href="/management/stuff" scroll={false}>
|
||||
{/* <Link href="/management/stuff" scroll={false}>
|
||||
<button type="button" className="btn-origin grey">
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin grey"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -1,31 +1,26 @@
|
||||
'use client'
|
||||
|
||||
import { useContext } from 'react'
|
||||
import { useContext, useEffect } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import dayjs from 'dayjs'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
// import { ManagementContext } from '@/app/management/ManagementProvider'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
export default function StuffHeader() {
|
||||
const { getMessage } = useMessage()
|
||||
|
||||
const { swalFire } = useSwal()
|
||||
const { managementState } = useContext(GlobalDataContext)
|
||||
|
||||
//물건번호 복사
|
||||
// const copyObjectNo = async (objectNo) => {
|
||||
// await navigator.clipboard.writeText(objectNo)
|
||||
// alert(getMessage('stuff.detail.header.successCopy'))
|
||||
// try {
|
||||
// } catch (error) {
|
||||
// alert(getMessage('stuff.detail.header.failCopy'))
|
||||
// }
|
||||
// }
|
||||
|
||||
const copyObjectNo = async (objectNo) => {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
await navigator.clipboard
|
||||
.writeText(objectNo)
|
||||
.then(() => {
|
||||
alert(getMessage('stuff.detail.header.successCopy'))
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.header.successCopy'),
|
||||
type: 'alert',
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
alert(getMessage('stuff.detail.header.failCopy'))
|
||||
@ -44,7 +39,10 @@ export default function StuffHeader() {
|
||||
|
||||
try {
|
||||
document.execCommand('copy')
|
||||
alert(getMessage('stuff.detail.header.successCopy'))
|
||||
swalFire({
|
||||
text: getMessage('stuff.detail.header.successCopy'),
|
||||
type: 'alert',
|
||||
})
|
||||
} catch (err) {
|
||||
alert(getMessage('stuff.detail.header.failCopy'))
|
||||
} finally {
|
||||
@ -69,7 +67,9 @@ export default function StuffHeader() {
|
||||
</div>
|
||||
<div className="sub-table-box">
|
||||
<div className="info-title">{getMessage('stuff.detail.header.specificationConfirmDate')}</div>
|
||||
<div className="info-inner">{managementState?.specificationConfirmDate}</div>
|
||||
<div className="info-inner">
|
||||
{managementState?.specificationConfirmDate ? `${dayjs(managementState.specificationConfirmDate).format('YYYY.MM.DD HH:mm:ss')}` : ''}
|
||||
</div>
|
||||
</div>
|
||||
<div className="sub-table-box">
|
||||
<div className="info-title">{getMessage('stuff.detail.header.lastEditDatetime')}</div>
|
||||
|
||||
@ -10,7 +10,7 @@ import JA from '@/locales/ja.json'
|
||||
import { stuffSearchState } from '@/store/stuffAtom'
|
||||
import { isEmptyArray } from '@/util/common-utils'
|
||||
import dayjs from 'dayjs'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import SingleDatePicker from '../common/datepicker/SingleDatePicker'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
@ -20,6 +20,7 @@ import { SessionContext } from '@/app/SessionProvider'
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
export default function StuffSearchCondition() {
|
||||
const router = useRouter()
|
||||
const { session } = useContext(SessionContext)
|
||||
const setAppMessageState = useSetRecoilState(appMessageStore)
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
@ -342,7 +343,7 @@ export default function StuffSearchCondition() {
|
||||
})
|
||||
} else {
|
||||
if (session?.storeLvl === '2') {
|
||||
if (otherSaleStoreList.length > 1) {
|
||||
if (otherSaleStoreList.length === 1) {
|
||||
setOtherSaleStoreId(session.storeId)
|
||||
stuffSearch.schOtherSelSaleStoreId = session.storeId
|
||||
stuffSearch.schObjectNo = ''
|
||||
@ -355,6 +356,24 @@ export default function StuffSearchCondition() {
|
||||
stuffSearch.schTempFlg = ''
|
||||
stuffSearch.schMyDataCheck = false
|
||||
|
||||
stuffSearch.startRow = 1
|
||||
stuffSearch.endRow = 100
|
||||
stuffSearch.schSortType = 'U'
|
||||
stuffSearch.pageNo = 1
|
||||
stuffSearch.pageSize = 100
|
||||
} else if (otherSaleStoreList.length > 1) {
|
||||
setOtherSaleStoreId('')
|
||||
stuffSearch.schOtherSelSaleStoreId = session.storeId
|
||||
stuffSearch.schObjectNo = ''
|
||||
stuffSearch.schAddress = ''
|
||||
stuffSearch.schObjectName = ''
|
||||
stuffSearch.schSaleStoreName = ''
|
||||
stuffSearch.schReceiveUser = ''
|
||||
stuffSearch.schDispCompanyName = ''
|
||||
stuffSearch.schDateType = 'U'
|
||||
stuffSearch.schTempFlg = ''
|
||||
stuffSearch.schMyDataCheck = false
|
||||
|
||||
stuffSearch.startRow = 1
|
||||
stuffSearch.endRow = 100
|
||||
stuffSearch.schSortType = 'U'
|
||||
@ -446,6 +465,7 @@ export default function StuffSearchCondition() {
|
||||
allList = res
|
||||
allList.sort((a, b) => (a.saleStoreId !== 'T01') - (b.saleStoreId !== 'T01') || a.saleStoreId - b.saleStoreId)
|
||||
favList = res.filter((row) => row.saleStoreId === 'T01' || row.priority !== 'B')
|
||||
|
||||
setSchSelSaleStoreList(allList)
|
||||
setFavoriteStoreList(favList)
|
||||
setShowSaleStoreList(favList)
|
||||
@ -503,13 +523,23 @@ export default function StuffSearchCondition() {
|
||||
})
|
||||
} else {
|
||||
if (stuffSearch.code === 'S') {
|
||||
setOtherSaleStoreId(session?.storeId)
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
code: 'S',
|
||||
schSelSaleStoreId: res[0].saleStoreId,
|
||||
schOtherSelSaleStoreId: otherList[0].saleStoreId,
|
||||
})
|
||||
if (otherList.length === 1) {
|
||||
setOtherSaleStoreId(session?.storeId)
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
code: 'S',
|
||||
schSelSaleStoreId: res[0].saleStoreId,
|
||||
schOtherSelSaleStoreId: otherList[0].saleStoreId,
|
||||
})
|
||||
} else {
|
||||
setOtherSaleStoreId('')
|
||||
setStuffSearch({
|
||||
...stuffSearch,
|
||||
code: 'S',
|
||||
schSelSaleStoreId: res[0].saleStoreId,
|
||||
schOtherSelSaleStoreId: '',
|
||||
})
|
||||
}
|
||||
} else {
|
||||
setOtherSaleStoreId(stuffSearch?.schOtherSelSaleStoreId)
|
||||
setStuffSearch({
|
||||
@ -542,7 +572,7 @@ export default function StuffSearchCondition() {
|
||||
const onInputChange = (key) => {
|
||||
//내 물건보기 체크 풀어주기
|
||||
setMyDataCheck(false)
|
||||
|
||||
stuffSearch.schMyDataCheck = false
|
||||
if (key !== '') {
|
||||
setShowSaleStoreList(schSelSaleStoreList)
|
||||
} else {
|
||||
@ -560,7 +590,6 @@ export default function StuffSearchCondition() {
|
||||
setOtherSaleStoreId('')
|
||||
setSchSelSaleStoreId(key.saleStoreId)
|
||||
stuffSearch.schSelSaleStoreId = key.saleStoreId
|
||||
//T01아닌 1차점은 본인으로 디폴트셋팅이고 수정할수없어서 여기안옴
|
||||
//고른 1차점의 saleStoreId로 2차점 API호출하기
|
||||
let url = `/api/object/saleStore/${key.saleStoreId}/list?firstFlg=0&userId=${session?.userId}`
|
||||
let otherList
|
||||
@ -719,19 +748,61 @@ export default function StuffSearchCondition() {
|
||||
setMyDataCheck(stuffSearch.schMyDataCheck)
|
||||
}
|
||||
} else {
|
||||
setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||
setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
|
||||
setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
|
||||
setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
|
||||
setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
|
||||
setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
|
||||
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
||||
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
||||
setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
|
||||
setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
|
||||
setMyDataCheck(stuffSearch.schMyDataCheck)
|
||||
if (session.storeLvl !== '1') {
|
||||
stuffSearch.schSelSaleStoreId = ''
|
||||
if (stuffSearch.code === 'DELETE') {
|
||||
//1차점인경우
|
||||
if (session.storeLvl === '1') {
|
||||
stuffSearch.schOtherSelSaleStoreId = ''
|
||||
setOtherSaleStoreId('')
|
||||
} else {
|
||||
//2차점 본인하나인경우
|
||||
//34있는경우
|
||||
stuffSearch.schOtherSelSaleStoreId = ''
|
||||
setOtherSaleStoreId('')
|
||||
}
|
||||
|
||||
setObjectNo('')
|
||||
setSaleStoreName('')
|
||||
setAddress('')
|
||||
setobjectName('')
|
||||
setDispCompanyName('')
|
||||
setReceiveUser('')
|
||||
objectNoRef.current.value = ''
|
||||
saleStoreNameRef.current.value = ''
|
||||
addressRef.current.value = ''
|
||||
objectNameRef.current.value = ''
|
||||
dispCompanyNameRef.current.value = ''
|
||||
receiveUserRef.current.value = ''
|
||||
stuffSearch.schObjectNo = ''
|
||||
stuffSearch.schAddress = ''
|
||||
stuffSearch.schObjectName = ''
|
||||
stuffSearch.schSaleStoreName = ''
|
||||
stuffSearch.schReceiveUser = ''
|
||||
stuffSearch.schDispCompanyName = ''
|
||||
stuffSearch.schDateType = 'U'
|
||||
stuffSearch.schTempFlg = ''
|
||||
stuffSearch.schMyDataCheck = false
|
||||
stuffSearch.schFromDt = dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD')
|
||||
stuffSearch.schToDt = dayjs(new Date()).format('YYYY-MM-DD')
|
||||
stuffSearch.startRow = 1
|
||||
stuffSearch.endRow = 100
|
||||
stuffSearch.schSortType = 'U'
|
||||
stuffSearch.pageNo = 1
|
||||
stuffSearch.pageSize = 100
|
||||
} else {
|
||||
setStartDate(stuffSearch?.schFromDt ? stuffSearch.schFromDt : dayjs(new Date()).add(-1, 'year').format('YYYY-MM-DD'))
|
||||
setEndDate(stuffSearch?.schToDt ? stuffSearch.schToDt : dayjs(new Date()).format('YYYY-MM-DD'))
|
||||
setObjectNo(stuffSearch.schObjectNo ? stuffSearch.schObjectNo : objectNo)
|
||||
setSaleStoreName(stuffSearch.schSaleStoreName ? stuffSearch.schSaleStoreName : saleStoreName)
|
||||
setAddress(stuffSearch.schAddress ? stuffSearch.schAddress : address)
|
||||
setobjectName(stuffSearch.schObjectName ? stuffSearch.schObjectName : objectName)
|
||||
setDispCompanyName(stuffSearch.schDispCompanyName ? stuffSearch.schDispCompanyName : dispCompanyName)
|
||||
setReceiveUser(stuffSearch.schReceiveUser ? stuffSearch.schReceiveUser : receiveUser)
|
||||
setDateType(stuffSearch.schDateType ? stuffSearch.schDateType : dateType)
|
||||
setTempFlg(stuffSearch.schTempFlg ? stuffSearch.schTempFlg : tempFlg)
|
||||
setMyDataCheck(stuffSearch.schMyDataCheck)
|
||||
if (session.storeLvl !== '1') {
|
||||
stuffSearch.schSelSaleStoreId = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -801,10 +872,12 @@ export default function StuffSearchCondition() {
|
||||
if (e.target.checked) {
|
||||
stuffSearch.schMyDataCheck = e.target.value
|
||||
setMyDataCheck(true)
|
||||
|
||||
if (otherSaleStoreList.length > 1) {
|
||||
stuffSearch.schSelSaleStoreId = otherSaleStoreId
|
||||
stuffSearch.schOtherSelSaleStoreId = ''
|
||||
stuffSearch.schOtherSelSaleStoreId = session.storeId
|
||||
setOtherSaleStoreId(session.storeId)
|
||||
} else {
|
||||
stuffSearch.schSelSaleStoreId = ''
|
||||
stuffSearch.schOtherSelSaleStoreId = session.storeId
|
||||
}
|
||||
} else {
|
||||
setMyDataCheck(false)
|
||||
@ -813,6 +886,30 @@ export default function StuffSearchCondition() {
|
||||
}
|
||||
}
|
||||
|
||||
const CustomOption = (props) => {
|
||||
const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
|
||||
const customClass = data.saleStoreId === 'T01' || data.priority !== 'B' ? 'special-option' : ''
|
||||
// 기본 선택/호버 상태 적용
|
||||
const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
|
||||
return (
|
||||
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
|
||||
{data.label}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const CustomOption2 = (props) => {
|
||||
const { data, innerRef, innerProps, isSelected, isFocused, isDisabled } = props
|
||||
const customClass = data.priority !== 'B' ? 'special-option' : ''
|
||||
// 기본 선택/호버 상태 적용
|
||||
const optionClass = `${customClass} ${isSelected ? 'custom__option--is-selected' : ''} ${isFocused ? 'custom__option--is-focused' : ''} ${isDisabled ? 'custom__option--is-disabled' : ''}`
|
||||
return (
|
||||
<div ref={innerRef} {...innerProps} className={`custom__option ${optionClass}`}>
|
||||
{data.label}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 퍼블적용시작 */}
|
||||
@ -822,12 +919,21 @@ export default function StuffSearchCondition() {
|
||||
<h3>{getMessage('stuff.search.title')}</h3>
|
||||
</div>
|
||||
<div className="left-unit-box">
|
||||
<Link href="/management/stuff/tempReg" scroll={false}>
|
||||
{/* <Link href="/management/stuff/tempdetail" scroll={false}> */}
|
||||
{/* <Link href="/management/stuff/tempReg" scroll={false}>
|
||||
<button type="button" className="btn-origin navy mr5">
|
||||
{getMessage('stuff.search.btn.register')}
|
||||
</button>
|
||||
</Link>
|
||||
</Link> */}
|
||||
<button
|
||||
type="button"
|
||||
className="btn-origin navy mr5"
|
||||
onClick={() => {
|
||||
setIsGlobalLoading(true)
|
||||
router.push(`/management/stuff/tempReg`, { scroll: false })
|
||||
}}
|
||||
>
|
||||
{getMessage('stuff.search.btn.register')}
|
||||
</button>
|
||||
<button type="button" className="btn-origin navy mr5" onClick={onSubmit}>
|
||||
{getMessage('stuff.search.btn.search')}
|
||||
</button>
|
||||
@ -1078,6 +1184,7 @@ export default function StuffSearchCondition() {
|
||||
})}
|
||||
isDisabled={session?.storeLvl !== '1' ? true : session?.storeId !== 'T01' ? true : false}
|
||||
isClearable={true}
|
||||
components={{ Option: CustomOption }}
|
||||
/>
|
||||
)}
|
||||
{session?.storeId !== 'T01' && session?.storeLvl === '1' && (
|
||||
@ -1162,6 +1269,7 @@ export default function StuffSearchCondition() {
|
||||
value={otherSaleStoreList.filter(function (option) {
|
||||
return option.saleStoreId === otherSaleStoreId
|
||||
})}
|
||||
components={{ Option: CustomOption2 }}
|
||||
/>
|
||||
</div>
|
||||
<div className="d-check-box light">
|
||||
|
||||
@ -40,8 +40,8 @@ export default function StuffSubHeader({ type }) {
|
||||
if (isObjectNotEmpty(managementState)) {
|
||||
if (managementState.createUser === 'T01') {
|
||||
if (session.userId !== 'T01') {
|
||||
//도면 작성은 이동 할 수 있도록 변경 #457
|
||||
// setButtonStyle('none')
|
||||
//도면 작성은 이동 할 수 있도록 변경 #457 다시 못하도록 변경#474
|
||||
setButtonStyle('none')
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,87 +66,85 @@ export default function StuffSubHeader({ type }) {
|
||||
}
|
||||
|
||||
return (
|
||||
!isGlobalLoading && (
|
||||
<>
|
||||
<div className="sub-header">
|
||||
<div className="sub-header-inner">
|
||||
{type === 'list' && (
|
||||
<>
|
||||
<Link href={'#'}>
|
||||
<h1 className="sub-header-title">{getMessage('header.menus.management')}</h1>
|
||||
</Link>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management.stuffList')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{type === 'temp' && (
|
||||
<>
|
||||
<ul className="sub-header-title-wrap">
|
||||
<li className="title-item">
|
||||
<Link className="sub-header-title" href={'#'}>
|
||||
{getMessage('stuff.temp.subTitle')}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management.newStuff')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{type === 'detail' && (
|
||||
<>
|
||||
<ul className="sub-header-title-wrap">
|
||||
<li className="title-item">
|
||||
<Link className="sub-header-title" href={'#'}>
|
||||
{getMessage('stuff.temp.subTitle')}
|
||||
</Link>
|
||||
</li>
|
||||
<li className="title-item" style={{ display: buttonStyle }}>
|
||||
<a className="sub-header-title" onClick={moveFloorPlan}>
|
||||
<span className="icon drawing"></span>
|
||||
{getMessage('stuff.temp.subTitle2')}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management.detail')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
<>
|
||||
<div className="sub-header">
|
||||
<div className="sub-header-inner">
|
||||
{type === 'list' && (
|
||||
<>
|
||||
<Link href={'#'}>
|
||||
<h1 className="sub-header-title">{getMessage('header.menus.management')}</h1>
|
||||
</Link>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management.stuffList')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{type === 'temp' && (
|
||||
<>
|
||||
<ul className="sub-header-title-wrap">
|
||||
<li className="title-item">
|
||||
<Link className="sub-header-title" href={'#'}>
|
||||
{getMessage('stuff.temp.subTitle')}
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management.newStuff')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
{type === 'detail' && (
|
||||
<>
|
||||
<ul className="sub-header-title-wrap">
|
||||
<li className="title-item">
|
||||
<Link className="sub-header-title" href={'#'}>
|
||||
{getMessage('stuff.temp.subTitle')}
|
||||
</Link>
|
||||
</li>
|
||||
<li className="title-item" style={{ display: buttonStyle }}>
|
||||
<a className="sub-header-title" onClick={moveFloorPlan}>
|
||||
<span className="icon drawing"></span>
|
||||
{getMessage('stuff.temp.subTitle2')}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul className="sub-header-location">
|
||||
<li className="location-item">
|
||||
<span className="home">
|
||||
<Image src="/static/images/main/home_icon.svg" alt="react" width={16} height={16} />
|
||||
</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management')}</span>
|
||||
</li>
|
||||
<li className="location-item">
|
||||
<span>{getMessage('header.menus.management.detail')}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -56,9 +56,6 @@ export default function FindAddressPop(props) {
|
||||
|
||||
//우편번호 검색
|
||||
const searchPostNum = () => {
|
||||
// //7830060
|
||||
// //9302226
|
||||
// //0790177 3개짜리
|
||||
const params = {
|
||||
zipcode: watch('zipNo'),
|
||||
}
|
||||
@ -122,6 +119,28 @@ export default function FindAddressPop(props) {
|
||||
}
|
||||
}
|
||||
|
||||
//그리드 더블클릭
|
||||
const getCellDoubleClicked = (event) => {
|
||||
setAddress1(event.data.address1)
|
||||
setAddress2(event.data.address2)
|
||||
setAddress3(event.data.address3)
|
||||
setPrefId(event.data.prefcode)
|
||||
setZipNo(event.data.zipcode)
|
||||
|
||||
if (event.data.prefcode == null) {
|
||||
return alert(getMessage('stuff.addressPopup.error.message2'))
|
||||
} else {
|
||||
props.zipInfo({
|
||||
zipNo: event.data.zipcode,
|
||||
address1: event.data.address1,
|
||||
address2: event.data.address2,
|
||||
address3: event.data.address3,
|
||||
prefId: event.data.prefcode,
|
||||
})
|
||||
}
|
||||
props.setShowAddressButtonValid(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal-popup">
|
||||
<div className="modal-dialog middle">
|
||||
@ -146,7 +165,7 @@ export default function FindAddressPop(props) {
|
||||
<button className="search-btn" onClick={searchPostNum}></button>
|
||||
</div>
|
||||
<div className="address-grid">
|
||||
<FindAddressPopQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} />
|
||||
<FindAddressPopQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} getCellDoubleClicked={getCellDoubleClicked} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-btn-wrap">
|
||||
|
||||
@ -48,6 +48,11 @@ export default function FindAddressPopGrid(props) {
|
||||
props.getSelectedRowdata(selectedData)
|
||||
}
|
||||
|
||||
//더블클릭
|
||||
const onCellDoubleClicked = useCallback((event) => {
|
||||
props.getCellDoubleClicked(event)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="ag-theme-quartz" style={{ height: 400 }}>
|
||||
<AgGridReact
|
||||
@ -58,6 +63,7 @@ export default function FindAddressPopGrid(props) {
|
||||
defaultColDef={defaultColDef}
|
||||
pagination={isPageable}
|
||||
onSelectionChanged={onSelectionChanged}
|
||||
onCellDoubleClicked={onCellDoubleClicked}
|
||||
overlayNoRowsTemplate={`<span className="ag-overlay-loading-center">${getMessage('stuff.grid.noData')}</span>`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -8,19 +8,12 @@ import SingleDatePicker from '@/components/common/datepicker/SingleDatePicker'
|
||||
import dayjs from 'dayjs'
|
||||
import PlanRequestPopQGrid from './PlanRequestPopQGrid'
|
||||
import { isObjectNotEmpty, queryStringFormatter } from '@/util/common-utils'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import Select from 'react-select'
|
||||
import QPagination from '@/components/common/pagination/QPagination'
|
||||
export default function PlanRequestPop(props) {
|
||||
const [pageNo, setPageNo] = useState(1) //현재 페이지 번호
|
||||
const [pageSize, setPageSize] = useState(20) //페이지 당 게시물 개수
|
||||
const [totalCount, setTotalCount] = useState(0) //총 갯수
|
||||
|
||||
//공통코드
|
||||
const { commonCode, findCommonCode } = useCommonCode()
|
||||
|
||||
// const [planStatCdList, setPlanStatCdList] = useState([])
|
||||
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
|
||||
const [planReqObject, setPlanReqObject] = useState({})
|
||||
@ -71,16 +64,6 @@ export default function PlanRequestPop(props) {
|
||||
}
|
||||
}
|
||||
|
||||
// 상태 검색조건 변경
|
||||
const onSelectionChange = (key) => {
|
||||
if (isObjectNotEmpty(key)) {
|
||||
setSchPlanStatCd(key.clCode)
|
||||
} else {
|
||||
//X누름
|
||||
setSchPlanStatCd('')
|
||||
}
|
||||
}
|
||||
|
||||
// 조회
|
||||
const onSubmit = (page, type) => {
|
||||
const params = {
|
||||
@ -194,7 +177,8 @@ export default function PlanRequestPop(props) {
|
||||
{
|
||||
field: 'title',
|
||||
headerName: getMessage('stuff.planReqPopup.gridHeader.title'),
|
||||
minWidth: 150,
|
||||
minWidth: 250,
|
||||
cellStyle: { textAlign: 'left' },
|
||||
},
|
||||
{
|
||||
field: 'address1',
|
||||
@ -234,13 +218,6 @@ export default function PlanRequestPop(props) {
|
||||
}
|
||||
}
|
||||
|
||||
// useEffect(() => {
|
||||
// const code1 = findCommonCode(115800) //상태
|
||||
// if (code1 != null) {
|
||||
// setPlanStatCdList(code1)
|
||||
// }
|
||||
// }, [commonCode])
|
||||
|
||||
useEffect(() => {
|
||||
onSubmit(pageNo, 'S')
|
||||
}, [])
|
||||
@ -266,6 +243,13 @@ export default function PlanRequestPop(props) {
|
||||
}
|
||||
}
|
||||
|
||||
// 더블클릭
|
||||
const getCellDoubleClicked = (event) => {
|
||||
setPlanReqObject(event.data)
|
||||
props.planReqInfo(event.data)
|
||||
props.setShowDesignRequestButtonValid(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="modal-popup">
|
||||
<div className="modal-dialog big">
|
||||
@ -431,9 +415,11 @@ export default function PlanRequestPop(props) {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<PlanRequestPopQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} />
|
||||
<div className="pagination-wrap">
|
||||
<QPagination pageNo={pageNo} pageSize={pageSize} pagePerBlock={10} totalCount={totalCount} handleChangePage={handleChangePage} />
|
||||
<div className="q-grid">
|
||||
<PlanRequestPopQGrid {...gridProps} getSelectedRowdata={getSelectedRowdata} getCellDoubleClicked={getCellDoubleClicked} />
|
||||
<div className="pagination-wrap">
|
||||
<QPagination pageNo={pageNo} pageSize={pageSize} pagePerBlock={10} totalCount={totalCount} handleChangePage={handleChangePage} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -22,8 +22,8 @@ export default function PlanRequestPopQGrid(props) {
|
||||
flex: 1,
|
||||
minWidth: 100,
|
||||
sortable: false,
|
||||
suppressMovable: false,
|
||||
resizable: false,
|
||||
suppressMovable: true,
|
||||
resizable: true,
|
||||
suppressSizeToFit: false,
|
||||
}
|
||||
}, [])
|
||||
@ -48,6 +48,11 @@ export default function PlanRequestPopQGrid(props) {
|
||||
props.getSelectedRowdata(selectedData)
|
||||
}
|
||||
|
||||
// 그리드 더블클릭
|
||||
const onCellDoubleClicked = useCallback((event) => {
|
||||
props.getCellDoubleClicked(event)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="ag-theme-quartz" style={{ height: 350 }}>
|
||||
<AgGridReact
|
||||
@ -58,6 +63,8 @@ export default function PlanRequestPopQGrid(props) {
|
||||
defaultColDef={defaultColDef}
|
||||
pagination={isPageable}
|
||||
onSelectionChanged={onSelectionChanged}
|
||||
onCellDoubleClicked={onCellDoubleClicked}
|
||||
autoSizeAllColumns={true}
|
||||
overlayNoRowsTemplate={`<span className="ag-overlay-loading-center">${getMessage('stuff.grid.noData')}</span>`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -39,7 +39,6 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
|
||||
|
||||
if (resultData) {
|
||||
setInfo(resultData)
|
||||
setPassword(resultData.password)
|
||||
} else {
|
||||
alert(getMessage('common.message.no.data'))
|
||||
}
|
||||
@ -236,7 +235,7 @@ export default function UserInfoModal({ userId, userInfoModal, setUserInfoModal
|
||||
<th>{getMessage('myinfo.info.category')}</th>
|
||||
<td>
|
||||
<div className="input-wrap">
|
||||
<input type="text" className="input-light" value={info?.groupName || ''} readOnly />
|
||||
<input type="text" className="input-light" value={info?.category || ''} readOnly />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@ -16,26 +16,23 @@ import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||
|
||||
import { convertNumberToPriceDecimal } from '@/util/common-utils'
|
||||
import { usePlan } from '@/hooks/usePlan'
|
||||
import { usePopup } from '@/hooks/usePopup'
|
||||
// import { useSearchParams } from 'next/navigation'
|
||||
import { usePopup, closeAll } from '@/hooks/usePopup'
|
||||
|
||||
import { QcastContext } from '@/app/QcastProvider'
|
||||
|
||||
export default function Simulator() {
|
||||
// global 로딩바
|
||||
const { setIsGlobalLoading } = useContext(QcastContext)
|
||||
|
||||
const { floorPlanState } = useContext(FloorPlanContext)
|
||||
const { objectNo, pid } = floorPlanState
|
||||
|
||||
// const searchParams = useSearchParams()
|
||||
// const objectNo = searchParams.get('objectNo')
|
||||
// const pid = searchParams.get('pid')
|
||||
const { selectedPlan } = usePlan()
|
||||
|
||||
const chartRef = useRef(null)
|
||||
|
||||
// 캔버스 메뉴 넘버 셋팅
|
||||
const { setMenuNumber } = useCanvasMenu()
|
||||
|
||||
useEffect(() => {
|
||||
setMenuNumber(6)
|
||||
}, [])
|
||||
const { closeAll } = usePopup()
|
||||
|
||||
const { get } = useAxios()
|
||||
const { getMessage } = useMessage()
|
||||
@ -43,12 +40,6 @@ export default function Simulator() {
|
||||
// 차트 관련
|
||||
const [chartData, setChartData] = useState([])
|
||||
|
||||
const { closeAll } = usePopup()
|
||||
|
||||
useEffect(() => {
|
||||
closeAll()
|
||||
}, [])
|
||||
|
||||
const data = {
|
||||
labels: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
datasets: [
|
||||
@ -114,7 +105,6 @@ export default function Simulator() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ useEffect ~ selectedPlan:', selectedPlan)
|
||||
/* 초기화 작업 */
|
||||
setChartData([])
|
||||
setObjectDetail({})
|
||||
@ -125,11 +115,13 @@ export default function Simulator() {
|
||||
setHatsudenryouPeakcutAll([])
|
||||
setHatsudenryouPeakcutAllSnow([])
|
||||
|
||||
if (objectNo) {
|
||||
fetchObjectDetail(objectNo)
|
||||
if (objectNo && pid && selectedPlan) {
|
||||
fetchObjectDetail(objectNo, selectedPlan.planNo)
|
||||
fetchSimulatorNotice()
|
||||
setPwrGnrSimType('D')
|
||||
setPwrRecoil({ ...pwrRecoil, type: 'D' })
|
||||
setMenuNumber(6)
|
||||
closeAll()
|
||||
}
|
||||
}, [objectNo, pid, selectedPlan])
|
||||
|
||||
@ -148,10 +140,13 @@ export default function Simulator() {
|
||||
const [hatsudenryouPeakcutAll, setHatsudenryouPeakcutAll] = useState([])
|
||||
const [hatsudenryouPeakcutAllSnow, setHatsudenryouPeakcutAllSnow] = useState([])
|
||||
|
||||
const fetchObjectDetail = async (objectNo) => {
|
||||
const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${pid}`
|
||||
const fetchObjectDetail = async (objectNo, currentPid) => {
|
||||
setIsGlobalLoading(true)
|
||||
|
||||
const apiUrl = `/api/pwrGnrSimulation/calculations?objectNo=${objectNo}&planNo=${currentPid}`
|
||||
|
||||
const resultData = await get({ url: apiUrl })
|
||||
|
||||
if (resultData) {
|
||||
setObjectDetail(resultData)
|
||||
if (resultData.hatsudenryouAll) {
|
||||
@ -174,12 +169,14 @@ export default function Simulator() {
|
||||
setModuleInfoList(resultData.roofModuleList)
|
||||
}
|
||||
}
|
||||
setIsGlobalLoading(false)
|
||||
}
|
||||
|
||||
// 시뮬레이션 안내사항 조회
|
||||
const [content, setContent] = useState('')
|
||||
|
||||
const fetchSimulatorNotice = async () => {
|
||||
setIsGlobalLoading(true)
|
||||
get({ url: '/api/pwrGnrSimulation/guideInfo' }).then((res) => {
|
||||
if (res.data) {
|
||||
setContent(res.data.replaceAll('\n', '<br/>'))
|
||||
@ -187,6 +184,7 @@ export default function Simulator() {
|
||||
setContent(getMessage('common.message.no.data'))
|
||||
}
|
||||
})
|
||||
setIsGlobalLoading(false)
|
||||
}
|
||||
|
||||
// 차트 데이터 변경 시, list type 셋팅
|
||||
@ -257,7 +255,7 @@ export default function Simulator() {
|
||||
{/* 적설조건 */}
|
||||
<div className="estimate-box">
|
||||
<div className="estimate-tit">{getMessage('simulator.title.sub7')}</div>
|
||||
<div className="estimate-name">{objectDetail.snowfall} cm</div>
|
||||
<div className="estimate-name">{objectDetail.snowfall ? `${objectDetail.snowfall}cm` : ''} </div>
|
||||
</div>
|
||||
{/* 풍속조건 */}
|
||||
<div className="estimate-box">
|
||||
@ -356,7 +354,10 @@ export default function Simulator() {
|
||||
{/* 지붕면 */}
|
||||
<td>{moduleInfo.roofSurface}</td>
|
||||
{/* 경사각 */}
|
||||
<td>{convertNumberToPriceDecimal(moduleInfo.slopeAngle)}{moduleInfo.classType == 0 ? "寸":"º"}</td>
|
||||
<td>
|
||||
{convertNumberToPriceDecimal(moduleInfo.slopeAngle)}
|
||||
{moduleInfo.classType == 0 ? '寸' : 'º'}
|
||||
</td>
|
||||
{/* 방위각(도) */}
|
||||
<td>{convertNumberToPriceDecimal(moduleInfo.azimuth)}</td>
|
||||
{/* 태양전지모듈 */}
|
||||
|
||||
@ -1,28 +1,90 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect } from 'react'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import useSWR from 'swr'
|
||||
import useSWRMutation from 'swr/mutation'
|
||||
import { useAxios } from '../useAxios'
|
||||
import { useRecoilState } from 'recoil'
|
||||
import { canvasPopupStatusStore } from '@/store/canvasPopupStatusAtom'
|
||||
import { unescapeString } from '@/util/common-utils'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { compasDegAtom } from '@/store/orientationAtom'
|
||||
import { currentCanvasPlanState } from '@/store/canvasAtom'
|
||||
|
||||
export function useCanvasPopupStatusController(popupType) {
|
||||
const [canvasPopupStatusState, setCanvasPopupStatusState] = useRecoilState(canvasPopupStatusStore)
|
||||
export function useCanvasPopupStatusController(param = 1) {
|
||||
const popupType = parseInt(param)
|
||||
|
||||
const [compasDeg, setCompasDeg] = useRecoilState(compasDegAtom)
|
||||
const [moduleSelectionDataStore, setModuleSelectionDataStore] = useRecoilState(moduleSelectionDataState)
|
||||
const { getFetcher, postFetcher } = useAxios()
|
||||
|
||||
const currentCanvasPlan = useRecoilValue(currentCanvasPlanState)
|
||||
// console.log('🚀 ~ Orientation ~ currentCanvasPlan:', currentCanvasPlan)
|
||||
|
||||
const {
|
||||
data: popupStatus,
|
||||
error,
|
||||
isLoading,
|
||||
} = useSWR(popupType ? 'canvas-popup-status--data' : null, () => getFetcher(`http://localhost:8080/api/tutorial?popupType=${popupType}`))
|
||||
} = useSWR(
|
||||
popupType ? `/api/v1/canvas-popup-status?objectNo=${currentCanvasPlan.objectNo}&planNo=${currentCanvasPlan.planNo}&popupType=${popupType}` : null,
|
||||
getFetcher,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('🚀 ~ useEffect ~ popupStatus:', popupStatus)
|
||||
if (popupStatus) {
|
||||
setCanvasPopupStatusState({ ...canvasPopupStatusState, [popupType]: popupStatus })
|
||||
switch (parseInt(popupStatus?.popupType)) {
|
||||
case 1:
|
||||
setCompasDeg(popupStatus.popupStatus)
|
||||
break
|
||||
case 2:
|
||||
setModuleSelectionDataStore(JSON.parse(unescapeString(popupStatus.popupStatus)))
|
||||
break
|
||||
case 3:
|
||||
break
|
||||
case 4:
|
||||
break
|
||||
case 5:
|
||||
break
|
||||
case 6:
|
||||
break
|
||||
default:
|
||||
}
|
||||
} else {
|
||||
switch (popupType) {
|
||||
case 1:
|
||||
setCompasDeg(0)
|
||||
break
|
||||
case 2:
|
||||
setModuleSelectionDataStore({
|
||||
common: {},
|
||||
roofConstructions: [],
|
||||
})
|
||||
break
|
||||
case 3:
|
||||
break
|
||||
case 4:
|
||||
break
|
||||
case 5:
|
||||
break
|
||||
case 6:
|
||||
break
|
||||
default:
|
||||
}
|
||||
}
|
||||
}, [popupStatus])
|
||||
|
||||
const { trigger, isMutating } = useSWRMutation('canvas-popup-status-update', postFetcher)
|
||||
const { trigger, isMutating } = useSWRMutation(
|
||||
`/api/v1/canvas-popup-status?objectNo=${currentCanvasPlan.objectNo}&planNo=${currentCanvasPlan.planNo}&popupType=${popupType}`,
|
||||
(url, { arg }) => {
|
||||
const params = {
|
||||
objectNo: currentCanvasPlan.objectNo,
|
||||
planNo: parseInt(currentCanvasPlan.planNo),
|
||||
popupType: popupType.toString(),
|
||||
popupStatus: popupType === 1 ? arg : JSON.stringify(arg).replace(/"/g, '\"'),
|
||||
}
|
||||
postFetcher(`/api/v1/canvas-popup-status`, params)
|
||||
},
|
||||
)
|
||||
|
||||
return { trigger }
|
||||
}
|
||||
|
||||
@ -523,10 +523,26 @@ export function useCommonUtils() {
|
||||
if (object) {
|
||||
canvas?.remove(object)
|
||||
|
||||
// if (object.id) {
|
||||
// const group = canvas.getObjects().filter((obj) => obj.id === object.id)
|
||||
// group.forEach((obj) => canvas?.remove(obj))
|
||||
// }
|
||||
if (object.id) {
|
||||
const group = canvas.getObjects().filter((obj) => obj.id === object.id)
|
||||
group.forEach((obj) => canvas?.remove(obj))
|
||||
}
|
||||
|
||||
if (object.type === 'group') {
|
||||
object._objects.forEach((obj) => {
|
||||
if (obj.hasOwnProperty('texts')) {
|
||||
obj.texts.forEach((text) => {
|
||||
canvas?.remove(text)
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
if (object.hasOwnProperty('texts')) {
|
||||
object.texts.forEach((text) => {
|
||||
canvas?.remove(text)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -609,6 +625,21 @@ export function useCommonUtils() {
|
||||
commonDeleteText(obj)
|
||||
})
|
||||
}
|
||||
|
||||
selectedObj.forEach((obj) => {
|
||||
if (obj.type === 'group') {
|
||||
obj._objects.forEach((lines) => {
|
||||
if (lines.hasOwnProperty('arrow')) {
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((obj1) => obj1.name === 'arrow' && lines.id === obj1.parentId)
|
||||
.forEach((arrow) => {
|
||||
canvas?.remove(arrow)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const moveObject = () => {
|
||||
|
||||
@ -4,6 +4,8 @@ import { useSwal } from '@/hooks/useSwal'
|
||||
import { getQueryString } from '@/util/common-utils'
|
||||
import { trestleRequest, constructionRequest, trestleDetailRequest } from '@/models/apiModels'
|
||||
import { POST } from '@/app/api/image-upload/route'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
|
||||
/**
|
||||
* 마스터 컨트롤러 훅
|
||||
@ -54,9 +56,9 @@ export function useMasterController() {
|
||||
*/
|
||||
const getTrestleList = async (params) => {
|
||||
const paramString = getQueryString(params)
|
||||
console.log('🚀🚀 ~ getTrestleList ~ paramString:', paramString)
|
||||
// console.log('🚀🚀 ~ getTrestleList ~ paramString:', paramString)
|
||||
return await get({ url: '/api/v1/master/getTrestleList' + paramString }).then((res) => {
|
||||
console.log('🚀🚀 ~ getTrestleList ~ res:', res)
|
||||
// console.log('🚀🚀 ~ getTrestleList ~ res:', res)
|
||||
return res
|
||||
})
|
||||
}
|
||||
@ -80,9 +82,9 @@ export function useMasterController() {
|
||||
*/
|
||||
const getConstructionList = async (params) => {
|
||||
const paramString = getQueryString(params)
|
||||
console.log('🚀🚀 ~ getConstructionList ~ paramString:', paramString)
|
||||
// console.log('🚀🚀 ~ getConstructionList ~ paramString:', paramString)
|
||||
return await get({ url: '/api/v1/master/getConstructionList' + paramString }).then((res) => {
|
||||
console.log('🚀🚀 ~ getConstructionList ~ res:', res)
|
||||
// console.log('🚀🚀 ~ getConstructionList ~ res:', res)
|
||||
return res
|
||||
})
|
||||
}
|
||||
@ -128,18 +130,88 @@ export function useMasterController() {
|
||||
}
|
||||
|
||||
/**
|
||||
* PCS 메이커, 시리즈 목록 조회
|
||||
* @param {PCS 메이커코드} pcsMkrCd
|
||||
* @param {혼합모듈번호} mixMatlNo
|
||||
* 모듈 타입별 아이템 목록 조회
|
||||
* @param {PCS 메이커코드} pcsMkrCd
|
||||
* @param {PCS시리즈코드 목록} pcsSerList
|
||||
* @param {모듈아이템 ID 목록} moduleItemList
|
||||
* @returns
|
||||
*/
|
||||
const getPcsModelList = async (params = null) => {
|
||||
const test = {
|
||||
pcsMkrCd: 'MKR003',
|
||||
pcsSerList: [{ pcsSerCd: 'SER007' }, { pcsSerCd: 'SER009' }, { pcsSerCd: 'SER010' }],
|
||||
moduleItemList: [{ itemId: '107015', mixMatlNo: '' }, { itemId: '107077' }, { itemId: '107015' }],
|
||||
moduleItemList: [
|
||||
{ itemId: '107015', mixMatlNo: null },
|
||||
{ itemId: '107077', mixMatlNo: null },
|
||||
{ itemId: '107015', mixMatlNo: null },
|
||||
],
|
||||
}
|
||||
return await post({ url: '/api/v1/master/getPcsSeriesItemList', data: test }).then((res) => {
|
||||
|
||||
return await post({ url: '/api/v1/master/getPcsSeriesItemList', data: params }).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 시리즈중 자동으로 추천 PCS 정보 조회
|
||||
* @param {Max접속(과적)여부} maxConnYn
|
||||
* @param {동일회로도여부} smpCirYn
|
||||
* @param {한랭지여부} coldZoneYn
|
||||
* @param {사용된 모듈 아이템 List} useModuleItemList
|
||||
* @param {지붕면별 목록} roofSurfaceList
|
||||
* @param {PCS 제품 목록} pcsItemList
|
||||
* @returns
|
||||
*/
|
||||
const getPcsAutoRecommendList = async (params = null) => {
|
||||
return await post({ url: '/api/v1/master/getPcsAutoRecommendList', data: params }).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
const getPcsManualConfChk = async (params = null) => {
|
||||
return await post({ url: '/api/v1/master/getPcsMenualConfChk', data: params }).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* PCS로 회로 구성 가능 여부 체크
|
||||
* @param {Max접속(과적)여부} maxConnYn
|
||||
* @param {동일회로도여부} smpCirYn
|
||||
* @param {한랭지여부} coldZoneYn
|
||||
* @param {사용된 모듈 아이템 List} useModuleItemList
|
||||
* @param {지붕면별 목록} roofSurfaceList
|
||||
* @param {PCS 제품 목록} pcsItemList
|
||||
* @returns
|
||||
*/
|
||||
const getPcsVoltageChk = async (params = null) => {
|
||||
return await post({ url: '/api/v1/master/getPcsVoltageChk', data: params }).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* PCS 승압설정 정보 조회
|
||||
* @param {Max접속(과적)여부} maxConnYn
|
||||
* @param {동일회로도여부} smpCirYn
|
||||
* @param {한랭지여부} coldZoneYn
|
||||
* @param {사용된 모듈아이템 목록} useModuleItemList
|
||||
* @param {지붕면 목록} roofSurfaceList
|
||||
* @param {PCS 아이템 목록} pcsItemList
|
||||
|
||||
* @returns
|
||||
*/
|
||||
const getPcsVoltageStepUpList = async (params2 = null) => {
|
||||
const params = {
|
||||
...params2,
|
||||
maxConnYn: params2.useYn.maxConnYn,
|
||||
smpCirYn: params2.useYn.smpCirYn,
|
||||
coldZoneYn: params2.useYn.coldZoneYn,
|
||||
useModuleItemList: params2.useModuleItemList,
|
||||
roofSurfaceList: params2.roofSurfaceList,
|
||||
pcsItemList: params2.pcsItemList,
|
||||
}
|
||||
|
||||
return await post({ url: '/api/v1/master/getPcsVoltageStepUpList', data: params }).then((res) => {
|
||||
return res
|
||||
})
|
||||
}
|
||||
@ -152,5 +224,9 @@ export function useMasterController() {
|
||||
getTrestleDetailList,
|
||||
getPcsMakerList,
|
||||
getPcsModelList,
|
||||
getPcsAutoRecommendList,
|
||||
getPcsVoltageChk,
|
||||
getPcsManualConfChk,
|
||||
getPcsVoltageStepUpList,
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,15 +20,24 @@ export function useRoofFn() {
|
||||
const { addPitchText } = useLine()
|
||||
|
||||
//면형상 선택 클릭시 지붕 패턴 입히기
|
||||
function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false, roofMaterial = selectedRoofMaterial) {
|
||||
function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false, roofMaterial = selectedRoofMaterial, isForceChange = false) {
|
||||
if (!polygon) {
|
||||
return
|
||||
}
|
||||
if (isForceChange) {
|
||||
if (polygon.roofMaterial) {
|
||||
polygon.roofMaterial = null
|
||||
}
|
||||
}
|
||||
|
||||
if (polygon.roofMaterial) {
|
||||
return
|
||||
}
|
||||
const ratio = window.devicePixelRatio || 1
|
||||
const layout = roofMaterial.layout
|
||||
|
||||
let width = (roofMaterial.width ?? 226) / 10
|
||||
let height = (roofMaterial.length ?? 158) / 10
|
||||
let width = (roofMaterial.width || 226) / 10
|
||||
let height = (roofMaterial.length || 158) / 10
|
||||
const index = roofMaterial.index ?? 0
|
||||
let roofStyle = 2
|
||||
const inputPatternSize = { width: width, height: height } //임시 사이즈
|
||||
|
||||
@ -80,6 +80,7 @@ export const useEstimateController = (planNo) => {
|
||||
|
||||
res.data.pkgAsp = roundedNumber.toString()
|
||||
}
|
||||
|
||||
setEstimateContextState(res.data)
|
||||
}
|
||||
}
|
||||
@ -384,7 +385,7 @@ export const useEstimateController = (planNo) => {
|
||||
if (res.status === 201) {
|
||||
estimateData.newFileList = []
|
||||
swalFire({ text: getMessage('estimate.detail.save.alertMsg'), type: 'alert' })
|
||||
fetchSetting(objectRecoil.floorPlanObjectNo, estimateData.planNo)
|
||||
fetchSetting(estimateData.objectNo, estimateData.planNo)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
@ -409,7 +410,7 @@ export const useEstimateController = (planNo) => {
|
||||
const params = {
|
||||
saleStoreId: session.storeId,
|
||||
sapSalesStoreCd: session.custCd,
|
||||
objectNo: objectRecoil.floorPlanObjectNo,
|
||||
objectNo: estimateData.objectNo,
|
||||
planNo: sendPlanNo,
|
||||
copySaleStoreId: otherSaleStoreId ? otherSaleStoreId : saleStoreId,
|
||||
copyReceiveUser: copyReceiveUser,
|
||||
|
||||
@ -389,6 +389,7 @@ export function useModule() {
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.id === activeModule.surfaceId)[0]
|
||||
let isWarning = false
|
||||
canvas.discardActiveObject()
|
||||
moduleSetupSurface.set({ modules: otherModules })
|
||||
canvas.remove(...columnModules)
|
||||
canvas.renderAll()
|
||||
|
||||
@ -503,6 +504,7 @@ export function useModule() {
|
||||
let isWarning = false
|
||||
|
||||
canvas.discardActiveObject()
|
||||
moduleSetupSurface.set({ modules: otherModules })
|
||||
canvas.remove(...rowModules)
|
||||
canvas.renderAll()
|
||||
|
||||
@ -852,8 +854,12 @@ export function useModule() {
|
||||
|
||||
const modulesRemove = () => {
|
||||
const activeModule = canvas.getObjects().filter((obj) => canvas.getActiveObjects()[0].id === obj.id)[0]
|
||||
const modules = canvas.getObjects().filter((obj) => obj.surfaceId === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE)
|
||||
canvas.remove(...modules)
|
||||
const modules = canvas
|
||||
.getObjects()
|
||||
.filter((obj) => obj.surfaceId === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE && activeModule.id !== obj.id)
|
||||
const surface = canvas.getObjects().filter((obj) => obj.id === activeModule.surfaceId && obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)[0]
|
||||
surface.set({ modules: modules })
|
||||
canvas.remove(activeModule)
|
||||
canvas.renderAll()
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom'
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import { canvasSettingState, canvasState, checkedModuleState, isManualModuleSetupState, selectedModuleState } from '@/store/canvasAtom'
|
||||
import { rectToPolygon, polygonToTurfPolygon, calculateVisibleModuleHeight, getDegreeByChon } from '@/util/canvas-util'
|
||||
import { basicSettingState, roofDisplaySelector } from '@/store/settingAtom'
|
||||
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
|
||||
@ -8,14 +8,13 @@ import { moduleSetupSurfaceState, moduleIsSetupState } from '@/store/canvasAtom'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { POLYGON_TYPE, BATCH_TYPE } from '@/common/common'
|
||||
import * as turf from '@turf/turf'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { canvasSettingState } from '@/store/canvasAtom'
|
||||
import { compasDegAtom } from '@/store/orientationAtom'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||
import { useEffect } from 'react'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { moduleStatisticsState } from '@/store/circuitTrestleAtom'
|
||||
|
||||
export function useModuleBasicSetting() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
@ -23,14 +22,17 @@ export function useModuleBasicSetting() {
|
||||
const roofDisplay = useRecoilValue(roofDisplaySelector)
|
||||
const [moduleSetupSurface, setModuleSetupSurface] = useRecoilState(moduleSetupSurfaceState)
|
||||
const [moduleIsSetup, setModuleIsSetup] = useRecoilState(moduleIsSetupState)
|
||||
const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent()
|
||||
const { addCanvasMouseEventListener, initEvent, removeMouseEvent } = useEvent()
|
||||
const { swalFire } = useSwal()
|
||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||
|
||||
const compasDeg = useRecoilValue(compasDegAtom)
|
||||
const { setSurfaceShapePattern } = useRoofFn()
|
||||
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
|
||||
const checkedModule = useRecoilValue(checkedModuleState)
|
||||
const [isManualModuleSetup, setIsManualModuleSetup] = useRecoilState(isManualModuleSetupState)
|
||||
const setModuleStatistics = useSetRecoilState(moduleStatisticsState)
|
||||
|
||||
const canvasSetting = useRecoilValue(canvasSettingState)
|
||||
|
||||
useEffect(() => {
|
||||
// console.log('basicSetting', basicSetting)
|
||||
@ -44,7 +46,6 @@ export function useModuleBasicSetting() {
|
||||
}, [])
|
||||
|
||||
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
|
||||
let selectedModuleInstSurfaceArray = []
|
||||
|
||||
//모듈,회로에서 다른메뉴 -> 배치면으로 갈 경수 초기화
|
||||
const restoreModuleInstArea = () => {
|
||||
@ -69,104 +70,6 @@ export function useModuleBasicSetting() {
|
||||
})
|
||||
}
|
||||
|
||||
const makeModuleInstArea = () => {
|
||||
//지붕 객체 반환
|
||||
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
|
||||
let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : -20
|
||||
|
||||
if (!roofs) {
|
||||
return
|
||||
}
|
||||
|
||||
roofs.forEach((roof) => {
|
||||
const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
|
||||
if (isExistSurface) {
|
||||
return
|
||||
}
|
||||
|
||||
setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
|
||||
const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
|
||||
//모듈설치영역?? 생성
|
||||
|
||||
const surfaceId = uuidv4()
|
||||
|
||||
let setupSurface = new QPolygon(offsetPoints, {
|
||||
stroke: 'red',
|
||||
fill: 'transparent',
|
||||
strokeDashArray: [10, 4],
|
||||
strokeWidth: 1,
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
selectable: true,
|
||||
parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌
|
||||
name: POLYGON_TYPE.MODULE_SETUP_SURFACE,
|
||||
flowDirection: roof.direction,
|
||||
direction: roof.direction,
|
||||
flipX: roof.flipX,
|
||||
flipY: roof.flipY,
|
||||
surfaceId: surfaceId,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
modules: [],
|
||||
roofMaterial: roof.roofMaterial,
|
||||
// angle: -compasDeg,
|
||||
})
|
||||
|
||||
setupSurface.setViewLengthText(false)
|
||||
canvas.add(setupSurface) //모듈설치면 만들기
|
||||
|
||||
//지붕면 선택 금지
|
||||
roof.set({
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
//모듈설치면 클릭이벤트
|
||||
addTargetMouseEventListener('mousedown', setupSurface, function () {
|
||||
toggleSelection(setupSurface)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
//설치 범위 지정 클릭 이벤트
|
||||
const toggleSelection = (setupSurface) => {
|
||||
const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
|
||||
//최초 선택일때
|
||||
if (!isExist) {
|
||||
//기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
|
||||
setupSurface.set({
|
||||
...setupSurface,
|
||||
strokeWidth: 3,
|
||||
strokeDashArray: [0],
|
||||
fill: 'transparent',
|
||||
})
|
||||
canvas.discardActiveObject() // 객체의 활성 상태 해제
|
||||
//중복으로 들어가는걸 방지하기 위한 코드
|
||||
|
||||
canvas?.renderAll()
|
||||
selectedModuleInstSurfaceArray.push(setupSurface)
|
||||
} else {
|
||||
//선택후 재선택하면 선택안됨으로 변경
|
||||
setupSurface.set({
|
||||
...setupSurface,
|
||||
fill: 'transparent',
|
||||
strokeDashArray: [10, 4],
|
||||
strokeWidth: 1,
|
||||
})
|
||||
canvas.discardActiveObject() // 객체의 활성 상태 해제
|
||||
|
||||
//폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
|
||||
const removeIndex = setupSurface.parentId
|
||||
const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex)
|
||||
selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1)
|
||||
}
|
||||
|
||||
canvas?.renderAll()
|
||||
setModuleSetupSurface([...selectedModuleInstSurfaceArray])
|
||||
}
|
||||
|
||||
/**
|
||||
* trestle에서 영역을 가져와 mouse:move 이벤트로 해당 영역에 진입했을때 booleanPointInPolygon 로 진입여부를 확인
|
||||
* 확인 후 셀을 이동시킴
|
||||
@ -188,15 +91,7 @@ export function useModuleBasicSetting() {
|
||||
}
|
||||
|
||||
const moduleSetupSurfaces = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) //모듈설치면를 가져옴
|
||||
const batchObjects = canvas
|
||||
?.getObjects()
|
||||
.filter(
|
||||
(obj) =>
|
||||
obj.name === BATCH_TYPE.OPENING ||
|
||||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||
obj.name === BATCH_TYPE.PENTAGON_DORMER ||
|
||||
obj.name === BATCH_TYPE.SHADOW,
|
||||
) //도머s 객체
|
||||
const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체
|
||||
|
||||
const moduleOptions = {
|
||||
fill: checkedModule[0].color,
|
||||
@ -447,17 +342,7 @@ export function useModuleBasicSetting() {
|
||||
//도머 객체를 가져옴
|
||||
if (batchObjects) {
|
||||
batchObjects.forEach((object) => {
|
||||
let dormerTurfPolygon
|
||||
|
||||
if (object.type === 'group') {
|
||||
//도머는 그룹형태임
|
||||
dormerTurfPolygon = batchObjectGroupToTurfPolygon(object)
|
||||
} else {
|
||||
//개구, 그림자
|
||||
object.set({ points: rectToPolygon(object) })
|
||||
dormerTurfPolygon = polygonToTurfPolygon(object)
|
||||
}
|
||||
|
||||
let dormerTurfPolygon = polygonToTurfPolygon(object, true)
|
||||
const intersection = turf.intersect(turf.featureCollection([dormerTurfPolygon, tempTurfModule])) //겹치는지 확인
|
||||
//겹치면 안됨
|
||||
if (intersection) {
|
||||
@ -479,9 +364,11 @@ export function useModuleBasicSetting() {
|
||||
//안겹치면 넣는다
|
||||
// tempModule.setCoords()
|
||||
moduleOptions.surfaceId = trestlePolygon.id
|
||||
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions })
|
||||
|
||||
let manualModule = new QPolygon(tempModule.points, { ...moduleOptions, moduleInfo: checkedModule[0] })
|
||||
canvas?.add(manualModule)
|
||||
manualDrawModules.push(manualModule)
|
||||
getModuleStatistics()
|
||||
} else {
|
||||
swalFire({ text: getMessage('module.place.overlab') })
|
||||
}
|
||||
@ -516,15 +403,7 @@ export function useModuleBasicSetting() {
|
||||
?.getObjects()
|
||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && !moduleSetupSurfaces.includes(obj)) //설치면이 아닌것
|
||||
|
||||
const batchObjects = canvas
|
||||
?.getObjects()
|
||||
.filter(
|
||||
(obj) =>
|
||||
obj.name === BATCH_TYPE.OPENING ||
|
||||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||
obj.name === BATCH_TYPE.PENTAGON_DORMER ||
|
||||
obj.name === BATCH_TYPE.SHADOW,
|
||||
) //도머s 객체
|
||||
const batchObjects = canvas?.getObjects().filter((obj) => obj.name === POLYGON_TYPE.OBJECT_SURFACE) //도머s 객체
|
||||
|
||||
if (moduleSetupSurfaces.length === 0) {
|
||||
swalFire({ text: getMessage('module.place.no.surface') })
|
||||
@ -578,18 +457,7 @@ export function useModuleBasicSetting() {
|
||||
const objectsIncludeSurface = (turfModuleSetupSurface) => {
|
||||
let containsBatchObjects = []
|
||||
containsBatchObjects = batchObjects.filter((batchObject) => {
|
||||
let convertBatchObject
|
||||
|
||||
if (batchObject.type === 'group') {
|
||||
//도머는 그룹형태임
|
||||
convertBatchObject = batchObjectGroupToTurfPolygon(batchObject)
|
||||
} else {
|
||||
//개구, 그림자
|
||||
batchObject.set({ points: rectToPolygon(batchObject) })
|
||||
canvas?.renderAll() // set된걸 바로 적용하기 위해
|
||||
convertBatchObject = polygonToTurfPolygon(batchObject) //rect를 폴리곤으로 변환 -> turf 폴리곤으로 변환
|
||||
}
|
||||
|
||||
let convertBatchObject = polygonToTurfPolygon(batchObject)
|
||||
// 폴리곤 안에 도머 폴리곤이 포함되어있는지 확인해서 반환하는 로직
|
||||
return turf.booleanContains(turfModuleSetupSurface, convertBatchObject) || turf.booleanWithin(convertBatchObject, turfModuleSetupSurface)
|
||||
})
|
||||
@ -697,6 +565,7 @@ export function useModuleBasicSetting() {
|
||||
|
||||
checkedModule.forEach((module, index) => {
|
||||
const { width, height } = getModuleWidthHeight(maxLengthLine, moduleSetupSurface, module)
|
||||
|
||||
const flowLines = getFlowLines(moduleSetupSurface, module)
|
||||
//육지붕이 아닐때만 넣는다 육지붕일땐 클릭 이벤트에 별도로 넣어놓음
|
||||
let startPoint = flowLines.bottom
|
||||
@ -746,8 +615,8 @@ export function useModuleBasicSetting() {
|
||||
for (let i = 0; i <= totalWidth; i++) {
|
||||
leftMargin = i === 0 ? 0 : intvHor * i
|
||||
chidoriLength = 0
|
||||
if (isChidori) {
|
||||
chidoriLength = j % 2 === 0 ? 0 : width / 2
|
||||
if (isChidori && !isMaxSetup) {
|
||||
chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
|
||||
}
|
||||
|
||||
square = [
|
||||
@ -762,7 +631,7 @@ export function useModuleBasicSetting() {
|
||||
let turfCoordnates = squarePolygon.geometry.coordinates[0].slice(0, -1)
|
||||
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
|
||||
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
|
||||
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
|
||||
|
||||
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
|
||||
@ -847,7 +716,7 @@ export function useModuleBasicSetting() {
|
||||
for (let j = 0; j < totalHeight; j++) {
|
||||
leftMargin = j === 0 ? 0 : intvVer * j
|
||||
chidoriLength = 0
|
||||
if (isChidori) {
|
||||
if (isChidori && !isMaxSetup) {
|
||||
chidoriLength = i % 2 === 0 ? 0 : height / 2
|
||||
}
|
||||
|
||||
@ -864,7 +733,7 @@ export function useModuleBasicSetting() {
|
||||
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
|
||||
|
||||
// if (disjointFromTrestle && isDisjoint) {
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
|
||||
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
|
||||
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
|
||||
let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects)
|
||||
@ -958,8 +827,8 @@ export function useModuleBasicSetting() {
|
||||
for (let i = 0; i < diffRightEndPoint; i++) {
|
||||
leftMargin = i === 0 ? 0 : intvHor * i
|
||||
chidoriLength = 0
|
||||
if (isChidori) {
|
||||
chidoriLength = j % 2 === 0 ? 0 : width / 2
|
||||
if (isChidori && !isMaxSetup) {
|
||||
chidoriLength = j % 2 === 0 ? 0 : width / 2 - intvHor
|
||||
}
|
||||
|
||||
square = [
|
||||
@ -975,7 +844,7 @@ export function useModuleBasicSetting() {
|
||||
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
|
||||
|
||||
// if (disjointFromTrestle && isDisjoint) {
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
|
||||
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
|
||||
|
||||
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
|
||||
@ -1058,8 +927,8 @@ export function useModuleBasicSetting() {
|
||||
leftMargin = j === 0 ? 0 : intvVer * j
|
||||
|
||||
chidoriLength = 0
|
||||
if (isChidori) {
|
||||
chidoriLength = i % 2 === 0 ? 0 : height / 2
|
||||
if (isChidori && !isMaxSetup) {
|
||||
chidoriLength = i % 2 === 0 ? 0 : height / 2 - intvHor
|
||||
}
|
||||
|
||||
square = [
|
||||
@ -1075,7 +944,7 @@ export function useModuleBasicSetting() {
|
||||
let points = turfCoordnates.map((coord) => ({ x: coord[0], y: coord[1] }))
|
||||
|
||||
// if (disjointFromTrestle && isDisjoint) {
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id }
|
||||
moduleOptions = { ...moduleOptions, fill: module.color, surfaceId: moduleSetupSurface.id, moduleInfo: module }
|
||||
let tempModule = new QPolygon(points, { ...moduleOptions, turfPoints: squarePolygon })
|
||||
let disjointFromTrestle = checkModuleDisjointSurface(squarePolygon, polygonToTurfPolygon(moduleSetupSurface, true))
|
||||
let isDisjoint = checkModuleDisjointObjects(squarePolygon, containsBatchObjects)
|
||||
@ -1118,6 +987,8 @@ export function useModuleBasicSetting() {
|
||||
|
||||
const flowDirection = moduleSetupSurface.flowDirection
|
||||
|
||||
console.log('moduleSetupSurface', moduleSetupSurface)
|
||||
|
||||
let intvHor =
|
||||
flowDirection === 'south' || flowDirection === 'north'
|
||||
? moduleSetupSurface.trestleDetail.moduleIntvlHor
|
||||
@ -1204,7 +1075,7 @@ export function useModuleBasicSetting() {
|
||||
})
|
||||
|
||||
moduleSetupSurface.set({ modules: moduleSetupArray })
|
||||
|
||||
getModuleStatistics()
|
||||
// const moduleArray = [...moduleIsSetup]
|
||||
// moduleArray.push({
|
||||
// surfaceId: moduleSetupSurface.surfaceId,
|
||||
@ -1304,13 +1175,13 @@ export function useModuleBasicSetting() {
|
||||
const pointX2 = coords[2].x + ((coords[2].y - top) / (coords[2].y - coords[1].y)) * (coords[1].x - coords[2].x)
|
||||
const pointY2 = top
|
||||
|
||||
const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 1,
|
||||
selectable: true,
|
||||
})
|
||||
canvas?.add(finalLine)
|
||||
canvas?.renderAll()
|
||||
// const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
|
||||
// stroke: 'red',
|
||||
// strokeWidth: 1,
|
||||
// selectable: true,
|
||||
// })
|
||||
// canvas?.add(finalLine)
|
||||
// canvas?.renderAll()
|
||||
|
||||
let rtnObj
|
||||
//평평하면
|
||||
@ -1427,13 +1298,13 @@ export function useModuleBasicSetting() {
|
||||
const pointX2 = top
|
||||
const pointY2 = coords[2].y + ((coords[2].x - top) / (coords[2].x - coords[1].x)) * (coords[1].y - coords[2].y)
|
||||
|
||||
const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
|
||||
stroke: 'red',
|
||||
strokeWidth: 1,
|
||||
selectable: true,
|
||||
})
|
||||
canvas?.add(finalLine)
|
||||
canvas?.renderAll()
|
||||
// const finalLine = new QLine([pointX1, pointY1, pointX2, pointY2], {
|
||||
// stroke: 'red',
|
||||
// strokeWidth: 1,
|
||||
// selectable: true,
|
||||
// })
|
||||
// canvas?.add(finalLine)
|
||||
// canvas?.renderAll()
|
||||
|
||||
let rtnObj
|
||||
//평평하면
|
||||
@ -1839,6 +1710,8 @@ export function useModuleBasicSetting() {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
getModuleStatistics()
|
||||
}
|
||||
|
||||
const autoFlatroofModuleSetup = (placementFlatRef) => {
|
||||
@ -2229,7 +2102,7 @@ export function useModuleBasicSetting() {
|
||||
})
|
||||
|
||||
moduleSetupSurface.set({ modules: setupedModules })
|
||||
|
||||
getModuleStatistics()
|
||||
// console.log('moduleSetupSurface', moduleSetupSurface)
|
||||
// console.log('setupedModules', setupedModules)
|
||||
|
||||
@ -2277,8 +2150,63 @@ export function useModuleBasicSetting() {
|
||||
return isDisjoint
|
||||
}
|
||||
|
||||
const getModuleStatistics = () => {
|
||||
const surfaces = canvas.getObjects().filter((obj) => POLYGON_TYPE.MODULE_SETUP_SURFACE === obj.name)
|
||||
console.log('🚀 ~ getModuleStatistics ~ surfaces:', surfaces)
|
||||
let totalWpout = 0
|
||||
let moduleInfo = {}
|
||||
const rows = surfaces.map((surface) => {
|
||||
let wpOut = 0
|
||||
moduleInfo = {}
|
||||
surface.modules.forEach((module) => {
|
||||
if (!moduleInfo[module.moduleInfo.itemId]) {
|
||||
moduleInfo[module.moduleInfo.itemId] = { name: module.moduleInfo.itemNm, amount: 0, id: module.moduleInfo.itemId }
|
||||
}
|
||||
wpOut += +module.moduleInfo.wpOut
|
||||
|
||||
moduleInfo[module.moduleInfo.itemId].amount++
|
||||
})
|
||||
totalWpout += wpOut
|
||||
console.log('🚀 ~ moduleData.rows=surfaces.map ~ module:', module)
|
||||
const rowObject = {}
|
||||
Object.keys(moduleInfo).forEach((key) => {
|
||||
rowObject[key] = moduleInfo[key].amount
|
||||
})
|
||||
return {
|
||||
...rowObject, // 총 발전량 = 발전량 * 모듈 개수
|
||||
...surface,
|
||||
name: canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].directionText, // 지붕면
|
||||
// powerGeneration: wpOut.toLocaleString('ko-KR', { maximumFractionDigits: 4 }),
|
||||
wpOut: wpOut,
|
||||
}
|
||||
})
|
||||
|
||||
console.log('🚀 ~ getModuleStatistics ~ rows:', rows)
|
||||
console.log('🚀 ~ getModuleStatistics ~ moduleInfo:', moduleInfo)
|
||||
const header = [
|
||||
{ name: getMessage('modal.panel.batch.statistic.roof.shape'), prop: 'name' },
|
||||
...Object.keys(moduleInfo).map((key) => {
|
||||
return { name: moduleInfo[key].name, prop: key }
|
||||
}),
|
||||
{ name: `${getMessage('modal.panel.batch.statistic.power.generation.amount')}(kW)`, prop: 'wpOut' },
|
||||
]
|
||||
let footer = ['합계']
|
||||
let footerData = {}
|
||||
rows.forEach((row) => {
|
||||
Object.keys(moduleInfo).map((key) => {
|
||||
if (!footerData[key]) footerData[key] = 0
|
||||
footerData[key] += row[key]
|
||||
})
|
||||
})
|
||||
Object.keys(footerData).forEach((key) => {
|
||||
footer.push(footerData[key])
|
||||
})
|
||||
footer.push(totalWpout)
|
||||
console.log({ header: header, rows, footer: footer })
|
||||
setModuleStatistics({ header: header, rows, footer: footer })
|
||||
}
|
||||
|
||||
return {
|
||||
makeModuleInstArea,
|
||||
manualModuleSetup,
|
||||
autoModuleSetup,
|
||||
restoreModuleInstArea,
|
||||
|
||||
@ -1,47 +1,59 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil'
|
||||
import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { canvasState } from '@/store/canvasAtom'
|
||||
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'
|
||||
|
||||
export function useModulePlace() {
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const moduleSelectionData = useRecoilValue(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
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)
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ useModulePlace ~ moduleSelectionData:', moduleSelectionData)
|
||||
}, [])
|
||||
if (moduleSelectionData) {
|
||||
const common = moduleSelectionData.common
|
||||
const roofConstructions = moduleSelectionData.roofConstructions
|
||||
|
||||
useEffect(() => {
|
||||
const common = moduleSelectionData.common
|
||||
const roofConstructions = moduleSelectionData.roofConstructions
|
||||
|
||||
const listParams = roofConstructions.map((item) => {
|
||||
return {
|
||||
...common,
|
||||
moduleTpCd: selectedModules.itemTp,
|
||||
roofMatlCd: item.trestle.roofMatlCd,
|
||||
trestleMkrCd: item.trestle.trestleMkrCd,
|
||||
constMthdCd: item.trestle.constMthdCd,
|
||||
roofBaseCd: item.trestle.roofBaseCd,
|
||||
constTp: item.construction.constTp,
|
||||
mixMatlNo: selectedModules.mixMatlNo,
|
||||
roofPitch: selectedModules.roofPchBase ? selectedModules.roofPchBase : null,
|
||||
inclCd: String(item.addRoof.pitch),
|
||||
roofIndex: item.addRoof.index,
|
||||
}
|
||||
})
|
||||
|
||||
setTrestleDetailParams(listParams)
|
||||
const listParams = roofConstructions.map((item) => {
|
||||
return {
|
||||
...common,
|
||||
moduleTpCd: selectedModules.itemTp,
|
||||
roofMatlCd: item.trestle.roofMatlCd,
|
||||
trestleMkrCd: item.trestle.trestleMkrCd,
|
||||
constMthdCd: item.trestle.constMthdCd,
|
||||
roofBaseCd: item.trestle.roofBaseCd,
|
||||
constTp: item.construction.constTp,
|
||||
mixMatlNo: selectedModules.mixMatlNo,
|
||||
roofPitch: item.addRoof.roofPchBase ? item.addRoof.roofPchBase : null,
|
||||
inclCd: String(item.addRoof.pitch),
|
||||
roofIndex: item.addRoof.index,
|
||||
workingWidth: item.addRoof.lenBase,
|
||||
}
|
||||
})
|
||||
setTrestleDetailParams(listParams)
|
||||
}
|
||||
}, [moduleSelectionData])
|
||||
|
||||
const getTrestleDetailListData = async () => {
|
||||
const trestleDetailList = await getTrestleDetailList(trestleDetailParams)
|
||||
setTrestleDetailList(trestleDetailList)
|
||||
if (trestleDetailList.length > 0) {
|
||||
setTrestleDetailList(trestleDetailList)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
@ -51,33 +63,168 @@ export function useModulePlace() {
|
||||
}, [trestleDetailParams])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ useModulePlace ~ trestleDetailList:', trestleDetailList)
|
||||
|
||||
//지붕을 가져옴
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((roof) => roof.name === 'roof')
|
||||
.forEach((roof) => {
|
||||
const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
|
||||
trestleDetailList.forEach((detail) => {
|
||||
if (Number(detail.data.roofIndex) === roofIndex) {
|
||||
//roof에 상세 데이터 추가
|
||||
roof.set({ trestleDetail: detail.data })
|
||||
|
||||
//surface에 상세 데이터 추가
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((surface) => surface.name === 'moduleSetupSurface' && surface.parentId === roof.id)
|
||||
.forEach((surface) => {
|
||||
surface.set({ trestleDetail: detail.data, roofMaterial: roof.roofMaterial })
|
||||
})
|
||||
}
|
||||
if (trestleDetailList.length > 0) {
|
||||
//지붕을 가져옴
|
||||
canvas
|
||||
.getObjects()
|
||||
.filter((roof) => roof.name === 'roof')
|
||||
.forEach((roof) => {
|
||||
const roofIndex = roof.roofMaterial.index //지붕의 지붕재의 순번
|
||||
trestleDetailList.forEach((detail) => {
|
||||
if (Number(detail.data.roofIndex) === roofIndex) {
|
||||
//roof에 상세 데이터 추가
|
||||
roof.set({ trestleDetail: detail.data })
|
||||
//배치면 설치 영역
|
||||
makeModuleInstArea(roof, detail.data)
|
||||
//surface에 상세 데이터 추가
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
console.log('roof', roof)
|
||||
})
|
||||
}
|
||||
}, [trestleDetailList])
|
||||
|
||||
const makeModuleInstArea = (roof, trestleDetail) => {
|
||||
//지붕 객체 반환
|
||||
|
||||
if (!roof) {
|
||||
return
|
||||
}
|
||||
|
||||
const batchObjects = canvas
|
||||
?.getObjects()
|
||||
.filter(
|
||||
(obj) =>
|
||||
obj.name === BATCH_TYPE.OPENING ||
|
||||
obj.name === BATCH_TYPE.SHADOW ||
|
||||
obj.name === BATCH_TYPE.TRIANGLE_DORMER ||
|
||||
obj.name === BATCH_TYPE.PENTAGON_DORMER,
|
||||
) //도머s 객체
|
||||
|
||||
//도머도 외곽을 따야한다
|
||||
|
||||
const batchObjectOptions = {
|
||||
stroke: 'red',
|
||||
fill: 'transparent',
|
||||
strokeDashArray: [10, 4],
|
||||
strokeWidth: 1,
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
selectable: true,
|
||||
name: POLYGON_TYPE.OBJECT_SURFACE,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
}
|
||||
|
||||
batchObjects.forEach((obj) => {
|
||||
if (obj.name === BATCH_TYPE.TRIANGLE_DORMER || obj.name === BATCH_TYPE.PENTAGON_DORMER) {
|
||||
const groupPoints = obj.groupPoints
|
||||
const offsetObjects = offsetPolygon(groupPoints, 10)
|
||||
const dormerOffset = new QPolygon(offsetObjects, batchObjectOptions)
|
||||
dormerOffset.setViewLengthText(false)
|
||||
canvas.add(dormerOffset) //모듈설치면 만들기
|
||||
} else {
|
||||
const points = obj.points
|
||||
const offsetObjects = offsetPolygon(points, 10)
|
||||
const offset = new QPolygon(offsetObjects, batchObjectOptions)
|
||||
offset.setViewLengthText(false)
|
||||
canvas.add(offset) //모듈설치면 만들기
|
||||
}
|
||||
})
|
||||
|
||||
const isExistSurface = canvas.getObjects().find((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && obj.parentId === roof.id)
|
||||
if (isExistSurface) {
|
||||
return
|
||||
}
|
||||
|
||||
let offsetLength = canvasSetting.roofSizeSet === 3 ? -90 : (trestleDetail.eaveIntvl / 10) * -1
|
||||
setSurfaceShapePattern(roof, roofDisplay.column, true) //패턴 변경
|
||||
const offsetPoints = offsetPolygon(roof.points, offsetLength) //안쪽 offset
|
||||
//모듈설치영역?? 생성
|
||||
|
||||
const surfaceId = uuidv4()
|
||||
|
||||
let setupSurface = new QPolygon(offsetPoints, {
|
||||
stroke: 'red',
|
||||
fill: 'transparent',
|
||||
strokeDashArray: [10, 4],
|
||||
strokeWidth: 1,
|
||||
lockMovementX: true,
|
||||
lockMovementY: true,
|
||||
lockRotation: true,
|
||||
lockScalingX: true,
|
||||
lockScalingY: true,
|
||||
selectable: true,
|
||||
parentId: roof.id, //가대 폴리곤의 임시 인덱스를 넣어줌
|
||||
name: POLYGON_TYPE.MODULE_SETUP_SURFACE,
|
||||
flowDirection: roof.direction,
|
||||
direction: roof.direction,
|
||||
flipX: roof.flipX,
|
||||
flipY: roof.flipY,
|
||||
surfaceId: surfaceId,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
modules: [],
|
||||
roofMaterial: roof.roofMaterial,
|
||||
trestleDetail: trestleDetail,
|
||||
// angle: -compasDeg,
|
||||
})
|
||||
|
||||
setupSurface.setViewLengthText(false)
|
||||
canvas.add(setupSurface) //모듈설치면 만들기
|
||||
|
||||
//지붕면 선택 금지
|
||||
roof.set({
|
||||
selectable: false,
|
||||
})
|
||||
|
||||
//모듈설치면 클릭이벤트
|
||||
addTargetMouseEventListener('mousedown', setupSurface, function () {
|
||||
toggleSelection(setupSurface)
|
||||
})
|
||||
}
|
||||
|
||||
let selectedModuleInstSurfaceArray = []
|
||||
|
||||
//설치 범위 지정 클릭 이벤트
|
||||
const toggleSelection = (setupSurface) => {
|
||||
const isExist = selectedModuleInstSurfaceArray.some((obj) => obj.parentId === setupSurface.parentId)
|
||||
//최초 선택일때
|
||||
if (!isExist) {
|
||||
//기본 선택이랑 스트로크 굵기가 같으면 선택 안됨으로 봄
|
||||
setupSurface.set({
|
||||
...setupSurface,
|
||||
strokeWidth: 3,
|
||||
strokeDashArray: [0],
|
||||
fill: 'transparent',
|
||||
})
|
||||
canvas.discardActiveObject() // 객체의 활성 상태 해제
|
||||
//중복으로 들어가는걸 방지하기 위한 코드
|
||||
|
||||
canvas?.renderAll()
|
||||
selectedModuleInstSurfaceArray.push(setupSurface)
|
||||
} else {
|
||||
//선택후 재선택하면 선택안됨으로 변경
|
||||
setupSurface.set({
|
||||
...setupSurface,
|
||||
fill: 'transparent',
|
||||
strokeDashArray: [10, 4],
|
||||
strokeWidth: 1,
|
||||
})
|
||||
canvas.discardActiveObject() // 객체의 활성 상태 해제
|
||||
|
||||
//폴리곤에 커스텀 인덱스를 가지고 해당 배열 인덱스를 찾아 삭제함
|
||||
const removeIndex = setupSurface.parentId
|
||||
const removeArrayIndex = selectedModuleInstSurfaceArray.findIndex((obj) => obj.parentId === removeIndex)
|
||||
selectedModuleInstSurfaceArray.splice(removeArrayIndex, 1)
|
||||
}
|
||||
|
||||
canvas?.renderAll()
|
||||
setModuleSetupSurface([...selectedModuleInstSurfaceArray])
|
||||
}
|
||||
|
||||
return {
|
||||
selectedModules,
|
||||
}
|
||||
|
||||
@ -3,42 +3,50 @@ import { useContext, useEffect, useState } from 'react'
|
||||
import { GlobalDataContext } from '@/app/GlobalDataProvider'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
|
||||
import { selectedModuleState, moduleSelectionInitParamsState } from '@/store/selectedModuleOptions'
|
||||
import { pitchSelector } from '@/store/canvasAtom'
|
||||
import { selectedModuleState, moduleSelectionInitParamsState, moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { isObjectNotEmpty } from '@/util/common-utils'
|
||||
|
||||
export function useModuleSelection(props) {
|
||||
const { managementState, setManagementState, managementStateLoaded } = useContext(GlobalDataContext)
|
||||
const globalPitch = useRecoilValue(pitchSelector) //피치
|
||||
|
||||
const [roughnessCodes, setRoughnessCodes] = useState([]) //면조도 목록
|
||||
const [windSpeedCodes, setWindSpeedCodes] = useState([]) //기준풍속 목록
|
||||
const [moduleList, setModuleList] = useState([{}]) //모듈 목록
|
||||
|
||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
|
||||
const [selectedSurfaceType, setSelectedSurfaceType] = useState({}) //선택된 면조도
|
||||
const [installHeight, setInstallHeight] = useState('0') //설치 높이
|
||||
const [installHeight, setInstallHeight] = useState() //설치 높이
|
||||
const [standardWindSpeed, setStandardWindSpeed] = useState({}) //기준풍속
|
||||
const [verticalSnowCover, setVerticalSnowCover] = useState('0') //수직적설량
|
||||
const [verticalSnowCover, setVerticalSnowCover] = useState() //수직적설량
|
||||
|
||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
|
||||
const [moduleSelectionInitParams, setModuleSelectionInitParams] = useRecoilState(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
|
||||
|
||||
const { getModuleTypeItemList } = useMasterController()
|
||||
|
||||
const { findCommonCode } = useCommonCode()
|
||||
|
||||
//탭별 파라메터 초기화
|
||||
useEffect(() => {
|
||||
const bindInitData = () => {
|
||||
setInstallHeight(managementState?.installHeight)
|
||||
setStandardWindSpeed(managementState?.standardWindSpeedId)
|
||||
setVerticalSnowCover(managementState?.verticalSnowCover)
|
||||
setSelectedSurfaceType(managementState?.surfaceType)
|
||||
}
|
||||
|
||||
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
|
||||
//탭별 파라메터 초기화
|
||||
useEffect(() => {
|
||||
bindInitData()
|
||||
const initParams = {
|
||||
illuminationTp: managementState?.surfaceTypeValue, //면조도
|
||||
instHt: managementState?.installHeight, //설치높이
|
||||
stdWindSpeed: managementState?.standardWindSpeedId, //기준풍속
|
||||
stdSnowLd: managementState?.verticalSnowCover, //기준적설량
|
||||
}
|
||||
|
||||
if (selectedModules) {
|
||||
initParams.moduleTpCd = selectedModules.itemTp
|
||||
initParams.moduleItemId = selectedModules.itemId
|
||||
}
|
||||
|
||||
setModuleSelectionInitParams(initParams)
|
||||
}, [managementState])
|
||||
|
||||
@ -67,8 +75,10 @@ export function useModuleSelection(props) {
|
||||
}
|
||||
|
||||
//새로고침시 데이터 날아가는거 방지
|
||||
if (!managementState) {
|
||||
if (managementState === null) {
|
||||
setManagementState(managementStateLoaded)
|
||||
} else {
|
||||
bindInitData()
|
||||
}
|
||||
|
||||
getModuleData(roofsIds)
|
||||
@ -76,14 +86,23 @@ export function useModuleSelection(props) {
|
||||
|
||||
const getModuleData = async (roofsIds) => {
|
||||
const list = await getModuleTypeItemList(roofsIds)
|
||||
//selectbox에 이름을 넣는다
|
||||
list.data.forEach((item) => {
|
||||
item.name = item.itemNm
|
||||
})
|
||||
//셀렉트박스 데이터 초기화
|
||||
setModuleList(list.data)
|
||||
if (list.data.length > 0) {
|
||||
//selectbox에 이름을 넣는다
|
||||
list.data.forEach((item) => {
|
||||
item.name = item.itemNm
|
||||
})
|
||||
//셀렉트박스 데이터 초기화
|
||||
setModuleList(list.data)
|
||||
}
|
||||
}
|
||||
|
||||
//데이터가 있으면 모듈 자동 선택
|
||||
useEffect(() => {
|
||||
if (moduleList.length > 0 && isObjectNotEmpty(moduleSelectionData.module)) {
|
||||
handleChangeModule(moduleSelectionData.module)
|
||||
}
|
||||
}, [moduleList])
|
||||
|
||||
const handleChangeModule = (option) => {
|
||||
//선택된 모듈
|
||||
setSelectedModules(option) //선택값 저장
|
||||
@ -101,31 +120,50 @@ export function useModuleSelection(props) {
|
||||
...moduleSelectionInitParams,
|
||||
illuminationTp: option.clCode,
|
||||
})
|
||||
|
||||
setManagementState({
|
||||
...managementState,
|
||||
surfaceType: option.clCodeNm,
|
||||
surfaceTypeValue: option.clCode,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeWindSpeed = (option) => {
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
surfaceType: option.clCode,
|
||||
stdWindSpeed: option.clCode,
|
||||
})
|
||||
|
||||
setManagementState({
|
||||
...managementState,
|
||||
standardWindSpeedId: option.clCode,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeInstallHeight = (option) => {
|
||||
setInstallHeight(option)
|
||||
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
instHt: option,
|
||||
})
|
||||
|
||||
setManagementState({
|
||||
...managementState,
|
||||
installHeight: option,
|
||||
})
|
||||
}
|
||||
|
||||
const handleChangeVerticalSnowCover = (option) => {
|
||||
setVerticalSnowCover(option)
|
||||
|
||||
setModuleSelectionInitParams({
|
||||
...moduleSelectionInitParams,
|
||||
stdSnowLd: option,
|
||||
})
|
||||
|
||||
setManagementState({
|
||||
...managementState,
|
||||
verticalSnowCover: option,
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
419
src/hooks/module/useModuleTabContents.js
Normal file
419
src/hooks/module/useModuleTabContents.js
Normal file
@ -0,0 +1,419 @@
|
||||
import { useEffect, useState, useRef } from 'react'
|
||||
import { useRecoilValue, useRecoilState } from 'recoil'
|
||||
import { pitchTextSelector } from '@/store/canvasAtom'
|
||||
import { useMasterController } from '@/hooks/common/useMasterController'
|
||||
import { useCommonCode } from '@/hooks/common/useCommonCode'
|
||||
import { moduleSelectionDataState, moduleSelectionInitParamsState, selectedModuleState } from '@/store/selectedModuleOptions'
|
||||
import { isObjectNotEmpty, isEqualObjects } from '@/util/common-utils'
|
||||
import { addedRoofsState } from '@/store/settingAtom'
|
||||
|
||||
export function useModuleTabContents({ tabIndex, addRoof, setAddedRoofs, roofTab, tempModuleSelectionData, setTempModuleSelectionData }) {
|
||||
const addRoofsArray = useRecoilValue(addedRoofsState)
|
||||
const globalPitchText = useRecoilValue(pitchTextSelector) //피치 텍스트
|
||||
|
||||
const { findCommonCode } = useCommonCode()
|
||||
const [raftCodes, setRaftCodes] = useState([]) //가대 목록
|
||||
|
||||
const [trestleList, setTrestleList] = useState([])
|
||||
const [constMthdList, setConstMthdList] = useState([])
|
||||
const [roofBaseList, setRoofBaseList] = useState([])
|
||||
const [constructionList, setConstructionList] = useState([{}]) //공법 목록
|
||||
|
||||
const [selectedRaftBase, setSelectedRaftBase] = useState({}) //선택된 가대
|
||||
const [selectedTrestle, setSelectedTrestle] = useState({}) //선택된 가대
|
||||
const [selectedConstMthd, setSelectedConstMthd] = useState({}) //선택된 공법
|
||||
const [selectedRoofBase, setSelectedRoofBase] = useState({}) //선택된 지붕밑바탕
|
||||
const [selectedConstruction, setSelectedConstruction] = useState({}) //선택된 공법
|
||||
const [constructionListParams, setConstructionListParams] = useState({})
|
||||
|
||||
const [trestleParams, setTrestleParams] = useState({}) //서까래, 가대메이커,공법,지붕밑바탕 관련 api호출 파라메터
|
||||
const [constructionParams, setConstructionParams] = useState({}) //공법 관련 api호출 파라메터
|
||||
const [roofBaseParams, setRoofBaseParams] = useState({}) //지붕밑바탕 관련 api호출 파라메터
|
||||
|
||||
const moduleSelectionInitParams = useRecoilValue(moduleSelectionInitParamsState) //모듈 기본 데이터 ex) 면조도, 높이등등
|
||||
const moduleSelectionInitOriginData = useRef(moduleSelectionInitParams)
|
||||
|
||||
const { getTrestleList, getConstructionList } = useMasterController()
|
||||
|
||||
const constructionRef = useRef([])
|
||||
const [cvrYn, setCvrYn] = useState('N')
|
||||
const [snowGdPossYn, setSnowGdPossYn] = useState('N')
|
||||
|
||||
const [cvrChecked, setCvrChecked] = useState(false)
|
||||
const [snowGdChecked, setSnowGdChecked] = useState(false)
|
||||
|
||||
const [isExistData, setIsExistData] = useState(false)
|
||||
|
||||
const [selectedModules, setSelectedModules] = useRecoilState(selectedModuleState) //선택된 모듈
|
||||
const [moduleConstructionSelectionData, setModuleConstructionSelectionData] = useState()
|
||||
|
||||
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState) //다음으로 넘어가는 최종 데이터
|
||||
|
||||
const [hajebichi, setHajebichi] = useState(0)
|
||||
const [lengthBase, setLengthBase] = useState(0)
|
||||
|
||||
const hajebichiRef = useRef()
|
||||
const lengthRef = useRef()
|
||||
|
||||
//서까래간격 변경
|
||||
const handleChangeRaftBase = (option) => {
|
||||
setSelectedRaftBase(option)
|
||||
setTrestleParams({ ...trestleParams, raftBaseCd: option.clCode }) //가대메이커
|
||||
setConstMthdList([]) //공법 초기화
|
||||
setRoofBaseList([]) //지붕밑바탕 초기화
|
||||
setConstructionList([]) //공법 초기화
|
||||
}
|
||||
|
||||
//처마력바 체크
|
||||
const handleCvrChecked = () => {
|
||||
setCvrChecked(!cvrChecked)
|
||||
setSelectedConstruction({ ...selectedConstruction, setupCover: !cvrChecked })
|
||||
}
|
||||
|
||||
//눈막이금구 체크
|
||||
const handleSnowGdChecked = () => {
|
||||
setSnowGdChecked(!snowGdChecked)
|
||||
setSelectedConstruction({ ...selectedConstruction, setupSnowCover: !snowGdChecked })
|
||||
}
|
||||
|
||||
const getConstructionListData = async (params) => {
|
||||
if (params.trestleMkrCd && params.constMthdCd && params.roofBaseCd) {
|
||||
const optionsList = await getConstructionList(params)
|
||||
setConstructionList(optionsList.data)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setHajebichi(addRoof.hajebichi)
|
||||
setLengthBase(addRoof.lenBase)
|
||||
|
||||
// 202600 경사도
|
||||
const raftCodeList = findCommonCode('203800')
|
||||
//서까래 코드
|
||||
raftCodeList.forEach((obj) => {
|
||||
obj.name = obj.clCodeNm
|
||||
obj.id = obj.clCode
|
||||
})
|
||||
setRaftCodes(raftCodeList)
|
||||
|
||||
console.log('moduleSelectionData', moduleSelectionData)
|
||||
}, [])
|
||||
|
||||
//리코일에 데이터가 담기는 시점에 시작
|
||||
useEffect(() => {
|
||||
if (
|
||||
isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex]) &&
|
||||
isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex].trestle) &&
|
||||
isObjectNotEmpty(moduleSelectionData.roofConstructions[tabIndex].construction)
|
||||
) {
|
||||
setModuleConstructionSelectionData(moduleSelectionData.roofConstructions[tabIndex])
|
||||
}
|
||||
}, [moduleSelectionData])
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(moduleConstructionSelectionData)) {
|
||||
setIsExistData(true)
|
||||
}
|
||||
}, [moduleConstructionSelectionData])
|
||||
|
||||
//높이를 변경하면 addRoofs에 적용
|
||||
// useEffect(() => {
|
||||
// const copyAddRoof = { ...addRoof }
|
||||
// copyAddRoof.length = Number(lengthBase)
|
||||
// copyAddRoof.lenBase = lengthBase
|
||||
// const index = addRoof.index
|
||||
// const newArray = [...addRoofsArray.slice(0, index), copyAddRoof, ...addRoofsArray.slice(index + 1)]
|
||||
// setAddedRoofs(newArray)
|
||||
// }, [lengthBase])
|
||||
|
||||
// //망둥어 피치를 변경하면 addRoof 변경
|
||||
// useEffect(() => {
|
||||
// const copyAddRoof = { ...addRoof }
|
||||
// copyAddRoof.hajebichi = Number(hajebichi)
|
||||
// copyAddRoof.roofPchBase = hajebichi
|
||||
// const index = addRoof.index
|
||||
// const newArray = [...addRoofsArray.slice(0, index), copyAddRoof, ...addRoofsArray.slice(index + 1)]
|
||||
// setAddedRoofs(newArray)
|
||||
// }, [hajebichi])
|
||||
|
||||
useEffect(() => {
|
||||
if (isExistData) {
|
||||
setConstructionListParams({
|
||||
...moduleSelectionInitParams,
|
||||
...roofBaseParams,
|
||||
roofBaseCd: selectedRoofBase.roofBaseCd,
|
||||
inclCd: addRoof.pitch,
|
||||
roofPitch: hajebichiRef.current ? hajebichiRef.current.value : 0,
|
||||
raftBaseCd: addRoof.raftBaseCd,
|
||||
})
|
||||
}
|
||||
}, [selectedRoofBase])
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isExistData &&
|
||||
constructionList.length > 0 &&
|
||||
isObjectNotEmpty(moduleConstructionSelectionData?.construction) &&
|
||||
moduleConstructionSelectionData?.construction.hasOwnProperty('constPossYn') ///키가 있으면
|
||||
) {
|
||||
const selectedIndex = moduleConstructionSelectionData.construction.selectedIndex
|
||||
const construction = constructionList[selectedIndex]
|
||||
if (construction.constPossYn === 'Y') {
|
||||
handleConstruction(selectedIndex)
|
||||
}
|
||||
}
|
||||
}, [constructionList])
|
||||
|
||||
//모듈 변경
|
||||
useEffect(() => {
|
||||
//lengbase는 무조건 있다고 가정 하고 최초에 실행 방지
|
||||
if (selectedModules) {
|
||||
//가대메이커 파라메터 만들기
|
||||
setTrestleParams({
|
||||
moduleTpCd: selectedModules.itemTp,
|
||||
roofMatlCd: addRoof.roofMatlCd,
|
||||
raftBaseCd: addRoof.raftBaseCd,
|
||||
workingWidth: lengthBase,
|
||||
})
|
||||
}
|
||||
}, [selectedModules])
|
||||
|
||||
//가대메이커 api 호출
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(trestleParams)) {
|
||||
getModuleOptionsListData(trestleParams, 'trestle')
|
||||
}
|
||||
}, [trestleParams])
|
||||
|
||||
//가대메이커 변경 함수
|
||||
const handleChangeTrestle = (option) => {
|
||||
setSelectedTrestle(option) //선택값 저장
|
||||
setConstructionParams({ ...trestleParams, trestleMkrCd: option.trestleMkrCd, constMthdCd: '', roofBaseCd: '' })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(constructionParams)) {
|
||||
getModuleOptionsListData(constructionParams, 'construction')
|
||||
}
|
||||
}, [constructionParams])
|
||||
|
||||
//공법 변경
|
||||
const handleChangeConstMthd = (option) => {
|
||||
setSelectedConstMthd(option) //선택된값 저장
|
||||
setRoofBaseParams({
|
||||
...trestleParams,
|
||||
trestleMkrCd: selectedTrestle.trestleMkrCd,
|
||||
constMthdCd: option.constMthdCd,
|
||||
roofBaseCd: '',
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(roofBaseParams)) {
|
||||
getModuleOptionsListData(roofBaseParams, 'roofBase')
|
||||
}
|
||||
}, [roofBaseParams])
|
||||
|
||||
const handleChangeRoofBase = (option) => {
|
||||
setConstructionListParams({
|
||||
...moduleSelectionInitParams,
|
||||
trestleMkrCd: selectedTrestle.trestleMkrCd,
|
||||
constMthdCd: selectedConstMthd.constMthdCd,
|
||||
roofBaseCd: option.roofBaseCd,
|
||||
inclCd: addRoof.pitch,
|
||||
roofPitch: hajebichiRef.current ? hajebichiRef.current.value : 0,
|
||||
raftBaseCd: addRoof.raftBaseCd,
|
||||
roofMatlCd: addRoof.roofMatlCd,
|
||||
})
|
||||
setSelectedRoofBase(option)
|
||||
}
|
||||
|
||||
//공법 리스트 변경 함수
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(constructionListParams)) {
|
||||
getConstructionListData(constructionListParams)
|
||||
}
|
||||
}, [constructionListParams])
|
||||
|
||||
//공법 선택 함수
|
||||
const handleConstruction = (index) => {
|
||||
if (index > -1) {
|
||||
const isPossibleIndex = constructionRef.current
|
||||
.map((el, i) => (el.classList.contains('white') || el.classList.contains('blue') ? i : -1))
|
||||
.filter((index) => index !== -1)
|
||||
|
||||
isPossibleIndex.forEach((index) => {
|
||||
if (constructionRef.current[index].classList.contains('blue')) {
|
||||
constructionRef.current[index].classList.remove('blue')
|
||||
constructionRef.current[index].classList.add('white')
|
||||
}
|
||||
})
|
||||
constructionRef.current[index].classList.remove('white')
|
||||
constructionRef.current[index].classList.add('blue')
|
||||
|
||||
const selectedConstruction = constructionList[index]
|
||||
selectedConstruction.roofIndex = roofTab
|
||||
selectedConstruction.setupCover = false //처마력바 설치 여부
|
||||
selectedConstruction.setupSnowCover = false //눈막이금구 설치 여부
|
||||
selectedConstruction.selectedIndex = index
|
||||
|
||||
setCvrYn(selectedConstruction.cvrYn)
|
||||
setSnowGdPossYn(selectedConstruction.snowGdPossYn)
|
||||
|
||||
//기존에 선택된 데이터가 있으면 체크한다
|
||||
if (moduleConstructionSelectionData && moduleConstructionSelectionData.construction) {
|
||||
selectedConstruction.setupCover = moduleConstructionSelectionData.construction.setupCover || false
|
||||
selectedConstruction.setupSnowCover = moduleConstructionSelectionData.construction.setupSnowCover || false
|
||||
setCvrChecked(selectedConstruction.setupCover)
|
||||
setSnowGdChecked(selectedConstruction.setupSnowCover)
|
||||
}
|
||||
|
||||
setSelectedConstruction(selectedConstruction)
|
||||
} else {
|
||||
constructionRef.current.forEach((ref) => {
|
||||
ref.classList.remove('blue')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
//공법 선택시 이후 프로세스
|
||||
useEffect(() => {
|
||||
if (isObjectNotEmpty(selectedRoofBase) && isObjectNotEmpty(selectedConstruction)) {
|
||||
if (tabIndex === roofTab) {
|
||||
const common = { ...moduleSelectionInitParams }
|
||||
const module = { ...selectedModules }
|
||||
const newRoofConstructions = {
|
||||
roofIndex: tabIndex,
|
||||
addRoof: addRoof,
|
||||
trestle: selectedRoofBase,
|
||||
construction: selectedConstruction,
|
||||
}
|
||||
|
||||
const index = tempModuleSelectionData.roofConstructions.findIndex((obj) => obj.roofIndex === tabIndex)
|
||||
|
||||
if (index > -1) {
|
||||
const newArray = [
|
||||
...tempModuleSelectionData.roofConstructions.slice(0, index),
|
||||
newRoofConstructions,
|
||||
...tempModuleSelectionData.roofConstructions.slice(index + 1),
|
||||
]
|
||||
setTempModuleSelectionData({ common: common, module: module, roofConstructions: newArray })
|
||||
} else {
|
||||
setTempModuleSelectionData({
|
||||
common: common,
|
||||
module: module,
|
||||
roofConstructions: [...tempModuleSelectionData.roofConstructions, { ...newRoofConstructions }],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [selectedConstruction])
|
||||
|
||||
const getModuleOptionsListData = async (params, type) => {
|
||||
const optionsList = await getTrestleList(params)
|
||||
|
||||
if (optionsList.data.length > 0) {
|
||||
if (type === 'trestle') {
|
||||
setTrestleList(optionsList.data)
|
||||
if (isExistData) {
|
||||
handleChangeTrestle(moduleConstructionSelectionData?.trestle)
|
||||
} else {
|
||||
setConstMthdList([])
|
||||
setRoofBaseList([])
|
||||
}
|
||||
} else if (type === 'construction') {
|
||||
setConstMthdList(optionsList.data)
|
||||
if (isExistData) {
|
||||
handleChangeConstMthd(moduleConstructionSelectionData?.trestle)
|
||||
} else {
|
||||
setRoofBaseList([])
|
||||
}
|
||||
} else if (type === 'roofBase') {
|
||||
setRoofBaseList(optionsList.data)
|
||||
if (isExistData) {
|
||||
handleChangeRoofBase(moduleConstructionSelectionData?.trestle)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
//모듈이 선택되어있을때
|
||||
if (moduleSelectionInitOriginData.current.moduleItemId && moduleSelectionInitOriginData.current.moduleTpCd) {
|
||||
//초기에 들어온 데이터가 수정된 데이터가 값이 다르다면`
|
||||
if (!isEqualObjects(moduleSelectionInitOriginData.current, moduleSelectionInitParams)) {
|
||||
//가대 선택 초기화
|
||||
setSelectedTrestle({})
|
||||
|
||||
//공법 선택 초기화
|
||||
setSelectedConstMthd({})
|
||||
|
||||
//지붕밑바탕 선택 초기화
|
||||
setSelectedRoofBase({})
|
||||
|
||||
//공법 리스트 초기화
|
||||
setConstructionList([])
|
||||
|
||||
// 기본 정보 초기화
|
||||
setModuleSelectionData({
|
||||
...moduleSelectionData,
|
||||
roofConstructions: [],
|
||||
})
|
||||
|
||||
// 선택 데이터 초 기화
|
||||
setModuleConstructionSelectionData({
|
||||
addRoof: addRoof,
|
||||
trestle: {},
|
||||
construction: {},
|
||||
})
|
||||
|
||||
//임시 데이터 초기화
|
||||
setTempModuleSelectionData({
|
||||
...moduleSelectionData,
|
||||
roofConstructions: [],
|
||||
})
|
||||
|
||||
//처마커버 해제
|
||||
setCvrChecked(false)
|
||||
//눈막이금구 해제
|
||||
setSnowGdChecked(false)
|
||||
|
||||
// 데이터 없음으로 변경
|
||||
setIsExistData(false)
|
||||
|
||||
//변경된 데이터를 ref에 저장
|
||||
moduleSelectionInitOriginData.current = moduleSelectionInitParams
|
||||
}
|
||||
}
|
||||
}, [moduleSelectionInitParams])
|
||||
|
||||
return {
|
||||
raftCodes,
|
||||
trestleList,
|
||||
constMthdList,
|
||||
roofBaseList,
|
||||
constructionList,
|
||||
globalPitchText,
|
||||
selectedTrestle,
|
||||
selectedConstMthd,
|
||||
selectedRoofBase,
|
||||
constructionRef,
|
||||
cvrYn,
|
||||
cvrChecked,
|
||||
snowGdPossYn,
|
||||
snowGdChecked,
|
||||
lengthBase,
|
||||
hajebichi,
|
||||
lengthRef,
|
||||
hajebichiRef,
|
||||
setLengthBase,
|
||||
setHajebichi,
|
||||
handleChangeRaftBase,
|
||||
handleChangeTrestle,
|
||||
handleChangeConstMthd,
|
||||
handleChangeRoofBase,
|
||||
handleConstruction,
|
||||
handleCvrChecked,
|
||||
handleSnowGdChecked,
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -93,7 +93,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
})
|
||||
|
||||
if (!selectedSurface) {
|
||||
swalFire({ text: '지붕안에 그려야해요', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
|
||||
initEvent() //이벤트 초기화
|
||||
if (setIsHidden) setIsHidden(false)
|
||||
return
|
||||
@ -150,7 +150,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
|
||||
//일단 지워
|
||||
deleteTempObjects()
|
||||
return
|
||||
@ -162,14 +162,14 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
|
||||
|
||||
if (isCross) {
|
||||
swalFire({ text: '겹치기 불가요...', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.notinstall.cross'), icon: 'error' })
|
||||
deleteTempObjects()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName, parentId: selectedSurface.id })
|
||||
rect.set({ name: objName, parentId: selectedSurface.id, points: rectToPolygon(rect) })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
|
||||
@ -232,7 +232,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(rectPolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '개구를 배치할 수 없습니다.', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
|
||||
//일단 지워
|
||||
deleteTempObjects()
|
||||
return
|
||||
@ -244,14 +244,14 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const isCross = preObjectsArray.some((object) => turf.booleanOverlap(pointsToTurfPolygon(object), rectPolygon))
|
||||
|
||||
if (isCross) {
|
||||
swalFire({ text: '겹치기 불가요...', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.notinstall.cross'), icon: 'error' })
|
||||
deleteTempObjects()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
isDown = false
|
||||
rect.set({ name: objName, parentId: selectedSurface.id })
|
||||
rect.set({ name: objName, parentId: selectedSurface.id, points: rectToPolygon(rect) })
|
||||
rect.setCoords()
|
||||
initEvent()
|
||||
if (setIsHidden) setIsHidden(false)
|
||||
@ -377,12 +377,9 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
const trianglePolygon = pointsToTurfPolygon(triangleToPolygon(dormer))
|
||||
const selectedSurfacePolygon = polygonToTurfPolygon(selectedSurface)
|
||||
|
||||
console.log('trianglePolygon', trianglePolygon)
|
||||
console.log('selectedSurfacePolygon', selectedSurfacePolygon)
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(trianglePolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '도머를 배치할 수 없습니다.', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
|
||||
//일단 지워
|
||||
deleteTempObjects()
|
||||
return
|
||||
@ -406,6 +403,8 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
direction = 'north'
|
||||
}
|
||||
|
||||
const groupPoints = offsetRef > 0 ? triangleToPolygon(dormerOffset) : triangleToPolygon(dormer)
|
||||
|
||||
let splitedTriangle = offsetRef > 0 ? splitDormerTriangle(dormerOffset, directionRef) : splitDormerTriangle(dormer, directionRef)
|
||||
canvas?.remove(offsetRef > 0 ? dormerOffset : dormer)
|
||||
|
||||
@ -499,6 +498,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
parentId: selectedSurface.id,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
groupPoints: groupPoints,
|
||||
})
|
||||
canvas?.add(objectGroup)
|
||||
|
||||
@ -604,7 +604,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
|
||||
//지붕 밖으로 그렸을때
|
||||
if (!turf.booleanWithin(pentagonPolygon, selectedSurfacePolygon)) {
|
||||
swalFire({ text: '도머를 배치할 수 없습니다.', icon: 'error' })
|
||||
swalFire({ text: getMessage('batch.object.outside.roof'), icon: 'error' })
|
||||
//일단 지워
|
||||
deleteTempObjects()
|
||||
return
|
||||
@ -708,6 +708,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
|
||||
const groupPolygon = offsetPolygon ? [leftPentagon, rightPentagon, offsetPolygon] : [leftPentagon, rightPentagon]
|
||||
const groupPoints = offsetRef > 0 ? pentagonOffsetPoints : pentagonPoints
|
||||
|
||||
const objectGroup = new fabric.Group(groupPolygon, {
|
||||
subTargetCheck: true,
|
||||
@ -717,6 +718,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
|
||||
groupYn: true,
|
||||
originX: 'center',
|
||||
originY: 'center',
|
||||
groupPoints: groupPoints,
|
||||
})
|
||||
canvas?.add(objectGroup)
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState, useRef } from 'react'
|
||||
import { useEffect, useState, useRef, useContext } from 'react'
|
||||
import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil'
|
||||
import {
|
||||
adsorptionPointModeState,
|
||||
@ -35,6 +35,7 @@ import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementSha
|
||||
import { useCanvasMenu } from '../common/useCanvasMenu'
|
||||
import { menuTypeState } from '@/store/menuAtom'
|
||||
import { usePopup } from '../usePopup'
|
||||
import { FloorPlanContext } from '@/app/floor-plan/FloorPlanProvider'
|
||||
|
||||
const defaultDotLineGridSetting = {
|
||||
INTERVAL: {
|
||||
@ -58,17 +59,22 @@ export function useCanvasSetting() {
|
||||
|
||||
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
|
||||
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
|
||||
const resetSettingModalFirstOptions = useResetRecoilState(settingModalFirstOptionsState)
|
||||
const resetSettingModalSecondOptions = useResetRecoilState(settingModalSecondOptionsState)
|
||||
|
||||
const [selectedFont, setSelectedFont] = useState()
|
||||
const [selectedFontWeight, setSelectedFontWeight] = useState()
|
||||
const [selectedFontSize, setSelectedFontSize] = useState()
|
||||
const [selectedFontColor, setSelectedFontColor] = useState()
|
||||
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
|
||||
const resetGlobalFont = useResetRecoilState(globalFontAtom)
|
||||
|
||||
const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
|
||||
const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState)
|
||||
const [planSizeSettingMode, setPlanSizeSettingMode] = useRecoilState(planSizeSettingState)
|
||||
const resetPlanSizeSettingMode = useResetRecoilState(planSizeSettingState)
|
||||
const [dimensionLineSettings, setDimensionLineSettings] = useRecoilState(dimensionLineSettingsState)
|
||||
const resetDimensionLineSettings = useResetRecoilState(dimensionLineSettingsState)
|
||||
|
||||
const setSettingModalGridOptions = useSetRecoilState(settingModalGridOptionsState)
|
||||
const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
|
||||
@ -117,9 +123,13 @@ export function useCanvasSetting() {
|
||||
|
||||
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
|
||||
|
||||
const { floorPlanState } = useContext(FloorPlanContext)
|
||||
|
||||
const { closeAll } = usePopup()
|
||||
|
||||
useEffect(() => {
|
||||
console.log('correntObjectNo', correntObjectNo)
|
||||
|
||||
setFetchRoofMaterials(!fetchRoofMaterials)
|
||||
if (fetchRoofMaterials) {
|
||||
addRoofMaterials()
|
||||
@ -159,21 +169,28 @@ export function useCanvasSetting() {
|
||||
setBasicSettings({ ...basicSetting, selectedRoofMaterial: selectedRoofMaterial })
|
||||
}
|
||||
|
||||
const previousObjectNoRef = useRef(null)
|
||||
const previousRoofMaterialsRef = useRef(null)
|
||||
|
||||
useEffect(() => {
|
||||
// 지붕재 select 정보가 존재해야 배치면초기설정 DB 정보 비교 후 지붕재 정보를 가져올 수 있음
|
||||
if (roofMaterials.length !== 0 && JSON.stringify(previousRoofMaterialsRef.current) !== JSON.stringify(roofMaterials)) {
|
||||
// 지붕재 select 정보 비교 후 변경된 것이 없으면 1회만 실행
|
||||
if (
|
||||
(!previousObjectNoRef.current && !correntObjectNo && previousObjectNoRef.current !== correntObjectNo) ||
|
||||
(roofMaterials.length !== 0 && JSON.stringify(previousRoofMaterialsRef.current) !== JSON.stringify(roofMaterials))
|
||||
) {
|
||||
// 1회만 실행
|
||||
if (roofMaterials && previousRoofMaterialsYn === 'N') {
|
||||
fetchBasicSettings()
|
||||
previousRoofMaterialsYn = 'Y'
|
||||
if (correntObjectNo) {
|
||||
fetchBasicSettings()
|
||||
previousRoofMaterialsYn = 'Y'
|
||||
}
|
||||
}
|
||||
|
||||
// 이전 값을 업데이트
|
||||
previousObjectNoRef.current = correntObjectNo
|
||||
previousRoofMaterialsRef.current = roofMaterials
|
||||
}
|
||||
}, [roofMaterials])
|
||||
}, [roofMaterials, correntObjectNo])
|
||||
|
||||
useEffect(() => {
|
||||
if (!canvas) {
|
||||
@ -181,6 +198,9 @@ export function useCanvasSetting() {
|
||||
}
|
||||
const { column } = corridorDimension
|
||||
const lengthTexts = canvas.getObjects().filter((obj) => obj.name === 'lengthText')
|
||||
lengthTexts.forEach((obj) => {
|
||||
obj.set({ text: '' })
|
||||
})
|
||||
switch (column) {
|
||||
case 'corridorDimension':
|
||||
lengthTexts.forEach((obj) => {
|
||||
@ -206,7 +226,6 @@ export function useCanvasSetting() {
|
||||
}, [corridorDimension])
|
||||
|
||||
useEffect(() => {
|
||||
console.log('🚀 ~ useEffect ~ settingsDataSave:', settingsDataSave)
|
||||
if (settingsDataSave !== undefined) onClickOption2()
|
||||
}, [settingsData])
|
||||
|
||||
@ -297,8 +316,8 @@ export function useCanvasSetting() {
|
||||
})
|
||||
roofsArray = res.map((item) => {
|
||||
return {
|
||||
roofApply: true,
|
||||
roofSeq: 0,
|
||||
roofApply: item.roofApply,
|
||||
roofSeq: item.roofSeq,
|
||||
roofMatlCd: item.roofMatlCd,
|
||||
roofWidth: item.roofWidth,
|
||||
roofHeight: item.roofHeight,
|
||||
@ -328,6 +347,7 @@ export function useCanvasSetting() {
|
||||
roofGap: 'HEI_455',
|
||||
roofLayout: 'P',
|
||||
roofPitch: 4,
|
||||
roofAngle: 21.8,
|
||||
},
|
||||
]
|
||||
}
|
||||
@ -354,7 +374,6 @@ export function useCanvasSetting() {
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log('🚀 ~ fetchBasicSettings ~ addRoofs:', addRoofs)
|
||||
setAddedRoofs(addRoofs)
|
||||
setBasicSettings({
|
||||
...basicSetting,
|
||||
@ -362,16 +381,16 @@ export function useCanvasSetting() {
|
||||
roofSizeSet: roofsRow[0].roofSizeSet,
|
||||
roofAngleSet: roofsRow[0].roofAngleSet,
|
||||
roofsData: roofsArray,
|
||||
selectedRoofMaterial: addRoofs[0],
|
||||
selectedRoofMaterial: addRoofs.find((roof) => roof.selected),
|
||||
})
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Data fetching error:', error)
|
||||
}
|
||||
|
||||
if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
|
||||
setBasicSettings({ ...canvasSetting })
|
||||
}
|
||||
// if (!(Object.keys(canvasSetting).length === 0 && canvasSetting.constructor === Object)) {
|
||||
// setBasicSettings({ ...canvasSetting })
|
||||
// }
|
||||
setCanvasSetting({ ...basicSetting })
|
||||
}
|
||||
|
||||
@ -438,7 +457,7 @@ export function useCanvasSetting() {
|
||||
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${correntObjectNo}` })
|
||||
console.log('res', res)
|
||||
|
||||
if (res) {
|
||||
if (Object.keys(res).length > 0) {
|
||||
const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
|
||||
const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
|
||||
const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
|
||||
@ -527,26 +546,27 @@ export function useCanvasSetting() {
|
||||
//그리드 색 설정
|
||||
setGridColor(res.gridColor)
|
||||
} else {
|
||||
//조회된 글꼴 데이터가 없는 경우
|
||||
//조회된 글꼴 데이터가 없는 경우 (데이터 초기화)
|
||||
|
||||
//흡착점 ON/OFF
|
||||
setAdsorptionPointMode({ ...adsorptionPointMode, adsorptionPoint: false })
|
||||
|
||||
//치수선 설정
|
||||
setDimensionLineSettings({ ...dimensionLineSettings })
|
||||
// setDimensionLineSettings({ ...dimensionLineSettings, ...dimensionLineSettingsState.default })
|
||||
resetDimensionLineSettings()
|
||||
|
||||
//도면크기 설정
|
||||
setPlanSizeSettingMode({ ...planSizeSettingMode })
|
||||
// setPlanSizeSettingMode({ ...planSizeSettingMode, ...planSizeSettingState.default })
|
||||
resetPlanSizeSettingMode()
|
||||
|
||||
// 데이터 설정
|
||||
setSettingModalFirstOptions({
|
||||
...settingModalFirstOptions,
|
||||
})
|
||||
setSettingModalSecondOptions({
|
||||
...settingModalSecondOptions,
|
||||
})
|
||||
// setSettingModalFirstOptions({ ...settingModalFirstOptions, ...settingModalFirstOptionsState.default })
|
||||
resetSettingModalFirstOptions()
|
||||
//setSettingModalSecondOptions({ ...settingModalSecondOptions, ...settingModalSecondOptionsState.default })
|
||||
resetSettingModalSecondOptions()
|
||||
|
||||
setGlobalFont({ ...globalFont })
|
||||
// setGlobalFont({ ...globalFont, ...globalFontAtom.default })
|
||||
resetGlobalFont()
|
||||
|
||||
//점/선 그리드
|
||||
setDotLineGridSettingState({ ...defaultDotLineGridSetting })
|
||||
@ -671,7 +691,7 @@ export function useCanvasSetting() {
|
||||
// HTTP POST 요청 보내기
|
||||
await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
|
||||
.then((res) => {
|
||||
// swalFire({ text: getMessage(res.returnMessage) })
|
||||
//swalFire({ text: getMessage(res.returnMessage) })
|
||||
|
||||
// Canvas 디스플레이 설정 시 해당 옵션 적용
|
||||
frontSettings()
|
||||
@ -679,7 +699,8 @@ export function useCanvasSetting() {
|
||||
fetchSettings()
|
||||
})
|
||||
.catch((error) => {
|
||||
swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
||||
//swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
|
||||
swalFire({ text: error.message, icon: 'error' })
|
||||
})
|
||||
|
||||
//setAdsorptionRange(item.range)
|
||||
@ -770,6 +791,7 @@ export function useCanvasSetting() {
|
||||
adsorptionRange,
|
||||
setAdsorptionRange,
|
||||
fetchSettings,
|
||||
fetchBasicSettings,
|
||||
frontSettings,
|
||||
globalFont,
|
||||
setGlobalFont,
|
||||
|
||||
@ -120,37 +120,49 @@ export function usePropertiesSetting(id) {
|
||||
}
|
||||
|
||||
const handleFix = () => {
|
||||
if (!confirm('외벽선 속성 설정을 완료하시겠습니까?')) {
|
||||
return
|
||||
}
|
||||
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||
const isClose = confirm('외벽선 속성 설정을 완료하시겠습니까?')
|
||||
if (isClose) {
|
||||
const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine')
|
||||
|
||||
const notSetAttributes = lines.filter((line) => !line.attributes?.type)
|
||||
if (notSetAttributes.length > 0) {
|
||||
alert('설정되지 않은 외벽선이 있습니다.')
|
||||
return
|
||||
}
|
||||
const notSetAttributes = lines.filter((line) => !line.attributes?.type)
|
||||
if (notSetAttributes.length > 0) {
|
||||
// 세팅이 하나라도 안되어있으면 초기화
|
||||
lines.forEach((line) => {
|
||||
line.set({
|
||||
stroke: '#000000',
|
||||
strokeWidth: 4,
|
||||
})
|
||||
})
|
||||
canvas.discardActiveObject()
|
||||
closePopup(id)
|
||||
return
|
||||
}
|
||||
|
||||
lines.forEach((line) => {
|
||||
line.set({
|
||||
attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
|
||||
stroke: '#000000',
|
||||
strokeWidth: 4,
|
||||
lines.forEach((line) => {
|
||||
line.set({
|
||||
attributes: line.attributes ? line.attributes : { offset: 0, type: LINE_TYPE.WALLLINE.WALL },
|
||||
stroke: '#000000',
|
||||
strokeWidth: 4,
|
||||
})
|
||||
|
||||
hideLine(line)
|
||||
})
|
||||
|
||||
hideLine(line)
|
||||
})
|
||||
const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
|
||||
|
||||
const wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' })
|
||||
wall.lines = [...lines]
|
||||
|
||||
wall.lines = [...lines]
|
||||
const roof = drawRoofPolygon(wall)
|
||||
|
||||
const roof = drawRoofPolygon(wall)
|
||||
setPoints([])
|
||||
canvas.renderAll()
|
||||
roof.drawHelpLine()
|
||||
|
||||
setPoints([])
|
||||
canvas.renderAll()
|
||||
roof.drawHelpLine()
|
||||
closePopup(id)
|
||||
closePopup(id)
|
||||
return
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const closeModal = (fn) => {
|
||||
|
||||
@ -24,6 +24,8 @@ import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
||||
import { globalLocaleStore } from '@/store/localeAtom'
|
||||
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
|
||||
import { moduleSelectionDataState } from '@/store/selectedModuleOptions'
|
||||
import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController'
|
||||
|
||||
// 지붕면 할당
|
||||
export function useRoofAllocationSetting(id) {
|
||||
@ -42,7 +44,7 @@ export function useRoofAllocationSetting(id) {
|
||||
const [currentRoofMaterial, setCurrentRoofMaterial] = useState(roofMaterials[0]) // 팝업 내 기준 지붕재
|
||||
const [roofList, setRoofList] = useRecoilState(addedRoofsState) // 배치면 초기설정에서 선택한 지붕재 배열
|
||||
const [editingLines, setEditingLines] = useState([])
|
||||
const [currentRoofList, setCurrentRoofList] = useState(null)
|
||||
const [currentRoofList, setCurrentRoofList] = useState([])
|
||||
const currentAngleType = useRecoilValue(currentAngleTypeSelector)
|
||||
const globalLocaleState = useRecoilValue(globalLocaleStore)
|
||||
const [basicInfo, setBasicInfo] = useState(null)
|
||||
@ -52,6 +54,8 @@ export function useRoofAllocationSetting(id) {
|
||||
|
||||
const { setSurfaceShapePattern } = useRoofFn()
|
||||
|
||||
const [moduleSelectionData, setModuleSelectionData] = useRecoilState(moduleSelectionDataState)
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentRoofList(roofList)
|
||||
}, [])
|
||||
@ -169,6 +173,7 @@ export function useRoofAllocationSetting(id) {
|
||||
roofSizeSet: res[0].roofSizeSet,
|
||||
roofAngleSet: res[0].roofAngleSet,
|
||||
roofsData: roofsArray,
|
||||
selectedRoofMaterial: selectRoofs.find((roof) => roof.selected),
|
||||
})
|
||||
setBasicInfo({
|
||||
roofSizeSet: '' + res[0].roofSizeSet,
|
||||
@ -188,7 +193,7 @@ export function useRoofAllocationSetting(id) {
|
||||
roofSizeSet: Number(basicSetting.roofSizeSet),
|
||||
roofAngleSet: basicSetting.roofAngleSet,
|
||||
roofAllocationList: currentRoofList.map((item, index) => ({
|
||||
roofApply: item.selected === null || item.selected === undefined ? 'true' : item.selected,
|
||||
roofApply: item.selected,
|
||||
roofSeq: index,
|
||||
roofMatlCd: item.roofMatlCd === null || item.roofMatlCd === undefined ? 'ROOF_ID_WA_53A' : item.roofMatlCd,
|
||||
roofWidth: item.width === null || item.width === undefined ? 0 : Number(item.width),
|
||||
@ -269,6 +274,7 @@ export function useRoofAllocationSetting(id) {
|
||||
setRoofList(newRoofList)
|
||||
const selectedRoofMaterial = newRoofList.find((roof) => roof.selected)
|
||||
setSurfaceShapePattern(currentObject, roofDisplay.column, false, selectedRoofMaterial)
|
||||
modifyModuleSelectionData()
|
||||
closeAll()
|
||||
}
|
||||
|
||||
@ -368,6 +374,8 @@ export function useRoofAllocationSetting(id) {
|
||||
closeAll()
|
||||
setMenuNumber(3)
|
||||
setMenuType('surface')
|
||||
|
||||
modifyModuleSelectionData()
|
||||
}
|
||||
|
||||
const setLineSize = (id, size) => {
|
||||
@ -499,6 +507,16 @@ export function useRoofAllocationSetting(id) {
|
||||
setCurrentRoofList(newRoofList)
|
||||
}
|
||||
|
||||
// 모듈 선택에서 선택한 데이터 초기화
|
||||
const modifyModuleSelectionData = () => {
|
||||
if (moduleSelectionData.roofConstructions.length > 0) {
|
||||
setModuleSelectionData({ ...moduleSelectionData, roofConstructions: [] })
|
||||
moduleSelectedDataTrigger({ ...moduleSelectionData, roofConstructions: [] })
|
||||
}
|
||||
}
|
||||
|
||||
const { trigger: moduleSelectedDataTrigger } = useCanvasPopupStatusController(2)
|
||||
|
||||
return {
|
||||
handleSave,
|
||||
onAddRoofMaterial,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { useRecoilState, useRecoilValue } from 'recoil'
|
||||
import { canvasState, globalPitchState } from '@/store/canvasAtom'
|
||||
import { MENU, POLYGON_TYPE } from '@/common/common'
|
||||
import { getIntersectionPoint } from '@/util/canvas-util'
|
||||
@ -16,11 +16,13 @@ import { fontSelector } from '@/store/fontAtom'
|
||||
import { slopeSelector } from '@/store/commonAtom'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { useRoofFn } from '@/hooks/common/useRoofFn'
|
||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||
|
||||
export function useSurfaceShapeBatch() {
|
||||
const { getMessage } = useMessage()
|
||||
const { drawDirectionArrow } = usePolygon()
|
||||
const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
|
||||
const [points, setPoints] = useRecoilState(outerLinePointsState)
|
||||
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
const globalPitch = useRecoilValue(globalPitchState)
|
||||
@ -649,11 +651,12 @@ export function useSurfaceShapeBatch() {
|
||||
|
||||
const deleteAllSurfacesAndObjects = () => {
|
||||
swalFire({
|
||||
text: '배치면 내용을 전부 삭제하시겠습니까?',
|
||||
text: getMessage('batch.canvas.delete.all'),
|
||||
type: 'confirm',
|
||||
confirmFn: () => {
|
||||
canvas.clear()
|
||||
swalFire({ text: '삭제 완료 되었습니다.' })
|
||||
setPoints([])
|
||||
swalFire({ text: getMessage('plan.message.delete') })
|
||||
},
|
||||
// denyFn: () => {
|
||||
// swalFire({ text: '취소되었습니다.', icon: 'error' })
|
||||
|
||||
@ -97,13 +97,11 @@ export function useAxios(lang = '') {
|
||||
|
||||
const getFetcher = async (url) => {
|
||||
const res = await get({ url })
|
||||
console.log('🚀 ~ getFetcher ~ res:', res)
|
||||
return res
|
||||
}
|
||||
|
||||
const postFetcher = async (url, { arg }) => {
|
||||
const postFetcher = async (url, arg) => {
|
||||
const res = await post({ url, data: arg })
|
||||
console.log('🚀 ~ postFetcher ~ res:', res)
|
||||
return res
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user