Merge branch 'qcast-pub' into dev

# Conflicts:
#	src/components/floor-plan/CanvasFrame.jsx
#	src/hooks/common/useCommonUtils.js
This commit is contained in:
minsik 2024-10-24 18:02:20 +09:00
commit 61165f56c9
27 changed files with 923 additions and 59 deletions

View File

@ -24,4 +24,4 @@ Allpainted : allPainted
개구: openSpace
도머: dormer
그림자: shadow
치수선: dimensionLine

View File

@ -3,9 +3,12 @@ import ColorPicker from '@/components/common/color-picker/ColorPicker'
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function ColorPickerModal(props) {
const { isShow, setIsShow, pos = { x: 770, y: -815 }, color = '#ff0000', setColor, id } = props
const contextPopupPosition = useRecoilValue(contextPopupPositionState) //
const { isShow, setIsShow, pos = contextPopupPosition, color = '#ff0000', setColor, id } = props
const { getMessage } = useMessage()
const [originColor, setOriginColor] = useState(color)
const { closePopup } = usePopup()
@ -15,14 +18,17 @@ export default function ColorPickerModal(props) {
}, [isShow])
return (
<WithDraggable isShow={true} pos={pos}>
<WithDraggable isShow={true} pos={pos ?? ''}>
<div className={`modal-pop-wrap lr mount`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.color.picker.title')}</h1>
<button
className="modal-close"
onClick={() => {
setIsShow(false)
if (setIsShow) {
setIsShow(false)
}
console.log(id)
closePopup(id)
}}
>
@ -40,8 +46,9 @@ export default function ColorPickerModal(props) {
<button
className="btn-frame modal act"
onClick={() => {
setColor(originColor)
setIsShow(false)
if (setColor) setColor(originColor)
if (setIsShow) setIsShow(false)
closePopup(id)
}}
>

View File

@ -1,11 +1,11 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import QSelectBox from '@/components/common/select/QSelectBox'
import { usePopup } from '@/hooks/usePopup'
import { useEffect, useState } from 'react'
import { useState } from 'react'
import { useMessage } from '@/hooks/useMessage'
import { useRecoilState, useRecoilValue } from 'recoil'
import { fontSelector, globalFontAtom } from '@/store/fontAtom'
import { useFont } from '@/hooks/common/useFont'
import { contextPopupPositionState } from '@/store/popupAtom'
const fonts = [
{ name: 'MS PGothic', value: 'MS PGothic' },
@ -46,7 +46,8 @@ const fontColors = [
{ name: '남색', value: 'darkblue' },
]
export default function FontSetting(props) {
const { id, setIsShow, pos = { x: 455, y: 180 }, type } = props
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, setIsShow, pos = contextPopupPosition, type } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const [globalFont, setGlobalFont] = useRecoilState(globalFontAtom)
@ -69,7 +70,7 @@ export default function FontSetting(props) {
},
}
})
setIsShow(false)
if (setIsShow) setIsShow(false)
closePopup(id)
}
@ -81,7 +82,7 @@ export default function FontSetting(props) {
<button
className="modal-close"
onClick={() => {
setIsShow(false)
if (setIsShow) setIsShow(false)
closePopup(id)
}}
>

View File

@ -20,7 +20,7 @@ export default function QSelectBox({ title = '', options, onChange, value }) {
<ul className="select-item-wrap">
{options?.map((option) => (
<li key={option.id} className="select-item" onClick={() => handleClickSelectOption(option)}>
<button>{option.name}</button>
<button key={option.id + 'btn'}>{option.name}</button>
</li>
))}
</ul>

View File

@ -16,7 +16,7 @@ export default function CanvasFrame({ plan }) {
const canvasRef = useRef(null)
const { canvas } = useCanvas('canvas')
const { handleZoomClear } = useCanvasEvent()
const { contextMenu, currentContextMenu, setCurrentContextMenu } = useContextMenu({
const { contextMenu, currentContextMenu, setCurrentContextMenu, handleClick } = useContextMenu({
externalFn: {
handleZoomClear,
},
@ -59,7 +59,7 @@ export default function CanvasFrame({ plan }) {
if (menu.fn) {
menu.fn()
}
setCurrentContextMenu(menu)
handleClick(e, menu)
}}
>
{menu.name}
@ -68,7 +68,6 @@ export default function CanvasFrame({ plan }) {
</ul>
))}
</QContextMenu>
{currentContextMenu?.component}
</div>
)
}

View File

@ -5,14 +5,13 @@ import { useRecoilState, useRecoilValue } from 'recoil'
import { useAxios } from '@/hooks/useAxios'
import { globalLocaleStore } from '@/store/localeAtom'
import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import '@/styles/contents.scss'
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
import '@/styles/contents.scss'
export default function FloorPlan() {
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get } = useAxios(globalLocaleState)
const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
const [objectNo, setObjectNo] = useState('test123240912001') //
@ -23,7 +22,6 @@ export default function FloorPlan() {
menuNumber,
setMenuNumber,
}
useEffect(() => {
console.log('FloorPlan useEffect 실행')
fetchSettings()

View File

@ -0,0 +1,55 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function AuxiliaryCopy(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm`}>
<div className="modal-head">
<h1 className="title">補助線のコピー </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="grid-option-tit">コピーする方向を入力してください</div>
<div className="grid-option-wrap">
<div className="grid-option-box">
<div className="move-form">
<p className="mb5">長さ</p>
<div className="input-move-wrap mb5">
<div className="input-move">
<input type="text" className="input-origin" defaultValue={910} />
</div>
<span>mm</span>
</div>
<div className="input-move-wrap">
<div className="input-move">
<input type="text" className="input-origin" defaultValue={910} />
</div>
<span>mm</span>
</div>
</div>
<div className="direction-move-wrap">
<button className="direction up"></button>
<button className="direction down act"></button>
<button className="direction left"></button>
<button className="direction right"></button>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">保存</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -1,14 +1,20 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import { usePopup } from '@/hooks/usePopup'
export default function AuxiliaryMove({ setCurrentContextMenu }) {
export default function AuxiliaryMove(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={{ x: 0, y: 150 }}>
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm`}>
<div className="modal-head">
<h1 className="title">補助線の移動 </h1>
<button className="modal-close" onClick={() => setCurrentContextMenu(null)}>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>

View File

@ -1,14 +1,20 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function AuxiliarySize({ setCurrentContextMenu }) {
export default function AuxiliarySize(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={{ x: 0, y: 150 }}>
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm`}>
<div className="modal-head">
<h1 className="title">補助線サイズ変更 </h1>
<button className="modal-close" onClick={() => setCurrentContextMenu(null)}>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>

View File

@ -6,6 +6,19 @@ export default function Orientation({ setTabNum }) {
const [compasDeg, setCompasDeg] = useState(0)
const [hasAnglePassivity, setHasAnglePassivity] = useState(false)
const getDegree = (degree) => {
if (degree % 15 === 0) return degree
let value = Math.floor(degree / 15)
const remain = ((degree / 15) % 1).toFixed(5)
if (remain > 0.4) {
value++
}
return value * 15
}
return (
<>
<div className="properties-setting-wrap">
@ -18,7 +31,7 @@ export default function Orientation({ setTabNum }) {
{Array.from({ length: 180 / 15 }).map((dot, index) => (
<div
key={index}
className={`circle ${compasDeg === 15 * (12 + index) ? 'act' : ''}`}
className={`circle ${getDegree(compasDeg) === 15 * (12 + index) ? 'act' : ''}`}
onClick={() => setCompasDeg(15 * (12 + index))}
>
{index === 0 && <i>180°</i>}
@ -26,13 +39,13 @@ export default function Orientation({ setTabNum }) {
</div>
))}
{Array.from({ length: 180 / 15 }).map((dot, index) => (
<div key={index} className={`circle ${compasDeg === 15 * index ? 'act' : ''}`} onClick={() => setCompasDeg(15 * index)}>
<div key={index} className={`circle ${getDegree(compasDeg) === 15 * index ? 'act' : ''}`} onClick={() => setCompasDeg(15 * index)}>
{index === 0 && <i>0°</i>}
{index === 6 && <i>90°</i>}
</div>
))}
<div className="compas">
<div className="compas-arr" style={{ transform: `rotate(${compasDeg}deg)` }}></div>
<div className="compas-arr" style={{ transform: `rotate(${getDegree(compasDeg)}deg)` }}></div>
</div>
</div>
</div>

View File

@ -0,0 +1,74 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { usePopup } from '@/hooks/usePopup'
import { useMessage } from '@/hooks/useMessage'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import QSelectBox from '@/components/common/select/QSelectBox'
export default function DimensionLineSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, setIsShow, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const SelectOption01 = [{ name: '0' }, { name: '0' }, { name: '0' }, { name: '0' }]
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm`}>
<div className="modal-head">
<h1 className="title">表示の変更 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="guide">寸法線に表示する数値を入力してください</div>
<div className="mb-box">
<div className="slope-wrap">
<div className="outline-form mb15">
<span className="mr10">既存の長さ</span>
<div className="input-grid mr5">
<input type="text" className="input-origin block" defaultValue={5933} readOnly />
</div>
</div>
<div className="mb-box">
<div className="outline-form">
<span className="mr10">変更の長さ</span>
<div className="input-grid mr5">
<input type="text" className="input-origin block" defaultValue={0} />
</div>
</div>
</div>
<div className="d-check-box pop">
<input type="checkbox" id="ch99" />
<label htmlFor="ch99">コーナーゴールの場合</label>
</div>
</div>
</div>
<div className="slope-wrap">
<div className="warning">傾斜を着せてください</div>
<div className="display-change-wrap">
<div className="outline-form mb15">
<span className="mr10">傾斜</span>
<div className="grid-select mr10">
<QSelectBox title={'0'} option={SelectOption01} />
</div>
<span className="thin">寸法</span>
</div>
<div className="outline-form">
<span className="mr10">傾斜</span>
<div className="grid-select mr10">
<QSelectBox title={'0'} option={SelectOption01} />
</div>
<span className="thin">寸法</span>
</div>
</div>
<div className="warning">傾き設定されている場合入力した数値に傾き計算をした数値が表示されます</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">保存</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,67 @@
import WithDraggable from '@/components/common/draggable/withDraggable'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function Distance(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition, distance } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xxxm`}>
<div className="modal-head">
<h1 className="title">距離測定 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="slope-wrap">
<div className="eaves-keraba-table">
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">2点間距離</div>
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '98px' }}>
<input type="text" className="input-origin block" defaultValue={0} value={distance.diagonal} readOnly />
</div>
<span className="thin">mm</span>
</div>
</div>
</div>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">水平距離</div>
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '98px' }}>
<input type="text" className="input-origin block" defaultValue={0} value={distance.horizon} readOnly />
</div>
<span className="thin">mm</span>
</div>
</div>
</div>
<div className="eaves-keraba-item">
<div className="eaves-keraba-th">垂直距離</div>
<div className="eaves-keraba-td">
<div className="outline-form">
<div className="input-grid mr5" style={{ width: '98px' }}>
<input type="text" className="input-origin block" defaultValue={0} value={distance.vertical} readOnly />
</div>
<span className="thin">mm</span>
</div>
</div>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">確認</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,150 @@
import WithDraggable from '@/components/common/draggable/withDraggable'
import { useState } from 'react'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
const SelectOption01 = [{ name: 'M' }, { name: 'M' }, { name: 'M' }, { name: 'M' }]
export default function FlowDirectionSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const [compasDeg, setCompasDeg] = useState(0)
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap lx`}>
<div className="modal-head">
<h1 className="title">面フローの設定 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="drawing-flow-wrap">
<div className="discrimination-box">
<div className="discrimination-tit mb15">流れ方向の設定</div>
<div className="guide">流れ方向を選択してください</div>
<div className="object-direction-wrap">
<div className="plane-direction">
<span className="top"></span>
<span className="right">ドン</span>
<span className="bottom"></span>
<span className="left">立つ</span>
<button className="plane-btn up"></button>
<button className="plane-btn right"></button>
<button className="plane-btn down act"></button>
<button className="plane-btn left"></button>
</div>
</div>
</div>
<div className="discrimination-box">
<div className="discrimination-tit mb15">方位設定</div>
<div className="guide">シミュレーション計算の方向を指定します面が向いている方位を選択してください</div>
<div className="mb-box">
<div className="d-check-radio pop mb15">
<input type="radio" name="radio01" id="ra01" />
<label htmlFor="ra01">8方位に選ぶ</label>
</div>
<div className="grid-select ">
<QSelectBox title={'M'} options={SelectOption01} />
</div>
</div>
<div className="mb-box">
<div className="d-check-radio pop">
<input type="radio" name="radio02" id="ra02" />
<label htmlFor="ra02">24方位から選択する (表記は8方位です)</label>
</div>
</div>
<div className="compas-box">
<div className="compas-box-inner">
<div className={`circle ${compasDeg === 180 ? 'act' : ''}`} onClick={() => setCompasDeg(180)}>
<i>13</i>
</div>
<div className={`circle ${compasDeg === 195 ? 'act' : ''}`} onClick={() => setCompasDeg(195)}>
<i>12</i>
</div>
<div className={`circle ${compasDeg === 210 ? 'act' : ''}`} onClick={() => setCompasDeg(210)}>
<i>11</i>
</div>
<div className={`circle ${compasDeg === 225 ? 'act' : ''}`} onClick={() => setCompasDeg(225)}>
<i>10</i>
</div>
<div className={`circle ${compasDeg === 240 ? 'act' : ''}`} onClick={() => setCompasDeg(240)}>
<i>9</i>
</div>
<div className={`circle ${compasDeg === 255 ? 'act' : ''}`} onClick={() => setCompasDeg(255)}>
<i>8</i>
</div>
<div className={`circle ${compasDeg === 270 ? 'act' : ''}`} onClick={() => setCompasDeg(270)}>
<i>7</i>
</div>
<div className={`circle ${compasDeg === 285 ? 'act' : ''}`} onClick={() => setCompasDeg(285)}>
<i>6</i>
</div>
<div className={`circle ${compasDeg === 300 ? 'act' : ''}`} onClick={() => setCompasDeg(300)}>
<i>5</i>
</div>
<div className={`circle ${compasDeg === 315 ? 'act' : ''}`} onClick={() => setCompasDeg(315)}>
<i>4</i>
</div>
<div className={`circle ${compasDeg === 330 ? 'act' : ''}`} onClick={() => setCompasDeg(330)}>
<i>3</i>
</div>
<div className={`circle ${compasDeg === 345 ? 'act' : ''}`} onClick={() => setCompasDeg(345)}>
<i>2</i>
</div>
<div className={`circle ${compasDeg === 0 ? 'act' : ''}`} onClick={() => setCompasDeg(0)}>
<i>1</i>
</div>
<div className={`circle ${compasDeg === 15 ? 'act' : ''}`} onClick={() => setCompasDeg(15)}>
<i>24</i>
</div>
<div className={`circle ${compasDeg === 30 ? 'act' : ''}`} onClick={() => setCompasDeg(30)}>
<i>23</i>
</div>
<div className={`circle ${compasDeg === 45 ? 'act' : ''}`} onClick={() => setCompasDeg(45)}>
<i>22</i>
</div>
<div className={`circle ${compasDeg === 60 ? 'act' : ''}`} onClick={() => setCompasDeg(60)}>
<i>21</i>
</div>
<div className={`circle ${compasDeg === 75 ? 'act' : ''}`} onClick={() => setCompasDeg(75)}>
<i>20</i>
</div>
<div className={`circle ${compasDeg === 90 ? 'act' : ''}`} onClick={() => setCompasDeg(90)}>
<i>19</i>
</div>
<div className={`circle ${compasDeg === 105 ? 'act' : ''}`} onClick={() => setCompasDeg(105)}>
<i>18</i>
</div>
<div className={`circle ${compasDeg === 120 ? 'act' : ''}`} onClick={() => setCompasDeg(120)}>
<i>17</i>
</div>
<div className={`circle ${compasDeg === 135 ? 'act' : ''}`} onClick={() => setCompasDeg(135)}>
<i>16</i>
</div>
<div className={`circle ${compasDeg === 150 ? 'act' : ''}`} onClick={() => setCompasDeg(150)}>
<i>15</i>
</div>
<div className={`circle ${compasDeg === 165 ? 'act' : ''}`} onClick={() => setCompasDeg(165)}>
<i>14</i>
</div>
<div className="compas">
<div className="compas-arr" style={{ transform: `rotate(${compasDeg}deg)` }}></div>
</div>
</div>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">保存</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -1,16 +1,21 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function GridCopy(props) {
const { setShowGridMoveModal, setShowGridCopyModal } = props
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={{ x: 50, y: 380 }}>
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm mount`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.grid.copy')} </h1>
<button className="modal-close" onClick={() => setShowGridCopyModal(false)}>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>

View File

@ -1,16 +1,21 @@
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function GridMove(props) {
const { setShowGridMoveModal, setShowGridCopyModal } = props
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={{ x: 50, y: 30 }}>
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm mount`}>
<div className="modal-head">
<h1 className="title">{getMessage('modal.grid.move')} </h1>
<button className="modal-close" onClick={() => setShowGridMoveModal(false)}>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>

View File

@ -0,0 +1,104 @@
import WithDraggable from '@/components/common/draggable/withDraggable'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import { useMessage } from '@/hooks/useMessage'
import { usePopup } from '@/hooks/usePopup'
export default function LinePropertySetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap r`}>
<div className="modal-head">
<h1 className="title">各辺属性の変更 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="guide">
<span className="mb10">属性を変更する辺を選択してください</span>
<span>選択した値 [龍丸]</span>
</div>
<div className="properties-setting-wrap outer">
<div className="setting-tit">設定</div>
<div className="outline-wrap">
<div className="radio-grid-wrap">
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra01" />
<label htmlFor="ra01">軒先</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra02" />
<label htmlFor="ra02">ケラバ</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra03" />
<label htmlFor="ra03">龍丸</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra04" />
<label htmlFor="ra04">ケラバ左</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra05" />
<label htmlFor="ra05">ヨセムネ</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra06" />
<label htmlFor="ra06">ケラバ右</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra07" />
<label htmlFor="ra07">片側の流れ</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra08" />
<label htmlFor="ra08"></label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra09" />
<label htmlFor="ra09">壁取り</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra10" />
<label htmlFor="ra10">Lの捨て渓谷</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra11" />
<label htmlFor="ra11">壁取り()</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra12" />
<label htmlFor="ra12">マンサード</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra13" />
<label htmlFor="ra13">壁取合(流れ)</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra14" />
<label htmlFor="ra14">設定なし</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra15" />
<label htmlFor="ra15">壁取合(流れ左)</label>
</div>
<div className="d-check-radio pop">
<input type="radio" name="radio01" id="ra16" />
<label htmlFor="ra16">壁取り(流れ右)</label>
</div>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">保存</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,55 @@
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
import { usePopup } from '@/hooks/usePopup'
export default function DormerOffset(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xm`}>
<div className="modal-head">
<h1 className="title">도머 오프셋 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="grid-option-tit">移動する方向を入力してください</div>
<div className="grid-option-wrap">
<div className="grid-option-box">
<div className="move-form">
<p className="mb5">長さ</p>
<div className="input-move-wrap mb5">
<div className="input-move">
<input type="text" className="input-origin" defaultValue={910} />
</div>
<span>mm</span>
</div>
<div className="input-move-wrap">
<div className="input-move">
<input type="text" className="input-origin" defaultValue={910} />
</div>
<span>mm</span>
</div>
</div>
<div className="direction-move-wrap">
<button className="direction up"></button>
<button className="direction down act"></button>
<button className="direction left"></button>
<button className="direction right"></button>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">保存</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,45 @@
'use client'
import { useRecoilValue } from 'recoil'
import { useMessage } from '@/hooks/useMessage'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { usePopup } from '@/hooks/usePopup'
import { contextPopupPositionState } from '@/store/popupAtom'
import QSelectBox from '@/components/common/select/QSelectBox'
export default function RoofMaterialSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const roofMaterials = [
{ name: '기와1', value: 'material1' },
{ name: '기와2', value: 'material2' },
{ name: '기와3', value: 'material3' },
{ name: '기와4', value: 'material4' },
{ name: '기와5', value: 'material5' },
]
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap xxxm`}>
<div className="modal-head">
<h1 className="title">変更 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="slope-wrap">
<div className="grid-select">
<QSelectBox title={'지붕재 선택'} options={roofMaterials} />
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">ストレージ</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -0,0 +1,71 @@
'use client'
import { useRecoilValue } from 'recoil'
import { useMessage } from '@/hooks/useMessage'
import { canvasState } from '@/store/canvasAtom'
import WithDraggable from '@/components/common/draggable/WithDraggable'
import { usePopup } from '@/hooks/usePopup'
import { contextPopupPositionState } from '@/store/popupAtom'
import { useState } from 'react'
export default function SizeSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const [settingTarget, setSettingTarget] = useState(1)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const canvas = useRecoilValue(canvasState)
const { closePopup } = usePopup()
return (
<WithDraggable isShow={true} pos={pos}>
<div className={`modal-pop-wrap ssm`}>
<div className="modal-head">
<h1 className="title">サイズ変更 </h1>
<button className="modal-close" onClick={() => closePopup(id)}>
닫기
</button>
</div>
<div className="modal-body">
<div className="slope-wrap">
<div className="size-option-top">
<div className="size-option-wrap">
<div className="size-option mb5">
<input type="text" className="input-origin mr5" defaultValue={1000} readOnly />
<span className="normal-font">mm</span>
</div>
<div className="size-option">
<input type="text" className="input-origin mr5" defaultValue={1000} />
<span className="normal-font">mm</span>
</div>
</div>
</div>
<div className="size-inner-warp">
<div className="size-option-side">
<div className="size-option-wrap">
<div className="size-option mb5">
<input type="text" className="input-origin mr5" defaultValue={1000} readOnly />
<span className="normal-font">mm</span>
</div>
<div className="size-option">
<input type="text" className="input-origin mr5" defaultValue={1000} />
<span className="normal-font">mm</span>
</div>
</div>
</div>
<div className="size-check-wrap">
<button className={`size-btn ${settingTarget === 1 ? 'act' : ''}`} onClick={() => setSettingTarget(1)}></button>
<button className={`size-btn ${settingTarget === 2 ? 'act' : ''}`} onClick={() => setSettingTarget(2)}></button>
<button className={`size-btn ${settingTarget === 3 ? 'act' : ''}`} onClick={() => setSettingTarget(3)}></button>
<button className={`size-btn ${settingTarget === 4 ? 'act' : ''}`} onClick={() => setSettingTarget(4)}></button>
<div className="size-box"></div>
</div>
</div>
</div>
<div className="grid-btn-wrap">
<button className="btn-frame modal act">作成</button>
</div>
</div>
</div>
</WithDraggable>
)
}

View File

@ -3,8 +3,12 @@ import WithDraggable from '@/components/common/draggable/WithDraggable'
import QSelectBox from '@/components/common/select/QSelectBox'
import { useRoofAllocationSetting } from '@/hooks/roofcover/useRoofAllocationSetting'
import { usePopup } from '@/hooks/usePopup'
import { useRecoilValue } from 'recoil'
import { contextPopupPositionState } from '@/store/popupAtom'
export default function RoofAllocationSetting({ id, pos = { x: 50, y: 230 } }) {
export default function RoofAllocationSetting(props) {
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
const { id, pos = contextPopupPosition } = props
const { getMessage } = useMessage()
const { closePopup } = usePopup()
const { handleSave, onAddRoofMaterial, onDeleteRoofMaterial, values, roofMaterials, selectedRoofMaterial, setSelectedRoofMaterial } =

View File

@ -6,6 +6,9 @@ import { checkLineOrientation, getDistance, setSurfaceShapePattern } from '@/uti
import { dimensionLineSettingsState } from '@/store/commonUtilsAtom'
import { fontSelector } from '@/store/fontAtom'
import { canvasState } from '@/store/canvasAtom'
import { v4 as uuidv4 } from 'uuid'
import { usePopup } from '@/hooks/usePopup'
import Distance from '@/components/floor-plan/modal/distance/Distance'
export function useCommonUtils({ commonFunctionState, setCommonFunctionState }) {
const canvas = useRecoilValue(canvasState)
@ -14,6 +17,7 @@ export function useCommonUtils({ commonFunctionState, setCommonFunctionState })
const dimensionSettings = useRecoilValue(dimensionLineSettingsState)
const dimensionLineTextFont = useRecoilValue(fontSelector('dimensionLineText'))
const commonTextFont = useRecoilValue(fontSelector('commonText'))
const { addPopup } = usePopup()
useEffect(() => {
initEvent()
@ -106,7 +110,8 @@ export function useCommonUtils({ commonFunctionState, setCommonFunctionState })
const lineOptions = {
stroke: dimensionSettings.color,
strokeWidth: dimensionSettings.pixel,
selectable: false,
name: 'dimensionLine',
selectable: true,
}
// 캔버스에 클릭 이벤트 추가
@ -375,6 +380,19 @@ export function useCommonUtils({ commonFunctionState, setCommonFunctionState })
// 거리 계산 후, 다음 측정을 위해 초기화
points = []
const id = uuidv4()
addPopup(
id,
1,
<Distance
id={id}
distance={{
horizon: distance3 * 10,
vertical: distance2 * 10,
diagonal: distance1 * 10,
}}
/>,
)
}
// 캔버스 다시 그리기

View File

@ -86,6 +86,12 @@ export function useRoofAllocationSetting(id) {
swalFire({ text: '할당할 지붕이 없습니다.' })
closePopup(id)
}
// if (type === 'roofBase') {
// // 지붕면 할당
//
// } else if ('roof') {
// // 지붕재 변경
// }
}, [])
const onAddRoofMaterial = () => {

View File

@ -1,18 +1,36 @@
import { useRecoilValue } from 'recoil'
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
import { currentMenuState, currentObjectState } from '@/store/canvasAtom'
import { useEffect, useState } from 'react'
import { MENU } from '@/common/common'
import AuxiliaryMove from '@/components/floor-plan/modal/auxiliary/AuxiliaryMove'
import AuxiliarySize from '@/components/floor-plan/modal/auxiliary/AuxiliarySize'
import { usePopup } from '@/hooks/usePopup'
import { v4 as uuidv4 } from 'uuid'
import GridMove from '@/components/floor-plan/modal/grid/GridMove'
import GridCopy from '@/components/floor-plan/modal/grid/GridCopy'
import ColorPickerModal from '@/components/common/color-picker/ColorPickerModal'
import { gridColorState } from '@/store/gridAtom'
import { contextPopupPositionState } from '@/store/popupAtom'
import AuxiliaryCopy from '@/components/floor-plan/modal/auxiliary/AuxiliaryCopy'
import SizeSetting from '@/components/floor-plan/modal/object/SizeSetting'
import RoofMaterialSetting from '@/components/floor-plan/modal/object/RoofMaterialSetting'
import DormerOffset from '@/components/floor-plan/modal/object/DormerOffset'
import FontSetting from '@/components/common/font/FontSetting'
import DimensionLineSetting from '@/components/floor-plan/modal/dimensionLine/DimensionLineSetting'
import RoofAllocationSetting from '@/components/floor-plan/modal/roofAllocation/RoofAllocationSetting'
import LinePropertySetting from '@/components/floor-plan/modal/lineProperty/LinePropertySetting'
import FlowDirectionSetting from '@/components/floor-plan/modal/flowDirection/FlowDirectionSetting'
export function useContextMenu({ externalFn }) {
const currentMenu = useRecoilValue(currentMenuState)
const [contextMenu, setContextMenu] = useState([[]])
const [currentContextMenu, setCurrentContextMenu] = useState(null)
const currentMenu = useRecoilValue(currentMenuState) // 현재 메뉴
const setContextPopupPosition = useSetRecoilState(contextPopupPositionState) // 현재 메뉴
const [contextMenu, setContextMenu] = useState([[]]) // 메뉴.object 별 context menu
const [currentContextMenu, setCurrentContextMenu] = useState(null) // 선택한 contextMenu
const currentObject = useRecoilValue(currentObjectState)
const currentMenuSetting = () => {
console.log(currentMenu)
const { addPopup } = usePopup()
const [popupId, setPopupId] = useState(uuidv4())
const [gridColor, setGridColor] = useRecoilState(gridColorState)
const currentMenuSetting = (position) => {
switch (currentMenu) {
case MENU.PLAN_DRAWING:
setContextMenu([
@ -20,14 +38,17 @@ export function useContextMenu({ externalFn }) {
{
id: 'gridMove',
name: '그리드 이동',
component: <GridMove id={popupId} />,
},
{
id: 'gridCopy',
name: '그리드 복사',
component: <GridCopy id={popupId} />,
},
{
id: 'gridColorEdit',
name: '그리드 색 변경',
component: <ColorPickerModal id={popupId} color={gridColor} setColor={setGridColor} />,
},
{
id: 'remove',
@ -84,16 +105,17 @@ export function useContextMenu({ externalFn }) {
{
id: 'sizeEdit',
name: '사이즈 변경',
component: <AuxiliarySize setCurrentContextMenu={setCurrentContextMenu} />,
component: <AuxiliarySize id={popupId} />,
},
{
id: 'auxiliaryMove',
name: '보조선 이동(M)',
component: <AuxiliaryMove setCurrentContextMenu={setCurrentContextMenu} />,
component: <AuxiliaryMove id={popupId} />,
},
{
id: 'auxiliaryCopy',
name: '보조선 복사(C)',
component: <AuxiliaryCopy id={popupId} />,
},
{
id: 'auxiliaryRemove',
@ -160,19 +182,35 @@ export function useContextMenu({ externalFn }) {
break
}
}
useEffect(() => {
currentMenuSetting()
}, [currentMenu])
const handleClick = (e, menu) => {
setContextPopupPosition({
x: e.clientX,
y: e.clientY,
})
setCurrentContextMenu(menu)
}
useEffect(() => {
currentMenuSetting()
}, [gridColor, currentMenu])
useEffect(() => {
if (currentContextMenu?.component) addPopup(popupId, 1, currentContextMenu?.component)
}, [currentContextMenu])
useEffect(() => {
console.log('object name', currentObject?.name)
if (currentObject?.name) {
switch (currentObject.name) {
case 'triangleDormer':
case 'pentagonDormer':
setContextMenu([
[
{
id: 'sizeEdit',
name: '사이즈 변경',
component: <SizeSetting id={popupId} />,
},
{
id: 'dormerRemove',
@ -189,10 +227,12 @@ export function useContextMenu({ externalFn }) {
{
id: 'roofMaterialEdit',
name: '지붕재 변경',
component: <RoofMaterialSetting id={popupId} />,
},
{
id: 'dormerOffset',
name: '도머 오프셋',
component: <DormerOffset id={popupId} />,
},
],
])
@ -203,6 +243,7 @@ export function useContextMenu({ externalFn }) {
{
id: 'sizeEdit',
name: '사이즈 변경',
component: <SizeSetting id={popupId} />,
},
{
id: 'roofMaterialRemove',
@ -221,14 +262,17 @@ export function useContextMenu({ externalFn }) {
{
id: 'roofMaterialEdit',
name: '지붕재 변경',
component: <RoofAllocationSetting id={popupId} />,
},
{
id: 'linePropertyEdit',
name: '각 변 속성 변경',
component: <LinePropertySetting id={popupId} />,
},
{
id: 'flowDirectionEdit',
name: '흐름 뱡향 변경',
component: <FlowDirectionSetting id={popupId} />,
},
],
])
@ -259,6 +303,127 @@ export function useContextMenu({ externalFn }) {
],
])
break
case 'lengthText':
setContextMenu([
[
{
id: 'lengthTextRemove',
name: '삭제',
},
{
id: 'lengthTextMove',
name: '이동',
},
{
id: 'lengthTextAuxiliaryLineEdit',
name: '치수 보조선 변경',
},
{
id: 'displayEdit',
name: '표시 변경',
},
],
])
break
case 'commonText':
setContextMenu([
[
{
id: 'commonTextRemove',
name: '삭제',
},
{
id: 'commonTextMove',
name: '이동',
},
{
id: 'commonTextCopy',
name: '복사',
},
{
id: 'commonTextFontSetting',
name: '폰트 설정',
component: <FontSetting id={popupId} type={'commonText'} />,
},
{
id: 'commonTextEdit',
name: '편집',
},
],
])
break
case 'lineGrid':
setContextMenu([
[
{
id: 'gridMove',
name: '그리드 이동',
},
{
id: 'gridCopy',
name: '그리드 복사',
},
{
id: 'gridColorEdit',
name: '그리드 색 변경',
},
{
id: 'remove',
name: '삭제',
},
{
id: 'removeAll',
name: '전체 삭제',
},
],
])
break
case 'dimensionLine':
setContextMenu([
[
{
id: 'dimensionLineRemove',
name: '삭제',
},
{
id: 'dimensionLineMove',
name: '이동',
},
{
id: 'dimensionAuxiliaryLineEdit',
name: '치수 보조선 변경',
},
{
id: 'dimensionLineDisplayEdit',
name: '표시 변경',
component: <DimensionLineSetting id={popupId} />,
},
],
])
break
case 'shadow':
setContextMenu([
[
{
id: 'sizeEdit',
name: '사이즈 변경',
component: <SizeSetting id={popupId} />,
},
{
id: 'remove',
name: '삭제(D)',
},
{
id: 'move',
name: '이동(M)',
},
{
id: 'copy',
name: '복사(C)',
},
],
])
break
default:
currentMenuSetting()
}
@ -267,13 +432,10 @@ export function useContextMenu({ externalFn }) {
}
}, [currentObject])
useEffect(() => {
console.log(currentContextMenu)
}, [currentContextMenu])
return {
contextMenu,
currentContextMenu,
setCurrentContextMenu,
handleClick,
}
}

View File

@ -1,20 +1,14 @@
import { useRecoilState } from 'recoil'
import { popupState } from '@/store/popupAtom'
import { useEffect } from 'react'
export function usePopup() {
const [popup, setPopup] = useRecoilState(popupState)
useEffect(() => {
console.log(popup)
}, [popup])
const addPopup = (id, depth, component) => {
setPopup({ children: [...filterDepth(depth), { id: id, depth: depth, component: component }] })
}
const closePopup = (id) => {
console.log(id)
setPopup({ children: [...filterChildrenPopup(id).filter((child) => child.id !== id)] })
}

View File

@ -11,3 +11,12 @@ export const popupState = atom({
},
dangerouslyAllowMutability: true,
})
export const contextPopupPositionState = atom({
key: 'contextPopupPositionState',
default: {
x: 50,
y: 180,
},
dangerouslyAllowMutability: true,
})

View File

@ -309,12 +309,12 @@
padding-top: 46.8px;
transition: all .17s ease-in-out;
.canvas-frame{
height: 86.3vh;
height: calc(100vh - 129.3px);
}
&.active{
padding-top: calc(46.8px + 50px);
.canvas-frame{
height: 81vh;
height: calc(100vh - 179.4px);
}
}
}
@ -1024,6 +1024,7 @@
display: flex;
padding: 20px;
.simulation-tit-wrap{
flex: none;
padding-right: 40px;
border-right: 1px solid #EEEEEE;
span{
@ -1047,6 +1048,7 @@
}
}
.simulation-guide-box{
flex: 1;
padding-left: 40px;
dl{
margin-bottom: 25px;
@ -1066,6 +1068,9 @@
margin-bottom: 0;
}
}
ul, ol{
list-style: unset;
}
}
}

View File

@ -405,10 +405,15 @@
display: flex;
align-items: center;
border: 1px solid #E5E9EF;
border-radius: 4px;
height: 45px;
padding-left: 40px;
padding-right: 15px;
margin-bottom: 15px;
transition: border .15s ease-in-out;
&.focus{
border-color: #A8B6C7;
}
.login-input{
flex: 1;
height: 100%;