Merge branch 'dev' into dev-yj

This commit is contained in:
yjnoh 2024-12-18 09:03:05 +09:00
commit a397c400fd
17 changed files with 563 additions and 251 deletions

View File

@ -13,6 +13,7 @@
"ag-grid-react": "^32.0.2", "ag-grid-react": "^32.0.2",
"axios": "^1.7.8", "axios": "^1.7.8",
"chart.js": "^4.4.6", "chart.js": "^4.4.6",
"dayjs": "^1.11.13",
"fabric": "^5.3.0", "fabric": "^5.3.0",
"framer-motion": "^11.2.13", "framer-motion": "^11.2.13",
"fs": "^0.0.1-security", "fs": "^0.0.1-security",
@ -32,12 +33,12 @@
"react-icons": "^5.3.0", "react-icons": "^5.3.0",
"react-loading-skeleton": "^3.5.0", "react-loading-skeleton": "^3.5.0",
"react-responsive-modal": "^6.4.2", "react-responsive-modal": "^6.4.2",
"react-select": "^5.8.1",
"recoil": "^0.7.7", "recoil": "^0.7.7",
"sweetalert2": "^11.14.1", "sweetalert2": "^11.14.1",
"sweetalert2-react-content": "^5.0.7", "sweetalert2-react-content": "^5.0.7",
"uuid": "^10.0.0", "usehooks-ts": "^3.1.0",
"dayjs": "^1.11.13", "uuid": "^10.0.0"
"react-select": "^5.8.1"
}, },
"devDependencies": { "devDependencies": {
"@turf/turf": "^7.0.0", "@turf/turf": "^7.0.0",

View File

@ -1,21 +1,29 @@
'use client' 'use client'
import { useEffect, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useOnClickOutside } from 'usehooks-ts'
export default function QSelectBox({ title = '', options, onChange, value, disabled = false, params = {} }) { export default function QSelectBox({ title = '', options, onChange, value, disabled = false, params = {} }) {
const [openSelect, setOpenSelect] = useState(false) const [openSelect, setOpenSelect] = useState(false)
const [selected, setSelected] = useState(title === '' ? options[0].name : title) const [selected, setSelected] = useState(title === '' ? options[0].name : title)
const ref = useRef(null)
const handleClickSelectOption = (option) => { const handleClickSelectOption = (option) => {
setSelected(option.name) setSelected(option.name)
onChange?.(option, params) onChange?.(option, params)
} }
const handleClose = () => {
setOpenSelect(false)
}
useEffect(() => { useEffect(() => {
value && handleClickSelectOption(value) value && handleClickSelectOption(value)
}, [value]) }, [value])
useOnClickOutside(ref, handleClose)
return ( return (
<div className={`sort-select ${openSelect ? 'active' : ''}`} onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}> <div className={`sort-select ${openSelect ? 'active' : ''}`} ref={ref} onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}>
<p>{selected}</p> <p>{selected}</p>
<ul className="select-item-wrap"> <ul className="select-item-wrap">
{options?.map((option, index) => ( {options?.map((option, index) => (

View File

@ -16,7 +16,13 @@ import { canvasSettingState, canvasState, canvasZoomState, currentMenuState, ver
import { sessionStore } from '@/store/commonAtom' import { sessionStore } from '@/store/commonAtom'
import { outerLinePointsState } from '@/store/outerLineAtom' import { outerLinePointsState } from '@/store/outerLineAtom'
import { appMessageStore, globalLocaleStore } from '@/store/localeAtom' import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
import { settingModalFirstOptionsState } from '@/store/settingAtom' import {
addedRoofsSelector,
basicSettingState,
roofMaterialsSelector,
selectedRoofMaterialSelector,
settingModalFirstOptionsState,
} from '@/store/settingAtom'
import KO from '@/locales/ko.json' import KO from '@/locales/ko.json'
import JA from '@/locales/ja.json' import JA from '@/locales/ja.json'
@ -75,10 +81,13 @@ export default function CanvasMenu(props) {
// const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useContext(EventContext) // const { initEvent, addCanvasMouseEventListener, addDocumentEventListener } = useContext(EventContext)
const commonUtils = useRecoilValue(commonUtilsState) const commonUtils = useRecoilValue(commonUtilsState)
const { commonFunctions } = useCommonUtils() const { commonFunctions } = useCommonUtils()
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext) const { floorPlanState, setFloorPlanState } = useContext(FloorPlanContext)
const { restoreModuleInstArea } = useModuleBasicSetting() const { restoreModuleInstArea } = useModuleBasicSetting()
const addedRoofs = useRecoilValue(addedRoofsSelector)
const [basicSetting, setBasicSetting] = useRecoilState(basicSettingState)
// //
const [buttonStyle, setButtonStyle] = useState('') const [buttonStyle, setButtonStyle] = useState('')
@ -112,6 +121,10 @@ export default function CanvasMenu(props) {
if (pathname !== '/floor-plan') router.push('/floor-plan') if (pathname !== '/floor-plan') router.push('/floor-plan')
} }
const changeSelectedRoofMaterial = (e) => {
setBasicSetting({ ...basicSetting, selectedRoofMaterial: e })
}
const settingsModalOptions = useRecoilState(settingModalFirstOptionsState) const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
useEffect(() => { useEffect(() => {
@ -292,9 +305,11 @@ export default function CanvasMenu(props) {
<button className={`btn02 ${commonUtils.dimension ? 'active' : ''} `} onClick={() => commonFunctions('dimension')}></button> <button className={`btn02 ${commonUtils.dimension ? 'active' : ''} `} onClick={() => commonFunctions('dimension')}></button>
<button className={`btn03 ${commonUtils.distance ? 'active' : ''} `} onClick={() => commonFunctions('distance')}></button> <button className={`btn03 ${commonUtils.distance ? 'active' : ''} `} onClick={() => commonFunctions('distance')}></button>
</div> </div>
<div className="select-box"> {addedRoofs.length > 0 && (
<QSelectBox title={'瓦53A'} option={SelectOption} /> <div className="select-box">
</div> {<QSelectBox value={addedRoofs.find((roof) => roof.selected)} options={addedRoofs} onChange={changeSelectedRoofMaterial} />}
</div>
)}
<div className="btn-from"> <div className="btn-from">
<button <button
className={`btn10 ${floorPlanState.refFileModalOpen && 'active'}`} className={`btn10 ${floorPlanState.refFileModalOpen && 'active'}`}

View File

@ -1,4 +1,4 @@
import { useEffect, useState } from 'react' import { useEffect, useRef, useState } from 'react'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
@ -8,10 +8,16 @@ import MaterialGuide from '@/components/floor-plan/modal/placementShape/Material
import WithDraggable from '@/components/common/draggable/WithDraggable' import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting' import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { roofMaterialsAtom } from '@/store/settingAtom' import { roofMaterialsAtom } from '@/store/settingAtom'
import { isObjectNotEmpty } from '@/util/common-utils' import { isObjectNotEmpty } from '@/util/common-utils'
import { useCommonCode } from '@/hooks/common/useCommonCode'
import QSelectBox from '@/components/common/select/QSelectBox'
export const ROOF_MATERIAL_LAYOUT = {
PARALLEL: 'P',
STAIRS: 'S',
}
export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) { export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, setShowPlaceShapeModal }) {
const [showSizeGuideModal, setShowSizeGuidModal] = useState(false) const [showSizeGuideModal, setShowSizeGuidModal] = useState(false)
const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false) const [showMaterialGuideModal, setShowMaterialGuidModal] = useState(false)
@ -20,25 +26,57 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
const roofMaterials = useRecoilValue(roofMaterialsAtom) const roofMaterials = useRecoilValue(roofMaterialsAtom)
const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting() const { basicSetting, setBasicSettings, fetchBasicSettings, basicSettingSave } = useCanvasSetting()
const [currentRoofMaterial, setCurrentRoofMaterial] = useState( const { findCommonCode } = useCommonCode()
isObjectNotEmpty(basicSetting.selectedRoofMaterial) ? basicSetting.selectedRoofMaterial : roofMaterials[0], const [raftCodes, setRaftCodes] = useState([])
) const [currentRoofMaterial, setCurrentRoofMaterial] = useState(basicSetting.selectedRoofMaterial)
const [roofLayout, setRoofLayout] = useState(basicSetting.selectedRoofMaterial.layout)
const roofRef = {
roofCd: useRef(null),
width: useRef(null),
length: useRef(null),
rafter: useRef(null),
hajebichi: useRef(null),
}
// //
useEffect(() => { useEffect(() => {
fetchBasicSettings() fetchBasicSettings()
const raftCodeList = findCommonCode('203800')
setRaftCodes(raftCodeList)
}, []) }, [])
useEffect(() => {
console.log(currentRoofMaterial)
}, [roofMaterials])
// Function to update the roofType and corresponding values // Function to update the roofType and corresponding values
const handleRoofTypeChange = (value) => { const handleRoofTypeChange = (value) => {
const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value) const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value)
setCurrentRoofMaterial(selectedRoofMaterial) setCurrentRoofMaterial(selectedRoofMaterial)
/*const newBasicSetting = { ...basicSetting } }
setBasicSettings({ ...newBasicSetting, selectedRoofMaterial: selectedRoofMaterial })*/
const handleSaveBtn = () => {
const roofInfo = {
...currentRoofMaterial,
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: roofLayout,
}
const addedRoofs = []
addedRoofs.push(roofInfo)
setBasicSettings({
...basicSetting,
selectedRoofMaterial: {
//
roofInfo,
},
roofs: addedRoofs,
})
basicSettingSave()
} }
return ( return (
@ -145,12 +183,25 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
</th> </th>
<td> <td>
<div className="placement-option"> <div className="placement-option">
<div className="select-wrap" style={{ width: '171px' }}> <div className="grid-select no-flx" style={{ width: '171px' }}>
{/* <QSelectBox
ref={roofRef.roofCd}
options={roofMaterials.map((roof, index) => {
return { name: roof.roofMatlNm, value: roof.roofMatlCd }
})}
value={currentRoofMaterial.roofMatlCd}
onChange={(e) => {
handleRoofTypeChange(e)
}}
/> */}
<select <select
className="select-light dark" className="select-light dark"
name="roofType" name="roofType"
ref={roofRef.roofCd}
value={currentRoofMaterial.roofMatlCd} value={currentRoofMaterial.roofMatlCd}
onChange={(e) => handleRoofTypeChange(e.target.value)} onChange={(e) => {
handleRoofTypeChange(e.target.value)
}}
> >
{roofMaterials.map((roof, index) => { {roofMaterials.map((roof, index) => {
return ( return (
@ -162,54 +213,61 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
</select> </select>
</div> </div>
{['R', 'C'].includes(currentRoofMaterial.widAuth) && ( {['R', 'C'].includes(currentRoofMaterial.widAuth) && (
<> <div className="flex-ment">
<div className="flex-ment"> <span>W</span>
<span>W</span> <div className="input-grid" style={{ width: '84px' }}>
<div className="select-wrap" style={{ width: '84px' }}> <input
<select type="text"
className="select-light dark" className="input-origin block"
name="roofWidth" ref={roofRef.width}
onChange={(e) => { defaultValue={parseInt(currentRoofMaterial.width)}
// readOnly={currentRoofMaterial.widAuth === 'R'}
setCurrentRoofMaterial({ ...currentRoofMaterial, roofWidth: e.target.value }) />
}}
>
<option value={parseInt(currentRoofMaterial.widBase)}>{parseInt(currentRoofMaterial.widBase)}</option>
</select>
</div>
</div> </div>
</> {/* <div className="input-grid" style={{ width: '63px' }}>
<input
type="text"
className="input-origin block"
ref={roofRef.width}
defaultValue={parseInt(currentRoofMaterial.width)}
/>
</div> */}
</div>
)} )}
{['R', 'C'].includes(currentRoofMaterial.lenAuth) && ( {['R', 'C'].includes(currentRoofMaterial.lenAuth) && (
<div className="flex-ment"> <div className="flex-ment">
<span>L</span> <span>L</span>
<div className="select-wrap" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '84px' }}>
<select <input
className="select-light dark" type="text"
name="roofHeight" className="input-origin block"
onChange={(e) => { ref={roofRef.length}
// defaultValue={parseInt(currentRoofMaterial.length)}
setCurrentRoofMaterial({ ...currentRoofMaterial, roofHeight: e.target.value }) readOnly={currentRoofMaterial.lenAuth === 'R'}
}} />
>
<option value={parseInt(currentRoofMaterial.lenBase)}>{parseInt(currentRoofMaterial.lenBase)}</option>
</select>
</div> </div>
{/* <div className="input-grid" style={{ width: '63px' }}>
<input
type="text"
className="input-origin block"
ref={roofRef.length}
defaultValue={parseInt(currentRoofMaterial.length)}
/>
</div> */}
</div> </div>
)} )}
{['C', 'R'].includes(currentRoofMaterial.raftAuth) && ( {['C', 'R'].includes(currentRoofMaterial.raftAuth) && (
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span> <span>{getMessage('modal.placement.initial.setting.rafter')}</span>
<div className="select-wrap" style={{ width: '84px' }}> <div className="select-wrap" style={{ width: '84px' }}>
<select <select className="select-light dark" name="roofGap" ref={roofRef.rafter}>
className="select-light dark" {raftCodes.map((raft, index) => {
name="roofGap" return (
onChange={(e) => { <option key={index} value={raft.clCode}>
// {raft.clCodeNm}
setCurrentRoofMaterial({ ...currentRoofMaterial, roofGap: e.target.value }) </option>
}} )
> })}
<option>455</option>
</select> </select>
</div> </div>
</div> </div>
@ -217,28 +275,42 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, set
{['C', 'R'].includes(currentRoofMaterial.roofPchAuth) && ( {['C', 'R'].includes(currentRoofMaterial.roofPchAuth) && (
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('hajebichi')}</span> <span>{getMessage('hajebichi')}</span>
<div className="grid-select no-flx" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '84px' }}>
<select <input
className="select-light dark" type="text"
name="roofHajebichi" className="input-origin block"
onChange={(e) => { ref={roofRef.hajebichi}
// value={parseInt(currentRoofMaterial.hajebichi)}
setCurrentRoofMaterial({ ...currentRoofMaterial, roofHajebichi: e.target.value }) readOnly={currentRoofMaterial.roofPchAuth === 'R'}
}} />
>
<option value={parseInt(currentRoofMaterial.roofPchBase)}>{parseInt(currentRoofMaterial.roofPchBase)}</option>
</select>
</div> </div>
</div> </div>
)} )}
</div> </div>
<div className="placement-roof-btn-wrap">
<div className="icon-btn-wrap mt10">
<button
className={`${roofLayout === ROOF_MATERIAL_LAYOUT.PARALLEL && 'act'}`}
onClick={() => setRoofLayout(ROOF_MATERIAL_LAYOUT.PARALLEL)}
>
{getMessage('modal.roof.alloc.select.parallel')}
<i className="allocation01"></i>
</button>
<button
className={`${roofLayout === ROOF_MATERIAL_LAYOUT.STAIRS && 'act'}`}
onClick={() => setRoofLayout(ROOF_MATERIAL_LAYOUT.STAIRS)}
>
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
</button>
</div>
</div>
</td> </td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div className="grid-btn-wrap"> <div className="grid-btn-wrap">
<button className="btn-frame modal act" onClick={() => basicSettingSave()}> <button className="btn-frame modal act" onClick={handleSaveBtn}>
{getMessage('modal.common.save')} {getMessage('modal.common.save')}
</button> </button>
</div> </div>

View File

@ -3,17 +3,38 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
import QSelectBox from '@/components/common/select/QSelectBox' import QSelectBox from '@/components/common/select/QSelectBox'
import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting' import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom' import { contextPopupPositionState } from '@/store/popupAtom'
import { useEffect, useState } from 'react'
import { basicSettingState } from '@/store/settingAtom'
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useCommonCode } from '@/hooks/common/useCommonCode'
export default function RoofAllocationSetting(props) { export default function RoofAllocationSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState) const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { handleSave, onAddRoofMaterial, onDeleteRoofMaterial, values, roofMaterials, selectedRoofMaterial, setSelectedRoofMaterial } = const {
useRoofAllocationSetting(id) handleSave,
onAddRoofMaterial,
onDeleteRoofMaterial,
roofMaterials,
setCurrentRoofMaterial,
roofList,
handleDefaultRoofMaterial,
handleChangeRoofMaterial,
} = useRoofAllocationSetting(id)
const { fetchBasicSettings } = useCanvasSetting()
const { findCommonCode } = useCommonCode()
const [raftCodes, setRaftCodes] = useState([])
useEffect(() => {
fetchBasicSettings()
const raftCodeList = findCommonCode('203800')
console.log('🚀 ~ useEffect ~ raftCodeList:', raftCodeList)
setRaftCodes(raftCodeList)
}, [])
return ( return (
<WithDraggable isShow={true} pos={pos}> <WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap ml mount`}> <div className={`modal-pop-wrap ml mount`}>
@ -28,7 +49,13 @@ export default function RoofAllocationSetting(props) {
<div className="allocation-select-wrap"> <div className="allocation-select-wrap">
<span>{getMessage('modal.roof.alloc.select.roof.material')}</span> <span>{getMessage('modal.roof.alloc.select.roof.material')}</span>
<div className="grid-select"> <div className="grid-select">
<QSelectBox options={roofMaterials} value={selectedRoofMaterial} onChange={(e) => setSelectedRoofMaterial(e)} /> <QSelectBox
options={roofMaterials}
onChange={(e) => {
const selected = roofMaterials.find((roofMaterial) => roofMaterial.roofMatlCd === e.id)
setCurrentRoofMaterial(selected)
}}
/>
</div> </div>
<button <button
className="allocation-edit" className="allocation-edit"
@ -41,117 +68,108 @@ export default function RoofAllocationSetting(props) {
</button> </button>
</div> </div>
<div className="grid-option-wrap"> <div className="grid-option-wrap">
{values.map((value, index) => ( {roofList.map((roof, index) => {
<div className="grid-option-box" key={index}> return (
<div className="d-check-radio pop no-text"> <div className="grid-option-box" key={index}>
<input type="radio" name="radio01" /> <div className="d-check-radio pop no-text">
<label htmlFor="ra01"></label> <input type="radio" name="radio01" checked={roof.selected && 'checked'} readOnly={true} />
</div> <label
<div className="grid-option-block-form"> htmlFor="ra01"
<div className="block-box"> onClick={(e) => {
<div className="flex-ment"> handleDefaultRoofMaterial(index)
<div className="grid-select" style={{ width: '248px' }}> }}
<QSelectBox options={roofMaterials} value={value} /> ></label>
</div>
{index === 0 && <span className="dec">基本屋根材</span>}
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(value.id)}></button>}
</div>
</div> </div>
<div className="block-box"> <div className="grid-option-block-form">
{value.type === 'A' ? ( <div className="block-box">
<> <div className="flex-ment">
<div className="grid-select" style={{ width: '248px' }}>
<QSelectBox
options={roofMaterials}
value={roofMaterials.find((r) => r.id === roof.id)}
onChange={(e) => handleChangeRoofMaterial(e, index)}
/>
</div>
{index === 0 && <span className="dec">基本屋根材</span>}
{index !== 0 && <button className="delete" onClick={() => onDeleteRoofMaterial(index)}></button>}
</div>
</div>
<div className="block-box">
{roof.widAuth && (
<div className="flex-ment"> <div className="flex-ment">
<span>W</span> <span>W</span>
<div className="select-wrap" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={roof.width} readOnly />
</div>
{/* <div className="select-wrap" style={{ width: '84px' }}>
<select className="select-light dark" name="" id=""> <select className="select-light dark" name="" id="">
<option>265</option> <option>265</option>
</select> </select>
</div> </div> */}
</div> </div>
)}
{roof.lenAuth && (
<div className="flex-ment"> <div className="flex-ment">
<span>L</span> <span>L</span>
<div className="select-wrap" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '100px' }}>
<input type="text" className="input-origin block" defaultValue={roof.length} readOnly />
</div>
{/* <div className="select-wrap" style={{ width: '84px' }}>
<select className="select-light dark" name="" id=""> <select className="select-light dark" name="" id="">
<option>235</option> <option>235</option>
</select> </select>
</div> </div> */}
</div> </div>
)}
{roof.raftAuth && (
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span> <span>{getMessage('modal.placement.initial.setting.rafter')}</span>
<div className="select-wrap" style={{ width: '84px' }}> <div className="grid-select" style={{ width: '84px' }}>
<select className="select-light dark" name="" id=""> <QSelectBox
<option>455</option> options={raftCodes.map((raft) => ({ name: raft.clCodeNm, value: raft.clCode }))}
</select> value={raftCodes.find((r) => r.id === roof.id)}
/>
{/* <select className="select-light dark" name="roofGap" ref={roofRef.rafter}>
{raftCodes.map((raft, index) => {
return (
<option key={index} value={raft.clCode}>
{raft.clCodeNm}
</option>
)
})}
</select> */}
</div> </div>
</div> </div>
</> )}
) : value.type === 'B' ? ( {roof.roofPchAuth && (
<>
<div className="flex-ment"> <div className="flex-ment">
<span>{getMessage('hajebichi')}</span> <span>{getMessage('hajebichi')}</span>
<div className="grid-select no-flx" style={{ width: '84px' }}> <div className="input-grid" style={{ width: '84px' }}>
<input type="text" className="input-origin block" value={parseInt(roof.hajebichi)} readOnly={roof.roofPchAuth === 'R'} />
</div>
{/* <div className="grid-select no-flx" style={{ width: '84px' }}>
<select className="select-light dark" name="" id=""> <select className="select-light dark" name="" id="">
<option>265</option> <option>265</option>
</select> </select>
</div> </div> */}
</div> </div>
<div className="flex-ment"> )}
<span>{getMessage('modal.placement.initial.setting.rafter')}</span> </div>
<div className="grid-select no-flx right" style={{ width: '84px' }}> <div className="block-box">
<select className="select-light dark" name="" id=""> <div className="icon-btn-wrap">
<option>265</option> <button className={roof.layout === ROOF_MATERIAL_LAYOUT.PARALLEL ? 'act' : ''}>
</select> {getMessage('modal.roof.alloc.select.parallel')}
</div> <i className="allocation01"></i>
</div> </button>
</> <button className={roof.layout === ROOF_MATERIAL_LAYOUT.STAIRS ? 'act' : ''}>
) : value.type === 'C' ? ( {getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
<> </button>
<div className="flex-ment"> </div>
<span>{getMessage('hajebichi')}</span>
<div className="grid-select no-flx" style={{ width: '84px' }}>
<select className="select-light dark" name="" id="">
<option>265</option>
</select>
</div>
</div>
</>
) : value.type === 'D' ? (
<>
<div className="flex-ment">
<span>L</span>
<div className="grid-select no-flx" style={{ width: '84px' }}>
<select className="select-light dark" name="" id="">
<option>265</option>
</select>
</div>
</div>
<div className="flex-ment">
<span>{getMessage('modal.placement.initial.setting.rafter')}</span>
<div className="grid-select no-flx right" style={{ width: '84px' }}>
<select className="select-light dark" name="" id="">
<option>265</option>
</select>
</div>
</div>
</>
) : (
''
)}
</div>
<div className="block-box">
<div className="icon-btn-wrap">
<button className={value.alignType === 'parallel' ? 'act' : ''}>
{getMessage('modal.roof.alloc.select.parallel')}
<i className="allocation01"></i>
</button>
<button className={value.alignType === 'stairs' ? 'act' : ''}>
{getMessage('modal.roof.alloc.select.stairs')} <i className="allocation02"></i>
</button>
</div> </div>
</div> </div>
</div> </div>
</div> )
))} })}
</div> </div>
<div className="grid-btn-wrap"> <div className="grid-btn-wrap">
<button className="btn-frame modal act" onClick={handleSave}> <button className="btn-frame modal act" onClick={handleSave}>

View File

@ -1,9 +1,8 @@
import React, { useEffect, useState } from 'react' import React, { useEffect, useState } from 'react'
import { useCanvasSetting } from '@/hooks/option/useCanvasSetting'
import { useMessage } from '@/hooks/useMessage' import { useMessage } from '@/hooks/useMessage'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { setSurfaceShapePattern } from '@/util/canvas-util'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { useRoofFn } from '@/hooks/common/useRoofFn'
export default function FirstOption(props) { export default function FirstOption(props) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -11,6 +10,7 @@ export default function FirstOption(props) {
let { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props let { canvas, settingModalFirstOptions, setSettingModalFirstOptions, settingsData, setSettingsData, settingsDataSave, setSettingsDataSave } = props
const { option1, option2, dimensionDisplay } = settingModalFirstOptions const { option1, option2, dimensionDisplay } = settingModalFirstOptions
const { initEvent } = useEvent() const { initEvent } = useEvent()
const { setSurfaceShapePattern } = useRoofFn()
// //
useEffect(() => { useEffect(() => {

View File

@ -2,12 +2,13 @@ import { useEffect } from 'react'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { basicSettingState, roofDisplaySelector, settingModalFirstOptionsState } from '@/store/settingAtom' import { basicSettingState, roofDisplaySelector, settingModalFirstOptionsState } from '@/store/settingAtom'
import { canvasState, dotLineGridSettingState, pitchText, pitchTextSelector, showAngleUnitSelector } from '@/store/canvasAtom' import { canvasState, dotLineGridSettingState, pitchText, pitchTextSelector, showAngleUnitSelector } from '@/store/canvasAtom'
import { getChonByDegree, getDegreeByChon, setSurfaceShapePattern } from '@/util/canvas-util' import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util'
import { useFont } from '@/hooks/common/useFont' import { useFont } from '@/hooks/common/useFont'
import { useGrid } from '@/hooks/common/useGrid' import { useGrid } from '@/hooks/common/useGrid'
import { globalFontAtom } from '@/store/fontAtom' import { globalFontAtom } from '@/store/fontAtom'
import { useRoof } from '@/hooks/common/useRoof' import { useRoof } from '@/hooks/common/useRoof'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { useRoofFn } from '@/hooks/common/useRoofFn'
export function useCanvasConfigInitialize() { export function useCanvasConfigInitialize() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -18,6 +19,7 @@ export function useCanvasConfigInitialize() {
const setDotLineGridSetting = useSetRecoilState(dotLineGridSettingState) const setDotLineGridSetting = useSetRecoilState(dotLineGridSettingState)
const pitchText = useRecoilValue(pitchTextSelector) const pitchText = useRecoilValue(pitchTextSelector)
const angleUnit = useRecoilValue(showAngleUnitSelector) const angleUnit = useRecoilValue(showAngleUnitSelector)
const { setSurfaceShapePattern } = useRoofFn()
const {} = useFont() const {} = useFont()
const {} = useGrid() const {} = useGrid()
const {} = useRoof() const {} = useRoof()

View File

@ -2,12 +2,13 @@ import { canvasState } from '@/store/canvasAtom'
import { allocDisplaySelector, roofDisplaySelector } from '@/store/settingAtom' import { allocDisplaySelector, roofDisplaySelector } from '@/store/settingAtom'
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { useEffect } from 'react' import { useEffect } from 'react'
import { useRoofFn } from '@/hooks/common/useRoofFn'
export function useRoof() { export function useRoof() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
const allocDisplay = useRecoilValue(allocDisplaySelector) const allocDisplay = useRecoilValue(allocDisplaySelector)
const roofDisplay = useRecoilValue(roofDisplaySelector) const roofDisplay = useRecoilValue(roofDisplaySelector)
const { setSurfaceShapePattern } = useRoofFn()
useEffect(() => { useEffect(() => {
if (!canvas) return if (!canvas) return
canvas canvas
@ -23,7 +24,7 @@ export function useRoof() {
canvas.renderAll() canvas.renderAll()
}, [allocDisplay]) }, [allocDisplay])
const setSurfaceShapePattern = (polygon, mode = 'onlyBorder') => { /*const setSurfaceShapePattern = (polygon, mode = 'onlyBorder') => {
const ratio = window.devicePixelRatio || 1 const ratio = window.devicePixelRatio || 1
let width = 265 / 10 let width = 265 / 10
@ -145,7 +146,7 @@ export function useRoof() {
polygon.set('fill', null) polygon.set('fill', null)
polygon.set('fill', pattern) polygon.set('fill', pattern)
polygon.canvas?.renderAll() polygon.canvas?.renderAll()
} }*/
return {} return {}
} }

View File

@ -0,0 +1,142 @@
import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom'
import { selectedRoofMaterialSelector } from '@/store/settingAtom'
export function useRoofFn() {
const canvas = useRecoilValue(canvasState)
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
//면형상 선택 클릭시 지붕 패턴 입히기
function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) {
const ratio = window.devicePixelRatio || 1
let width = selectedRoofMaterial.width / 10
let height = selectedRoofMaterial.length / 10
let roofStyle = 2
const inputPatternSize = { width: width, height: height } //임시 사이즈
const patternSize = { ...inputPatternSize } // 입력된 값을 뒤집기 위해
if (polygon.direction === 'east' || polygon.direction === 'west') {
//세로형이면 width height를 바꿈
;[patternSize.width, patternSize.height] = [inputPatternSize.height, patternSize.width]
}
// 패턴 소스를 위한 임시 캔버스 생성
const patternSourceCanvas = document.createElement('canvas')
patternSourceCanvas.width = polygon.width * ratio
patternSourceCanvas.height = polygon.height * ratio
const ctx = patternSourceCanvas.getContext('2d')
let offset = roofStyle === 1 ? 0 : patternSize.width / 2
const rows = Math.floor(patternSourceCanvas.height / patternSize.height)
const cols = Math.floor(patternSourceCanvas.width / patternSize.width)
ctx.strokeStyle = mode === 'allPainted' ? 'black' : 'green'
ctx.lineWidth = mode === 'allPainted' ? 1 : 0.4
ctx.fillStyle = mode === 'allPainted' ? 'rgba(0, 159, 64, 0.7)' : 'white'
if (trestleMode) {
ctx.strokeStyle = 'black'
ctx.lineWidth = 0.2
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'
} else {
ctx.fillStyle = 'rgba(255, 255, 255, 1)'
}
if (polygon.direction === 'east' || polygon.direction === 'west') {
offset = roofStyle === 1 ? 0 : patternSize.height / 2
for (let col = 0; col <= cols; col++) {
const x = col * patternSize.width
const yStart = 0
const yEnd = patternSourceCanvas.height
ctx.beginPath()
ctx.moveTo(x, yStart) // 선 시작점
ctx.lineTo(x, yEnd) // 선 끝점
ctx.stroke()
if (mode === 'allPainted' || trestleMode) {
ctx.fillRect(x, yStart, patternSize.width, yEnd - yStart)
}
for (let row = 0; row <= rows; row++) {
const y = row * patternSize.height + (col % 2 === 0 ? 0 : offset)
const xStart = col * patternSize.width
const xEnd = xStart + patternSize.width
ctx.beginPath()
ctx.moveTo(xStart, y) // 선 시작점
ctx.lineTo(xEnd, y) // 선 끝점
ctx.stroke()
if (mode === 'allPainted' || trestleMode) {
ctx.fillRect(xStart, y, xEnd - xStart, patternSize.height)
}
}
}
} else {
for (let row = 0; row <= rows; row++) {
const y = row * patternSize.height
ctx.beginPath()
ctx.moveTo(0, y) // 선 시작점
ctx.lineTo(patternSourceCanvas.width, y) // 선 끝점
ctx.stroke()
if (mode === 'allPainted' || trestleMode) {
ctx.fillRect(0, y, patternSourceCanvas.width, patternSize.height)
}
for (let col = 0; col <= cols; col++) {
const x = col * patternSize.width + (row % 2 === 0 ? 0 : offset)
const yStart = row * patternSize.height
const yEnd = yStart + patternSize.height
ctx.beginPath()
ctx.moveTo(x, yStart) // 선 시작점
ctx.lineTo(x, yEnd) // 선 끝점
ctx.stroke()
if (mode === 'allPainted' || trestleMode) {
ctx.fillRect(x, yStart, patternSize.width, yEnd - yStart)
}
}
}
}
const hachingPatternSourceCanvas = document.createElement('canvas')
if (mode === 'lineHatch') {
hachingPatternSourceCanvas.width = polygon.width * ratio
hachingPatternSourceCanvas.height = polygon.height * ratio
const ctx1 = hachingPatternSourceCanvas.getContext('2d')
const gap = 10
ctx1.strokeStyle = 'green' // 선 색상
ctx1.lineWidth = 0.3 // 선 두께
for (let x = 0; x < hachingPatternSourceCanvas.width + hachingPatternSourceCanvas.height; x += gap) {
ctx1.beginPath()
ctx1.moveTo(x, 0) // 선 시작점
ctx1.lineTo(0, x) // 선 끝점
ctx1.stroke()
}
}
const combinedPatternCanvas = document.createElement('canvas')
combinedPatternCanvas.width = polygon.width * ratio
combinedPatternCanvas.height = polygon.height * ratio
const combinedCtx = combinedPatternCanvas.getContext('2d')
// 첫 번째 패턴을 그린 후 두 번째 패턴을 덧입힘
combinedCtx.drawImage(patternSourceCanvas, 0, 0)
combinedCtx.drawImage(hachingPatternSourceCanvas, 0, 0)
// 패턴 생성
const pattern = new fabric.Pattern({
source: combinedPatternCanvas,
repeat: 'repeat',
})
polygon.set('fill', null)
polygon.set('fill', pattern)
polygon.canvas?.renderAll()
}
return { setSurfaceShapePattern }
}

View File

@ -1,6 +1,6 @@
import { useRecoilState, useRecoilValue } from 'recoil' import { useRecoilState, useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { rectToPolygon, setSurfaceShapePattern } from '@/util/canvas-util' import { rectToPolygon } from '@/util/canvas-util'
import { roofDisplaySelector } from '@/store/settingAtom' import { roofDisplaySelector } from '@/store/settingAtom'
import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils' import offsetPolygon, { calculateAngle } from '@/util/qpolygon-utils'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
@ -13,6 +13,7 @@ import { useSwal } from '@/hooks/useSwal'
import { canvasSettingState } from '@/store/canvasAtom' import { canvasSettingState } from '@/store/canvasAtom'
import { compasDegAtom } from '@/store/orientationAtom' import { compasDegAtom } from '@/store/orientationAtom'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
import { useRoofFn } from '@/hooks/common/useRoofFn'
export function useModuleBasicSetting() { export function useModuleBasicSetting() {
const canvas = useRecoilValue(canvasState) const canvas = useRecoilValue(canvasState)
@ -23,6 +24,7 @@ export function useModuleBasicSetting() {
const { swalFire } = useSwal() const { swalFire } = useSwal()
const canvasSetting = useRecoilValue(canvasSettingState) const canvasSetting = useRecoilValue(canvasSettingState)
const compasDeg = useRecoilValue(compasDegAtom) const compasDeg = useRecoilValue(compasDegAtom)
const { setSurfaceShapePattern } = useRoofFn()
// const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext) // const { addTargetMouseEventListener, addCanvasMouseEventListener, initEvent } = useContext(EventContext)
let selectedModuleInstSurfaceArray = [] let selectedModuleInstSurfaceArray = []

View File

@ -5,13 +5,14 @@ import { useRecoilValue } from 'recoil'
import { canvasState } from '@/store/canvasAtom' import { canvasState } from '@/store/canvasAtom'
import { BATCH_TYPE, INPUT_TYPE } from '@/common/common' import { BATCH_TYPE, INPUT_TYPE } from '@/common/common'
import { useEvent } from '@/hooks/useEvent' import { useEvent } from '@/hooks/useEvent'
import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, setSurfaceShapePattern, triangleToPolygon } from '@/util/canvas-util' import { pointsToTurfPolygon, polygonToTurfPolygon, rectToPolygon, triangleToPolygon } from '@/util/canvas-util'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import * as turf from '@turf/turf' import * as turf from '@turf/turf'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { fontSelector } from '@/store/fontAtom' import { fontSelector } from '@/store/fontAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
export function useObjectBatch({ isHidden, setIsHidden }) { export function useObjectBatch({ isHidden, setIsHidden }) {
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -20,6 +21,7 @@ export function useObjectBatch({ isHidden, setIsHidden }) {
// const { addCanvasMouseEventListener, initEvent, addDocumentEventListener } = useContext(EventContext) // const { addCanvasMouseEventListener, initEvent, addDocumentEventListener } = useContext(EventContext)
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { drawDirectionArrow } = usePolygon() const { drawDirectionArrow } = usePolygon()
const { setSurfaceShapePattern } = useRoofFn()
const lengthTextFont = useRecoilValue(fontSelector('lengthText')) const lengthTextFont = useRecoilValue(fontSelector('lengthText'))
useEffect(() => { useEffect(() => {

View File

@ -21,6 +21,7 @@ import {
basicSettingState, basicSettingState,
settingsState, settingsState,
roofMaterialsAtom, roofMaterialsAtom,
selectedRoofMaterialSelector,
} from '@/store/settingAtom' } from '@/store/settingAtom'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { globalFontAtom } from '@/store/fontAtom' import { globalFontAtom } from '@/store/fontAtom'
@ -28,6 +29,8 @@ import { dimensionLineSettingsState } from '@/store/commonUtilsAtom'
import { gridColorState } from '@/store/gridAtom' import { gridColorState } from '@/store/gridAtom'
import { useColor } from 'react-color-palette' import { useColor } from 'react-color-palette'
import { useMasterController } from '@/hooks/common/useMasterController' import { useMasterController } from '@/hooks/common/useMasterController'
import { isObjectNotEmpty } from '@/util/common-utils'
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
const defaultDotLineGridSetting = { const defaultDotLineGridSetting = {
INTERVAL: { INTERVAL: {
@ -92,7 +95,7 @@ export function useCanvasSetting() {
const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState) const [canvasSetting, setCanvasSetting] = useRecoilState(canvasSettingState)
const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState) const [basicSetting, setBasicSettings] = useRecoilState(basicSettingState)
const { getRoofMaterialList } = useMasterController() const { getRoofMaterialList, getModuleTypeItemList } = useMasterController()
const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom) const [roofMaterials, setRoofMaterials] = useRecoilState(roofMaterialsAtom)
const SelectOptions = [ const SelectOptions = [
@ -102,13 +105,44 @@ export function useCanvasSetting() {
{ id: 4, name: '1/10', value: 1 / 10 }, { id: 4, name: '1/10', value: 1 / 10 },
] ]
const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
useEffect(() => { useEffect(() => {
if (roofMaterials.length !== 0) {
return
}
addRoofMaterials() addRoofMaterials()
}, []) }, [])
useEffect(() => {
if (!selectedRoofMaterial || !isObjectNotEmpty(selectedRoofMaterial)) {
return
}
const { id } = selectedRoofMaterial
console.log(getModuleTypeItemList(id))
}, [selectedRoofMaterial])
//지붕재 초기세팅
const addRoofMaterials = async () => { const addRoofMaterials = async () => {
const { data } = await getRoofMaterialList() const { data } = await getRoofMaterialList()
setRoofMaterials(data) const roofLists = data.map((item, idx) => ({
...item,
id: item.roofMatlCd,
name: item.roofMatlNm,
selected: idx === 0,
nameJp: item.roofMatlNmJp,
length: item.lenBase && parseInt(item.lenBase),
width: item.widBase && parseInt(item.widBase),
raft: item.raftBase && parseInt(item.raftBase),
layout: ROOF_MATERIAL_LAYOUT.PARALLEL,
hajebichi: item.roofPchBase && parseInt(item.roofPchBase),
}))
setRoofMaterials(roofLists)
const selectedRoofMaterial = roofLists[0]
const addRoofs = []
addRoofs.push({ ...selectedRoofMaterial, selected: true })
setBasicSettings({ ...basicSetting, roofMaterials: selectedRoofMaterial, roofs: addRoofs })
} }
useEffect(() => { useEffect(() => {
@ -144,6 +178,7 @@ export function useCanvasSetting() {
// 배치면 초기설정 변경 시 // 배치면 초기설정 변경 시
useEffect(() => { useEffect(() => {
//console.log('useCanvasSetting canvasSetting 실행', canvasSetting) //console.log('useCanvasSetting canvasSetting 실행', canvasSetting)
if (canvasSetting.flag) { if (canvasSetting.flag) {
basicSettingSave() basicSettingSave()
} }

View File

@ -1,10 +1,9 @@
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom' import { canvasState, currentMenuState, currentObjectState } from '@/store/canvasAtom'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { setSurfaceShapePattern } from '@/util/canvas-util'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
import { usePolygon } from '@/hooks/usePolygon' import { usePolygon } from '@/hooks/usePolygon'
import { roofDisplaySelector } from '@/store/settingAtom' import { basicSettingState, roofDisplaySelector, roofMaterialsSelector, selectedRoofMaterialSelector } from '@/store/settingAtom'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { POLYGON_TYPE } from '@/common/common' import { POLYGON_TYPE } from '@/common/common'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
@ -13,6 +12,7 @@ import { useMessage } from '@/hooks/useMessage'
import useMenu from '@/hooks/common/useMenu' import useMenu from '@/hooks/common/useMenu'
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
import { menuTypeState } from '@/store/menuAtom' import { menuTypeState } from '@/store/menuAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
// 지붕면 할당 // 지붕면 할당
export function useRoofAllocationSetting(id) { export function useRoofAllocationSetting(id) {
@ -26,69 +26,18 @@ export function useRoofAllocationSetting(id) {
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { setMenuNumber } = useCanvasMenu() const { setMenuNumber } = useCanvasMenu()
const setMenuType = useSetRecoilState(menuTypeState) const setMenuType = useSetRecoilState(menuTypeState)
const roofMaterials = [ const roofMaterials = useRecoilValue(roofMaterialsSelector)
{ const selectedRoofMaterial = useRecoilValue(selectedRoofMaterialSelector)
id: 'A', const [basicSetting, setBasicSetting] = useRecoilState(basicSettingState)
name: '기와1', const [currentRoofMaterial, setCurrentRoofMaterial] = useState(roofMaterials[0]) // 팝업 내 기준 지붕재
type: 'A', const [roofList, setRoofList] = useState([])
width: '200',
length: '200',
alignType: 'parallel',
},
{
id: 'B',
name: '기와2',
type: 'B',
rafter: '200',
alignType: 'parallel',
},
{
id: 'C',
name: '기와3',
type: 'C',
hajebichi: '200',
alignType: 'stairs',
},
{
id: 'D',
name: '기와4',
type: 'D',
length: '200',
alignType: 'stairs',
},
]
const widths = [
{ name: '200', id: 'q' },
{ name: '250', id: 'q1' },
{ name: '300', id: 'q2' },
]
const lengths = [
{ name: '200', id: 'w' },
{ name: '250', id: 'w1' },
{ name: '300', id: 'w2' },
]
const rafters = [
{ name: '200', id: 'e' },
{ name: '250', id: 'e1' },
{ name: '300', id: 'e2' },
]
const [values, setValues] = useState([
{
id: 'A',
type: 'A',
roofMaterial: { name: '기와1' },
width: { name: '200' },
length: { name: '250' },
rafter: { name: '300' },
alignType: 'stairs',
},
])
const [radioValue, setRadioValue] = useState('A')
const [editingLines, setEditingLines] = useState([]) const [editingLines, setEditingLines] = useState([])
const [selectedRoofMaterial, setSelectedRoofMaterial] = useState(roofMaterials[0]) const { setSurfaceShapePattern } = useRoofFn()
useEffect(() => {
setRoofList(basicSetting.roofs)
}, [basicSetting])
useEffect(() => { useEffect(() => {
const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // roofPolygon.innerLines const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) // roofPolygon.innerLines
@ -130,11 +79,15 @@ export function useRoofAllocationSetting(id) {
}, []) }, [])
const onAddRoofMaterial = () => { const onAddRoofMaterial = () => {
setValues([...values, selectedRoofMaterial]) if (roofList.length >= 4) {
swalFire({ type: 'alert', icon: 'error', text: getMessage('지붕재는 4개까지 선택 가능합니다.') })
return
}
setRoofList([...roofList, { ...currentRoofMaterial, selected: false, id: currentRoofMaterial.roofMatlCd, name: currentRoofMaterial.roofMatlNm }])
} }
const onDeleteRoofMaterial = (id) => { const onDeleteRoofMaterial = (idx) => {
setValues(values.filter((value) => value.id !== id)) setRoofList([...roofList.filter((_, index) => index !== idx)])
} }
const { handleMenu } = useMenu() const { handleMenu } = useMenu()
@ -207,6 +160,13 @@ export function useRoofAllocationSetting(id) {
canvas.remove(wallLine) canvas.remove(wallLine)
}) })
setBasicSetting((prev) => {
return {
...prev,
roofs: roofList,
}
})
const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof')
roofs.forEach((roof) => { roofs.forEach((roof) => {
@ -246,25 +206,45 @@ export function useRoofAllocationSetting(id) {
canvas?.renderAll() canvas?.renderAll()
} }
const handleRadioOnChange = (e) => { //roof input값 변경
setRadioValue(e.target) const handleChangeInput = (type, value, index) => {}
// 지붕재 변경
const handleChangeRoofMaterial = (value, index) => {
const selectedRoofMaterial = roofMaterials.find((roof) => roof.roofMatlCd === value.id)
const newRoofList = roofList.map((roof, idx) => {
if (idx === index) {
return { ...selectedRoofMaterial }
}
return roof
})
setRoofList(newRoofList)
}
// 기본 지붕재 radio값 변경
const handleDefaultRoofMaterial = (index) => {
const newRoofList = roofList.map((roof, idx) => {
return { ...roof, selected: idx === index }
})
setRoofList(newRoofList)
} }
return { return {
handleSave, handleSave,
onAddRoofMaterial, onAddRoofMaterial,
onDeleteRoofMaterial, onDeleteRoofMaterial,
handleRadioOnChange,
handleAlloc, handleAlloc,
setLineSize, setLineSize,
widths,
lengths,
rafters,
values,
roofMaterials, roofMaterials,
selectedRoofMaterial, selectedRoofMaterial,
setSelectedRoofMaterial, basicSetting,
radioValue, setBasicSetting,
setRadioValue, currentRoofMaterial,
setCurrentRoofMaterial,
roofList,
handleDefaultRoofMaterial,
handleChangeRoofMaterial,
} }
} }

View File

@ -13,7 +13,7 @@ import { useMouse } from '@/hooks/useMouse'
import { useLine } from '@/hooks/useLine' import { useLine } from '@/hooks/useLine'
import { useTempGrid } from '@/hooks/useTempGrid' import { useTempGrid } from '@/hooks/useTempGrid'
import { useEffect, useRef } from 'react' import { useEffect, useRef } from 'react'
import { distanceBetweenPoints, setSurfaceShapePattern } from '@/util/canvas-util' import { distanceBetweenPoints } from '@/util/canvas-util'
import { fabric } from 'fabric' import { fabric } from 'fabric'
import { calculateAngle } from '@/util/qpolygon-utils' import { calculateAngle } from '@/util/qpolygon-utils'
import { import {
@ -33,6 +33,7 @@ import { POLYGON_TYPE } from '@/common/common'
import { usePopup } from '@/hooks/usePopup' import { usePopup } from '@/hooks/usePopup'
import { roofDisplaySelector } from '@/store/settingAtom' import { roofDisplaySelector } from '@/store/settingAtom'
import { useRoofFn } from '@/hooks/common/useRoofFn'
// 면형상 배치 // 면형상 배치
export function usePlacementShapeDrawing(id) { export function usePlacementShapeDrawing(id) {
@ -46,6 +47,7 @@ export function usePlacementShapeDrawing(id) {
const { addLine, removeLine } = useLine() const { addLine, removeLine } = useLine()
const { addPolygonByLines, drawDirectionArrow } = usePolygon() const { addPolygonByLines, drawDirectionArrow } = usePolygon()
const { tempGridMode } = useTempGrid() const { tempGridMode } = useTempGrid()
const { setSurfaceShapePattern } = useRoofFn()
const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState)

View File

@ -3,7 +3,7 @@
import { useRecoilValue } from 'recoil' import { useRecoilValue } from 'recoil'
import { canvasState, globalPitchState } from '@/store/canvasAtom' import { canvasState, globalPitchState } from '@/store/canvasAtom'
import { MENU, POLYGON_TYPE } from '@/common/common' import { MENU, POLYGON_TYPE } from '@/common/common'
import { getIntersectionPoint, setSurfaceShapePattern } from '@/util/canvas-util' import { getIntersectionPoint } from '@/util/canvas-util'
import { degreesToRadians } from '@turf/turf' import { degreesToRadians } from '@turf/turf'
import { QPolygon } from '@/components/fabric/QPolygon' import { QPolygon } from '@/components/fabric/QPolygon'
import { useSwal } from '@/hooks/useSwal' import { useSwal } from '@/hooks/useSwal'
@ -15,6 +15,7 @@ import { usePolygon } from '@/hooks/usePolygon'
import { fontSelector } from '@/store/fontAtom' import { fontSelector } from '@/store/fontAtom'
import { slopeSelector } from '@/store/commonAtom' import { slopeSelector } from '@/store/commonAtom'
import { QLine } from '@/components/fabric/QLine' import { QLine } from '@/components/fabric/QLine'
import { useRoofFn } from '@/hooks/common/useRoofFn'
export function useSurfaceShapeBatch() { export function useSurfaceShapeBatch() {
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -29,6 +30,7 @@ export function useSurfaceShapeBatch() {
const { addCanvasMouseEventListener, initEvent } = useEvent() const { addCanvasMouseEventListener, initEvent } = useEvent()
// const { addCanvasMouseEventListener, initEvent } = useContext(EventContext) // const { addCanvasMouseEventListener, initEvent } = useContext(EventContext)
const { closePopup } = usePopup() const { closePopup } = usePopup()
const { setSurfaceShapePattern } = useRoofFn()
const applySurfaceShape = (surfaceRefs, selectedType, id) => { const applySurfaceShape = (surfaceRefs, selectedType, id) => {
let length1, length2, length3, length4, length5 let length1, length2, length3, length4, length5

View File

@ -203,8 +203,10 @@ export const basicSettingState = atom({
default: { default: {
roofSizeSet: 1, roofSizeSet: 1,
roofAngleSet: 'slope', roofAngleSet: 'slope',
selectedRoofMaterial: {}, selectedRoofMaterial: {}, // 선택된 지붕재
roofs: [], // 지붕면 할당에서 추가된 지붕재 목록
}, },
dangerouslyAllowMutability: true,
}) })
// db에 등록된 지붕재 목록 // db에 등록된 지붕재 목록
@ -213,6 +215,34 @@ export const roofMaterialsAtom = atom({
default: [], default: [],
}) })
//현재 선택된 지붕재
export const selectedRoofMaterialSelector = selector({
key: 'selectedRoofMaterialSelector',
get: ({ get }) => {
const basicSetting = get(basicSettingState)
return basicSetting.selectedRoofMaterial
},
})
// QSelectBox에서 사용할 지붕재 목록
export const roofMaterialsSelector = selector({
key: 'roofMaterialsSelector',
get: ({ get }) => {
const roofMaterials = get(roofMaterialsAtom)
return roofMaterials.map((material) => ({ ...material, id: material.roofMatlCd, name: material.roofMatlNm }))
},
})
// 지붕면 할당에서 추가된 지붕재 목록
export const addedRoofsSelector = selector({
key: 'addedRoofsSelector',
get: ({ get }) => {
const basicSetting = get(basicSettingState)
return basicSetting.roofs
},
dangerouslyAllowMutability: true,
})
/** /**
* 현재 선택된 물건 번호 * 현재 선택된 물건 번호
*/ */

View File

@ -792,7 +792,7 @@ export const rectToPolygon = (rect) => {
} }
//면형상 선택 클릭시 지붕 패턴 입히기 //면형상 선택 클릭시 지붕 패턴 입히기
export function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) { function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false) {
const ratio = window.devicePixelRatio || 1 const ratio = window.devicePixelRatio || 1
let width = 265 / 10 let width = 265 / 10