Merge branch 'dev' of https://git.hanasys.jp/qcast3/qcast-front into feature/skeleton-dev
# Conflicts: # src/hooks/roofcover/useMovementSetting.js # src/util/skeleton-utils.js
This commit is contained in:
commit
dd0f4cbc91
@ -58,7 +58,8 @@ export default async function RootLayout({ children }) {
|
||||
pwdInitYn: session.pwdInitYn,
|
||||
custCd: session.custCd,
|
||||
isLoggedIn: session.isLoggedIn,
|
||||
builderNo: session.builderNo
|
||||
builderNo: session.builderNo,
|
||||
custNm: session.custNm
|
||||
}
|
||||
}
|
||||
if (!headerPathname.includes('/login') && !session.isLoggedIn) {
|
||||
|
||||
@ -61,6 +61,7 @@ export const LINE_TYPE = {
|
||||
*/
|
||||
DEFAULT: 'default',
|
||||
EAVES: 'eaves',
|
||||
EAVE_HELP_LINE: 'eaveHelpLine',
|
||||
GABLE: 'gable',
|
||||
GABLE_LEFT: 'gableLeft', //케라바 왼쪽
|
||||
GABLE_RIGHT: 'gableRight', //케라바 오른쪽
|
||||
|
||||
@ -362,6 +362,8 @@ let fileCheck = false;
|
||||
<td>{dayjs(new Date()).format('YYYY-MM-DD')}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Customer</th>
|
||||
<td><input type="text" className="input-light" value={sessionState?.custNm || ''} readOnly /></td>
|
||||
<th>{getMessage('qna.reg.header.regUserNm')}<span className="red">*</span></th>
|
||||
<td ><input type="text" className="input-light" required
|
||||
ref={regUserNmRef}
|
||||
@ -369,7 +371,7 @@ let fileCheck = false;
|
||||
onChange={(e) => setQnaData({...qnaData, regUserNm: e.target.value })}
|
||||
onBlur={(e) => setQnaData({ ...qnaData, regUserNm: e.target.value })} /> </td>
|
||||
<th>{getMessage('qna.reg.header.regUserTelNo')}</th>
|
||||
<td colSpan={3}><input type="text" className="input-light"
|
||||
<td ><input type="text" className="input-light"
|
||||
ref={regUserTelNoRef}
|
||||
maxLength={13}
|
||||
value={qnaData?.regUserTelNo || '' }
|
||||
|
||||
@ -2,7 +2,7 @@ import { fabric } from 'fabric'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { QLine } from '@/components/fabric/QLine'
|
||||
import { distanceBetweenPoints, findTopTwoIndexesByDistance, getDirectionByPoint, sortedPointLessEightPoint, sortedPoints } from '@/util/canvas-util'
|
||||
import { calculateAngle, drawGableRoof, drawRidgeRoof, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils'
|
||||
import { calculateAngle, drawGableRoof, drawRoofByAttribute, drawShedRoof, toGeoJSON } from '@/util/qpolygon-utils'
|
||||
import * as turf from '@turf/turf'
|
||||
import { LINE_TYPE, POLYGON_TYPE } from '@/common/common'
|
||||
import Big from 'big.js'
|
||||
@ -314,14 +314,18 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
}
|
||||
|
||||
const getParallelEavesLines = function (shedLines, lines) {
|
||||
const eavesLines = lines.filter((line) => line.attributes?.type === LINE_TYPE.WALLLINE.EAVES)
|
||||
|
||||
const referenceAngle = calculateAngle(shedLines[0].startPoint, shedLines[0].endPoint)
|
||||
|
||||
return eavesLines.filter((line) => {
|
||||
const eavesAngle = calculateAngle(line.startPoint, line.endPoint)
|
||||
return Math.abs(referenceAngle - eavesAngle) === 180
|
||||
const otherSideLines = lines.filter((line) => {
|
||||
const lineAngle = calculateAngle(line.startPoint, line.endPoint)
|
||||
return Math.abs(referenceAngle - lineAngle) === 180
|
||||
})
|
||||
const containNotEaves = otherSideLines.filter((line) => line.attributes?.type !== LINE_TYPE.WALLLINE.EAVES)
|
||||
|
||||
if (containNotEaves.length === 0) {
|
||||
return otherSideLines
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
const parallelEaves = getParallelEavesLines(shedLines, lines)
|
||||
@ -336,8 +340,8 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
if (types.every((type) => type === LINE_TYPE.WALLLINE.EAVES)) {
|
||||
// 용마루 -- straight-skeleton
|
||||
console.log('용마루 지붕')
|
||||
//drawRidgeRoof(this.id, this.canvas, textMode)
|
||||
drawSkeletonRidgeRoof(this.id, this.canvas, textMode);
|
||||
///drawRidgeRoof(this.id, this.canvas, textMode)
|
||||
drawSkeletonRidgeRoof(this.id, this.canvas, textMode)
|
||||
} else if (isGableRoof(types)) {
|
||||
// A형, B형 박공 지붕
|
||||
console.log('패턴 지붕')
|
||||
@ -347,7 +351,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, {
|
||||
drawShedRoof(this.id, this.canvas, textMode)
|
||||
} else {
|
||||
console.log('변별로 설정')
|
||||
drawRidgeRoof(this.id, this.canvas, textMode)
|
||||
drawRoofByAttribute(this.id, this.canvas, textMode)
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@ import { currentObjectState } from '@/store/canvasAtom'
|
||||
import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { normalizeDigits } from '@/util/input-utils'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default function AuxiliaryEdit(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
@ -66,7 +67,19 @@ export default function AuxiliaryEdit(props) {
|
||||
<p className="mb5">{getMessage('length')}</p>
|
||||
<div className="input-move-wrap mb5">
|
||||
<div className="input-move">
|
||||
<input type="text" className="input-origin" value={verticalSize} onChange={(e) => setVerticalSize(normalizeDigits(e.target.value))} />
|
||||
{/*<input type="text" className="input-origin" value={verticalSize} onChange={(e) => setVerticalSize(normalizeDigits(e.target.value))} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={verticalSize}
|
||||
onChange={(value) => setVerticalSize(value)}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span>mm</span>
|
||||
<div className="direction-move-wrap">
|
||||
@ -88,7 +101,19 @@ export default function AuxiliaryEdit(props) {
|
||||
</div>
|
||||
<div className="input-move-wrap">
|
||||
<div className="input-move">
|
||||
<input type="text" className="input-origin" value={horizonSize} onChange={(e) => setHorizonSize(normalizeDigits(e.target.value))} />
|
||||
{/*<input type="text" className="input-origin" value={horizonSize} onChange={(e) => setHorizonSize(normalizeDigits(e.target.value))} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={horizonSize}
|
||||
onChange={(value) => setHorizonSize(value)}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span>mm</span>
|
||||
<div className="direction-move-wrap">
|
||||
|
||||
@ -8,19 +8,21 @@ import { useEffect, useState } from 'react'
|
||||
import Big from 'big.js'
|
||||
import { calcLineActualSize, calcLinePlaneSize } from '@/util/qpolygon-utils'
|
||||
import { normalizeDigits } from '@/util/input-utils'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default function AuxiliarySize(props) {
|
||||
const contextPopupPosition = useRecoilValue(contextPopupPositionState)
|
||||
const { id, pos = contextPopupPosition } = props
|
||||
const [checkedRadio, setCheckedRadio] = useState(null)
|
||||
const [value1, setValue1] = useState(null)
|
||||
const [value2, setValue2] = useState(null)
|
||||
const [value1, setValue1] = useState('')
|
||||
const [value2, setValue2] = useState('')
|
||||
const [size, setSize] = useState(0)
|
||||
const { getMessage } = useMessage()
|
||||
const { closePopup } = usePopup()
|
||||
const currentObject = useRecoilValue(currentObjectState)
|
||||
const canvas = useRecoilValue(canvasState)
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
canvas?.discardActiveObject()
|
||||
@ -37,7 +39,7 @@ export default function AuxiliarySize(props) {
|
||||
}, [currentObject])
|
||||
|
||||
const handleInput = (e) => {
|
||||
let value = e.target.value.replace(/^0+/, '')
|
||||
let value = e.replace(/^0+/, '')
|
||||
if (value === '') {
|
||||
if (checkedRadio === 1) setValue1(value)
|
||||
if (checkedRadio === 2) setValue2(value)
|
||||
@ -130,7 +132,20 @@ export default function AuxiliarySize(props) {
|
||||
<div className="outline-form">
|
||||
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
||||
<div className="input-grid mr5">
|
||||
<input type="text" className="input-origin block" value={value1} readOnly={checkedRadio !== 1} onChange={handleInput} />
|
||||
{/*<input type="text" className="input-origin block" value={value1} readOnly={checkedRadio !== 1} onChange={handleInput} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={value1}
|
||||
onChange={handleInput}
|
||||
readOnly={checkedRadio !== 1}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
@ -149,7 +164,20 @@ export default function AuxiliarySize(props) {
|
||||
<div className="outline-form">
|
||||
<span style={{ width: 'auto' }}>{getMessage('length')}</span>
|
||||
<div className="input-grid mr5">
|
||||
<input type="text" className="input-origin block" value={value2} readOnly={checkedRadio !== 2} onChange={handleInput} />
|
||||
{/*<input type="text" className="input-origin block" value={value2} readOnly={checkedRadio !== 2} onChange={handleInput} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={value2}
|
||||
onChange={handleInput}
|
||||
readOnly={checkedRadio !== 2}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -2,6 +2,7 @@ import { useMessage } from '@/hooks/useMessage'
|
||||
import { useState } from 'react'
|
||||
import { currentObjectState } from '@/store/canvasAtom'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
const FLOW_LINE_TYPE = {
|
||||
DOWN_LEFT: 'downLeft',
|
||||
@ -69,13 +70,27 @@ export default function FlowLine({ FLOW_LINE_REF }) {
|
||||
<div className="outline-form">
|
||||
<span>{getMessage('modal.movement.flow.line.movement')}</span>
|
||||
<div className="input-grid mr5">
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-origin block"*/}
|
||||
{/* ref={FLOW_LINE_REF.FILLED_INPUT_REF}*/}
|
||||
{/* value={filledInput}*/}
|
||||
{/* onFocus={handleFocus}*/}
|
||||
{/* onChange={handleInput}*/}
|
||||
{/*/>*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
ref={FLOW_LINE_REF.FILLED_INPUT_REF}
|
||||
value={filledInput}
|
||||
onFocus={handleFocus}
|
||||
onChange={handleInput}
|
||||
onChange={(value)=>{setFilledInput(value)}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
|
||||
@ -3,6 +3,7 @@ import { useState } from 'react'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { currentObjectState } from '@/store/canvasAtom'
|
||||
import { normalizeDigits } from '@/util/input-utils'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
const UP_DOWN_TYPE = {
|
||||
UP: 'up',
|
||||
@ -35,6 +36,7 @@ export default function Updown({ UP_DOWN_REF }) {
|
||||
<span>{getMessage('modal.movement.flow.line.position')}</span>
|
||||
<div className="input-grid mr5">
|
||||
<input type="text" className="input-origin block" defaultValue={100} readOnly={true} ref={UP_DOWN_REF.POINTER_INPUT_REF} />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className="moving-tab-content">
|
||||
@ -68,13 +70,27 @@ export default function Updown({ UP_DOWN_REF }) {
|
||||
<div className="outline-form">
|
||||
<span>{getMessage('modal.movement.flow.line.movement')}</span>
|
||||
<div className="input-grid mr5">
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-origin block"*/}
|
||||
{/* ref={UP_DOWN_REF.FILLED_INPUT_REF}*/}
|
||||
{/* value={filledInput}*/}
|
||||
{/* onFocus={handleFocus}*/}
|
||||
{/* onChange={handleInput}*/}
|
||||
{/*/>*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
ref={UP_DOWN_REF.FILLED_INPUT_REF}
|
||||
value={filledInput}
|
||||
onFocus={handleFocus}
|
||||
onChange={handleInput}
|
||||
onChange={(value)=>{setFilledInput(value)}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
|
||||
@ -59,9 +59,9 @@ export default function DormerOffset(props) {
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={arrow1LengthRef.current.value ?? 0}
|
||||
value={arrow1LengthRef.current?.value ?? 0}
|
||||
ref={arrow1LengthRef}
|
||||
onChange={(value) => setArrow1Length(value)}
|
||||
onChange={() => {}} // No-op function to prevent error
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false,
|
||||
@ -86,7 +86,20 @@ export default function DormerOffset(props) {
|
||||
</div>
|
||||
<div className="input-move-wrap">
|
||||
<div className="input-move">
|
||||
<input type="text" className="input-origin" ref={arrow2LengthRef} placeholder="0" />
|
||||
{/*<input type="text" className="input-origin" ref={arrow2LengthRef} placeholder="0" />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={arrow2LengthRef.current?.value ?? 0}
|
||||
ref={arrow2LengthRef}
|
||||
onChange={() => {}} // No-op function to prevent error
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span>mm</span>
|
||||
<div className="direction-move-wrap">
|
||||
|
||||
@ -350,7 +350,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
||||
label=""
|
||||
className="input-origin block"
|
||||
readOnly={currentRoof?.roofAngleSet !== item.value}
|
||||
value={index === 0 ? currentRoof?.pitch || '0' : currentRoof?.angle || '0'}
|
||||
value={index === 0 ? (currentRoof?.pitch ?? basicSetting?.inclBase ?? '0') : (currentRoof?.angle ?? '0')}
|
||||
onChange={(value) => {
|
||||
if (index === 0) {
|
||||
const pitch = value === '' ? '' : Number(value);
|
||||
@ -372,7 +372,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
||||
}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: true //(index !== 0),
|
||||
allowDecimal: true
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@ -520,7 +520,7 @@ export default function PlacementShapeSetting({ id, pos = { x: 50, y: 180 }, pla
|
||||
label=""
|
||||
className="input-origin block"
|
||||
ref={roofRef.hajebichi}
|
||||
value={currentRoof?.hajebichi || '0'}
|
||||
value={currentRoof?.hajebichi ?? basicSetting?.roofPchBase ?? '0'}
|
||||
onChange={(value) => {
|
||||
const hajebichi = value === '' ? '' : Number(value);
|
||||
setCurrentRoof(prev => ({
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import Image from 'next/image'
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { forwardRef, useState } from 'react'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
const PlacementSurface = forwardRef((props, refs) => {
|
||||
const { getMessage } = useMessage()
|
||||
@ -74,10 +75,32 @@ const PlacementSurface = forwardRef((props, refs) => {
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '57px' }}>
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-origin plane block"*/}
|
||||
{/* defaultValue={line.value}*/}
|
||||
{/* ref={*/}
|
||||
{/* line.isDiagonal*/}
|
||||
{/* ? lengthetc*/}
|
||||
{/* : index === 0*/}
|
||||
{/* ? length1*/}
|
||||
{/* : index === 1*/}
|
||||
{/* ? length2*/}
|
||||
{/* : index === 2*/}
|
||||
{/* ? length3*/}
|
||||
{/* : index === 3*/}
|
||||
{/* ? length4*/}
|
||||
{/* : length5*/}
|
||||
{/* }*/}
|
||||
{/*/>*/}
|
||||
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin plane block"
|
||||
defaultValue={line.value}
|
||||
value={line.value}
|
||||
onChange={()=>{}}
|
||||
ref={
|
||||
line.isDiagonal
|
||||
? lengthetc
|
||||
@ -91,6 +114,10 @@ const PlacementSurface = forwardRef((props, refs) => {
|
||||
? length4
|
||||
: length5
|
||||
}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
|
||||
@ -43,7 +43,20 @@ export default function Eaves({ offsetRef, pitchRef, pitchText }) {
|
||||
{getMessage('eaves.offset')}
|
||||
</span>
|
||||
<div className="input-grid mr5">
|
||||
<input type="text" className="input-origin block" defaultValue={500} ref={offsetRef} />
|
||||
{/*<input type="text" className="input-origin block" defaultValue={500} ref={offsetRef} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={offsetRef.current?.value ?? 500} // Set default value to 500
|
||||
ref={offsetRef}
|
||||
onChange={() => {}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useRecoilValue } from 'recoil'
|
||||
import { currentAngleTypeSelector } from '@/store/canvasAtom'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default function Gable({ offsetRef }) {
|
||||
const { getMessage } = useMessage()
|
||||
@ -12,7 +13,20 @@ export default function Gable({ offsetRef }) {
|
||||
{getMessage('gable.offset')}
|
||||
</span>
|
||||
<div className="input-grid mr5">
|
||||
<input type="text" className="input-origin block" defaultValue={300} ref={offsetRef} />
|
||||
{/*<input type="text" className="input-origin block" defaultValue={300} ref={offsetRef} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={offsetRef.current?.value ?? 300} // Set default value to 500
|
||||
ref={offsetRef}
|
||||
onChange={() => {}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default function Shed({ offsetRef }) {
|
||||
const { getMessage } = useMessage()
|
||||
@ -9,7 +10,20 @@ export default function Shed({ offsetRef }) {
|
||||
{getMessage('shed.width')}
|
||||
</span>
|
||||
<div className="input-grid mr5">
|
||||
<input type="text" className="input-origin block" defaultValue={300} ref={offsetRef} />
|
||||
{/*<input type="text" className="input-origin block" defaultValue={300} ref={offsetRef} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={offsetRef.current?.value ?? 300} // Set default value to 500
|
||||
ref={offsetRef}
|
||||
onChange={() => {}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default function Offset({ length1Ref, arrow1Ref, currentWallLineRef }) {
|
||||
const { getMessage } = useMessage()
|
||||
@ -74,7 +75,20 @@ export default function Offset({ length1Ref, arrow1Ref, currentWallLineRef }) {
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} ref={length1Ref} />
|
||||
{/*<input type="text" className="input-origin block" placeholder={0} ref={length1Ref} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={length1Ref.current?.value ?? 0}
|
||||
ref={length1Ref}
|
||||
onChange={() => {}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { useMessage } from '@/hooks/useMessage'
|
||||
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'
|
||||
import { useEvent } from '@/hooks/useEvent'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default forwardRef(function WallLine({ length1Ref, length2Ref, arrow1Ref, arrow2Ref, radioTypeRef, currentWallLineRef }, ref) {
|
||||
const { getMessage } = useMessage()
|
||||
@ -46,7 +47,21 @@ export default forwardRef(function WallLine({ length1Ref, length2Ref, arrow1Ref,
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} readOnly={type !== 1} ref={length1Ref} />
|
||||
{/*<input type="text" className="input-origin block" placeholder={0} readOnly={type !== 1} ref={length1Ref} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={length1Ref.current?.value ?? 0}
|
||||
ref={length1Ref}
|
||||
onChange={() => {}}
|
||||
readOnly={type !== 1}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
@ -80,7 +95,21 @@ export default forwardRef(function WallLine({ length1Ref, length2Ref, arrow1Ref,
|
||||
<div className="eaves-keraba-td">
|
||||
<div className="outline-form">
|
||||
<div className="input-grid mr5" style={{ width: '100px' }}>
|
||||
<input type="text" className="input-origin block" placeholder={0} readOnly={type !== 2} ref={length2Ref} />
|
||||
{/*<input type="text" className="input-origin block" placeholder={0} readOnly={type !== 2} ref={length2Ref} />*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-origin block"
|
||||
value={length2Ref.current?.value ?? 0}
|
||||
ref={length2Ref}
|
||||
onChange={() => {}}
|
||||
readOnly={type !== 2}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="thin">mm</span>
|
||||
</div>
|
||||
|
||||
@ -23,6 +23,7 @@ import { QcastContext } from '@/app/QcastProvider'
|
||||
import { useCanvasMenu } from '@/hooks/common/useCanvasMenu'
|
||||
import { useSwal } from '@/hooks/useSwal'
|
||||
import { sanitizeIntegerInputEvent } from '@/util/input-utils'
|
||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||
|
||||
export default function StuffDetail() {
|
||||
const [stuffSearch, setStuffSearch] = useRecoilState(stuffSearchState)
|
||||
@ -1204,8 +1205,10 @@ export default function StuffDetail() {
|
||||
}
|
||||
|
||||
// 저장
|
||||
const onValid = async () => {
|
||||
const formData = form.getValues()
|
||||
const onValid = async (actionType) => {
|
||||
const formData = form.getValues();
|
||||
if(actionType !== 'save') return false
|
||||
console.log('Action type:', actionType); // 'save' 또는 'tempSave'
|
||||
let errors = {}
|
||||
let fieldNm
|
||||
|
||||
@ -1715,7 +1718,7 @@ export default function StuffDetail() {
|
||||
<button type="button" className="btn-origin grey mr5" onClick={onTempSave} style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.tempSave')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
<button type="button" onClick={() => onValid('save')} className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</button>
|
||||
<button
|
||||
@ -2113,13 +2116,25 @@ export default function StuffDetail() {
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr10" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-light"*/}
|
||||
{/* onInput={handleKeyUp}*/}
|
||||
{/* onBlur={handleBlur}*/}
|
||||
{/* value={form.watch('verticalSnowCover') || ''}*/}
|
||||
{/* {...register('verticalSnowCover')}*/}
|
||||
{/*/>*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-light"
|
||||
onInput={handleKeyUp}
|
||||
onBlur={handleBlur}
|
||||
value={form.watch('verticalSnowCover') || ''}
|
||||
{...register('verticalSnowCover')}
|
||||
onChange={()=>{}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="mr10">cm</span>
|
||||
@ -2173,13 +2188,25 @@ export default function StuffDetail() {
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr10" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-light"*/}
|
||||
{/* onInput={handleKeyUp}*/}
|
||||
{/* onBlur={handleBlur}*/}
|
||||
{/* value={form.watch('installHeight') || ''}*/}
|
||||
{/* {...register('installHeight')}*/}
|
||||
{/*/>*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-light"
|
||||
onInput={handleKeyUp}
|
||||
onBlur={handleBlur}
|
||||
value={form.watch('installHeight') || ''}
|
||||
{...register('installHeight')}
|
||||
onChange={()=>{}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span>m</span>
|
||||
@ -2216,7 +2243,7 @@ export default function StuffDetail() {
|
||||
<button type="button" className="btn-origin grey mr5" onClick={onTempSave} style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.tempSave')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
<button type="button" onClick={() => onValid('save')} className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</button>
|
||||
<button
|
||||
@ -2253,7 +2280,7 @@ export default function StuffDetail() {
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
<button type="button" onClick={() => onValid('save')} className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</button>
|
||||
<button type="button" className="btn-origin grey" onClick={onDelete} style={{ display: showButton }}>
|
||||
@ -2267,7 +2294,7 @@ export default function StuffDetail() {
|
||||
<button type="button" className="btn-origin grey mr5" onClick={onTempSave} style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.tempSave')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
<button type="button" onClick={() => onValid('save')} className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</button>
|
||||
<button
|
||||
@ -2685,13 +2712,25 @@ export default function StuffDetail() {
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr10" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-light"*/}
|
||||
{/* onInput={handleKeyUp}*/}
|
||||
{/* onBlur={handleBlur}*/}
|
||||
{/* value={form.watch('verticalSnowCover') || ''}*/}
|
||||
{/* {...register('verticalSnowCover')}*/}
|
||||
{/*/>*/}
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-light"
|
||||
onInput={handleKeyUp}
|
||||
onBlur={handleBlur}
|
||||
value={form.watch('verticalSnowCover') || ''}
|
||||
{...register('verticalSnowCover')}
|
||||
onChange={()=>{}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span className="mr10">cm</span>
|
||||
@ -2748,13 +2787,26 @@ export default function StuffDetail() {
|
||||
<td>
|
||||
<div className="flx-box">
|
||||
<div className="input-wrap mr10" style={{ width: '200px' }}>
|
||||
<input
|
||||
type="text"
|
||||
{/*<input*/}
|
||||
{/* type="text"*/}
|
||||
{/* className="input-light"*/}
|
||||
{/* onInput={handleKeyUp}*/}
|
||||
{/* onBlur={handleBlur}*/}
|
||||
{/* value={form.watch('installHeight') || ''}*/}
|
||||
{/* {...register('installHeight')}*/}
|
||||
{/*/>*/}
|
||||
|
||||
<CalculatorInput
|
||||
id=""
|
||||
name=""
|
||||
label=""
|
||||
className="input-light"
|
||||
onInput={handleKeyUp}
|
||||
onBlur={handleBlur}
|
||||
value={form.watch('installHeight') || ''}
|
||||
{...register('installHeight')}
|
||||
onChange={()=>{}}
|
||||
options={{
|
||||
allowNegative: false,
|
||||
allowDecimal: false
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<span>m</span>
|
||||
@ -2835,7 +2887,7 @@ export default function StuffDetail() {
|
||||
>
|
||||
{getMessage('stuff.detail.btn.moveList')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
<button type="button" onClick={() => onValid('save')} className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</button>
|
||||
<button type="button" className="btn-origin grey" onClick={onDelete} style={{ display: showButton }}>
|
||||
@ -2849,7 +2901,7 @@ export default function StuffDetail() {
|
||||
<button type="button" className="btn-origin grey mr5" onClick={onTempSave} style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.tempSave')}
|
||||
</button>
|
||||
<button type="submit" className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
<button type="button" onClick={() => onValid('save')} className="btn-origin navy mr5" style={{ display: showButton }}>
|
||||
{getMessage('stuff.detail.btn.save')}
|
||||
</button>
|
||||
<button
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRecoilValue, useResetRecoilState } from 'recoil'
|
||||
import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
|
||||
import { canvasState, currentObjectState } from '@/store/canvasAtom'
|
||||
import { selectedRoofMaterialSelector } from '@/store/settingAtom'
|
||||
import { ROOF_MATERIAL_LAYOUT } from '@/components/floor-plan/modal/placementShape/PlacementShapeSetting'
|
||||
@ -25,6 +25,7 @@ export function useRoofFn() {
|
||||
const { addPitchText } = useLine()
|
||||
const { setPolygonLinesActualSize } = usePolygon()
|
||||
const { changeCorridorDimensionText } = useText()
|
||||
const [outerLinePoints, setOuterLinePoints] = useRecoilState(outerLinePointsState)
|
||||
|
||||
//면형상 선택 클릭시 지붕 패턴 입히기
|
||||
function setSurfaceShapePattern(polygon, mode = 'onlyBorder', trestleMode = false, roofMaterial, isForceChange = false, isDisplay = false) {
|
||||
@ -263,6 +264,9 @@ export function useRoofFn() {
|
||||
const deltaX = roof.left - originalRoofLeft
|
||||
const deltaY = roof.top - originalRoofTop
|
||||
|
||||
const originOuterLinePoints = [...outerLinePoints]
|
||||
setOuterLinePoints(originOuterLinePoints.map((point) => ({ x: point.x + deltaX, y: point.y + deltaY })))
|
||||
|
||||
// Move all related objects by the delta
|
||||
allRoofObject.forEach((obj) => {
|
||||
if (obj.points !== undefined) {
|
||||
|
||||
@ -116,6 +116,7 @@ export function useEavesGableEdit(id) {
|
||||
|
||||
useEffect(() => {
|
||||
typeRef.current = type
|
||||
radioTypeRef.current = '1'
|
||||
}, [type])
|
||||
|
||||
const mouseOverEvent = (e) => {
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import { useRecoilValue, useResetRecoilState } from 'recoil'
|
||||
import { canvasSettingState, canvasState, currentCanvasPlanState, currentObjectState, globalPitchState } from '@/store/canvasAtom'
|
||||
import {
|
||||
canvasSettingState,
|
||||
canvasState,
|
||||
currentCanvasPlanState,
|
||||
currentObjectState,
|
||||
globalPitchState,
|
||||
} from '@/store/canvasAtom'
|
||||
import { LINE_TYPE, MENU, POLYGON_TYPE } from '@/common/common'
|
||||
import { getIntersectionPoint } from '@/util/canvas-util'
|
||||
import { degreesToRadians } from '@turf/turf'
|
||||
@ -879,7 +885,7 @@ export function useSurfaceShapeBatch({ isHidden, setIsHidden }) {
|
||||
}
|
||||
})
|
||||
|
||||
// roof.fire('polygonMoved')
|
||||
roof.fire('polygonMoved')
|
||||
roof.fire('modified')
|
||||
drawDirectionArrow(roof)
|
||||
changeCorridorDimensionText()
|
||||
|
||||
@ -867,7 +867,6 @@ export const usePolygon = () => {
|
||||
// innerLine.attributes.isStart = true
|
||||
// innerLine.parentLine = polygonLine
|
||||
|
||||
|
||||
// 매핑된 innerLine의 attributes를 변경 (교차점 계산 전에 적용)
|
||||
innerLineMapping.forEach((polygonLine, innerLine) => {
|
||||
innerLine.attributes.planeSize = innerLine.attributes.planeSize ?? polygonLine.attributes.planeSize
|
||||
@ -877,7 +876,6 @@ export const usePolygon = () => {
|
||||
innerLine.attributes.isStart = true
|
||||
innerLine.parentLine = polygonLine
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1387,7 +1385,7 @@ export const usePolygon = () => {
|
||||
let representLine
|
||||
|
||||
// 지붕을 그리면서 기존 polygon의 line중 연결된 line을 찾는다.
|
||||
[...polygonLines, ...innerLines].forEach((line) => {
|
||||
;[...polygonLines, ...innerLines].forEach((line) => {
|
||||
let startFlag = false
|
||||
let endFlag = false
|
||||
const startPoint = line.startPoint
|
||||
@ -1402,7 +1400,10 @@ export const usePolygon = () => {
|
||||
})
|
||||
|
||||
if (startFlag && endFlag) {
|
||||
if (!representLines.includes(line) && line.attributes.type === LINE_TYPE.WALLLINE.EAVES) {
|
||||
if (
|
||||
!representLines.includes(line) &&
|
||||
(line.attributes.type === LINE_TYPE.WALLLINE.EAVES || line.attributes.type === LINE_TYPE.WALLLINE.EAVE_HELP_LINE)
|
||||
) {
|
||||
representLines.push(line)
|
||||
} else if (!representLines.includes(line) && line.attributes.type === LINE_TYPE.WALLLINE.HIPANDGABLE) {
|
||||
representLines.push(line)
|
||||
@ -1631,79 +1632,80 @@ export const usePolygon = () => {
|
||||
// }
|
||||
|
||||
function findShortestPath(start, end, graph, epsilon = 1) {
|
||||
const startKey = pointToKey(start, epsilon);
|
||||
const endKey = pointToKey(end, epsilon);
|
||||
const startKey = pointToKey(start, epsilon)
|
||||
const endKey = pointToKey(end, epsilon)
|
||||
|
||||
// 거리와 이전 노드 추적
|
||||
const distances = { [startKey]: 0 };
|
||||
const previous = {};
|
||||
const visited = new Set();
|
||||
const distances = { [startKey]: 0 }
|
||||
const previous = {}
|
||||
const visited = new Set()
|
||||
|
||||
// 우선순위 큐 (거리가 짧은 순으로 정렬)
|
||||
const queue = [{ key: startKey, dist: 0 }];
|
||||
const queue = [{ key: startKey, dist: 0 }]
|
||||
|
||||
// 모든 노드 초기화
|
||||
for (const key in graph) {
|
||||
if (key !== startKey) {
|
||||
distances[key] = Infinity;
|
||||
distances[key] = Infinity
|
||||
}
|
||||
}
|
||||
|
||||
// 우선순위 큐에서 다음 노드 선택
|
||||
const getNextNode = () => {
|
||||
if (queue.length === 0) return null;
|
||||
queue.sort((a, b) => a.dist - b.dist);
|
||||
return queue.shift();
|
||||
};
|
||||
if (queue.length === 0) return null
|
||||
queue.sort((a, b) => a.dist - b.dist)
|
||||
return queue.shift()
|
||||
}
|
||||
|
||||
let current;
|
||||
let current
|
||||
while ((current = getNextNode())) {
|
||||
const currentKey = current.key;
|
||||
const currentKey = current.key
|
||||
|
||||
// 목적지에 도달하면 종료
|
||||
if (currentKey === endKey) break;
|
||||
if (currentKey === endKey) break
|
||||
|
||||
// 이미 방문한 노드는 건너뜀
|
||||
if (visited.has(currentKey)) continue;
|
||||
visited.add(currentKey);
|
||||
if (visited.has(currentKey)) continue
|
||||
visited.add(currentKey)
|
||||
|
||||
// 인접 노드 탐색
|
||||
for (const neighbor of graph[currentKey] || []) {
|
||||
const neighborKey = pointToKey(neighbor.point, epsilon);
|
||||
if (visited.has(neighborKey)) continue;
|
||||
const neighborKey = pointToKey(neighbor.point, epsilon)
|
||||
if (visited.has(neighborKey)) continue
|
||||
|
||||
const alt = distances[currentKey] + neighbor.distance;
|
||||
const alt = distances[currentKey] + neighbor.distance
|
||||
|
||||
// 더 짧은 경로를 찾은 경우 업데이트
|
||||
if (alt < (distances[neighborKey] || Infinity)) {
|
||||
distances[neighborKey] = alt;
|
||||
previous[neighborKey] = currentKey;
|
||||
distances[neighborKey] = alt
|
||||
previous[neighborKey] = currentKey
|
||||
|
||||
// 우선순위 큐에 추가
|
||||
queue.push({ key: neighborKey, dist: alt });
|
||||
queue.push({ key: neighborKey, dist: alt })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 경로 재구성
|
||||
const path = [];
|
||||
let currentKey = endKey;
|
||||
const path = []
|
||||
let currentKey = endKey
|
||||
|
||||
// 시작점에 도달할 때까지 역추적
|
||||
while (previous[currentKey] !== undefined) {
|
||||
const [x, y] = currentKey.split(',').map(Number);
|
||||
path.unshift({ x, y });
|
||||
currentKey = previous[currentKey];
|
||||
const [x, y] = currentKey.split(',').map(Number)
|
||||
path.unshift({ x, y })
|
||||
currentKey = previous[currentKey]
|
||||
}
|
||||
|
||||
// 시작점 추가
|
||||
if (path.length > 0) {
|
||||
const [sx, sy] = startKey.split(',').map(Number);
|
||||
path.unshift({ x: sx, y: sy });
|
||||
const [sx, sy] = startKey.split(',').map(Number)
|
||||
path.unshift({ x: sx, y: sy })
|
||||
}
|
||||
|
||||
return path.length > 0 ? path : null;
|
||||
return path.length > 0 ? path : null
|
||||
}
|
||||
|
||||
// 최종 함수
|
||||
function getPath(start, end, graph, epsilon = 1) {
|
||||
// startPoint와 arrivalPoint가 될 수 있는 점은 line.attributes.type이 'default' 혹은 null이 아닌 line인 경우에만 가능
|
||||
|
||||
@ -49,6 +49,7 @@ export async function setSession(data) {
|
||||
session.custCd = data.custCd
|
||||
session.isLoggedIn = true
|
||||
session.builderNo = data.builderNo
|
||||
session.custNm = data.custNm
|
||||
|
||||
await session.save()
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user