From 32c6bb5d7f34f4717ad19997dd49408d5e132368 Mon Sep 17 00:00:00 2001 From: minsik Date: Thu, 26 Sep 2024 10:28:30 +0900 Subject: [PATCH 1/3] =?UTF-8?q?-=20=EB=A9=94=EB=89=B4=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EB=B0=8F=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/common.js | 8 +++++ src/components/floor-plan/CanvasMenu.jsx | 12 +++---- src/components/floor-plan/MenuDepth01.jsx | 36 ++++++++++--------- .../modal/setting01/SettingModal01.jsx | 2 +- src/locales/ja.json | 13 ++++--- src/locales/ko.json | 13 +++++-- 6 files changed, 53 insertions(+), 31 deletions(-) diff --git a/src/common/common.js b/src/common/common.js index 9de60c9a..157a01b5 100644 --- a/src/common/common.js +++ b/src/common/common.js @@ -4,19 +4,27 @@ export const MENU = { ROOF_COVERING: { EXTERIOR_WALL_LINE: 'exteriorWallLine', // 외벽선 그리기 ROOF_SHAPE_SETTINGS: 'roofShapeSettings', // 지붕형상 설정 + ROOF_SHAPE_PASSIVITY_SETTINGS: 'roofShapePassivitySettings', // 지붕형상 수동설정 ROOF_SHAPE_EDITING: 'roofShapeEditing', // 지붕형상 편집 HELP_LINE_DRAWING: 'helpLineDrawing', // 보조선 그리기 + EAVES_KERAVA_EDIT: 'eavesKeravaEdit', // 처마.케라마 변경 + MOVEMENT_SHAPE_UPDOWN: 'movementShapeUpdown', // 동선이동.형올림내림 + OUTLINE_EDIT_OFFSET: 'outlineEditOffset', // 외벽선 편집 및 오프셋 + ROOF_SHAPE_ALLOC: 'rootShapeAlloc', // 지붕면 항당 DEFAULT: 'roofCoveringDefault', // 아무것도 선택 안할 경우 }, // 지붕덮개 BATCH_CANVAS: { + SLOPE_SETTING: 'slopeSetting', // 경사 설정 BATCH_DRAWING: 'batchDrawing', // 배치면 그리기 SURFACE_SHAPE_BATCH: 'surfaceShapeBatch', // 면형상 배치 OBJECT_BATCH: 'objectBatch', // 오브젝트 배치 + ALL_REMOVE: 'allRemove', // 전체 삭제 DEFAULT: 'batchCanvasDefault', // default }, // 배치면 MODULE_CIRCUIT_SETTING: { BASIC_SETTING: 'basicSetting', // 기본설정 CIRCUIT_TRESTLE_SETTING: 'circuitTrestleSetting', // 회로가대설정 + PLAN_ORIENTATION: 'planOrientation', // 도면 방위적용 DEFAULT: 'moduleCircuitSettingDefault', }, // 모듈회로구성 ESTIMATE: 'estimate', // todo 견적서 diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx index 58dad7f1..7b030a0d 100644 --- a/src/components/floor-plan/CanvasMenu.jsx +++ b/src/components/floor-plan/CanvasMenu.jsx @@ -113,17 +113,17 @@ export default function CanvasMenu(props) {
{menuNumber !== 6 && menuNumber !== 5 && ( <> + { +
+ {getMessage('plan.mode.vertical.horizontal')} + +
+ }
- {menuNumber !== 4 && ( -
- {getMessage('plan.mode.vertical.horizontal')} - -
- )}
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx index 5db7e3d5..a6b12877 100644 --- a/src/components/floor-plan/MenuDepth01.jsx +++ b/src/components/floor-plan/MenuDepth01.jsx @@ -1,6 +1,5 @@ 'use client' -import { ToggleonMouse } from '@/components/header/Header' import { useMessage } from '@/hooks/useMessage' import { useEffect, useState } from 'react' import { MENU } from '@/common/common' @@ -30,23 +29,39 @@ export default function MenuDepth01(props) { // 지붕덮개 { id: 0, name: 'plan.menu.roof.cover.outline.drawing', menu: MENU.ROOF_COVERING.EXTERIOR_WALL_LINE }, { id: 1, name: 'plan.menu.roof.cover.roof.shape.setting', menu: MENU.ROOF_COVERING.ROOF_SHAPE_SETTINGS }, - { id: 2, name: 'plan.menu.roof.cover.roof.shape.edit', menu: MENU.ROOF_COVERING.ROOF_SHAPE_EDITING }, + { + id: 2, + name: 'plan.menu.roof.cover.roof.shape.passivity.setting', + menu: MENU.ROOF_COVERING.ROOF_SHAPE_PASSIVITY_SETTINGS, + }, { id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing', menu: MENU.ROOF_COVERING.HELP_LINE_DRAWING }, + { id: 4, name: 'plan.menu.roof.cover.eaves.kerava.edit', menu: MENU.ROOF_COVERING.EAVES_KERAVA_EDIT }, + { id: 5, name: 'plan.menu.roof.cover.movement.shape.updown', menu: MENU.ROOF_COVERING.MOVEMENT_SHAPE_UPDOWN }, + { id: 6, name: 'plan.menu.roof.cover.outline.edit.offset', menu: MENU.ROOF_COVERING.OUTLINE_EDIT_OFFSET }, + { id: 7, name: 'plan.menu.roof.cover.roof.surface.alloc', menu: MENU.ROOF_COVERING.ROOF_SHAPE_ALLOC }, ], surface: [ // 배치면 - { id: 0, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING }, - { id: 1, name: 'plan.menu.placement.surface.surface', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH }, - { id: 2, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH }, + { id: 0, name: 'plan.menu.placement.surface.slope.setting', menu: MENU.BATCH_CANVAS.SLOPE_SETTING }, + { id: 1, name: 'plan.menu.placement.surface.drawing', menu: MENU.BATCH_CANVAS.BATCH_DRAWING }, + { id: 2, name: 'plan.menu.placement.surface.arrangement', menu: MENU.BATCH_CANVAS.SURFACE_SHAPE_BATCH }, + { id: 3, name: 'plan.menu.placement.surface.object', menu: MENU.BATCH_CANVAS.OBJECT_BATCH }, + { id: 4, name: 'plan.menu.placement.surface.all.remove', menu: MENU.BATCH_CANVAS.ALL_REMOVE }, ], module: [ // 모듈, 회로 구성 + { id: 0, name: 'plan.menu.module.circuit.setting.default', menu: MENU.MODULE_CIRCUIT_SETTING.BASIC_SETTING }, { id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting', menu: MENU.MODULE_CIRCUIT_SETTING.CIRCUIT_TRESTLE_SETTING, }, + { + id: 2, + name: 'plan.menu.module.circuit.setting.plan.orientation', + menu: MENU.MODULE_CIRCUIT_SETTING.PLAN_ORIENTATION, + }, ], } return ( @@ -60,17 +75,6 @@ export default function MenuDepth01(props) { ) })} -
) } diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx index 88f3a972..293d29df 100644 --- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx +++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx @@ -14,7 +14,7 @@ export default function SettingModal01(props) { return ( -
+

{getMessage('modal.canvas.setting')}

- + +
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx index 386e98cd..7d389540 100644 --- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx +++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx @@ -8,8 +8,10 @@ import { useEvent } from '@/hooks/useEvent' import { adsorptionPointAddModeState, adsorptionPointModeState, + adsorptionRangeState, canvasHistoryState, canvasState, + dotLineIntervalSelector, verticalHorizontalModeState, } from '@/store/canvasAtom' import { @@ -27,22 +29,22 @@ import { distanceBetweenPoints } from '@/util/canvas-util' import { calculateAngle } from '@/util/qpolygon-utils' import { usePolygon } from '@/hooks/usePolygon' import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils' +import { useMouse } from '@/hooks/useMouse' export default function OuterLineWall(props) { const { setShowOutlineModal } = props const { getMessage } = useMessage() - const { - addCanvasMouseEventListener, - addDocumentEventListener, - removeAllMouseEventListeners, - removeAllDocumentEventListeners, - removeMouseEvent, - getIntersectMousePoint, - } = useEvent() + const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent } = + useEvent() + const { getIntersectMousePoint } = useMouse() const { addLine, removeLine } = useLine() + const { addPolygonByLines } = usePolygon() const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState) const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) + const adsorptionPointMode = useRecoilValue(adsorptionPointModeState) + const adsorptionRange = useRecoilValue(adsorptionRangeState) + const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 const length1Ref = useRef(null) const length2Ref = useRef(null) @@ -72,7 +74,7 @@ export default function OuterLineWall(props) { return () => { removeAllMouseEventListeners() } - }, [verticalHorizontalMode, points, adsorptionPointAddMode]) + }, [verticalHorizontalMode, points, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, interval]) useEffect(() => { arrow1Ref.current = arrow1 diff --git a/src/components/floor-plan/modal/setting01/SecondOption.jsx b/src/components/floor-plan/modal/setting01/SecondOption.jsx index e850f403..3aa2567d 100644 --- a/src/components/floor-plan/modal/setting01/SecondOption.jsx +++ b/src/components/floor-plan/modal/setting01/SecondOption.jsx @@ -113,11 +113,11 @@ export default function SecondOption() { // HTTP POST 요청 보내기 await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => { toastUp({ message: getMessage(res.returnMessage), type: 'success' }) - setAdsorptionRange(option.range) }) } catch (error) { toastUp({ message: getMessage(res.returnMessage), type: 'error' }) } + setAdsorptionRange(option.range) } return ( <> diff --git a/src/hooks/useAdsorptionPoint.js b/src/hooks/useAdsorptionPoint.js new file mode 100644 index 00000000..44e2495b --- /dev/null +++ b/src/hooks/useAdsorptionPoint.js @@ -0,0 +1,45 @@ +import { useRecoilState, useRecoilValue } from 'recoil' +import { adsorptionPointAddModeState, adsorptionPointModeState, adsorptionRangeState, canvasState } from '@/store/canvasAtom' +import { fabric } from 'fabric' +import { useMouse } from '@/hooks/useMouse' + +export function useAdsorptionPoint() { + const canvas = useRecoilValue(canvasState) + const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState) + const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState) + const [adsorptionRange, setAdsorptionRange] = useRecoilState(adsorptionRangeState) + + const { getIntersectMousePoint } = useMouse() + + const getAdsorptionPoints = () => { + return canvas.getObjects().filter((obj) => obj.visible && obj.name === 'adsorptionPoint') + } + + const adsorptionPointAddModeStateEvent = (opt) => { + //흡착점 모드일 경우 + let pointer = getIntersectMousePoint(opt) + + const adsorptionPoint = new fabric.Circle({ + radius: 3, + fill: 'red', + left: pointer.x - 3, + top: pointer.y - 3, + x: pointer.x, + y: pointer.y, + selectable: false, + name: 'adsorptionPoint', + }) + + canvas.add(adsorptionPoint) + + canvas.renderAll() + } + + return { + adsorptionPointAddMode, + adsorptionPointMode, + adsorptionRange, + getAdsorptionPoints, + adsorptionPointAddModeStateEvent, + } +} diff --git a/src/hooks/useDotLineGrid.js b/src/hooks/useDotLineGrid.js new file mode 100644 index 00000000..7ccd87c6 --- /dev/null +++ b/src/hooks/useDotLineGrid.js @@ -0,0 +1,51 @@ +import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil' +import { canvasState, dotLineGridSettingState, dotLineIntervalSelector } from '@/store/canvasAtom' +import { calculateDistance } from '@/util/canvas-util' +import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' + +export function useDotLineGrid() { + const canvas = useRecoilValue(canvasState) + const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState) + const interval = useRecoilValue(dotLineIntervalSelector) // 가로 세로 간격 + + const { adsorptionRange } = useAdsorptionPoint() + + const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState) + + const getLineGrids = () => { + return canvas.getObjects().filter((obj) => obj.name === 'lineGrid') + } + + const getClosestLineGrid = (point) => { + const lines = getLineGrids() + if (lines.length === 0) { + return null + } + + let closestLine = null + let minDistance = Infinity + + lines.forEach((line) => { + const distance = calculateDistance(point, line) + + if (distance < minDistance) { + minDistance = distance + closestLine = line + } + }) + + if (minDistance > adsorptionRange) { + return null + } + + return closestLine + } + + return { + dotLineGridSetting, + resetDotLineGridSetting, + getLineGrids, + getClosestLineGrid, + interval, + } +} diff --git a/src/hooks/useEvent.js b/src/hooks/useEvent.js index 34af6ca9..01f61d3c 100644 --- a/src/hooks/useEvent.js +++ b/src/hooks/useEvent.js @@ -9,7 +9,10 @@ import { currentMenuState, } from '@/store/canvasAtom' import { fabric } from 'fabric' -import { calculateIntersection, distanceBetweenPoints } from '@/util/canvas-util' +import { calculateDistance, calculateIntersection, distanceBetweenPoints, findClosestPoint } from '@/util/canvas-util' +import { useAdsorptionPoint } from '@/hooks/useAdsorptionPoint' +import { useMouse } from '@/hooks/useMouse' +import { useDotLineGrid } from '@/hooks/useDotLineGrid' export function useEvent() { const canvas = useRecoilValue(canvasState) @@ -17,10 +20,9 @@ export function useEvent() { const keyboardEventListeners = useRef([]) const mouseEventListeners = useRef([]) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) - const adsorptionPointAddMode = useRecoilValue(adsorptionPointAddModeState) - const adsorptionPointMode = useRecoilValue(adsorptionPointModeState) - const adsorptionRange = useRecoilValue(adsorptionRangeState) + const { adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, getAdsorptionPoints, adsorptionPointAddModeStateEvent } = useAdsorptionPoint() + const { dotLineGridSetting, interval, getClosestLineGrid } = useDotLineGrid() useEffect(() => { if (!canvas) { return @@ -35,7 +37,7 @@ export function useEvent() { canvas?.on('mouse:wheel', wheelEvent) addDefaultEvent() - }, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange]) + }, [currentMenu, canvas, adsorptionPointAddMode, adsorptionPointMode, adsorptionRange, dotLineGridSetting]) const addDefaultEvent = () => { //default Event 추가 @@ -53,26 +55,6 @@ export function useEvent() { e.stopPropagation() } - const adsorptionPointAddModeStateEvent = (opt) => { - //흡착점 모드일 경우 - let pointer = getIntersectMousePoint(opt) - - const adsorptionPoint = new fabric.Circle({ - radius: 3, - fill: 'red', - left: pointer.x - 3, - top: pointer.y - 3, - x: pointer.x, - y: pointer.y, - selectable: false, - name: 'adsorptionPoint', - }) - - canvas.add(adsorptionPoint) - - canvas.renderAll() - } - const wheelEvent = (opt) => { const delta = opt.e.deltaY // 휠 이동 값 (양수면 축소, 음수면 확대) let zoom = canvas.getZoom() // 현재 줌 값 @@ -107,17 +89,61 @@ export function useEvent() { let arrivalPoint = { x: pointer.x, y: pointer.y } if (adsorptionPointMode) { - // pointer와 adsorptionPoints의 거리를 계산하여 가장 가까운 점을 찾는다. - let minDistance = adsorptionRange - let adsorptionPoint = null - adsorptionPoints.forEach((point) => { - const distance = distanceBetweenPoints(pointer, point) - if (distance < minDistance) { - minDistance = distance - adsorptionPoint = point + if (dotLineGridSetting.LINE) { + const closestLine = getClosestLineGrid(pointer) + + if (closestLine) { + const distance = calculateDistance(pointer, closestLine) + + if (distance < adsorptionRange) { + arrivalPoint = closestLine.direction === 'vertical' ? { x: closestLine.x1, y: pointer.y } : { x: pointer.x, y: closestLine.y1 } + } } - }) - if (adsorptionPoint) { + } + + if (dotLineGridSetting.DOT) { + const horizontalInterval = interval.horizontalInterval + const verticalInterval = interval.verticalInterval + + const x = pointer.x - horizontalInterval * Math.floor(pointer.x / horizontalInterval) + const y = pointer.y - verticalInterval * Math.floor(pointer.y / verticalInterval) + + const xRate = (x / horizontalInterval) * 100 + const yRate = (y / verticalInterval) * 100 + + let tempPoint + + if (xRate <= adsorptionRange && yRate <= adsorptionRange) { + tempPoint = { + x: Math.round(pointer.x / horizontalInterval) * horizontalInterval + horizontalInterval / 2, + y: Math.round(pointer.y / verticalInterval) * verticalInterval + horizontalInterval / 2, + } + } else if (xRate <= adsorptionRange && yRate >= adsorptionRange) { + tempPoint = { + x: Math.round(pointer.x / horizontalInterval) * horizontalInterval + horizontalInterval / 2, + y: Math.round(pointer.y / verticalInterval) * verticalInterval - horizontalInterval / 2, + } + } else if (xRate >= adsorptionRange && yRate <= adsorptionRange) { + tempPoint = { + x: Math.round(pointer.x / horizontalInterval) * horizontalInterval - horizontalInterval / 2, + y: Math.round(pointer.y / verticalInterval) * verticalInterval + horizontalInterval / 2, + } + } else if (xRate >= adsorptionRange && yRate >= adsorptionRange) { + tempPoint = { + x: Math.round(pointer.x / horizontalInterval) * horizontalInterval - horizontalInterval / 2, + y: Math.round(pointer.y / verticalInterval) * verticalInterval - horizontalInterval / 2, + } + } + + if (distanceBetweenPoints(pointer, tempPoint) <= adsorptionRange) { + arrivalPoint = tempPoint + } + } + + // pointer와 adsorptionPoints의 거리를 계산하여 가장 가까운 점을 찾는다. + let adsorptionPoint = findClosestPoint(pointer, adsorptionPoints) + + if (adsorptionPoint && distanceBetweenPoints(pointer, adsorptionPoint) <= adsorptionRange) { arrivalPoint = { ...adsorptionPoint } } } @@ -203,28 +229,11 @@ export function useEvent() { }) } - const getAdsorptionPoints = () => { - return canvas.getObjects().filter((obj) => obj.visible && obj.name === 'adsorptionPoint') - } - - //가로선, 세로선의 교차점을 return - const getIntersectMousePoint = (e) => { - let pointer = canvas.getPointer(e.e) - const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine') - - if (mouseLines.length < 2) { - return pointer - } - - return calculateIntersection(mouseLines[0], mouseLines[1]) ?? pointer - } - return { addDocumentEventListener, addCanvasMouseEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners, removeMouseEvent, - getIntersectMousePoint, } } diff --git a/src/hooks/useMouse.js b/src/hooks/useMouse.js new file mode 100644 index 00000000..d484930a --- /dev/null +++ b/src/hooks/useMouse.js @@ -0,0 +1,23 @@ +import { useRecoilValue } from 'recoil' +import { canvasState } from '@/store/canvasAtom' +import { calculateIntersection } from '@/util/canvas-util' + +export function useMouse() { + const canvas = useRecoilValue(canvasState) + + //가로선, 세로선의 교차점을 return + const getIntersectMousePoint = (e) => { + let pointer = canvas.getPointer(e.e) + const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine') + + if (mouseLines.length < 2) { + return pointer + } + + return calculateIntersection(mouseLines[0], mouseLines[1]) || pointer + } + + return { + getIntersectMousePoint, + } +} diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 7f942f59..89acba2f 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -205,7 +205,7 @@ export const verticalHorizontalModeState = atom({ // 흡착점 모드 export const adsorptionPointModeState = atom({ key: 'adsorptionPointModeState', - default: false, + default: true, }) // 흡착점 추가모드 export const adsorptionPointAddModeState = atom({ @@ -218,3 +218,35 @@ export const adsorptionRangeState = atom({ key: 'adsorptionRangeState', default: 50, }) + +// 점,선 그리드 설정 +export const dotLineGridSettingState = atom({ + key: 'gridSettingState', + default: { + INTERVAL: { + type: 2, // 1: 가로,세로 간격 수동, 2: 비율 간격 + ratioInterval: 910, + verticalInterval: 910, + horizontalInterval: 910, + dimension: 1, // 치수 + }, + DOT: false, + LINE: false, + }, +}) + +export const dotLineIntervalSelector = selector({ + key: 'dotLineIntervalSelector', + get: ({ get }) => { + const gridSetting = get(dotLineGridSettingState) + return gridSetting.INTERVAL.type === 1 + ? { + horizontalInterval: Math.round(gridSetting.INTERVAL.horizontalInterval / 10), + verticalInterval: Math.round(gridSetting.INTERVAL.verticalInterval / 10), + } + : { + horizontalInterval: Math.round((gridSetting.INTERVAL.ratioInterval * gridSetting.INTERVAL.dimension) / 10), + verticalInterval: Math.round((gridSetting.INTERVAL.ratioInterval * gridSetting.INTERVAL.dimension) / 10), + } + }, +}) diff --git a/src/store/settingAtom.js b/src/store/settingAtom.js index 5541cc14..8c9f976d 100644 --- a/src/store/settingAtom.js +++ b/src/store/settingAtom.js @@ -50,9 +50,9 @@ export const settingModalSecondOptionsState = atom({ ], option4: [ { id: 1, column: 'adsorpRangeSmall', name: 'modal.canvas.setting.font.plan.absorption.small', selected: true, range: 10 }, - { id: 2, column: 'adsorpRangeSmallSemi', name: 'modal.canvas.setting.font.plan.absorption.small.semi', selected: false, range: 30 }, - { id: 3, column: 'adsorpRangeMedium', name: 'modal.canvas.setting.font.plan.absorption.medium', selected: false, range: 50 }, - { id: 4, column: 'adsorpRangeLarge', name: 'modal.canvas.setting.font.plan.absorption.large', selected: false, range: 80 }, + { id: 2, column: 'adsorpRangeSmallSemi', name: 'modal.canvas.setting.font.plan.absorption.small.semi', selected: false, range: 20 }, + { id: 3, column: 'adsorpRangeMedium', name: 'modal.canvas.setting.font.plan.absorption.medium', selected: false, range: 30 }, + { id: 4, column: 'adsorpRangeLarge', name: 'modal.canvas.setting.font.plan.absorption.large', selected: false, range: 40 }, ], }, dangerouslyAllowMutability: true, diff --git a/src/util/input-utils.js b/src/util/input-utils.js index e2409cab..f674e6cd 100644 --- a/src/util/input-utils.js +++ b/src/util/input-utils.js @@ -2,7 +2,7 @@ export const onlyNumberInputChange = (e, callback) => { let value = e.target.value.replace(/^0+/, '') value = value.replace(/[^-0-9]/g, '') - callback(value) + callback(value, e) } //소수점 둘째자리 숫자만 입력가능 @@ -12,9 +12,9 @@ export const onlyNumberWithDotInputChange = (e, callback) => { const pattern = /^-?(\d{1,4}([.]\d{0,2})?)?$/ if (!pattern.test(val)) { // prev에서 마지막 자리 제거 - callback(val.slice(0, val.length - 1)) + callback(val.slice(0, val.length - 1), e) return } - callback(val) + callback(val, e) } From e9009ffdd5a88e559ab9686902feca572696b098 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Thu, 26 Sep 2024 14:58:32 +0900 Subject: [PATCH 3/3] fix: Add Sync SessionStore at userSession MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 세션 스토어와 유저 세션을 동기화 하는 로직추가 / layout 컴포넌트 코드 수정 --- src/app/layout.js | 24 +++++++++++++++++++++++- src/components/header/Header.jsx | 24 ++++++++++++++++++------ 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/app/layout.js b/src/app/layout.js index 4f7acb9d..b77e75d0 100644 --- a/src/app/layout.js +++ b/src/app/layout.js @@ -31,6 +31,28 @@ export default async function RootLayout({ children }) { // const isLoggedIn = await checkSession() const session = await getSession() console.log('session[layout]:', session) + + let sessionProps = {} + + if (session.isLoggedIn) { + sessionProps = { + userId: session.userId, + saleStoreId: session.saleStoreId, + name: session.name, + mail: session.mail, + tel: session.tel, + storeId: session.storeId, + userNm: session.userNm, + userNmKana: session.userNmKana, + category: session.category, + telNo: session.telNo, + fax: session.fax, + email: session.email, + pwdInitYn: session.pwdInitYn, + isLoggedIn: session.isLoggedIn, + } + } + if (!headerPathname.includes('/login') && !session.isLoggedIn) { redirect('/login') } @@ -41,7 +63,7 @@ export default async function RootLayout({ children }) { {/*{headerPathname !== '/login' && }*/}
-
+
diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx index 9e84f642..456cb09f 100644 --- a/src/components/header/Header.jsx +++ b/src/components/header/Header.jsx @@ -1,13 +1,16 @@ 'use client' -import { Fragment, useState } from 'react' +import { Fragment, useCallback, useEffect, useState } from 'react' + import Link from 'next/link' -import { usePathname, useRouter } from 'next/navigation' +import { usePathname } from 'next/navigation' + +import { useRecoilState, useRecoilValue } from 'recoil' +import { dimmedStore, sessionStore } from '@/store/commonAtom' + import { useMessage } from '@/hooks/useMessage' import { logout } from '@/lib/authActions' import QSelectBox from '@/components/common/select/QSelectBox' -import { useRecoilValue } from 'recoil' -import { dimmedStore } from '@/store/commonAtom' export const ToggleonMouse = (e, act, target) => { const listWrap = e.target.closest(target) @@ -25,7 +28,8 @@ export const ToggleonMouse = (e, act, target) => { } export default function Header(props) { - const { loginedUserNm } = props + const { userSession } = props + const [sessionState, setSessionState] = useRecoilState(sessionStore) const { getMessage } = useMessage() const pathName = usePathname() // if (pathName.includes('login') || pathName.includes('join')) { @@ -65,6 +69,14 @@ export default function Header(props) { }, ] + const syncSession = useCallback(() => { + setSessionState({ ...userSession }) + }) + + useEffect(() => { + syncSession() + }, [userSession]) + const onChangeSelect = (option) => { setSelected(option) } @@ -125,7 +137,7 @@ export default function Header(props) {
- +