Compare commits
7 Commits
5ac023d72d
...
ddd3eaf82a
| Author | SHA1 | Date | |
|---|---|---|---|
| ddd3eaf82a | |||
| 3a3afe9b3b | |||
| 4651ebc365 | |||
| 861fd31825 | |||
| a5dc5caaf3 | |||
| 47de1ef61d | |||
| c499653e79 |
@ -224,6 +224,7 @@ export const SAVE_KEY = [
|
|||||||
'viewportTransform',
|
'viewportTransform',
|
||||||
'outerLineFix',
|
'outerLineFix',
|
||||||
'adjustRoofLines',
|
'adjustRoofLines',
|
||||||
|
'northModuleYn',
|
||||||
]
|
]
|
||||||
|
|
||||||
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
|
export const OBJECT_PROTOTYPE = [fabric.Line.prototype, fabric.Polygon.prototype, fabric.Triangle.prototype, fabric.Group.prototype]
|
||||||
|
|||||||
@ -23,8 +23,23 @@ export const CalculatorInput = forwardRef(
|
|||||||
}, [ref])
|
}, [ref])
|
||||||
|
|
||||||
// Sync displayValue with value prop
|
// Sync displayValue with value prop
|
||||||
|
// useEffect(() => {
|
||||||
|
// setDisplayValue(value || '0')
|
||||||
|
// }, [value])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setDisplayValue(value || '0')
|
const newValue = value || '0'
|
||||||
|
setDisplayValue(newValue)
|
||||||
|
|
||||||
|
// 외부에서 value가 변경될 때 계산기 내부 상태도 동기화
|
||||||
|
const calculator = calculatorRef.current
|
||||||
|
if (calculator) {
|
||||||
|
// 연산 중이 아닐 때 외부에서 값이 들어오면 현재 피연산자로 설정
|
||||||
|
calculator.currentOperand = newValue.toString()
|
||||||
|
calculator.previousOperand = ''
|
||||||
|
calculator.operation = undefined
|
||||||
|
setHasOperation(false)
|
||||||
|
}
|
||||||
}, [value])
|
}, [value])
|
||||||
|
|
||||||
// 클릭 외부 감지
|
// 클릭 외부 감지
|
||||||
|
|||||||
@ -123,10 +123,14 @@ export default function PassivityCircuitAllocation(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// targetModule중 북면 설치 여부가 Y인 것과 N인 것이 혼합이면 안됨.
|
// targetModule중 북면 설치 여부가 Y인 것과 N인 것이 혼합이면 안됨.
|
||||||
const targetModuleGroup = [...new Set(canvas
|
const targetModuleGroup = [
|
||||||
.getObjects()
|
...new Set(
|
||||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE && targetModules.includes(obj.id))
|
canvas
|
||||||
.map((obj) => obj.moduleInfo.northModuleYn))]
|
.getObjects()
|
||||||
|
.filter((obj) => obj.name === POLYGON_TYPE.MODULE && targetModules.includes(obj.id))
|
||||||
|
.map((obj) => obj.moduleInfo.northModuleYn),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
if (targetModuleGroup.length > 1) {
|
if (targetModuleGroup.length > 1) {
|
||||||
swalFire({
|
swalFire({
|
||||||
@ -142,16 +146,12 @@ export default function PassivityCircuitAllocation(props) {
|
|||||||
const originHaveThisPcsModules = canvas
|
const originHaveThisPcsModules = canvas
|
||||||
.getObjects()
|
.getObjects()
|
||||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.pcs && obj.pcs.id === selectedPcs.id)
|
.filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.pcs && obj.pcs.id === selectedPcs.id)
|
||||||
// 이미 해당 pcs로 설치된 모듈의 surface의 방향을 구한다.
|
// 1. 북면모듈, 북면외모듈 혼합 여부 체크
|
||||||
const originSurfaceList = canvas
|
const targetModuleInfos = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && targetModules.includes(obj.id))
|
||||||
.getObjects()
|
debugger
|
||||||
.filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE && originHaveThisPcsModules.map((obj) => obj.surfaceId).includes(obj.id))
|
const newTargetModuleGroup = [...new Set(targetModuleInfos.concat(originHaveThisPcsModules).map((obj) => obj.moduleInfo.northModuleYn))]
|
||||||
|
|
||||||
originSurfaceList.concat(originSurfaceList).forEach((surface) => {
|
if (newTargetModuleGroup.length > 1) {
|
||||||
surfaceType[`${surface.direction}-${surface.roofMaterial.pitch}`] = surface
|
|
||||||
})
|
|
||||||
|
|
||||||
if (Object.keys(surfaceType).length > 1) {
|
|
||||||
swalFire({
|
swalFire({
|
||||||
text: getMessage('module.circuit.fix.not.same.roof.error'),
|
text: getMessage('module.circuit.fix.not.same.roof.error'),
|
||||||
type: 'alert',
|
type: 'alert',
|
||||||
@ -244,6 +244,7 @@ export default function PassivityCircuitAllocation(props) {
|
|||||||
roofSurface: surface.direction,
|
roofSurface: surface.direction,
|
||||||
roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
|
roofSurfaceIncl: +canvas.getObjects().filter((obj) => obj.id === surface.parentId)[0].pitch,
|
||||||
roofSurfaceNorthYn: surface.direction === 'north' ? 'Y' : 'N',
|
roofSurfaceNorthYn: surface.direction === 'north' ? 'Y' : 'N',
|
||||||
|
roofSurfaceNorthModuleYn: surface.northModuleYn,
|
||||||
moduleList: surface.modules.map((module) => {
|
moduleList: surface.modules.map((module) => {
|
||||||
return {
|
return {
|
||||||
itemId: module.moduleInfo.itemId,
|
itemId: module.moduleInfo.itemId,
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import Image from 'next/image'
|
|||||||
import { useMessage } from '@/hooks/useMessage'
|
import { useMessage } from '@/hooks/useMessage'
|
||||||
import { normalizeDecimalLimit, normalizeDigits } from '@/util/input-utils'
|
import { normalizeDecimalLimit, normalizeDigits } from '@/util/input-utils'
|
||||||
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
import { CalculatorInput } from '@/components/common/input/CalcInput'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
export default function Angle({ props }) {
|
export default function Angle({ props }) {
|
||||||
const { getMessage } = useMessage()
|
const { getMessage } = useMessage()
|
||||||
@ -31,11 +32,21 @@ export default function Angle({ props }) {
|
|||||||
className="input-origin block"
|
className="input-origin block"
|
||||||
value={angle1}
|
value={angle1}
|
||||||
ref={angle1Ref}
|
ref={angle1Ref}
|
||||||
onChange={(value) => setAngle1(value)}
|
onChange={(value) => {
|
||||||
|
// Calculate the final value first
|
||||||
|
let finalValue = value;
|
||||||
|
const numValue = parseInt(value, 10);
|
||||||
|
if (!isNaN(numValue)) {
|
||||||
|
const clampedValue = Math.min(180, Math.max(-180, numValue));
|
||||||
|
finalValue = String(clampedValue);
|
||||||
|
}
|
||||||
|
// Set state once with the final value
|
||||||
|
setAngle1(finalValue);
|
||||||
|
}}
|
||||||
placeholder="45"
|
placeholder="45"
|
||||||
onFocus={() => (angle1Ref.current.value = '')}
|
onFocus={() => (angle1Ref.current.value = '')}
|
||||||
options={{
|
options={{
|
||||||
allowNegative: false,
|
allowNegative: true,
|
||||||
allowDecimal: true
|
allowDecimal: true
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -11,44 +11,9 @@ export default function OuterLineWall({ props }) {
|
|||||||
|
|
||||||
const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props
|
const { length1, setLength1, length1Ref, arrow1, setArrow1 } = props
|
||||||
|
|
||||||
const resetCalculatorValue = () => {
|
|
||||||
// 1. 즉시 상태를 0으로 변경
|
|
||||||
setLength1(0);
|
|
||||||
|
|
||||||
if (length1Ref.current) {
|
|
||||||
// 2. input에 포커스를 주어 계산기 UI가 떠있는 상태를 유지하게 함
|
|
||||||
length1Ref.current.focus();
|
|
||||||
length1Ref.current.value = '';
|
|
||||||
|
|
||||||
// 3. 약간의 시간차를 두어 계산기 UI 내부의 버튼을 찾음
|
|
||||||
setTimeout(() => {
|
|
||||||
const acButton = document.querySelector('.keypad-btn.ac, .btn-ac') ||
|
|
||||||
Array.from(document.querySelectorAll('button')).find(el => el.textContent === 'AC');
|
|
||||||
|
|
||||||
if (acButton) {
|
|
||||||
acButton.click();
|
|
||||||
} else {
|
|
||||||
// 버튼을 못 찾으면 강제로 input 이벤트와 Enter/Escape 등을 시뮬레이션
|
|
||||||
length1Ref.current.dispatchEvent(new Event('input', { bubbles: true }));
|
|
||||||
}
|
|
||||||
// 다시 포커스를 주어 키패드가 유지되도록 함 (필요시)
|
|
||||||
length1Ref.current.focus();
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 키보드 입력 처리
|
// 키보드 입력 처리
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleKeyDown = (e) => {
|
const handleKeyDown = (e) => {
|
||||||
|
|
||||||
if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key)) {
|
|
||||||
// 계산기 값이 확정된 후 초기화하기 위해 약간의 지연을 줌
|
|
||||||
setTimeout(() => {
|
|
||||||
resetCalculatorValue();
|
|
||||||
}, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 계산기 키패드가 보이는지 확인
|
// 계산기 키패드가 보이는지 확인
|
||||||
const keypadVisible = document.querySelector('.keypad-container')
|
const keypadVisible = document.querySelector('.keypad-container')
|
||||||
|
|
||||||
@ -123,58 +88,37 @@ export default function OuterLineWall({ props }) {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button className="reset-btn" onClick={() => setLength1(0)}></button>
|
||||||
className="reset-btn"
|
|
||||||
onClick={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
resetCalculatorValue()
|
|
||||||
}}
|
|
||||||
></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="outline-form">
|
<div className="outline-form">
|
||||||
<span>{getMessage('modal.cover.outline.arrow')}</span>
|
<span>{getMessage('modal.cover.outline.arrow')}</span>
|
||||||
<div className="grid-direction">
|
<div className="grid-direction">
|
||||||
<button
|
<button
|
||||||
className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
|
className={`direction up ${arrow1 === '↑' ? 'act' : ''}`}
|
||||||
onClick={(e) => {
|
onClick={() => {
|
||||||
|
|
||||||
setArrow1('↑')
|
setArrow1('↑')
|
||||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp' }))
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
resetCalculatorValue()
|
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
<button
|
<button
|
||||||
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
|
className={`direction down ${arrow1 === '↓' ? 'act' : ''}`}
|
||||||
onClick={(e) => {
|
onClick={() => {
|
||||||
setArrow1('↓')
|
setArrow1('↓')
|
||||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
resetCalculatorValue()
|
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
<button
|
<button
|
||||||
className={`direction left ${arrow1 === '←' ? 'act' : ''}`}
|
className={`direction left ${arrow1 === '←' ? 'act' : ''}`}
|
||||||
onClick={(e) => {
|
onClick={() => {
|
||||||
setArrow1('←')
|
setArrow1('←')
|
||||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft' }))
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
resetCalculatorValue()
|
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
<button
|
<button
|
||||||
className={`direction right ${arrow1 === '→' ? 'act' : ''}`}
|
className={`direction right ${arrow1 === '→' ? 'act' : ''}`}
|
||||||
onClick={(e) => {
|
onClick={() => {
|
||||||
setArrow1('→')
|
setArrow1('→')
|
||||||
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight' }))
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
resetCalculatorValue()
|
|
||||||
}}
|
}}
|
||||||
></button>
|
></button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -830,7 +830,7 @@ export const useTrestle = () => {
|
|||||||
return -surfaceCompass
|
return -surfaceCompass
|
||||||
}
|
}
|
||||||
|
|
||||||
let resultAzimuth = moduleCompass
|
let resultAzimuth = parseInt(moduleCompass, 10)
|
||||||
|
|
||||||
switch (direction) {
|
switch (direction) {
|
||||||
case 'south': {
|
case 'south': {
|
||||||
|
|||||||
@ -99,6 +99,12 @@ export function useCircuitTrestle(executeEffect = false) {
|
|||||||
// 지붕면 목록
|
// 지붕면 목록
|
||||||
const getRoofSurfaceList = () => {
|
const getRoofSurfaceList = () => {
|
||||||
const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
const roofSurfaceList = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE_SETUP_SURFACE)
|
||||||
|
|
||||||
|
roofSurfaceList.forEach((roofSurface) => {
|
||||||
|
const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE && obj.surfaceId === roofSurface.id)
|
||||||
|
roofSurface.northModuleYn = modules.every((module) => module.moduleInfo.northModuleYn === 'Y') ? 'Y' : 'N'
|
||||||
|
})
|
||||||
|
|
||||||
roofSurfaceList.sort((a, b) => a.left - b.left || b.top - a.top)
|
roofSurfaceList.sort((a, b) => a.left - b.left || b.top - a.top)
|
||||||
|
|
||||||
const result = roofSurfaceList
|
const result = roofSurfaceList
|
||||||
@ -119,6 +125,7 @@ export function useCircuitTrestle(executeEffect = false) {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
roofSurfaceNorthYn: obj.direction === 'north' ? 'Y' : 'N',
|
roofSurfaceNorthYn: obj.direction === 'north' ? 'Y' : 'N',
|
||||||
|
roofSurfaceNorthModuleYn: obj.northModuleYn,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.filter((surface) => surface.moduleList.length > 0)
|
.filter((surface) => surface.moduleList.length > 0)
|
||||||
@ -139,11 +146,14 @@ export function useCircuitTrestle(executeEffect = false) {
|
|||||||
let remaining = [...arr]
|
let remaining = [...arr]
|
||||||
|
|
||||||
while (remaining.length > 0) {
|
while (remaining.length > 0) {
|
||||||
const { roofSurface, roofSurfaceIncl } = remaining[0]
|
const { roofSurface, roofSurfaceIncl, roofSurfaceNorthModuleYn } = remaining[0]
|
||||||
const key = `${roofSurface}|${roofSurfaceIncl}`
|
const key = `${roofSurface}|${roofSurfaceIncl}|${roofSurfaceNorthModuleYn}`
|
||||||
|
|
||||||
// 해당 그룹 추출
|
// 해당 그룹 추출
|
||||||
const group = remaining.filter((item) => item.roofSurface === roofSurface && item.roofSurfaceIncl === roofSurfaceIncl)
|
const group = remaining.filter(
|
||||||
|
(item) =>
|
||||||
|
item.roofSurface === roofSurface && item.roofSurfaceIncl === roofSurfaceIncl && item.roofSurfaceNorthModuleYn === roofSurfaceNorthModuleYn,
|
||||||
|
)
|
||||||
|
|
||||||
// 이미 처리했는지 체크 후 저장
|
// 이미 처리했는지 체크 후 저장
|
||||||
if (!seen.has(key)) {
|
if (!seen.has(key)) {
|
||||||
@ -152,7 +162,14 @@ export function useCircuitTrestle(executeEffect = false) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remaining에서 제거
|
// remaining에서 제거
|
||||||
remaining = remaining.filter((item) => !(item.roofSurface === roofSurface && item.roofSurfaceIncl === roofSurfaceIncl))
|
remaining = remaining.filter(
|
||||||
|
(item) =>
|
||||||
|
!(
|
||||||
|
item.roofSurface === roofSurface &&
|
||||||
|
item.roofSurfaceIncl === roofSurfaceIncl &&
|
||||||
|
item.roofSurfaceNorthModuleYn === roofSurfaceNorthModuleYn
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
@ -80,7 +80,7 @@ export const getCenterPoint = (point1, point2) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getDistance = (x1, y1, x2, y2) => {
|
export const getDistance = (x1, y1, x2, y2) => {
|
||||||
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)).toFixed(0)
|
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)).toFixed(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// polygon의 각 변에 해당 점과 점 사이의 거리를 나타내는 IText를 추가하는 함수
|
// polygon의 각 변에 해당 점과 점 사이의 거리를 나타내는 IText를 추가하는 함수
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user