2025-03-19 11:10:12 +09:00

487 lines
19 KiB
JavaScript

import { useEffect, useRef, useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import SizeGuide from '@/components/floor-plan/modal/placementShape/SizeGuide'
import MaterialGuide from '@/components/floor-plan/modal/placementShape/MaterialGuide'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useRecoilState, useRecoilValue } from 'recoil'
import { addedRoofsState, roofDisplaySelector, roofMaterialsAtom } from '@/store/settingAtom'
import { useCommonCode } from '@/hooks/common/useCommonCode'
import QSelectBox from '@/components/common/select/QSelectBox'
import { globalLocaleStore } from '@/store/localeAtom'
import { onlyNumberInputChange } from '@/util/input-utils'
import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
import { usePolygon } from '@/hooks/usePolygon'
import { canvasState } from '@/store/canvasAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
/**
* 지붕 레이아웃
*/
export const ROOF_MATERIAL_LAYOUT = {
PARALLEL: 'P',
STAIRS: 'S',
}
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, planNo, openPoint }) {
const [showSizeGuideModal, setShowSizeGuidModal] = useState(false)
const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false)
const { getMessage } = useMessage()
const roofMaterials = useRecoilValue(roofMaterialsAtom)
const globalLocale = useRecoilValue(globalLocaleStore)
const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting()
const [addedRoofs, setAddedRoofs] = useRecoilState(addedRoofsState)
const { findCommonCode } = useCommonCode()
const [raftCodes, setRaftCodes] = useState([]) /** 서까래 정보 */
const [currentRoof, setCurrentRoof] = useState(null) /** 현재 선택된 지붕재 정보 */
const { closePopup } = usePopup() /** usePopup에서 closePopup 함수 가져오기 */
const { drawDirectionArrow } = usePolygon()
const { setSurfaceShapePattern } = useRoofFn()
const canvas = useRecoilValue(canvasState)
const roofDisplay = useRecoilValue(roofDisplaySelector)
const roofRef = {
roofCd: useRef(null),
width: useRef(null),
length: useRef(null),
rafter: useRef(null),
hajebichi: useRef(null),
}
/**
* 치수 입력방법(복시도입력/실측값입력/육지붕)
*/
const roofSizeSetArray = [
{ id: 'ra01', name: 'roofSizeSet', value: '1', message: 'modal.placement.initial.setting.size.roof' },
{ id: 'ra02', name: 'roofSizeSet', value: '2', message: 'modal.placement.initial.setting.size.actual' },
{ id: 'ra03', name: 'roofSizeSet', value: '3', message: 'modal.placement.initial.setting.size.none.pitch' },
]
/**
* 지붕각도 설정(경사/각도)
*/
const roofAngleSetArray = [
{ id: 'ra04', name: 'roofAngleSet', value: 'slope', message: 'modal.placement.initial.setting.roof.pitch' },
{ id: 'ra05', name: 'roofAngleSet', value: 'flat', message: 'modal.placement.initial.setting.roof.angle' },
]
/**
* 지붕재 초기값
*/
const DEFAULT_ROOF_SETTINGS = {
roofSizeSet: '1',
roofAngleSet: 'slope',
angle: 21.8,
hajebichi: null,
id: 'ROOF_ID_WA_53A',
index: 0,
layout: ROOF_MATERIAL_LAYOUT.PARALLEL,
lenAuth: 'R',
lenBase: '235.000',
length: 235,
name: '일본기와 A',
nameJp: '和瓦A',
pitch: 4,
planNo: planNo,
raft: '',
raftAuth: 'C',
raftBaseCd: 'HEI_455',
roofCd: '',
roofMatlCd: 'ROOF_ID_WA_53A',
roofMatlNm: '일본기와 A',
roofMatlNmJp: '和瓦A',
roofPchAuth: null,
roofPchBase: null,
selected: true,
widAuth: 'R',
widBase: '265.000',
width: 265,
}
useEffect(() => {
/**
* 메뉴에서 배치면초기설정 선택 시 조회 후 화면 오픈
*/
if (openPoint && openPoint === 'canvasMenus') fetchBasicSettings(planNo, openPoint)
}, [])
/**
* 배치면초기설정 데이터 조회 후 화면 오픈
*/
useEffect(() => {
if (addedRoofs.length > 0) {
const raftCodeList = findCommonCode('203800')
setRaftCodes(raftCodeList)
setCurrentRoof({ ...addedRoofs[0], planNo: planNo, roofSizeSet: String(basicSetting.roofSizeSet), roofAngleSet: basicSetting.roofAngleSet })
} else {
/** 데이터 설정 확인 후 데이터가 없으면 기본 데이터 설정 */
setCurrentRoof({ ...DEFAULT_ROOF_SETTINGS })
}
}, [addedRoofs])
/**
* 배치면초기설정 정보 변경 시 basicSettings 설정
*/
useEffect(() => {
if (!currentRoof) return
setBasicSettings({
...basicSetting,
planNo: Number(currentRoof.planNo),
roofSizeSet: String(currentRoof.roofSizeSet),
roofAngleSet: currentRoof.roofAngleSet,
roofsData: {
planNo: Number(currentRoof.planNo),
roofApply: true,
roofSeq: 0,
roofMatlCd: currentRoof.roofMatlCd,
roofWidth: currentRoof.width,
roofHeight: currentRoof.length,
roofHajebichi: currentRoof.hajebichi,
roofGap: currentRoof.raft,
roofLayout: currentRoof.layout,
roofPitch: currentRoof.pitch,
roofAngle: currentRoof.angle,
},
})
}, [currentRoof])
const handleRoofSizeSetChange = (value) => {
setCurrentRoof({ ...currentRoof, roofSizeSet: value })
}
const handleRoofAngleSetChange = (value) => {
setCurrentRoof({ ...currentRoof, roofAngleSet: value })
}
/**
* 지붕재 변경 시 현재 지붕 정보 변경
*/
const handleRoofTypeChange = (value) => {
const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value)
setCurrentRoof({
...selectedRoofMaterial,
pitch: currentRoof?.pitch,
angle: currentRoof?.angle,
index: 0,
planNo: currentRoof.planNo,
roofSizeSet: String(currentRoof.roofSizeSet),
roofAngleSet: currentRoof.roofAngleSet,
})
}
/**
* 입력 값 변경 시 현재 지붕 정보 변경
*/
const changeInput = (value, e) => {
const { name } = e.target
setCurrentRoof({ ...currentRoof, [name]: Number(value) })
}
/**
* 서까래 변경 시 현재 지붕 정보 변경
*/
const handleRafterChange = (value) => {
setCurrentRoof({ ...currentRoof, raft: value })
}
/**
* 지붕 레이아웃 변경 시 현재 지붕 정보 변경
*/
const handleRoofLayoutChange = (value) => {
if (+currentRoof.roofSizeSet === 3) {
setCurrentRoof({ ...currentRoof, layout: ROOF_MATERIAL_LAYOUT.PARALLEL })
return
}
setCurrentRoof({ ...currentRoof, layout: value })
}
/**
* 배치면초기설정 저장 버튼 클릭
*/
const handleSaveBtn = () => {
const roofInfo = {
...currentRoof,
planNo: basicSetting.planNo,
roofCd: roofRef.roofCd.current?.value,
width: roofRef.width.current?.value,
length: roofRef.length.current?.value,
hajebichi: roofRef.hajebichi.current?.value,
raft: roofRef.rafter.current?.value,
selected: true,
layout: currentRoof.layout,
index: 0,
}
const newAddedRoofs = [...addedRoofs]
newAddedRoofs[0] = { ...roofInfo }
setAddedRoofs(newAddedRoofs)
console.log('save Info', {
...basicSetting,
selectedRoofMaterial: {
roofInfo,
},
})
/**
* 배치면초기설정 저장
*/
basicSettingSave({
...basicSetting,
/**
* 선택된 지붕재 정보
*/
selectedRoofMaterial: {
roofInfo,
},
})
const roofs = canvas.getObjects().filter((obj) => obj.roofMaterial?.index === 0)
roofs.forEach((roof) => {
/** 모양 패턴 설정 */
setSurfaceShapePattern(roof, roofDisplay.column, false, { ...roofInfo })
roof.roofMaterial = { ...roofInfo }
drawDirectionArrow(roof)
})
/* 저장 후 화면 닫기 */
closePopup(id)
}
return (
<WithDraggable isShow={true} pos={pos} className="ll">
<WithDraggable.Header title={getMessage('plan.menu.placement.surface.initial.setting')} />
<WithDraggable.Body>
<div className="left-bar modal-handle"></div>
<div className="right-bar modal-handle"></div>
<div className="placement-table">
<table>
<colgroup>
<col style={{ width: '151px' }} />
<col />
</colgroup>
<tbody>
<tr>
<th>{getMessage('modal.placement.initial.setting.plan.drawing')}</th>
<td>
{getMessage('modal.placement.initial.setting.plan.drawing.size.stuff')}
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{getMessage('modal.placement.initial.setting.plan.drawing.only.number')}
</td>
</tr>
<tr>
<th>
<div className="tip-wrap">
{getMessage('modal.placement.initial.setting.size')}
<button className="tooltip" onClick={() => setShowSizeGuidModal(true)}></button>
</div>
</th>
<td>
<div className="pop-form-radio">
{currentRoof &&
roofSizeSetArray.map((item) => (
<div className="d-check-radio pop" key={item.id}>
<input
type="radio"
id={item.id}
name={item.name}
value={item.value}
checked={String(currentRoof?.roofSizeSet) === item.value}
onChange={(e) => setCurrentRoof({ ...currentRoof, roofSizeSet: e.target.value })}
/>
<label htmlFor={item.id}>{getMessage(item.message)}</label>
</div>
))}
</div>
</td>
</tr>
<tr>
<th>{getMessage('modal.placement.initial.setting.roof.angle.setting')}</th>
<td>
<div className="pop-form-radio place">
{currentRoof &&
roofAngleSetArray.map((item, index) => (
<div className="outline-form" key={item.id}>
<span>
<div className="d-check-radio pop">
<input
type="radio"
id={item.id}
name={item.name}
value={item.value}
checked={String(currentRoof?.roofAngleSet) === item.value}
onChange={(e) => setCurrentRoof({ ...currentRoof, roofAngleSet: e.target.value })}
/>
<label htmlFor={item.id}>{getMessage(item.message)}</label>
</div>
</span>
<div className="input-grid mr5">
<input
type="number"
className="input-origin block"
readOnly={currentRoof?.roofAngleSet !== item.value}
value={index === 0 ? currentRoof?.pitch : currentRoof?.angle}
onChange={(e) =>
index === 0
? setCurrentRoof({ ...currentRoof, pitch: e.target.value, angle: getDegreeByChon(e.target.value) })
: setCurrentRoof({ ...currentRoof, pitch: getChonByDegree(e.target.value), angle: e.target.value })
}
/>
</div>
<span className="thin">{index === 0 ? '寸' : '度'}</span>
</div>
))}
</div>
</td>
</tr>
<tr>
<th>
<div className="tip-wrap">
{getMessage('modal.placement.initial.setting.roof.material')}
<button className="tooltip" onClick={() => setShowMaterialGuidModal(true)}></button>
</div>
</th>
<td>
<div className="placement-option">
<div className="grid-select no-flx" style={{ width: '171px' }}>
<QSelectBox
title={
currentRoof?.roofSizeSet === '3'
? getMessage('modal.placement.initial.setting.size.none.pitch')
: globalLocale === 'ko'
? currentRoof?.roofMatlNm
: currentRoof?.roofMatlNmJp
}
options={roofMaterials.map((roof) => {
return { ...roof, name: globalLocale === 'ko' ? roof.roofMatlNm : roof.roofMatlNmJp }
})}
value={currentRoof?.roofSizeSet === '3' ? null : currentRoof?.roofMatlCd}
onChange={(e) => handleRoofTypeChange(e.roofMatlCd)}
sourceKey="id"
targetKey="id"
showKey="name"
disabled={currentRoof?.roofSizeSet === '3'}
/>
</div>
{currentRoof && ['R', 'C'].includes(currentRoof.widAuth) && (
<div className="flex-ment">
<span>W</span>
<div className="input-grid" style={{ width: '84px' }}>
<input
type="text"
className="input-origin block"
name={`width`}
ref={roofRef.width}
value={parseInt(currentRoof?.width)}
onChange={(e) => onlyNumberInputChange(e, changeInput)}
readOnly={currentRoof?.widAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'}
/>
</div>
</div>
)}
{currentRoof && ['R', 'C'].includes(currentRoof.lenAuth) && (
<div className="flex-ment">
<span>L</span>
<div className="input-grid" style={{ width: '84px' }}>
<input
type="text"
className="input-origin block"
name={`length`}
ref={roofRef.length}
value={parseInt(currentRoof?.length)}
onChange={(e) => onlyNumberInputChange(e, changeInput)}
readOnly={currentRoof?.lenAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'}
/>
</div>
</div>
)}
{currentRoof && ['C', 'R'].includes(currentRoof.raftAuth) && (
<div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
{raftCodes?.length > 0 && (
<div className="select-wrap" style={{ width: '160px' }}>
<QSelectBox
options={raftCodes}
title={
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)}
sourceKey="clCode"
targetKey={currentRoof?.raft ? 'raft' : 'raftBaseCd'}
showKey="clCodeNm"
disabled={currentRoof?.roofSizeSet === '3'}
/>
</div>
)}
</div>
)}
{currentRoof && ['C', 'R'].includes(currentRoof?.roofPchAuth) && (
<div className="flex-ment">
<span>{getMessage('hajebichi')}</span>
<div className="input-grid" style={{ width: '84px' }}>
<input
type="text"
className="input-origin block"
name={`hajebichi`}
ref={roofRef.hajebichi}
value={parseInt(currentRoof?.hajebichi)}
onChange={(e) => onlyNumberInputChange(e, changeInput)}
readOnly={currentRoof?.roofPchAuth === 'R'}
disabled={currentRoof?.roofSizeSet === '3'}
/>
</div>
</div>
)}
</div>
{/* {currentRoof && (
<div className="placement-roof-btn-wrap">
<div className="icon-btn-wrap mt10">
<button
className={`${+currentRoof.roofSizeSet !== 3 && currentRoof?.layout === ROOF_MATERIAL_LAYOUT.PARALLEL && 'act'}`}
value={ROOF_MATERIAL_LAYOUT.PARALLEL}
disabled={currentRoof?.roofSizeSet === '3'}
onClick={() => handleRoofLayoutChange(ROOF_MATERIAL_LAYOUT.PARALLEL)}
>
{getMessage('modal.roof.alloc.select.parallel')}
<i className="allocation01"></i>
</button>
<button
className={`${+currentRoof.roofSizeSet !== 3 && currentRoof.layout === ROOF_MATERIAL_LAYOUT.STAIRS && 'act'}`}
disabled={currentRoof?.roofSizeSet === '3'}
value={ROOF_MATERIAL_LAYOUT.STAIRS}
onClick={() => handleRoofLayoutChange(ROOF_MATERIAL_LAYOUT.STAIRS)}
>
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
</button>
</div>
</div>
)} */}
</td>
</tr>
</tbody>
</table>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act" onClick={handleSaveBtn}>
{getMessage('modal.common.save')}
</button>
</div>
</WithDraggable.Body>
{showSizeGuideModal && <SizeGuide setShowSizeGuidModal={setShowSizeGuidModal} />}
{showMaterialGuideModal && <MaterialGuide setShowMaterialGuidModal={setShowMaterialGuidModal} />}
</WithDraggable>
)
}