From 0f2719a2f0b29196ffbd2ee4231aba29eae59770 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 19 Aug 2025 10:17:27 +0900 Subject: [PATCH 01/19] =?UTF-8?q?=EC=A4=8C=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EA=B7=B8?= =?UTF-8?q?=EB=A6=AC=EB=93=9C=20=EC=83=81=ED=83=9C=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20=ED=9D=A1=EC=B0=A9=EC=A0=90=20=EB=AA=A8=EB=93=9C=20=EC=8B=9C?= =?UTF-8?q?=EC=9E=91=20=EC=8B=9C=20ON?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/common/useGrid.js | 53 +++++++++++++++++++--------- src/hooks/option/useCanvasSetting.js | 46 ++++++++++++++---------- src/hooks/useCanvas.js | 50 ++++++++++++++++++++++++-- 3 files changed, 113 insertions(+), 36 deletions(-) diff --git a/src/hooks/common/useGrid.js b/src/hooks/common/useGrid.js index c320360f..4d427b21 100644 --- a/src/hooks/common/useGrid.js +++ b/src/hooks/common/useGrid.js @@ -1,15 +1,18 @@ import { useRecoilValue } from 'recoil' -import { canvasState, dotLineGridSettingState } from '@/store/canvasAtom' +import { canvasState, canvasZoomState, dotLineGridSettingState } from '@/store/canvasAtom' import { useEffect } from 'react' import { gridColorState } from '@/store/gridAtom' import { gridDisplaySelector } from '@/store/settingAtom' + const GRID_PADDING = 5 + export function useGrid() { const canvas = useRecoilValue(canvasState) const dotLineGridSetting = useRecoilValue(dotLineGridSettingState) const gridColor = useRecoilValue(gridColorState) const isGridDisplay = useRecoilValue(gridDisplaySelector) + const zoom = useRecoilValue(canvasZoomState) useEffect(() => { if (!canvas) { @@ -90,14 +93,32 @@ export function useGrid() { } if (patternData.lineGridDisplay) { - for (let i = 0; i < 5000 / patternData.gridVertical + 1; i++) { + // 캔버스의 실제 보이는 영역 계산 + const canvasWidth = canvas.getWidth() + const canvasHeight = canvas.getHeight() + const currentZoom = canvas.getZoom() + const viewportTransform = canvas.viewportTransform + + const visibleLeft = -viewportTransform[4] / currentZoom + const visibleTop = -viewportTransform[5] / currentZoom + const visibleRight = visibleLeft + canvasWidth / currentZoom + const visibleBottom = visibleTop + canvasHeight / currentZoom + + // 여유 공간 추가 + const padding = 200 + const gridLeft = visibleLeft - padding + const gridTop = visibleTop - padding + const gridRight = visibleRight + padding + const gridBottom = visibleBottom + padding + + // 가로선 생성 (수평선) + const horizontalGridRange = gridBottom - gridTop + const horizontalGridCount = Math.ceil(horizontalGridRange / patternData.gridVertical) + 2 + + for (let i = 0; i < horizontalGridCount; i++) { + const y = gridTop + i * patternData.gridVertical const horizontalLine = new fabric.Line( - [ - -1500, - -1500 + i * patternData.gridVertical - patternData.gridVertical / 2, - 3000, - -1500 + i * patternData.gridVertical - patternData.gridVertical / 2, - ], + [gridLeft, y, gridRight, y], { stroke: gridColor, strokeWidth: 1, @@ -118,14 +139,14 @@ export function useGrid() { canvas.add(horizontalLine) } - for (let i = 0; i < 5000 / patternData.gridHorizon + 1; i++) { + // 세로선 생성 (수직선) + const verticalGridRange = gridRight - gridLeft + const verticalGridCount = Math.ceil(verticalGridRange / patternData.gridHorizon) + 2 + + for (let i = 0; i < verticalGridCount; i++) { + const x = gridLeft + i * patternData.gridHorizon const verticalLine = new fabric.Line( - [ - -1500 + i * patternData.gridHorizon - patternData.gridHorizon / 2, - -1500, - -1500 + i * patternData.gridHorizon - patternData.gridHorizon / 2, - 3000, - ], + [x, gridTop, x, gridBottom], { stroke: gridColor, strokeWidth: 1, @@ -148,7 +169,7 @@ export function useGrid() { } canvas.renderAll() - }, [dotLineGridSetting]) + }, [dotLineGridSetting, zoom]) const move = (object, x, y) => { object.set({ diff --git a/src/hooks/option/useCanvasSetting.js b/src/hooks/option/useCanvasSetting.js index b63b6ffa..150d53f4 100644 --- a/src/hooks/option/useCanvasSetting.js +++ b/src/hooks/option/useCanvasSetting.js @@ -1,29 +1,29 @@ -import { useEffect, useState, useRef, useContext } from 'react' +import { useContext, useEffect, useState } from 'react' import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil' import { adsorptionPointModeState, adsorptionRangeState, - canvasState, - planSizeSettingState, - dotLineGridSettingState, canvasSettingState, + canvasState, currentMenuState, + dotLineGridSettingState, + planSizeSettingState, } from '@/store/canvasAtom' import { globalLocaleStore } from '@/store/localeAtom' import { useMessage } from '@/hooks/useMessage' import { useAxios } from '@/hooks/useAxios' import { useSwal } from '@/hooks/useSwal' import { + addedRoofsState, + basicSettingState, correntObjectNoState, corridorDimensionSelector, - settingModalFirstOptionsState, - settingModalSecondOptionsState, - settingModalGridOptionsState, - basicSettingState, + fetchRoofMaterialsState, roofMaterialsAtom, selectedRoofMaterialSelector, - addedRoofsState, - fetchRoofMaterialsState, + settingModalFirstOptionsState, + settingModalGridOptionsState, + settingModalSecondOptionsState, } from '@/store/settingAtom' import { MENU, POLYGON_TYPE } from '@/common/common' import { globalFontAtom } from '@/store/fontAtom' @@ -339,11 +339,11 @@ export function useCanvasSetting(executeEffect = true) { */ const fetchBasicSettings = async (planNo, openPoint) => { // 지붕재 데이터가 없으면 먼저 로드 - let materials = roofMaterials; + let materials = roofMaterials if (!materials || materials.length === 0) { - logger.log("Waiting for roofMaterials to be loaded..."); - materials = await addRoofMaterials(); - logger.log("roofMaterials loaded:", materials); + logger.log('Waiting for roofMaterials to be loaded...') + materials = await addRoofMaterials() + logger.log('roofMaterials loaded:', materials) } try { @@ -529,8 +529,14 @@ export function useCanvasSetting(executeEffect = true) { ? params.selectedRoofMaterial.raftBaseCd : params.roofsData.raft, roofLayout: params.roofsData.roofLayout === null || params.roofsData.roofLayout === undefined ? 'P' : params.roofsData.roofLayout, - roofPitch: params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined || params.roofsData.roofPitch === '' ? 0 : params.roofsData.roofPitch, - roofAngle: params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined || params.roofsData.roofAngle === '' ? 0 : params.roofsData.roofAngle, + roofPitch: + params.roofsData.roofPitch === null || params.roofsData.roofPitch === undefined || params.roofsData.roofPitch === '' + ? 0 + : params.roofsData.roofPitch, + roofAngle: + params.roofsData.roofAngle === null || params.roofsData.roofAngle === undefined || params.roofsData.roofAngle === '' + ? 0 + : params.roofsData.roofAngle, }, ], } @@ -643,7 +649,11 @@ export function useCanvasSetting(executeEffect = true) { setDimensionLineSettings({ ...dimensionLineSettings, pixel: res.originPixel, color: res.originColor }) /** 도면크기 설정 */ - setPlanSizeSettingMode({ ...planSizeSettingMode, originHorizon: res.originHorizon, originVertical: res.originVertical }) + setPlanSizeSettingMode({ + ...planSizeSettingMode, + originHorizon: res.originHorizon, + originVertical: res.originVertical, + }) canvas.setWidth(res.originHorizon) canvas.setHeight(res.originVertical) canvas.renderAll() @@ -723,7 +733,7 @@ export function useCanvasSetting(executeEffect = true) { /** 조회된 글꼴 데이터가 없는 경우 (데이터 초기화) */ /** 흡착점 ON/OFF */ - setAdsorptionPointMode(false) + setAdsorptionPointMode(true) /** 치수선 설정 */ resetDimensionLineSettings() diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 4945fdd7..5dc29c0d 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -26,6 +26,7 @@ export function useCanvas(id) { const isImageDisplay = useRecoilValue(imageDisplaySelector) const {} = useFont() const resetCanvasZoom = useResetRecoilState(canvasZoomState) + const zoom = useRecoilValue(canvasZoomState) /** * 처음 셋팅 @@ -50,8 +51,53 @@ export function useCanvas(id) { }, []) useEffect(() => { - // canvas 사이즈가 변경되면 다시 - }, [canvasSize]) + // zoom 상태가 변경될 때 tempGrid 라인들의 크기를 캔버스에 맞게 조정 + if (canvas) { + adjustTempGridLines() + } + }, [zoom]) + + const adjustTempGridLines = () => { + if (!canvas) return + + const canvasWidth = canvas.getWidth() + const canvasHeight = canvas.getHeight() + const currentZoom = canvas.getZoom() + const viewportTransform = canvas.viewportTransform + + // 실제 보이는 캔버스 영역 계산 (zoom과 pan 고려) + const visibleLeft = -viewportTransform[4] / currentZoom + const visibleTop = -viewportTransform[5] / currentZoom + const visibleRight = visibleLeft + canvasWidth / currentZoom + const visibleBottom = visibleTop + canvasHeight / currentZoom + + // tempGrid 라인들을 찾아서 크기 조정 + const tempGridLines = canvas.getObjects().filter((obj) => ['tempGrid', 'lineGrid'].includes(obj.name)) + + tempGridLines.forEach((line) => { + if (line.direction === 'vertical') { + // 세로 라인: y축을 캔버스 전체 높이로 설정 + line.set({ + x1: line.x1, + y1: visibleTop - 100, // 여유 공간 추가 + x2: line.x1, + y2: visibleBottom + 100, // 여유 공간 추가 + }) + } else if (line.direction === 'horizontal') { + // 가로 라인: x축을 캔버스 전체 너비로 설정 + line.set({ + x1: visibleLeft - 100, // 여유 공간 추가 + y1: line.y1, + x2: visibleRight + 100, // 여유 공간 추가 + y2: line.y1, + }) + } + + line.setCoords() + }) + + canvas.renderAll() + } useEffect(() => { canvas From 2aca4d22ec80bd91691f836ed56782b69c424c63 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 19 Aug 2025 10:33:18 +0900 Subject: [PATCH 02/19] =?UTF-8?q?=EC=A4=8C=20=EC=83=81=ED=83=9C=EC=97=90?= =?UTF-8?q?=20=EB=94=B0=EB=9D=BC=20=EA=B7=B8=EB=A6=AC=EB=93=9C=20=EB=B3=B5?= =?UTF-8?q?=EC=82=AC,=20=EC=9D=B4=EB=8F=99=20=EC=8B=9C=20=EC=9E=98?= =?UTF-8?q?=EB=A6=AC=EB=8A=94=20=ED=98=84=EC=83=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/floor-plan/modal/grid/GridCopy.jsx | 10 +++++----- src/components/floor-plan/modal/grid/GridMove.jsx | 10 ++++------ src/hooks/useCanvas.js | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/components/floor-plan/modal/grid/GridCopy.jsx b/src/components/floor-plan/modal/grid/GridCopy.jsx index 805cf186..84eddb15 100644 --- a/src/components/floor-plan/modal/grid/GridCopy.jsx +++ b/src/components/floor-plan/modal/grid/GridCopy.jsx @@ -5,9 +5,9 @@ import { useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' import { useState } from 'react' import { canvasState, currentObjectState } from '@/store/canvasAtom' -import { useGrid } from '@/hooks/common/useGrid' import { gridColorState } from '@/store/gridAtom' import { gridDisplaySelector } from '@/store/settingAtom' + const GRID_PADDING = 5 export default function GridCopy(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -25,10 +25,10 @@ export default function GridCopy(props) { } const copy = (object, length) => { - const lineStartX = object.direction === 'vertical' ? object.x1 + length : 0 - const lineEndX = object.direction === 'vertical' ? object.x2 + length : canvas.width - const lineStartY = object.direction === 'vertical' ? 0 : object.y1 + length - const lineEndY = object.direction === 'vertical' ? canvas.width : object.y1 + length + const lineStartX = object.direction === 'vertical' ? object.x1 + length : object.x1 + const lineEndX = object.direction === 'vertical' ? object.x2 + length : object.x2 + const lineStartY = object.direction === 'vertical' ? object.y1 : object.y1 + length + const lineEndY = object.direction === 'vertical' ? object.y2 : object.y1 + length const line = new fabric.Line([lineStartX, lineStartY, lineEndX, lineEndY], { stroke: gridColor, diff --git a/src/components/floor-plan/modal/grid/GridMove.jsx b/src/components/floor-plan/modal/grid/GridMove.jsx index 52084e00..eb83d2f1 100644 --- a/src/components/floor-plan/modal/grid/GridMove.jsx +++ b/src/components/floor-plan/modal/grid/GridMove.jsx @@ -3,11 +3,9 @@ import { useMessage } from '@/hooks/useMessage' import { usePopup } from '@/hooks/usePopup' import { useRecoilState, useRecoilValue } from 'recoil' import { contextPopupPositionState } from '@/store/popupAtom' -import { useCanvas } from '@/hooks/useCanvas' import { canvasState, currentObjectState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import { useSwal } from '@/hooks/useSwal' -import { set } from 'react-hook-form' export default function GridMove(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -70,10 +68,10 @@ export default function GridMove(props) { const move = (object, x, y) => { object.set({ ...object, - x1: object.direction === 'vertical' ? object.x1 + x : 0, - x2: object.direction === 'vertical' ? object.x1 + x : canvas.width, - y1: object.direction === 'vertical' ? 0 : object.y1 + y, - y2: object.direction === 'vertical' ? canvas.height : object.y1 + y, + x1: object.direction === 'vertical' ? object.x1 + x : object.x1, + x2: object.direction === 'vertical' ? object.x1 + x : object.x2, + y1: object.direction === 'vertical' ? object.y1 : object.y1 + y, + y2: object.direction === 'vertical' ? object.y2 : object.y1 + y, }) } diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js index 5dc29c0d..679b17fa 100644 --- a/src/hooks/useCanvas.js +++ b/src/hooks/useCanvas.js @@ -72,7 +72,7 @@ export function useCanvas(id) { const visibleBottom = visibleTop + canvasHeight / currentZoom // tempGrid 라인들을 찾아서 크기 조정 - const tempGridLines = canvas.getObjects().filter((obj) => ['tempGrid', 'lineGrid'].includes(obj.name)) + const tempGridLines = canvas.getObjects().filter((obj) => ['tempGrid', 'lineGrid', 'mouseLine'].includes(obj.name)) tempGridLines.forEach((line) => { if (line.direction === 'vertical') { From 102cc4d672730c77c6cecf3ea6f2197146cf3772 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 19 Aug 2025 15:32:33 +0900 Subject: [PATCH 03/19] =?UTF-8?q?=EC=A4=8C=20=EC=83=81=ED=83=9C=EC=97=90?= =?UTF-8?q?=20=EB=94=B0=EB=9D=BC=20mouseLine=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useEvent.js | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 6499f2f3..748e680a 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -369,18 +369,39 @@ export function useEvent() { } const drawMouseLine = (pointer) => { - const horizontalLine = new fabric.Line([-2 * canvas.width, pointer.y, 2 * canvas.width, pointer.y], { + // 캔버스의 실제 보이는 영역 계산 (zoom과 pan 고려) + const canvasWidth = canvas.getWidth() + const canvasHeight = canvas.getHeight() + const currentZoom = canvas.getZoom() + const viewportTransform = canvas.viewportTransform + + const visibleLeft = -viewportTransform[4] / currentZoom + const visibleTop = -viewportTransform[5] / currentZoom + const visibleRight = visibleLeft + canvasWidth / currentZoom + const visibleBottom = visibleTop + canvasHeight / currentZoom + + // 여유 공간 추가 + const padding = 200 + const lineLeft = visibleLeft - padding + const lineTop = visibleTop - padding + const lineRight = visibleRight + padding + const lineBottom = visibleBottom + padding + + // 가로선 (수평선) + const horizontalLine = new fabric.Line([lineLeft, pointer.y, lineRight, pointer.y], { stroke: 'red', strokeWidth: 1, selectable: false, + direction: 'horizontal', name: 'mouseLine', }) - // 세로선 - const verticalLine = new fabric.Line([pointer.x, -2 * canvas.height, pointer.x, 2 * canvas.height], { + // 세로선 (수직선) + const verticalLine = new fabric.Line([pointer.x, lineTop, pointer.x, lineBottom], { stroke: 'red', strokeWidth: 1, selectable: false, + direction: 'vertical', name: 'mouseLine', }) From 4a914e0aea15b0cb831529e4e1d6206a256f2db0 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Tue, 19 Aug 2025 18:26:11 +0900 Subject: [PATCH 04/19] =?UTF-8?q?roof=EC=9D=98=20=EC=A4=91=EC=95=99=20?= =?UTF-8?q?=EC=A7=80=EC=A0=90=EC=97=90=EC=84=9C=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=A6=B0=EC=83=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../circuitTrestle/CircuitTrestleSetting.jsx | 76 ++++++++++--------- 1 file changed, 41 insertions(+), 35 deletions(-) diff --git a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx index 44deb1a0..4c09868a 100644 --- a/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/CircuitTrestleSetting.jsx @@ -120,7 +120,44 @@ export default function CircuitTrestleSetting({ id }) { const beforeCapture = (type) => { setCanvasZoom(100) canvas.set({ zoom: 1 }) - canvas.viewportTransform = [1, 0, 0, 1, 0, 0] + + // roof 객체들을 찾아서 중앙점 계산 + const roofs = canvas.getObjects().filter((obj) => obj.name === 'roof') + + if (roofs.length > 0) { + // 모든 roof의 x, y 좌표를 수집 + const allPoints = [] + roofs.forEach((roof) => { + if (roof.getCurrentPoints()) { + roof.getCurrentPoints().forEach((point) => { + allPoints.push({ x: point.x, y: point.y }) + }) + } + }) + + if (allPoints.length > 0) { + // 모든 점들의 중앙값 계산 + const minX = Math.min(...allPoints.map((p) => p.x)) + const maxX = Math.max(...allPoints.map((p) => p.x)) + const minY = Math.min(...allPoints.map((p) => p.y)) + const maxY = Math.max(...allPoints.map((p) => p.y)) + + const centerX = (minX + maxX) / 2 + const centerY = (minY + maxY) / 2 + + // 캔버스 중앙으로 이동하기 위한 오프셋 계산 + const canvasWidth = canvas.getWidth() + const canvasHeight = canvas.getHeight() + const offsetX = canvasWidth / 2 - centerX + const offsetY = canvasHeight / 2 - centerY + + canvas.viewportTransform = [1, 0, 0, 1, offsetX, offsetY] + } else { + canvas.viewportTransform = [1, 0, 0, 1, 0, 0] + } + } else { + canvas.viewportTransform = [1, 0, 0, 1, 0, 0] + } const modules = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.MODULE) const circuitNumberTexts = canvas.getObjects().filter((obj) => obj.name === 'circuitNumber') @@ -139,40 +176,9 @@ export default function CircuitTrestleSetting({ id }) { // roof polygon들의 중간점 계산 const roofPolygons = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) let x, y - x = 0 //canvas.width / 2 - y = 1000 //canvas.height / 2 - - /*if (roofPolygons.length > 0) { - let minX = Infinity, - minY = Infinity, - maxX = -Infinity, - maxY = -Infinity - - roofPolygons.forEach((obj) => { - const boundingRect = obj.getBoundingRect() - minX = Math.min(minX, boundingRect.left) - minY = Math.min(minY, boundingRect.top) - maxX = Math.max(maxX, boundingRect.left + boundingRect.width) - maxY = Math.max(maxY, boundingRect.top + boundingRect.height) - }) - - x = (minX + maxX) / 2 - y = (minY + maxY) / 2 - } else { - // roof polygon이 없으면 기본 중앙점 사용 - x = canvas.width / 2 - y = canvas.height / 2 - } - - if (x > 1600) { - x = 0 - y = 0 - } - if (y > 1600) { - x = 0 - y = 0 - }*/ - + x = canvas.width / 2 + y = canvas.height / 2 + canvas.zoomToPoint(new fabric.Point(x, y), 0.4) changeFontSize('lengthText', '28') changeFontSize('circuitNumber', '28') From d98eba97a78e65ea925a1c03a45775c77ed7625a Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Wed, 20 Aug 2025 14:02:09 +0900 Subject: [PATCH 05/19] =?UTF-8?q?pcsMaker=EB=8A=94=20=ED=95=AD=EC=83=81=20?= =?UTF-8?q?=EC=83=88=EB=A1=9C=20=EB=B6=88=EB=9F=AC=EC=98=A4=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modal/circuitTrestle/step/PowerConditionalSelect.jsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx index cf79634f..2009e63f 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/PowerConditionalSelect.jsx @@ -74,11 +74,9 @@ export default function PowerConditionalSelect(props) { ] useEffect(() => { - if (makers.length === 0) { - getPcsMakerList().then((res) => { - setMakers(res.data) - }) - } + getPcsMakerList().then((res) => { + setMakers(res.data) + }) }, []) const onCheckSeries = (data) => { From 5cf5ef55af1ac8e884bf60bb352b6cba1320d614 Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 20 Aug 2025 17:00:17 +0900 Subject: [PATCH 06/19] =?UTF-8?q?[1267]=20500=EC=97=90=EB=9F=AC=20-=20str?= =?UTF-8?q?=20=3D>=20Number=20=EB=B3=80=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QLine.js | 2 +- src/components/fabric/QPolygon.js | 12 ++++++------ src/util/canvas-util.js | 8 ++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index af9dd7a4..48680343 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -17,7 +17,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { initialize: function (points, options, length = 0) { // 소수점 전부 제거 - points = points.map((point) => Number(point?.toFixed(1))) + points = points.map((point) => Number(point).toFixed(1)) this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true }) if (options.id) { diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index b50cdaa3..e1c80f4d 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -710,14 +710,14 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { inPolygonImproved(point) { const vertices = this.points let inside = false - const testX = Number(point.x.toFixed(this.toFixed)) - const testY = Number(point.y.toFixed(this.toFixed)) + const testX = Number(point.x).toFixed(this.toFixed) + const testY = Number(point.y).toFixed(this.toFixed) for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) { - const xi = Number(vertices[i].x.toFixed(this.toFixed)) - const yi = Number(vertices[i].y.toFixed(this.toFixed)) - const xj = Number(vertices[j].x.toFixed(this.toFixed)) - const yj = Number(vertices[j].y.toFixed(this.toFixed)) + const xi = Number(vertices[i].x).toFixed(this.toFixed) + const yi = Number(vertices[i].y).toFixed(this.toFixed) + const xj = Number(vertices[j].x).toFixed(this.toFixed) + const yj = Number(vertices[j].y).toFixed(this.toFixed) // 점이 정점 위에 있는지 확인 if (Math.abs(xi - testX) < 0.01 && Math.abs(yi - testY) < 0.01) { diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index 0af492a1..dc3b3c93 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -342,6 +342,14 @@ export const findIntersection1 = (line1, line2) => { } export const calculateIntersection = (line1, line2) => { + line1.x1 = Number(line1.x1) + line1.y1 = Number(line1.y1) + line1.x2 = Number(line1.x2) + line1.y2 = Number(line1.y2) + line2.x1 = Number(line2.x1) + line2.y1 = Number(line2.y1) + line2.x2 = Number(line2.x2) + line2.y2 = Number(line2.y2) const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2]) if (!result) { return null From a663faf359f95cb1437a5afb255b31e498f8050d Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 20 Aug 2025 18:28:47 +0900 Subject: [PATCH 07/19] =?UTF-8?q?[1267]=20500=EC=97=90=EB=9F=AC=20-=20str?= =?UTF-8?q?=20=3D>=20Number=20=EB=B3=80=ED=99=98=20(=EC=9D=B4=EC=A0=84?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=B5=EA=B5=AC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QLine.js | 2 +- src/components/fabric/QPolygon.js | 12 ++++++------ src/util/canvas-util.js | 8 -------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 48680343..af9dd7a4 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -17,7 +17,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { initialize: function (points, options, length = 0) { // 소수점 전부 제거 - points = points.map((point) => Number(point).toFixed(1)) + points = points.map((point) => Number(point?.toFixed(1))) this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true }) if (options.id) { diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index e1c80f4d..b50cdaa3 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -710,14 +710,14 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { inPolygonImproved(point) { const vertices = this.points let inside = false - const testX = Number(point.x).toFixed(this.toFixed) - const testY = Number(point.y).toFixed(this.toFixed) + const testX = Number(point.x.toFixed(this.toFixed)) + const testY = Number(point.y.toFixed(this.toFixed)) for (let i = 0, j = vertices.length - 1; i < vertices.length; j = i++) { - const xi = Number(vertices[i].x).toFixed(this.toFixed) - const yi = Number(vertices[i].y).toFixed(this.toFixed) - const xj = Number(vertices[j].x).toFixed(this.toFixed) - const yj = Number(vertices[j].y).toFixed(this.toFixed) + const xi = Number(vertices[i].x.toFixed(this.toFixed)) + const yi = Number(vertices[i].y.toFixed(this.toFixed)) + const xj = Number(vertices[j].x.toFixed(this.toFixed)) + const yj = Number(vertices[j].y.toFixed(this.toFixed)) // 점이 정점 위에 있는지 확인 if (Math.abs(xi - testX) < 0.01 && Math.abs(yi - testY) < 0.01) { diff --git a/src/util/canvas-util.js b/src/util/canvas-util.js index dc3b3c93..0af492a1 100644 --- a/src/util/canvas-util.js +++ b/src/util/canvas-util.js @@ -342,14 +342,6 @@ export const findIntersection1 = (line1, line2) => { } export const calculateIntersection = (line1, line2) => { - line1.x1 = Number(line1.x1) - line1.y1 = Number(line1.y1) - line1.x2 = Number(line1.x2) - line1.y2 = Number(line1.y2) - line2.x1 = Number(line2.x1) - line2.y1 = Number(line2.y1) - line2.x2 = Number(line2.x2) - line2.y2 = Number(line2.y2) const result = intersect([line1.x1, line1.y1], [line1.x2, line1.y2], [line2.x1, line2.y1], [line2.x2, line2.y2]) if (!result) { return null From cef764fd0e3b047dba449e3551c671b609737698 Mon Sep 17 00:00:00 2001 From: ysCha Date: Wed, 20 Aug 2025 19:01:44 +0900 Subject: [PATCH 08/19] =?UTF-8?q?[1267]=20500=EC=97=90=EB=9F=AC=20-=20str?= =?UTF-8?q?=20=3D>=20Number=20=EB=B3=80=ED=99=98=20(Number=EB=A1=9C=20?= =?UTF-8?q?=ED=95=9C=EB=B2=88=EB=8D=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/fabric/QLine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index af9dd7a4..e9049ca8 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -17,7 +17,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { initialize: function (points, options, length = 0) { // 소수점 전부 제거 - points = points.map((point) => Number(point?.toFixed(1))) + points = points.map((point) => Number(Number(point)?.toFixed(1))) this.callSuper('initialize', points, { ...options, selectable: options.selectable ?? true }) if (options.id) { From 6c89e6ffa60f45efc5613339f0f1644314304dbe Mon Sep 17 00:00:00 2001 From: ysCha Date: Thu, 21 Aug 2025 09:26:51 +0900 Subject: [PATCH 09/19] =?UTF-8?q?[1249]=20=EC=A3=BC=EC=86=8C=EC=9D=98=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A3=BC=EC=86=8C=EB=9E=80=EC=9D=98=20?= =?UTF-8?q?=ED=95=84=EC=88=98=20=EC=9E=85=EB=A0=A5=EC=9D=84=20=EC=A4=91?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/StuffDetail.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index df8b235f..2bff0eb3 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -1239,10 +1239,10 @@ export default function StuffDetail() { } //주소 - if (!formData.address) { - fieldNm = getMessage('stuff.detail.address') - errors = fieldNm - } + // if (!formData.address) { + // fieldNm = getMessage('stuff.detail.address') + // errors = fieldNm + // } //도도부현 if (!formData.prefId || formData.prefId === '0') { From 301e6c136c91668e396384275d90854e7e5d4244 Mon Sep 17 00:00:00 2001 From: ysCha Date: Thu, 21 Aug 2025 18:45:02 +0900 Subject: [PATCH 10/19] =?UTF-8?q?[1252]=20=EC=9D=BC=EB=B3=B8=EC=9D=98=20?= =?UTF-8?q?=EC=A0=84=EA=B0=81=20=EC=88=AB=EC=9E=90,=20=EB=B0=98=EA=B0=81?= =?UTF-8?q?=20=EC=88=AB=EC=9E=90=20=EC=9E=85=EB=A0=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/estimate/Estimate.jsx | 36 +++++++++--------- .../modal/auxiliary/AuxiliaryEdit.jsx | 13 ++++--- .../modal/auxiliary/AuxiliarySize.jsx | 4 +- .../floor-plan/modal/basic/step/Module.jsx | 5 ++- .../modal/basic/step/Orientation.jsx | 18 +++++---- .../floor-plan/modal/basic/step/Placement.jsx | 3 +- .../floor-plan/modal/basic/step/Trestle.jsx | 29 +++++++++++++- .../step/type/PassivityCircuitAllocation.jsx | 16 +++++++- .../dimensionLine/DimensionLineSetting.jsx | 10 ++++- .../modal/eavesGable/type/Eaves.jsx | 38 +++++++++++++++++-- .../floor-plan/modal/grid/DotLineGrid.jsx | 8 ++-- .../floor-plan/modal/grid/GridMove.jsx | 13 ++++--- .../floor-plan/modal/lineTypes/Angle.jsx | 6 +-- .../floor-plan/modal/lineTypes/Diagonal.jsx | 8 ++-- .../modal/lineTypes/DoublePitch.jsx | 11 +++--- .../modal/lineTypes/OuterLineWall.jsx | 4 +- .../floor-plan/modal/lineTypes/RightAngle.jsx | 6 +-- .../floor-plan/modal/movement/type/Updown.jsx | 4 +- .../floor-plan/modal/object/ObjectSetting.jsx | 11 +++--- .../placementShape/PlacementShapeSetting.jsx | 28 ++++++++------ .../roofAllocation/ActualSizeSetting.jsx | 3 +- .../ContextRoofAllocationSetting.jsx | 10 ++++- .../roofAllocation/RoofAllocationSetting.jsx | 18 +++++++-- .../modal/roofShape/type/Direction.jsx | 30 ++++++++++++--- .../modal/roofShape/type/Pattern.jsx | 8 ++-- .../floor-plan/modal/roofShape/type/Ridge.jsx | 6 +-- .../modal/roofShape/type/option/Eaves.jsx | 6 +-- .../modal/roofShape/type/option/Gable.jsx | 4 +- .../roofShape/type/option/HipAndGable.jsx | 8 ++-- .../roofShape/type/option/Jerkinhead.jsx | 8 ++-- .../modal/roofShape/type/option/Shed.jsx | 6 +-- .../modal/roofShape/type/option/Wall.jsx | 4 +- .../setting01/planSize/PlanSizeSetting.jsx | 21 +++++----- src/components/management/StuffDetail.jsx | 11 ++++-- .../management/popup/FindAddressPop.jsx | 13 ++++--- .../management/popup/PlanRequestPop.jsx | 10 +++-- src/util/input-utils.js | 38 +++++++++++++++++++ 37 files changed, 327 insertions(+), 148 deletions(-) diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx index 4a3337db..f6517960 100644 --- a/src/components/estimate/Estimate.jsx +++ b/src/components/estimate/Estimate.jsx @@ -23,6 +23,7 @@ import { usePopup } from '@/hooks/usePopup' import { useSwal } from '@/hooks/useSwal' import { QcastContext } from '@/app/QcastProvider' import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' +import {normalizeDigits, normalizeDecimal} from '@/util/input-utils' export default function Estimate({}) { const [uniqueData, setUniqueData] = useState([]) const [handlePricingFlag, setHandlePricingFlag] = useState(false) @@ -645,11 +646,14 @@ export default function Estimate({}) { newValue = parts[0] + '.' + parts[1].substring(0, 2) } - let pkgAsp = newValue || '0' + let pkgAsp = normalizeDecimal(newValue || '0') //현재 PKG용량값 가져오기 let totVolKw = estimateContextState.totVolKw * 1000 - let pkgTotPrice = parseFloat(pkgAsp?.replaceAll(',', '')) * totVolKw * 1000 + // let pkgTotPrice = parseFloat(pkgAsp?.replaceAll(',', '')) * totVolKw * 1000 + + const pkgAspNumber = Number(normalizeDecimal(pkgAsp)) + const pkgTotPrice = pkgAspNumber * totVolKw * 1000 setEstimateContextState({ pkgAsp: pkgAsp, @@ -663,7 +667,7 @@ export default function Estimate({}) { // 수량 변경 const onChangeAmount = (value, dispOrder, index) => { //itemChangeFlg = 1, partAdd = 0 셋팅 - let amount = Number(value.replace(/[^0-9]/g, '').replaceAll(',', '')) + let amount = Number(normalizeDigits(value)) if (isNaN(amount)) { amount = '0' @@ -701,7 +705,8 @@ export default function Estimate({}) { // 단가 변경 const onChangeSalePrice = (value, dispOrder, index) => { //itemChangeFlg, partAdd 받아온 그대로 - let salePrice = Number(value.replace(/[^0-9]/g, '').replaceAll(',', '')) + let salePrice = Number(normalizeDecimal(value)) + if (isNaN(salePrice)) { salePrice = 0 } else { @@ -940,7 +945,7 @@ export default function Estimate({}) { delete item.showSalePrice delete item.showSaleTotPrice if (item.delFlg === '0') { - let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0 + let amount = Number(normalizeDigits(item.amount)) || 0 let price if (amount === 0) { price = 0 @@ -975,7 +980,7 @@ export default function Estimate({}) { makeUniqueSpecialNoteCd(itemList) itemList.forEach((item) => { if (item.delFlg === '0') { - let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0 + let amount = Number(normalizeDigits(item.amount)) || 0 let salePrice if (item.moduleFlg === '1') { const volKw = (item.pnowW * amount) / 1000 @@ -1009,8 +1014,8 @@ export default function Estimate({}) { } } }) - let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 - + //let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 + const pkgAsp = Number(normalizeDecimal(estimateContextState.pkgAsp)) totals.pkgTotPrice = pkgAsp * totals.totVolKw * 1000 totals.supplyPrice = totals.addSupplyPrice + totals.pkgTotPrice totals.vatPrice = totals.supplyPrice * 0.1 @@ -1069,7 +1074,7 @@ export default function Estimate({}) { let dispCableFlgCnt = 0 estimateContextState.itemList.forEach((item) => { if (item.delFlg === '0') { - let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0 + let amount = Number(normalizeDigits(item.amount)) || 0 let salePrice if (item.moduleFlg === '1') { const volKw = (item.pnowW * amount) / 1000 @@ -1102,7 +1107,7 @@ export default function Estimate({}) { item.showSaleTotPrice = '0' } - if (item.dispCableFlg === '1' ) { + if (item.dispCableFlg === '1') { dispCableFlgCnt++ if(item.itemTpCd === 'M12' || item.itemTpCd === 'S13') { setCableDbItem(item.itemId) @@ -1118,9 +1123,10 @@ export default function Estimate({}) { setCableDbItem('100037') } - let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 - + // let pkgAsp = estimateContextState.pkgAsp ? Number(estimateContextState.pkgAsp.replaceAll(',', '')) : 0 + const pkgAsp = Number(normalizeDecimal(estimateContextState.pkgAsp)) totals.pkgTotPrice = pkgAsp * totals.totVolKw * 1000 + totals.supplyPrice = totals.addSupplyPrice + totals.pkgTotPrice totals.vatPrice = totals.supplyPrice * 0.1 totals.totPrice = totals.supplyPrice + totals.vatPrice @@ -1150,7 +1156,7 @@ export default function Estimate({}) { delete item.showSalePrice delete item.showSaleTotPrice if (item.delFlg === '0') { - let amount = Number(item.amount?.replace(/[^0-9]/g, '').replaceAll(',', '')) || 0 + let amount = Number(normalizeDigits(item.amount)) || 0 let price if (amount === 0) { price = 0 @@ -1176,10 +1182,6 @@ export default function Estimate({}) { if (item.dispCableFlg === '1') { dispCableFlgCnt++ - } - - if (item.dispCableFlg === '1'){ - if(item.itemTpCd === 'M12' || item.itemTpCd === 'S13') { setCableDbItem(item.itemId) }else{ diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx index f10322ca..938b5244 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliaryEdit.jsx @@ -7,6 +7,7 @@ import { useState } from 'react' import { currentObjectState } from '@/store/canvasAtom' import { useAuxiliaryDrawing } from '@/hooks/roofcover/useAuxiliaryDrawing' import { useSwal } from '@/hooks/useSwal' +import { normalizeDigits } from '@/util/input-utils' export default function AuxiliaryEdit(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -40,15 +41,15 @@ export default function AuxiliaryEdit(props) { if (currentObject) { copy( currentObject, - arrow2 ? (arrow2 === '←' ? Number(+horizonSize / 10) * -1 : Number(+horizonSize / 10)) : 0, - arrow1 ? (arrow1 === '↑' ? Number(+verticalSize / 10) * -1 : Number(+verticalSize / 10)) : 0, + arrow2 ? (arrow2 === '←' ? (Number(normalizeDigits(horizonSize)) / 10) * -1 : Number(normalizeDigits(horizonSize)) / 10) : 0, + arrow1 ? (arrow1 === '↑' ? (Number(normalizeDigits(verticalSize)) / 10) * -1 : Number(normalizeDigits(verticalSize)) / 10) : 0, ) } } else { move( currentObject, - arrow2 ? (arrow2 === '←' ? Number(+horizonSize / 10) * -1 : Number(+horizonSize / 10)) : 0, - arrow1 ? (arrow1 === '↑' ? Number(+verticalSize / 10) * -1 : Number(+verticalSize / 10)) : 0, + arrow2 ? (arrow2 === '←' ? (Number(normalizeDigits(horizonSize)) / 10) * -1 : Number(normalizeDigits(horizonSize)) / 10) : 0, + arrow1 ? (arrow1 === '↑' ? (Number(normalizeDigits(verticalSize)) / 10) * -1 : Number(normalizeDigits(verticalSize)) / 10) : 0, ) } @@ -65,7 +66,7 @@ export default function AuxiliaryEdit(props) {

{getMessage('length')}

- setVerticalSize(e.target.value)} /> + setVerticalSize(normalizeDigits(e.target.value))} />
mm
@@ -87,7 +88,7 @@ export default function AuxiliaryEdit(props) {
- setHorizonSize(e.target.value)} /> + setHorizonSize(normalizeDigits(e.target.value))} />
mm
diff --git a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx index 3bb94a4f..5a9cde6f 100644 --- a/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx +++ b/src/components/floor-plan/modal/auxiliary/AuxiliarySize.jsx @@ -7,6 +7,7 @@ import { canvasState, currentObjectState } from '@/store/canvasAtom' import { useEffect, useState } from 'react' import Big from 'big.js' import { calcLineActualSize, calcLinePlaneSize } from '@/util/qpolygon-utils' +import { normalizeDigits } from '@/util/input-utils' export default function AuxiliarySize(props) { const contextPopupPosition = useRecoilValue(contextPopupPositionState) @@ -42,7 +43,8 @@ export default function AuxiliarySize(props) { if (checkedRadio === 2) setValue2(value) setSize(0) } else { - value = Big(value.replace(/[^0-9]/g, '')) + //value = Big(value.replace(/[^0-9]/g, '')) + value = Big(normalizeDigits(value)) if (checkedRadio === 1) setValue1(value.toNumber()) if (checkedRadio === 2) setValue2(value.toNumber()) setSize(value.div(10).toNumber()) diff --git a/src/components/floor-plan/modal/basic/step/Module.jsx b/src/components/floor-plan/modal/basic/step/Module.jsx index 8ab6f394..2402b3e0 100644 --- a/src/components/floor-plan/modal/basic/step/Module.jsx +++ b/src/components/floor-plan/modal/basic/step/Module.jsx @@ -10,6 +10,7 @@ import { useDebounceValue } from 'usehooks-ts' import { moduleSelectionDataState } from '@/store/selectedModuleOptions' import { useCanvasPopupStatusController } from '@/hooks/common/useCanvasPopupStatusController' import { isObjectNotEmpty } from '@/util/common-utils' +import { normalizeDecimal} from '@/util/input-utils' export default function Module({ setTabNum }) { const { getMessage } = useMessage() @@ -188,7 +189,7 @@ export default function Module({ setTabNum }) { type="text" className="input-origin block" value={inputInstallHeight} - onChange={(e) => setInputInstallHeight(e.target.value)} + onChange={(e) => setInputInstallHeight(normalizeDecimal(e.target.value))} />
m @@ -225,7 +226,7 @@ export default function Module({ setTabNum }) { type="text" className="input-origin block" value={inputVerticalSnowCover} - onChange={(e) => setInputVerticalSnowCover(e.target.value)} + onChange={(e) => setInputVerticalSnowCover(normalizeDecimal(e.target.value))} />
cm diff --git a/src/components/floor-plan/modal/basic/step/Orientation.jsx b/src/components/floor-plan/modal/basic/step/Orientation.jsx index 0b603aed..14618a20 100644 --- a/src/components/floor-plan/modal/basic/step/Orientation.jsx +++ b/src/components/floor-plan/modal/basic/step/Orientation.jsx @@ -8,6 +8,7 @@ import QSelectBox from '@/components/common/select/QSelectBox' import { roofsState } from '@/store/roofAtom' import { useModuleBasicSetting } from '@/hooks/module/useModuleBasicSetting' import Swal from 'sweetalert2' +import { normalizeDecimal} from '@/util/input-utils' export const Orientation = forwardRef((props, ref) => { const { getMessage } = useMessage() @@ -177,9 +178,10 @@ export const Orientation = forwardRef((props, ref) => { setInputCompasDeg('-0') return } - if (Number(e) >= -180 && Number(e) <= 180) { - if (numberCheck(Number(e))) { - setInputCompasDeg(Number(e)) + const n = Number(normalizeDecimal(e)) + if (n >= -180 && n <= 180) { + if (numberCheck(n)) { + setInputCompasDeg(n) } } else { setInputCompasDeg(compasDeg) @@ -398,7 +400,7 @@ export const Orientation = forwardRef((props, ref) => {
{getMessage('modal.module.basic.setting.module.placement.area')}
- setInputMargin(e.target.value)} /> + setInputMargin(normalizeDecimal(e.target.value))} />
m
@@ -427,10 +429,10 @@ export const Orientation = forwardRef((props, ref) => { {getMessage('modal.module.basic.setting.module.fitting.height')}
handleChangeInstallHeight(e.target.value)} + onChange={(e) => handleChangeInstallHeight(normalizeDecimal(e.target.value))} />
m @@ -455,10 +457,10 @@ export const Orientation = forwardRef((props, ref) => { {getMessage('modal.module.basic.setting.module.standard.snowfall.amount')}
handleChangeVerticalSnowCover(e.target.value)} + onChange={(e) => handleChangeVerticalSnowCover(normalizeDecimal(e.target.value))} />
cm diff --git a/src/components/floor-plan/modal/basic/step/Placement.jsx b/src/components/floor-plan/modal/basic/step/Placement.jsx index 497d1307..e96cf5c0 100644 --- a/src/components/floor-plan/modal/basic/step/Placement.jsx +++ b/src/components/floor-plan/modal/basic/step/Placement.jsx @@ -12,6 +12,7 @@ import { import { useRecoilState, useRecoilValue, useResetRecoilState, useSetRecoilState } from 'recoil' import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedModuleOptions' import { isObjectNotEmpty } from '@/util/common-utils' +import { normalizeDigits } from '@/util/input-utils' import Image from 'next/image' const Placement = forwardRef((props, refs) => { @@ -155,7 +156,7 @@ const Placement = forwardRef((props, refs) => { newLayoutSetup[index] = { ...newLayoutSetup[index], moduleId: itemId, - [e.target.name]: Number(e.target.value), + [e.target.name]: Number(normalizeDigits(e.target.value)), } props.setLayoutSetup(newLayoutSetup) } diff --git a/src/components/floor-plan/modal/basic/step/Trestle.jsx b/src/components/floor-plan/modal/basic/step/Trestle.jsx index e2e7bb78..d017803a 100644 --- a/src/components/floor-plan/modal/basic/step/Trestle.jsx +++ b/src/components/floor-plan/modal/basic/step/Trestle.jsx @@ -9,6 +9,7 @@ import { moduleSelectionDataState, selectedModuleState } from '@/store/selectedM import { forwardRef, useContext, useEffect, useImperativeHandle, useRef, useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' import Swal from 'sweetalert2' +import { normalizeDigits } from '@/util/input-utils' const Trestle = forwardRef((props, ref) => { const { tabNum, setTabNum, trestleTrigger, roofs, setRoofs, moduleSelectionData, setModuleSelectionData, setRoofsStore } = props @@ -558,7 +559,19 @@ const Trestle = forwardRef((props, ref) => { type="text" className="input-origin block" value={lengthBase} - onChange={(e) => onChangeLength(e.target.value)} + onChange={(e) => { + const v = e.target.value + if (v === '') { + onChangeLength('') + return + } + const n = Number(normalizeDigits(v)) + if (Number.isNaN(n)) { + onChangeLength('') + } else { + onChangeLength(n) + } + }} disabled={selectedRoof.lenAuth === 'R'} />
@@ -598,7 +611,19 @@ const Trestle = forwardRef((props, ref) => { type="text" className="input-origin block" disabled={selectedRoof.roofPchAuth === 'R'} - onChange={(e) => onChangeHajebichi(e.target.value)} + onChange={(e) => { + const v = e.target.value + if (v === '') { + onChangeHajebichi('') + return + } + const n = Number(normalizeDigits(v)) + if (Number.isNaN(n)) { + onChangeHajebichi('') + } else { + onChangeHajebichi(n) + } + }} value={hajebichi} /> diff --git a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx index 281ae5a8..8b880336 100644 --- a/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx +++ b/src/components/floor-plan/modal/circuitTrestle/step/type/PassivityCircuitAllocation.jsx @@ -12,6 +12,7 @@ import { selectedModuleState } from '@/store/selectedModuleOptions' import { circuitNumDisplaySelector } from '@/store/settingAtom' import { useContext, useEffect, useState } from 'react' import { useRecoilState, useRecoilValue } from 'recoil' +import { normalizeDigits } from '@/util/input-utils' export default function PassivityCircuitAllocation(props) { const { @@ -580,7 +581,20 @@ export default function PassivityCircuitAllocation(props) { value={circuitNumber} min={1} max={99} - onChange={(e) => setCircuitNumber(e.target.value)} + onChange={(e) => { + const v = e.target.value + if (v === '') { + setCircuitNumber('') + return + } + const n = Number(normalizeDigits(v)) + if (Number.isNaN(n)) { + setCircuitNumber('') + } else { + const clamped = Math.max(1, Math.min(99, n)) + setCircuitNumber(clamped) + } + }} />