diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx
index f9bee2a4..9c8c9d38 100644
--- a/src/components/floor-plan/CanvasFrame.jsx
+++ b/src/components/floor-plan/CanvasFrame.jsx
@@ -1,14 +1,32 @@
+'use client'
+
+import { useEffect, useRef } from 'react'
+
import { useCanvas } from '@/hooks/useCanvas'
-import { useRef } from 'react'
import { useEvent } from '@/hooks/useEvent'
-export default function CanvasFrame() {
+export default function CanvasFrame({ plan }) {
const canvasRef = useRef(null)
- useCanvas('canvas')
+ const { canvas } = useCanvas('canvas')
useEvent()
+ const loadCanvas = () => {
+ if (canvas) {
+ canvas?.clear() // 캔버스를 초기화합니다.
+ if (plan?.canvasStatus) {
+ canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () {
+ canvas?.renderAll() // 캔버스를 다시 그립니다.
+ })
+ }
+ }
+ }
+
+ useEffect(() => {
+ loadCanvas()
+ }, [plan])
+
return (
-
+
)
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx
index 9990aa21..5d3817a2 100644
--- a/src/components/floor-plan/CanvasLayout.jsx
+++ b/src/components/floor-plan/CanvasLayout.jsx
@@ -1,43 +1,86 @@
'use client'
import { useEffect, useState } from 'react'
-import CanvasFrame from './CanvasFrame'
import { useRecoilState, useRecoilValue } from 'recoil'
-import { currentMenuState, stepState } from '@/store/canvasAtom'
+import CanvasFrame from './CanvasFrame'
+import { usePlan } from '@/hooks/usePlan'
+import { globalLocaleStore } from '@/store/localeAtom'
+import { currentCanvasPlanState, initCanvasPlansState } from '@/store/canvasAtom'
export default function CanvasLayout() {
- const [plans, setPlans] = useState([
- { id: 0, name: 'Plan 1', isCurrent: false },
- { id: 1, name: 'Plan 2', isCurrent: false },
- { id: 2, name: 'Plan 3', isCurrent: false },
- ])
- const [idxNum, setIdxNum] = useState(null)
+ const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요
+ const [addCanvasPlans, setAddCanvasPlans] = useState([])
+ const [planNum, setPlanNum] = useState(0)
+ const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
+ const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState)
+ const globalLocaleState = useRecoilValue(globalLocaleStore)
- const onClickPlane = (num) => {
- setIdxNum(num)
+ const { getCanvasByObjectNo } = usePlan()
+
+ const handleCurrentPlan = (newCurrentId) => {
+ if (!currentCanvasPlan?.id || currentCanvasPlan.id !== newCurrentId) {
+ setInitCanvasPlans((plans) =>
+ plans.map((plan) => {
+ return { ...plan, isCurrent: plan.id === newCurrentId }
+ }),
+ )
+ setAddCanvasPlans((plans) =>
+ plans.map((plan) => {
+ return { ...plan, isCurrent: plan.id === newCurrentId }
+ }),
+ )
+ }
}
+ useEffect(() => {
+ setCurrentCanvasPlan([...initCanvasPlans, ...addCanvasPlans].find((plan) => plan.isCurrent) || null)
+ }, [initCanvasPlans, addCanvasPlans])
const handleDeletePlan = (e, id) => {
e.stopPropagation() // 이벤트 버블링 방지
- setPlans(plans.filter((plan) => plan.id !== id)) // 삭제할 아이디와 다른 아이템만 남김
+
+ // 삭제할 아이디와 다른 아이템만 남김
+ const filterInitPlans = initCanvasPlans.filter((plan) => plan.id !== id)
+ setInitCanvasPlans(filterInitPlans)
+ const filterAddPlans = addCanvasPlans.filter((plan) => plan.id !== id)
+ setAddCanvasPlans(filterAddPlans)
+
+ const combinedPlans = [...filterInitPlans, ...filterAddPlans]
+ if (combinedPlans.length === 0) {
+ // 모든 데이터가 삭제된 경우
+ setPlanNum(0)
+ } else {
+ const lastPlanId = combinedPlans.at(-1).id
+ if (id !== lastPlanId) {
+ handleCurrentPlan(lastPlanId)
+ }
+ }
}
const addNewPlan = () => {
- setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }])
+ setAddCanvasPlans([...addCanvasPlans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }])
+ handleCurrentPlan(planNum)
+ setPlanNum(planNum + 1)
}
useEffect(() => {
- if (plans.length === 1) {
- setPlans([{ id: 0, name: 'Plan 1', isCurrent: false }])
- }
+ getCanvasByObjectNo(objectNo).then((res) => {
+ console.log('canvas 목록 ', res)
+ if (res.length > 0) {
+ setInitCanvasPlans(res)
+ handleCurrentPlan(res.at(-1).id) // last 데이터에 포커싱
+ setPlanNum(res.length)
+ } else {
+ addNewPlan()
+ }
+ })
}, [])
return (
- {plans.map((plan, idx) => (
-
-
+
plan.isCurrent === true)} />
)
}
diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx
index c916a0fc..99b3e048 100644
--- a/src/components/floor-plan/CanvasMenu.jsx
+++ b/src/components/floor-plan/CanvasMenu.jsx
@@ -1,162 +1,135 @@
'use client'
import { useEffect, useState } from 'react'
+
+import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'
+
import MenuDepth01 from './MenuDepth01'
import QSelectBox from '@/components/common/select/QSelectBox'
+
import { useMessage } from '@/hooks/useMessage'
-import { post } from '@/lib/Axios'
-import { useRecoilState, useRecoilValue } from 'recoil'
-import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
-import { canvasZoomState, verticalHorizontalModeState } from '@/store/canvasAtom'
+import { usePlan } from '@/hooks/usePlan'
+import { canvasState, canvasZoomState, currentMenuState, verticalHorizontalModeState } from '@/store/canvasAtom'
+import { sessionStore } from '@/store/commonAtom'
+import { outerLinePointsState } from '@/store/outerLineAtom'
+import { appMessageStore, globalLocaleStore } from '@/store/localeAtom'
+import { MENU } from '@/common/common'
+
+import KO from '@/locales/ko.json'
+import JA from '@/locales/ja.json'
+import { settingModalFirstOptionsState } from '@/store/settingAtom'
+
+const canvasMenus = [
+ { index: 0, name: 'plan.menu.plan.drawing', icon: 'con00', title: MENU.PLAN_DRAWING },
+ { index: 1, name: 'plan.menu.placement.surface.initial.setting', icon: 'con01', title: MENU.INITIAL_CANVAS_SETTING },
+ { index: 2, name: 'plan.menu.roof.cover', icon: 'con02', title: MENU.ROOF_COVERING.DEFAULT },
+ { index: 3, name: 'plan.menu.placement.surface', icon: 'con03', title: MENU.BATCH_CANVAS.DEFAULT },
+ { index: 4, name: 'plan.menu.module.circuit.setting', icon: 'con04', title: MENU.MODULE_CIRCUIT_SETTING.DEFAULT },
+ { index: 5, name: 'plan.menu.estimate', icon: 'con06', title: MENU.ESTIMATE.DEFAULT },
+ { index: 6, name: 'plan.menu.simulation', icon: 'con05', title: MENU.POWER_GENERATION_SIMULATION.DEFAULT },
+]
export default function CanvasMenu(props) {
- const [objectNo] = useState('test123240912001') // 이후 삭제 필요
const { setShowCanvasSettingModal, showOutlineModal, setShowOutlineModal } = props
+
const [menuNumber, setMenuNumber] = useState(null)
- const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
- const [vertical, setVertical] = useState(true)
const [type, setType] = useState('')
+
+ const [verticalHorizontalMode, setVerticalHorizontalMode] = useRecoilState(verticalHorizontalModeState)
+ const [appMessageState, setAppMessageState] = useRecoilState(appMessageStore)
+ const setCurrentMenu = useSetRecoilState(currentMenuState)
+ const setPoints = useSetRecoilState(outerLinePointsState)
+ const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState)
+
+ const globalLocale = useRecoilValue(globalLocaleStore)
+ const canvas = useRecoilValue(canvasState)
+ const sessionState = useRecoilValue(sessionStore)
+
const { getMessage } = useMessage()
- const canvasZoom = useRecoilValue(canvasZoomState)
+ const { saveCanvas } = usePlan()
+
const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
- const onClickNav = (number) => {
- setMenuNumber(number)
- if (number === 2) setType('outline')
- if (number === 3) setType('surface')
- if (number === 4) setType('module')
+ const onClickNav = (menu) => {
+ setMenuNumber(menu.index)
+ setCurrentMenu(menu.title)
+
+ switch (menu.index) {
+ case 2:
+ setType('outline')
+ break
+ case 3:
+ setType('surface')
+ break
+ case 4:
+ setType('module')
+ break
+ }
}
const menuProps = {
setShowOutlineModal,
type,
}
- const firstOptions = useRecoilState(settingModalFirstOptionsState)
- const secondOptions = useRecoilState(settingModalSecondOptionsState)
+ const settingsModalOptions = useRecoilState(settingModalFirstOptionsState)
- useEffect(() => {}, [menuNumber, type])
+ useEffect(() => {
+ if (menuNumber !== 2 && showOutlineModal) setShowOutlineModal(false)
+ }, [menuNumber, type])
// 저장버튼(btn08) 클릭 시 호출되는 함수
- const handleSaveSettings = async () => {
- try {
- // 서버에 전송할 데이터
- const dataToSend = {
- firstOption1: firstOptions[0].option1.map((item) => ({
- column: item.column,
- selected: item.selected,
- })),
- firstOption2: firstOptions[0].option2.map((item) => ({
- column: item.column,
- selected: item.selected,
- })),
- // secondOption1: secondOptions[0].option1.map((item) => ({
- // name: item.name,
- // // 필요한 경우 추가 데이터 항목
- // })),
- secondOption2: secondOptions[0].option2.map((item) => ({
- column: item.column,
- selected: item.selected,
- })),
- }
-
- const patternData = {
- objectNo,
- assignDisplay: dataToSend.firstOption1[0].selected,
- drawDisplay: dataToSend.firstOption1[1].selected,
- gridDisplay: dataToSend.firstOption1[2].selected,
- charDisplay: dataToSend.firstOption1[3].selected,
- flowDisplay: dataToSend.firstOption1[4].selected,
- hallwayDimenDisplay: dataToSend.firstOption1[5].selected,
- actualDimenDisplay: dataToSend.firstOption1[6].selected,
- noDimenDisplay: dataToSend.firstOption1[7].selected,
- trestleDisplay: dataToSend.firstOption1[8].selected,
- coordiDisplay: dataToSend.firstOption1[9].selected,
- drawConverDisplay: dataToSend.firstOption1[10].selected,
- onlyBorder: dataToSend.firstOption2[0].selected,
- lineHatch: dataToSend.firstOption2[1].selected,
- allPainted: dataToSend.firstOption2[2].selected,
- adsorpRangeSmall: dataToSend.secondOption2[0].selected,
- adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
- adsorpRangeMedium: dataToSend.secondOption2[2].selected,
- adsorpRangeLarge: dataToSend.secondOption2[3].selected,
- }
-
- // HTTP POST 요청 보내기
- await post({ url: `/api/canvas-management/canvas-settings`, data: patternData })
-
- // 응답 처리
- alert('설정이 저장되었습니다.')
- } catch (error) {
- console.error('설정을 저장하는 동안 오류가 발생했습니다:', error)
- alert('설정을 저장하는 중 오류가 발생했습니다.')
- }
+ const handleSaveCanvas = () => {
+ saveCanvas(sessionState.userId)
}
+ const handleClear = () => {
+ setPoints([])
+ canvas?.clear()
+ }
+
+ const handleZoomClear = () => {
+ setCanvasZoom(100)
+ canvas.set({ zoom: 1 })
+ canvas.viewportTransform = [1, 0, 0, 1, 0, 0]
+ canvas.renderAll()
+ }
+
+ useEffect(() => {
+ if (globalLocale === 'ko') {
+ setAppMessageState(KO)
+ } else {
+ setAppMessageState(JA)
+ }
+ }, [menuNumber, type, globalLocale])
+
return (
- - onClickNav(0)}>
-
-
- {getMessage('plan.menu.plan.drawing')}
-
-
- - onClickNav(1)}>
-
-
- {getMessage('plan.menu.placement.surface.initial.setting')}
-
-
- - {
- onClickNav(2)
- }}
- >
-
-
- {getMessage('plan.menu.roof.cover')}
-
-
- - onClickNav(3)}>
-
-
- {getMessage('plan.menu.placement.surface')}
-
-
- - onClickNav(4)}>
-
-
- {getMessage('plan.menu.module.circuit.setting')}
-
-
- - onClickNav(5)}>
-
-
- {getMessage('plan.menu.estimate')}
-
-
- - onClickNav(6)}>
-
-
- {getMessage('plan.menu.simulation')}
-
-
+ {canvasMenus.map((menu) => {
+ return (
+ - onClickNav(menu)}>
+
+
+ {getMessage(menu.name)}
+
+
+ )
+ })}
{menuNumber !== 6 && menuNumber !== 5 && (
<>
+ {
+
+ {getMessage('plan.mode.vertical.horizontal')}
+ setVerticalHorizontalMode(!verticalHorizontalMode)}>{verticalHorizontalMode ? 'ON' : 'OFF'}
+
+ }
- {menuNumber !== 4 && (
-
- {getMessage('plan.mode.vertical.horizontal')}
- setVerticalHorizontalMode(!verticalHorizontalMode)}>{verticalHorizontalMode ? 'ON' : 'OFF'}
-
- )}
@@ -168,11 +141,11 @@ export default function CanvasMenu(props) {
{canvasZoom}%
-
+
-
-
+
+
>
diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx
index 33e522ee..c610948f 100644
--- a/src/components/floor-plan/FloorPlan.jsx
+++ b/src/components/floor-plan/FloorPlan.jsx
@@ -1,14 +1,16 @@
'use client'
+import { useEffect, useState } from 'react'
+import { useRecoilState, useRecoilValue } from 'recoil'
+import { useAxios } from '@/hooks/useAxios'
+import { globalLocaleStore } from '@/store/localeAtom'
+import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
+import '@/styles/contents.scss'
import CanvasMenu from '@/components/floor-plan/CanvasMenu'
import SettingModal01 from '@/components/floor-plan/modal/setting01/SettingModal01'
import CanvasLayout from '@/components/floor-plan/CanvasLayout'
-import '@/styles/contents.scss'
import OuterLineWall from '@/components/floor-plan/modal/outerlinesetting/OuterLineWall'
-import { useEffect, useState } from 'react'
-import { globalLocaleStore } from '@/store/localeAtom'
-import { useRecoilValue } from 'recoil'
-import { useAxios } from '@/hooks/useAxios'
+import DotLineGrid from '@/components/floor-plan/modal/grid/DotLineGrid'
export default function FloorPlan() {
const [showCanvasSettingModal, setShowCanvasSettingModal] = useState(false)
@@ -16,8 +18,16 @@ export default function FloorPlan() {
const globalLocaleState = useRecoilValue(globalLocaleStore)
const { get } = useAxios(globalLocaleState)
+ const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
+ const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
+ const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
+
+ const [showDotLineGridModal, setShowDotLineGridModal] = useState(true)
+ const [showGridCopyModal, setShowGridCopyModal] = useState(false)
+ const [showGridMoveModal, setShowGridMoveModal] = useState(false)
const canvasSettingProps = {
setShowCanvasSettingModal,
+ setShowDotLineGridModal,
}
const outlineProps = {
@@ -30,6 +40,41 @@ export default function FloorPlan() {
setShowOutlineModal,
}
+ useEffect(() => {
+ console.log('FloorPlan useEffect 실행')
+ fetchSettings()
+ }, [showOutlineModal, objectNo])
+
+ // Canvas Setting 조회
+ const fetchSettings = async () => {
+ try {
+ const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
+ const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
+ const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({
+ ...item,
+ }))
+ // 데이터 설정
+ setSettingModalFirstOptions({
+ option1: optionData1,
+ option2: optionData2,
+ dimensionDisplay: optionData5,
+ })
+ setSettingModalSecondOptions({
+ option3: optionData3,
+ option4: optionData4,
+ })
+ } catch (error) {
+ console.error('Data fetching error:', error)
+ }
+ }
+ const dotLineProps = {
+ showDotLineGridModal,
+ setShowDotLineGridModal,
+ }
+
useEffect(() => {}, [showOutlineModal])
return (
@@ -40,6 +85,7 @@ export default function FloorPlan() {
{showCanvasSettingModal &&
}
{showOutlineModal &&
}
+ {showDotLineGridModal &&
}
>
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx
index cf0ad1e8..a6b12877 100644
--- a/src/components/floor-plan/MenuDepth01.jsx
+++ b/src/components/floor-plan/MenuDepth01.jsx
@@ -1,76 +1,80 @@
'use client'
-import { ToggleonMouse } from '@/components/header/Header'
import { useMessage } from '@/hooks/useMessage'
import { useEffect, useState } from 'react'
+import { MENU } from '@/common/common'
+import { currentMenuState } from '@/store/canvasAtom'
+import { useSetRecoilState } from 'recoil'
export default function MenuDepth01(props) {
const { setShowOutlineModal, type } = props
const { getMessage } = useMessage()
const [activeMenu, setActiveMenu] = useState()
- const onClickMenu = (menuNum) => {
- setActiveMenu(menuNum)
- setShowOutlineModal(menuNum === 0)
+ const setCurrentMenu = useSetRecoilState(currentMenuState)
+ const onClickMenu = ({ id, menu, name }) => {
+ setActiveMenu(menu)
+ setShowOutlineModal(menu === MENU.ROOF_COVERING.EXTERIOR_WALL_LINE)
+ setCurrentMenu(menu)
+ if (type === 'outline') {
+ setShowOutlineModal(id === 0)
+ }
}
- const menus = [
- { id: 0, name: '外壁線を描' },
- { id: 1, name: '補助線を描' },
- { id: 2, name: '屋根形状設定' },
- { id: 3, name: '軒下変更' },
- { id: 4, name: '外壁線の上げ下げ' },
- { id: 5, name: '銅線移動' },
- { id: 6, name: '特殊コーナー形状' },
- ]
+ useEffect(() => {
+ setActiveMenu(null)
+ }, [type])
const menuInfo = {
outline: [
// 지붕덮개
- { id: 0, name: 'plan.menu.roof.cover.outline.drawing' },
- { id: 1, name: 'plan.menu.roof.cover.roof.shape.setting' },
- { id: 2, name: 'plan.menu.roof.cover.roof.shape.edit' },
- { id: 3, name: 'plan.menu.roof.cover.auxiliary.line.drawing' },
+ { 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.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' },
- { id: 1, name: 'plan.menu.placement.surface.surface' },
- { id: 2, name: 'plan.menu.placement.surface.object' },
+ { 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' },
- { id: 1, name: 'plan.menu.module.circuit.setting.circuit.trestle.setting' },
+
+ { 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,
+ },
],
}
-
- useEffect(() => {
- menus.forEach((menu) => {
- menu.isActive = menu.id === activeMenu
- })
- }, [menus, activeMenu])
return (
{menuInfo[type].map((menu) => {
return (
- -
- onClickMenu(menu.id)}>{getMessage(menu.name)}
+
-
+ onClickMenu(menu)}>{getMessage(menu.name)}
)
})}
-
- - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
- {getMessage('plan.menu.estimate.roof.alloc')}
-
- - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
- 屋根材の設定と変更
-
- - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
- 屋根面全体削除
-
-
)
}
diff --git a/src/components/floor-plan/modal/grid/DotLineGrid.jsx b/src/components/floor-plan/modal/grid/DotLineGrid.jsx
new file mode 100644
index 00000000..d0e06fa9
--- /dev/null
+++ b/src/components/floor-plan/modal/grid/DotLineGrid.jsx
@@ -0,0 +1,328 @@
+import WithDraggable from '@/components/common/draggable/withDraggable'
+import QSelectBox from '@/components/common/select/QSelectBox'
+import { useState } from 'react'
+import { useMessage } from '@/hooks/useMessage'
+import { canvasState, dotLineGridSettingState, dotLineIntervalSelector } from '@/store/canvasAtom'
+import { useRecoilState, useRecoilValue, useResetRecoilState } from 'recoil'
+import { onlyNumberInputChange } from '@/util/input-utils'
+import { fabric } from 'fabric'
+import { gridColorState } from '@/store/gridAtom'
+
+const TYPE = {
+ DOT: 'DOT',
+ LINE: 'LINE',
+}
+
+export default function DotLineGrid(props) {
+ // const [modalOption, setModalOption] = useRecoilState(modalState); //modal 열림닫힘 state
+ const [close, setClose] = useState(false)
+ const { setShowDotLineGridModal } = props
+ const gridColor = useRecoilValue(gridColorState)
+ const canvas = useRecoilValue(canvasState)
+
+ const [dotLineGridSetting, setDotLineGridSettingState] = useRecoilState(dotLineGridSettingState)
+ const resetDotLineGridSetting = useResetRecoilState(dotLineGridSettingState)
+ const interval = useRecoilValue(dotLineIntervalSelector)
+
+ const { getMessage } = useMessage()
+ const SelectOption = [
+ { id: 1, name: getMessage('modal.canvas.setting.grid.dot.line.setting.line.origin'), value: 1 },
+ { id: 2, name: '1/2', value: 1 / 2 },
+ {
+ id: 3,
+ name: '1/4',
+ value: 1 / 4,
+ },
+ { id: 4, name: '1/10', value: 1 / 10 },
+ ]
+ const [selectOption, setSelectOption] = useState(SelectOption[0])
+
+ const HandleClickClose = () => {
+ // setClose(true)
+ // setTimeout(() => {
+ // setModalOption({ ...modalOption, gridoption: false })
+ // setClose(false)
+ // }, 180)
+ }
+
+ const handleCheckBoxChange = (e) => {
+ const { value, checked } = e.target
+ setDotLineGridSettingState((prev) => {
+ return {
+ ...prev,
+ [value]: checked,
+ }
+ })
+ }
+
+ const handleSave = () => {
+ // 1. 점.선 그리드 설정으로 만들어진 기존 오브젝트 제거
+ canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'lineGrid')
+ .forEach((obj) => canvas?.remove(obj))
+ canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'dotGrid')
+ .forEach((obj) => canvas?.remove(obj))
+
+ const horizontalInterval = interval.horizontalInterval
+ const verticalInterval = interval.verticalInterval
+
+ if (dotLineGridSetting.DOT) {
+ const circle = new fabric.Circle({
+ radius: 2,
+ fill: 'red',
+ strokeWidth: 0.7,
+ originX: 'center',
+ originY: 'center',
+ selectable: false,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ })
+
+ const patternSourceCanvas = new fabric.StaticCanvas(null, {
+ width: horizontalInterval,
+ height: verticalInterval,
+ })
+
+ patternSourceCanvas.add(circle)
+
+ circle.set({
+ left: patternSourceCanvas.width / 2,
+ top: patternSourceCanvas.height / 2,
+ })
+
+ patternSourceCanvas.renderAll()
+
+ const pattern = new fabric.Pattern({
+ source: patternSourceCanvas.getElement(),
+ repeat: 'repeat',
+ })
+
+ const backgroundPolygon = new fabric.Polygon(
+ [
+ { x: 0, y: 0 },
+ { x: canvas.width, y: 0 },
+ { x: canvas.width, y: canvas.height },
+ { x: 0, y: canvas.height },
+ ],
+ {
+ fill: pattern,
+ selectable: false,
+ name: 'dotGrid',
+ },
+ )
+
+ canvas.add(backgroundPolygon)
+ backgroundPolygon.sendToBack()
+ canvas.renderAll()
+ }
+
+ if (dotLineGridSetting.LINE) {
+ for (let i = 0; i < canvas.height / verticalInterval + 1; i++) {
+ const horizontalLine = new fabric.Line(
+ [0, i * verticalInterval - verticalInterval / 2, canvas.width, i * verticalInterval - verticalInterval / 2],
+ {
+ stroke: gridColor,
+ strokeWidth: 1,
+ selectable: true,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ name: 'lineGrid',
+ strokeDashArray: [5, 2],
+ opacity: 0.3,
+ direction: 'horizontal',
+ },
+ )
+ canvas.add(horizontalLine)
+ }
+
+ for (let i = 0; i < canvas.width / horizontalInterval + 1; i++) {
+ const verticalLine = new fabric.Line(
+ [i * horizontalInterval - horizontalInterval / 2, 0, i * horizontalInterval - horizontalInterval / 2, canvas.height],
+ {
+ stroke: 'black',
+ strokeWidth: 1,
+ selectable: true,
+ lockMovementX: true,
+ lockMovementY: true,
+ lockRotation: true,
+ lockScalingX: true,
+ lockScalingY: true,
+ name: 'lineGrid',
+ strokeDashArray: [5, 2],
+ opacity: 0.3,
+ direction: 'vertical',
+ },
+ )
+ canvas.add(verticalLine)
+ }
+ }
+
+ canvas.renderAll()
+ }
+
+ const handleRadioChange = (e) => {
+ const { value, name, checked, selected } = e.target
+
+ setDotLineGridSettingState((prev) => {
+ return {
+ ...prev,
+ INTERVAL: {
+ ...prev.INTERVAL,
+ type: Number(value),
+ },
+ }
+ })
+ }
+
+ const changeInput = (value, e) => {
+ const { name } = e.target
+ setDotLineGridSettingState((prev) => {
+ return {
+ ...prev,
+ INTERVAL: {
+ ...prev.INTERVAL,
+ [name]: value,
+ },
+ }
+ })
+ }
+
+ const changeDimension = (result) => {
+ const { value } = result
+ setDotLineGridSettingState((prev) => {
+ return {
+ ...prev,
+ INTERVAL: {
+ ...prev.INTERVAL,
+ dimension: value,
+ },
+ }
+ })
+ }
+
+ // 초기화
+ const reset = () => {
+ canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'lineGrid')
+ .forEach((obj) => canvas?.remove(obj))
+ canvas
+ ?.getObjects()
+ .filter((obj) => obj.name === 'dotGrid')
+ .forEach((obj) => canvas?.remove(obj))
+ resetDotLineGridSetting()
+ setSelectOption(SelectOption[0])
+ }
+
+ return (
+
+
+
+
{getMessage('modal.canvas.setting.grid.dot.line.setting')}
+ setShowDotLineGridModal(false)}>
+ 닫기
+
+
+
+
+
+
+
+
+
+
+
+
{getMessage('modal.canvas.setting.grid.dot.line.setting.horizon')}
+
+ onlyNumberInputChange(e, changeInput)}
+ />
+
+
mm
+
+
+
{getMessage('modal.canvas.setting.grid.dot.line.setting.vertical')}
+
+ onlyNumberInputChange(e, changeInput)}
+ />
+
+
mm
+
+
+
+
+
+
+
+
+
{getMessage('modal.canvas.setting.grid.dot.line.setting.ratio')}
+
+ onlyNumberInputChange(e, changeInput)}
+ />
+
+
mm
+
+
+
+
+
+
+
+
+ {getMessage('modal.canvas.setting.grid.dot.line.setting.reset')}
+
+
+ {getMessage('modal.canvas.setting.grid.dot.line.setting.save')}
+
+
+
+
+
+ )
+}
diff --git a/src/components/floor-plan/modal/grid/GridCopy.jsx b/src/components/floor-plan/modal/grid/GridCopy.jsx
new file mode 100644
index 00000000..92609d80
--- /dev/null
+++ b/src/components/floor-plan/modal/grid/GridCopy.jsx
@@ -0,0 +1,43 @@
+import WithDraggable from '@/components/common/draggable/withDraggable'
+import { useMessage } from '@/hooks/useMessage'
+
+export default function GridCopy(props) {
+ const { setShowGridMoveModal, setShowGridCopyModal } = props
+ const { getMessage } = useMessage()
+
+ return (
+
+
+
+
{getMessage('modal.grid.copy')}
+ setShowGridCopyModal(false)}>
+ 닫기
+
+
+
+
{getMessage('modal.grid.copy.info')}
+
+
+
+
{getMessage('modal.grid.copy.length')}
+
+
+
+
mm
+
+
+
+
+
+
+
+
+
+
+ {getMessage('modal.grid.copy.save')}
+
+
+
+
+ )
+}
diff --git a/src/components/floor-plan/modal/grid/GridMove.jsx b/src/components/floor-plan/modal/grid/GridMove.jsx
new file mode 100644
index 00000000..1da8b6fa
--- /dev/null
+++ b/src/components/floor-plan/modal/grid/GridMove.jsx
@@ -0,0 +1,55 @@
+import WithDraggable from '@/components/common/draggable/withDraggable'
+import { useMessage } from '@/hooks/useMessage'
+
+export default function GridMove(props) {
+ const { setShowGridMoveModal, setShowGridCopyModal } = props
+ const { getMessage } = useMessage()
+
+ return (
+
+
+
+
{getMessage('modal.grid.move')}
+ setShowGridMoveModal(false)}>
+ 닫기
+
+
+
+
{getMessage('modal.grid.move.info')}
+
+
+
+
+
+
+
+
{getMessage('modal.grid.move.length')}
+
+
+
+
+
+
+
+
+
+
+
+
+ {getMessage('modal.grid.move.save')}
+
+
+
+
+ )
+}
diff --git a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx
index 05d7cb0c..6e9f1c34 100644
--- a/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx
+++ b/src/components/floor-plan/modal/outerlinesetting/OuterLineWall.jsx
@@ -1,457 +1,20 @@
'use client'
-import { useEffect, useRef } from 'react'
import WithDraggable from '@/components/common/draggable/withDraggable'
-import { useRecoilState, useRecoilValue } from 'recoil'
import { useMessage } from '@/hooks/useMessage'
-import { useEvent } from '@/hooks/useEvent'
-import { canvasState, verticalHorizontalModeState } from '@/store/canvasAtom'
-import {
- OUTER_LINE_TYPE,
- outerLineArrow1State,
- outerLineArrow2State,
- outerLineLength1State,
- outerLineLength2State,
- outerLinePointsState,
- outerLineTypeState,
-} from '@/store/outerLineAtom'
-import { QLine } from '@/components/fabric/QLine'
-import { useLine } from '@/hooks/useLine'
-import { distanceBetweenPoints } from '@/util/canvas-util'
+import { OUTER_LINE_TYPE } from '@/store/outerLineAtom'
+import { onlyNumberInputChange, onlyNumberWithDotInputChange } from '@/util/input-utils'
+import { useOuterLineWall } from '@/hooks/roofcover/useOuterLineWall'
export default function OuterLineWall(props) {
const { setShowOutlineModal } = props
const { getMessage } = useMessage()
- const { addCanvasMouseEventListener, addDocumentEventListener, removeAllMouseEventListeners, removeAllDocumentEventListeners } = useEvent()
- const { addLineText, removeLineText } = useLine()
- const verticalHorizontalMode = useRecoilValue(verticalHorizontalModeState)
+ const { points, length1, setLength1, length2, setLength2, length1Ref, length2Ref, arrow1, arrow2, type, setType, handleFix, handleRollback } =
+ useOuterLineWall()
- const length1Ref = useRef(null)
- const length2Ref = useRef(null)
- const [length1, setLength1] = useRecoilState(outerLineLength1State)
- const [length2, setLength2] = useRecoilState(outerLineLength2State)
- const [arrow1, setArrow1] = useRecoilState(outerLineArrow1State)
- const [arrow2, setArrow2] = useRecoilState(outerLineArrow2State)
- const [points, setPoints] = useRecoilState(outerLinePointsState)
- const [type, setType] = useRecoilState(outerLineTypeState)
- const arrow1Ref = useRef(arrow1)
- const arrow2Ref = useRef(arrow2)
-
- const canvas = useRecoilValue(canvasState)
-
- useEffect(() => {
- removeAllMouseEventListeners()
- addCanvasMouseEventListener('mouse:down', mouseDown)
- }, [verticalHorizontalMode, points])
-
- useEffect(() => {
- arrow1Ref.current = arrow1
- }, [arrow1])
-
- useEffect(() => {
- arrow2Ref.current = arrow2
- }, [arrow2])
-
- useEffect(() => {
- removeAllDocumentEventListeners()
- addDocumentEventListener('keydown', document, keydown[type])
- clear()
- }, [type])
-
- const clear = () => {
- setLength1(0)
- setLength2(0)
-
- setArrow1('')
- setArrow2('')
- }
-
- const mouseDown = (e) => {
- const pointer = canvas.getPointer(e.e)
- if (points.length === 0) {
- setPoints((prev) => [...prev, pointer])
- } else {
- const lastPoint = points[points.length - 1]
- let newPoint = { x: pointer.x, y: pointer.y }
- const length = distanceBetweenPoints(lastPoint, newPoint)
- if (verticalHorizontalMode) {
- const vector = {
- x: pointer.x - points[points.length - 1].x,
- y: pointer.y - points[points.length - 1].y,
- }
- const slope = Math.abs(vector.y / vector.x) // 기울기 계산
-
- let scaledVector
- if (slope >= 1) {
- // 기울기가 1 이상이면 x축 방향으로 그림
- scaledVector = {
- x: 0,
- y: vector.y >= 0 ? Number(length) : -Number(length),
- }
- } else {
- // 기울기가 1 미만이면 y축 방향으로 그림
- scaledVector = {
- x: vector.x >= 0 ? Number(length) : -Number(length),
- y: 0,
- }
- }
-
- const verticalLength = scaledVector.y
- const horizontalLength = scaledVector.x
-
- newPoint = {
- x: lastPoint.x + horizontalLength,
- y: lastPoint.y + verticalLength,
- }
- }
- setPoints((prev) => [...prev, newPoint])
- }
- }
-
- useEffect(() => {
- canvas
- ?.getObjects()
- .filter((obj) => obj.name === 'outerLine')
- .forEach((obj) => {
- canvas?.remove(obj)
- removeLineText(obj)
- })
-
- canvas
- ?.getObjects()
- .filter((obj) => obj.name === 'helpGuideLine' || (obj.name === 'lengthTxt' && obj.parent?.name === 'helpGuideLine'))
- .forEach((obj) => canvas?.remove(obj))
-
- canvas?.remove(canvas?.getObjects().find((obj) => obj.name === 'startPoint'))
-
- // point가 변경 될때마다 이벤트 리스너를 제거하고 다시 등록
- removeAllDocumentEventListeners()
- addDocumentEventListener('keydown', document, keydown[type])
-
- if (points.length === 0) {
- return
- }
-
- if (points.length === 1) {
- const point = new fabric.Circle({
- radius: 5,
- fill: 'transparent',
- stroke: 'red',
- left: points[0].x - 5,
- top: points[0].y - 5,
- selectable: false,
- name: 'startPoint',
- })
-
- canvas?.add(point)
- } else {
- points.forEach((point, idx) => {
- if (idx === 0) {
- return
- }
- drawLine(points[idx - 1], point, idx)
- })
-
- const lastPoint = points[points.length - 1]
- const firstPoint = points[0]
-
- if (points.length < 3) {
- return
- }
-
- if (lastPoint.x === firstPoint.x && lastPoint.y === firstPoint.y) {
- return
- }
-
- if (lastPoint.x === firstPoint.x || lastPoint.y === firstPoint.y) {
- const line = new QLine([lastPoint.x, lastPoint.y, firstPoint.x, firstPoint.y], {
- stroke: 'grey',
- strokeWidth: 1,
- selectable: false,
- name: 'helpGuideLine',
- })
-
- canvas?.add(line)
- addLineText(line)
- } else {
- const guideLine1 = new QLine([lastPoint.x, lastPoint.y, lastPoint.x, firstPoint.y], {
- stroke: 'grey',
- strokeWidth: 1,
- strokeDashArray: [1, 1, 1],
- name: 'helpGuideLine',
- })
-
- const guideLine2 = new QLine([guideLine1.x2, guideLine1.y2, firstPoint.x, firstPoint.y], {
- stroke: 'grey',
- strokeWidth: 1,
- strokeDashArray: [1, 1, 1],
- name: 'helpGuideLine',
- })
- if (guideLine1.length > 0) {
- canvas?.add(guideLine1)
- addLineText(guideLine1)
- }
-
- canvas?.add(guideLine2)
-
- addLineText(guideLine2)
- }
- }
- }, [points])
-
- const drawLine = (point1, point2, idx) => {
- const line = new QLine([point1.x, point1.y, point2.x, point2.y], {
- stroke: 'black',
- strokeWidth: 3,
- idx: idx,
- selectable: false,
- name: 'outerLine',
- })
-
- canvas?.add(line)
- addLineText(line)
- }
-
- // 직각 완료될 경우 확인
- const checkRightAngle = () => {
- const length1Num = Number(length1Ref.current.value) / 10
- const length2Num = Number(length2Ref.current.value) / 10
-
- if (points.length === 0) {
- return
- }
-
- if (length1Num === 0 || length2Num === 0 || arrow1Ref.current === '' || arrow2Ref.current === '') {
- return
- }
-
- if (arrow1Ref.current === '↓' && arrow2Ref.current === '→') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y + length1Num }]
- })
- } else if (arrow1Ref.current === '↓' && arrow2Ref.current === '←') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y + length1Num }]
- })
- } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '→') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x + length2Num, y: prev[prev.length - 1].y - length1Num }]
- })
- } else if (arrow1Ref.current === '↑' && arrow2Ref.current === '←') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x - length2Num, y: prev[prev.length - 1].y - length1Num }]
- })
- } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↓') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y + length2Num }]
- })
- } else if (arrow1Ref.current === '→' && arrow2Ref.current === '↑') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x + length1Num, y: prev[prev.length - 1].y - length2Num }]
- })
- } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↓') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y + length2Num }]
- })
- } else if (arrow1Ref.current === '←' && arrow2Ref.current === '↑') {
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x - length1Num, y: prev[prev.length - 1].y - length2Num }]
- })
- }
- }
-
- const keydown = {
- outerLine: (e) => {
- if (points.length === 0) {
- return
- }
- const key = e.key
-
- if (!length1Ref.current) {
- return
- }
-
- const lengthNum = Number(length1Ref.current.value) / 10
- if (lengthNum === 0) {
- return
- }
- switch (key) {
- case 'Down': // IE/Edge에서 사용되는 값
- case 'ArrowDown': {
- setArrow1('↓')
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y + lengthNum }]
- })
- break
- }
- case 'Up': // IE/Edge에서 사용되는 값
- case 'ArrowUp':
- setArrow1('↑')
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x, y: prev[prev.length - 1].y - lengthNum }]
- })
- break
- case 'Left': // IE/Edge에서 사용되는 값
- case 'ArrowLeft':
- setArrow1('←')
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x - lengthNum, y: prev[prev.length - 1].y }]
- })
- break
- case 'Right': // IE/Edge에서 사용되는 값
- case 'ArrowRight':
- setArrow1('→')
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[prev.length - 1].x + lengthNum, y: prev[prev.length - 1].y }]
- })
- break
- }
- },
- rightAngle: (e) => {
- if (points.length === 0) {
- return
- }
- const key = e.key
-
- const activeElem = document.activeElement
-
- switch (key) {
- case 'Down': // IE/Edge에서 사용되는 값
- case 'ArrowDown': {
- if (activeElem === length1Ref.current) {
- setArrow1('↓')
- arrow1Ref.current = '↓'
- length2Ref.current.focus()
- } else if (activeElem === length2Ref.current) {
- if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
- break
- }
- setArrow2('↓')
- arrow2Ref.current = '↓'
- checkRightAngle()
- }
-
- break
- }
- case 'Up': // IE/Edge에서 사용되는 값
- case 'ArrowUp':
- if (activeElem === length1Ref.current) {
- setArrow1('↑')
- arrow1Ref.current = '↑'
- length2Ref.current.focus()
- } else if (activeElem === length2Ref.current) {
- if (arrow1Ref.current === '↓' || arrow1Ref.current === '↑') {
- break
- }
- setArrow2('↑')
- arrow2Ref.current = '↑'
- checkRightAngle()
- }
-
- break
- case 'Left': // IE/Edge에서 사용되는 값
- case 'ArrowLeft':
- if (activeElem === length1Ref.current) {
- setArrow1('←')
- arrow1Ref.current = '←'
- length2Ref.current.focus()
- } else if (activeElem === length2Ref.current) {
- if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
- break
- }
- setArrow2('←')
- arrow2Ref.current = '←'
- checkRightAngle()
- }
-
- break
- case 'Right': // IE/Edge에서 사용되는 값
- case 'ArrowRight':
- if (activeElem === length1Ref.current) {
- setArrow1('→')
- arrow1Ref.current = '→'
- length2Ref.current.focus()
- } else if (activeElem === length2Ref.current) {
- if (arrow1Ref.current === '←' || arrow1Ref.current === '→') {
- break
- }
- setArrow2('→')
- arrow2Ref.current = '→'
- checkRightAngle()
- }
-
- break
- }
- },
- leeGubae: (e) => {
- console.log('leegubae')
- },
- angle: (e) => {
- console.log('angle')
- },
- diagonalLine: (e) => {
- console.log('diagonalLine')
- },
- }
-
- /**
- * 일변전으로 돌아가기
- */
- const handleRollback = () => {
- //points의 마지막 요소를 제거
- setPoints((prev) => prev.slice(0, prev.length - 1))
- }
-
- const handleFix = () => {
- if (points.length < 3) {
- return
- }
- setPoints((prev) => {
- if (prev.length === 0) {
- return []
- }
- return [...prev, { x: prev[0].x, y: prev[0].y }]
- })
- }
return (
-
-
+
+
{getMessage('modal.cover.outline.drawing')}
setShowOutlineModal(false)}>
@@ -500,9 +63,7 @@ export default function OuterLineWall(props) {
className="input-origin block"
value={length1}
ref={length1Ref}
- onChange={(e) => {
- setLength1(e.target.value.replace(/[^-0-9]/g, ''))
- }}
+ onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
@@ -520,9 +81,7 @@ export default function OuterLineWall(props) {
className="input-origin block"
value={length1}
ref={length1Ref}
- onChange={(e) => {
- setLength1(e.target.value.replace(/[^-0-9]/g, ''))
- }}
+ onChange={(e) => onlyNumberInputChange(e, setLength1)}
placeholder="3000"
/>
@@ -537,9 +96,7 @@ export default function OuterLineWall(props) {
className="input-origin block"
value={length2}
ref={length2Ref}
- onChange={(e) => {
- setLength2(e.target.value.replace(/[^-0-9]/g, ''))
- }}
+ onChange={(e) => onlyNumberInputChange(e, setLength2)}
placeholder="3000"
/>
@@ -548,6 +105,30 @@ export default function OuterLineWall(props) {
+ ) : type === OUTER_LINE_TYPE.ANGLE ? (
+
) : (
<>>
)}
diff --git a/src/components/floor-plan/modal/setting01/FirstOption.jsx b/src/components/floor-plan/modal/setting01/FirstOption.jsx
index 8c292a05..ac8f08d6 100644
--- a/src/components/floor-plan/modal/setting01/FirstOption.jsx
+++ b/src/components/floor-plan/modal/setting01/FirstOption.jsx
@@ -1,65 +1,189 @@
import { useRecoilState } from 'recoil'
-import { settingModalFirstOptionsState } from '@/store/settingAtom'
+import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react'
-import { get } from '@/lib/Axios'
+import { useAxios } from '@/hooks/useAxios'
+import { useSwal } from '@/hooks/useSwal'
+import { adsorptionPointAddModeState } from '@/store/canvasAtom'
export default function FirstOption() {
- const [objectNo] = useState('test123240912001') // 이후 삭제 필요
- const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
- const { option1, option2 } = settingsModalOptions
+ const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
+ const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
+ const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
+ const { option1, option2, dimensionDisplay } = settingModalFirstOptions
+ const { option3, option4 } = settingModalSecondOptions
const { getMessage } = useMessage()
-
- const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
+ const { get, post } = useAxios()
+ const { swalFire } = useSwal()
// 데이터를 최초 한 번만 조회
useEffect(() => {
console.log('FirstOption useEffect 실행')
- if (!isFetched) {
- // 조회가 안 되었을 때만 fetchSettings 실행
- fetchSettings()
- }
- }, [isFetched]) // isFetched 상태가 변할 때마다 확인
+ fetchSettings()
+ }, [objectNo])
// Canvas Setting 조회 및 초기화
const fetchSettings = async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
-
- const options1 = [
- 'assignDisplay',
- 'drawDisplay',
- 'gridDisplay',
- 'charDisplay',
- 'flowDisplay',
- 'hallwayDimenDisplay',
- 'actualDimenDisplay',
- 'noDimenDisplay',
- 'trestleDisplay',
- 'coordiDisplay',
- 'drawConverDisplay',
- ]
- const option1 = settingsModalOptions.option1.map((item, index) => ({ ...item, selected: res[options1[index]] }))
-
- const options2 = ['onlyBorder', 'lineHatch', 'allPainted']
- const option2 = settingsModalOptions.option2.map((item, index) => ({ ...item, selected: res[options2[index]] }))
+ const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
+ const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
// 데이터 설정
- setSettingModalOptions({
- option1,
- option2,
+ setSettingModalFirstOptions({
+ option1: optionData1,
+ option2: optionData2,
+ dimensionDisplay: optionData5,
})
- setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
+ setSettingModalSecondOptions({
+ option3: optionData3,
+ option4: optionData4,
+ })
} catch (error) {
console.error('Data fetching error:', error)
}
}
- const onClickOption = (option) => {
+ const onClickOption = async (option) => {
option.selected = !option.selected
- setSettingModalOptions({ option1, option2 })
+ setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
+ setSettingModalSecondOptions({ option3, option4 })
+
+ try {
+ // 서버에 전송할 데이터
+ const dataToSend = {
+ firstOption1: option1.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption2: option2.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption3: dimensionDisplay.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ // secondOption1: secondOptions[0].option1.map((item) => ({
+ // name: item.id,
+ // name: item.name,
+ // // 필요한 경우 데이터 항목 추가
+ // })),
+ secondOption2: option4.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ }
+
+ const patternData = {
+ objectNo,
+ //디스플레이 설정(다중)
+ allocDisplay: dataToSend.firstOption1[0].selected,
+ outlineDisplay: dataToSend.firstOption1[1].selected,
+ gridDisplay: dataToSend.firstOption1[2].selected,
+ lineDisplay: dataToSend.firstOption1[3].selected,
+ wordDisplay: dataToSend.firstOption1[4].selected,
+ circuitNumDisplay: dataToSend.firstOption1[5].selected,
+ flowDisplay: dataToSend.firstOption1[6].selected,
+ trestleDisplay: dataToSend.firstOption1[7].selected,
+ totalDisplay: dataToSend.firstOption1[8].selected,
+ //차수 표시(다건)
+ corridorDimension: dataToSend.firstOption3[0].selected,
+ realDimension: dataToSend.firstOption3[1].selected,
+ noneDimension: dataToSend.firstOption3[2].selected,
+ //화면 표시(다중)
+ onlyBorder: dataToSend.firstOption2[0].selected,
+ lineHatch: dataToSend.firstOption2[1].selected,
+ allPainted: dataToSend.firstOption2[2].selected,
+ //흡착범위 설정(단건)
+ adsorpRangeSmall: dataToSend.secondOption2[0].selected,
+ adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
+ adsorpRangeMedium: dataToSend.secondOption2[2].selected,
+ adsorpRangeLarge: dataToSend.secondOption2[3].selected,
+ }
+
+ // HTTP POST 요청 보내기
+ await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
+ swalFire({ text: getMessage(res.returnMessage) })
+ })
+ } catch (error) {
+ swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
+ }
+ }
+
+ const onClickDimension = async (item) => {
+ const options = settingModalFirstOptions?.dimensionDisplay.map((option) => {
+ option.selected = option.id === item.id
+ return option
+ })
+
+ setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
+
+ try {
+ // 서버에 전송할 데이터
+ const dataToSend = {
+ firstOption1: option1.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption2: option2.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption3: dimensionDisplay.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ // secondOption1: secondOptions[0].option1.map((item) => ({
+ // name: item.id,
+ // name: item.name,
+ // // 필요한 경우 데이터 항목 추가
+ // })),
+ secondOption2: option4.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ }
+
+ const patternData = {
+ objectNo,
+ //디스플레이 설정(다중)
+ allocDisplay: dataToSend.firstOption1[0].selected,
+ outlineDisplay: dataToSend.firstOption1[1].selected,
+ gridDisplay: dataToSend.firstOption1[2].selected,
+ lineDisplay: dataToSend.firstOption1[3].selected,
+ wordDisplay: dataToSend.firstOption1[4].selected,
+ circuitNumDisplay: dataToSend.firstOption1[5].selected,
+ flowDisplay: dataToSend.firstOption1[6].selected,
+ trestleDisplay: dataToSend.firstOption1[7].selected,
+ totalDisplay: dataToSend.firstOption1[8].selected,
+ //차수 표시(다건)
+ corridorDimension: dataToSend.firstOption3[0].selected,
+ realDimension: dataToSend.firstOption3[1].selected,
+ noneDimension: dataToSend.firstOption3[2].selected,
+ //화면 표시(다중)
+ onlyBorder: dataToSend.firstOption2[0].selected,
+ lineHatch: dataToSend.firstOption2[1].selected,
+ allPainted: dataToSend.firstOption2[2].selected,
+ //흡착범위 설정(단건)
+ adsorpRangeSmall: dataToSend.secondOption2[0].selected,
+ adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
+ adsorpRangeMedium: dataToSend.secondOption2[2].selected,
+ adsorpRangeLarge: dataToSend.secondOption2[3].selected,
+ }
+
+ // HTTP POST 요청 보내기
+ await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
+ swalFire({ text: getMessage(res.returnMessage) })
+ })
+ } catch (error) {
+ swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
+ }
}
return (
@@ -67,23 +191,37 @@ export default function FirstOption() {
{getMessage('modal.canvas.setting.first.option.info')}
- {settingsModalOptions?.option1?.map((item) => (
- onClickOption(item)}>
-
- {getMessage(item.name)}
-
- ))}
+ {settingModalFirstOptions &&
+ settingModalFirstOptions.option1.map((item) => (
+ onClickOption(item)}>
+
+ {getMessage(item.name)}
+
+ ))}
+
+
+
+
{getMessage('modal.canvas.setting.first.option.dimension')}
+
+ {settingModalFirstOptions &&
+ settingModalFirstOptions.dimensionDisplay.map((item) => (
+ onClickDimension(item)}>
+
+ {getMessage(item.name)}
+
+ ))}
{getMessage('modal.canvas.setting.first.option.display')}
- {settingsModalOptions?.option2?.map((item) => (
- onClickOption(item)}>
-
- {getMessage(item.name)}
-
- ))}
+ {settingModalFirstOptions &&
+ settingModalFirstOptions.option2.map((item) => (
+ onClickOption(item)}>
+
+ {getMessage(item.name)}
+
+ ))}
>
diff --git a/src/components/floor-plan/modal/setting01/GridOption.jsx b/src/components/floor-plan/modal/setting01/GridOption.jsx
new file mode 100644
index 00000000..edf1e802
--- /dev/null
+++ b/src/components/floor-plan/modal/setting01/GridOption.jsx
@@ -0,0 +1,80 @@
+import React, { useEffect } from 'react'
+import { useRecoilState } from 'recoil'
+import { settingModalGridOptionsState } from '@/store/settingAtom'
+import { useMessage } from '@/hooks/useMessage'
+import { adsorptionPointAddModeState } from '@/store/canvasAtom'
+import { useTempGrid } from '@/hooks/useTempGrid'
+import { gridColorState } from '@/store/gridAtom'
+import { useColor } from 'react-color-palette'
+
+export default function GridOption(props) {
+ const { setShowDotLineGridModal } = props
+ const [gridOptions, setGridOptions] = useRecoilState(settingModalGridOptionsState)
+ const [gridColor, setGridColor] = useRecoilState(gridColorState)
+ const [adsorptionPointAddMode, setAdsorptionPointAddMode] = useRecoilState(adsorptionPointAddModeState)
+ const { getMessage } = useMessage()
+ const { tempGridMode, setTempGridMode } = useTempGrid()
+
+ const [color, setColor] = useColor(gridColor)
+
+ useEffect(() => {
+ console.log(color)
+ setGridColor(color.hex)
+ }, [color])
+
+ const onClickOption = (option) => {
+ const newGridOptions = [...gridOptions]
+ newGridOptions.map((item) => {
+ if (item.id === option.id) {
+ item.selected = !item.selected
+ }
+ })
+
+ if (option.id === 1) {
+ // 점 그리드
+ setAdsorptionPointAddMode(false)
+ setTempGridMode(option.selected)
+ newGridOptions[2].selected = false
+ }
+
+ if (option.id === 2) {
+ // 점.선 그리드
+ if (option.selected) {
+ setShowDotLineGridModal(true)
+ } else {
+ setShowDotLineGridModal(false)
+ }
+ }
+
+ if (option.name === 'modal.canvas.setting.grid.absorption.add') {
+ setAdsorptionPointAddMode(!adsorptionPointAddMode)
+ setTempGridMode(false)
+ newGridOptions[0].selected = false
+ }
+
+ if (option.id === 4) {
+ // 그리드 색 설정
+ if (option.selected) {
+ setColorPickerShow(true)
+ }
+ }
+
+ setGridOptions(newGridOptions)
+ }
+
+ return (
+ <>
+
+
{getMessage('modal.canvas.setting.grid')}
+
+ {gridOptions?.map((option) => (
+ onClickOption(option)}>
+
+ {getMessage(option.name)}
+
+ ))}
+
+
+ >
+ )
+}
diff --git a/src/components/floor-plan/modal/setting01/SecondOption.jsx b/src/components/floor-plan/modal/setting01/SecondOption.jsx
index 0a568b67..f6cf6e30 100644
--- a/src/components/floor-plan/modal/setting01/SecondOption.jsx
+++ b/src/components/floor-plan/modal/setting01/SecondOption.jsx
@@ -1,75 +1,145 @@
-import { useRecoilState } from 'recoil'
-import { settingModalSecondOptionsState } from '@/store/settingAtom'
+import { useRecoilState, useSetRecoilState } from 'recoil'
+import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom'
import { useMessage } from '@/hooks/useMessage'
import React, { useEffect, useState } from 'react'
-import { get } from '@/lib/Axios'
+import { useAxios } from '@/hooks/useAxios'
+import { useSwal } from '@/hooks/useSwal'
+import { adsorptionPointModeState, adsorptionRangeState } from '@/store/canvasAtom'
export default function SecondOption() {
- const [objectNo] = useState('test123240912001') // 이후 삭제 필요
- const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
- const { option1, option2 } = settingsModalOptions
- const { getMessage } = useMessage()
+ const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요
+ const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState)
+ const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState)
+ const [adsorptionPointMode, setAdsorptionPointMode] = useRecoilState(adsorptionPointModeState)
+ const setAdsorptionRange = useSetRecoilState(adsorptionRangeState)
- const [isFetched, setIsFetched] = useState(false) // 조회 여부 상태
+ const { option1, option2, dimensionDisplay } = settingModalFirstOptions
+ const { option3, option4 } = settingModalSecondOptions
+ const { getMessage } = useMessage()
+ const { get, post } = useAxios()
+ const { swalFire } = useSwal()
// 데이터를 최초 한 번만 조회
useEffect(() => {
console.log('SecondOption useEffect 실행')
- if (!isFetched) {
- // 조회가 안 되었을 때만 fetchSettings 실행
- fetchSettings()
- }
- }, [isFetched]) // isFetched 상태가 변할 때마다 확인
+ fetchSettings()
+ }, [objectNo])
+ // Canvas Setting 조회 및 초기화
const fetchSettings = async () => {
try {
const res = await get({ url: `/api/canvas-management/canvas-settings/by-object/${objectNo}` })
+ const optionData1 = settingModalFirstOptions.option1.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData2 = settingModalFirstOptions.option2.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData5 = settingModalFirstOptions.dimensionDisplay.map((item) => ({ ...item, selected: res[item.column] }))
+ const optionData3 = settingModalSecondOptions.option3.map((item) => ({ ...item }))
+ const optionData4 = settingModalSecondOptions.option4.map((item) => ({ ...item, selected: res[item.column] }))
- //const options1 = ['1', '2', '3', '4']
- //const option1 = settingsModalOptions.option1.map((item, index) => ({ ...item, selected: res[options1[index]] }))
-
- const options2 = ['adsorpRangeSmall', 'adsorpRangeSmallSemi', 'adsorpRangeMedium', 'adsorpRangeLarge']
- const option2 = settingsModalOptions.option2.map((item, index) => ({ ...item, selected: res[options2[index]] }))
-
- // 데이터 설정
- setSettingModalOptions({
- option1,
- option2,
+ setSettingModalFirstOptions({
+ option1: optionData1,
+ option2: optionData2,
+ dimensionDisplay: optionData5,
+ })
+ setSettingModalSecondOptions({
+ option3: optionData3,
+ option4: optionData4,
})
-
- setIsFetched(true) // 조회가 완료되면 isFetched를 true로 설정
} catch (error) {
console.error('Data fetching error:', error)
}
}
- const onClickOption = (option) => {
- // option2에서 한 개만 선택 가능하도록 처리
- const updatedOption2 = option2.map((item) => (item.id === option.id ? { ...item, selected: true } : { ...item, selected: false }))
+ const onClickOption = async (option) => {
+ // option4에서 한 개만 선택 가능하도록 처리
+ const updatedOption4 = option4.map((item) => (item.id === option.id ? { ...item, selected: true } : { ...item, selected: false }))
- setSettingModalOptions({ option1, option2: updatedOption2 })
+ setSettingModalFirstOptions({ option1, option2, dimensionDisplay })
+ setSettingModalSecondOptions({ option3, option4: updatedOption4 })
+
+ try {
+ // 서버에 전송할 데이터
+ const dataToSend = {
+ firstOption1: option1.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption2: option2.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ firstOption3: dimensionDisplay.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ // secondOption1: secondOptions[0].option3.map((item) => ({
+ // name: item.id,
+ // name: item.name,
+ // // 필요한 경우 데이터 항목 추가
+ // })),
+ secondOption2: updatedOption4.map((item) => ({
+ column: item.column,
+ selected: item.selected,
+ })),
+ }
+ const patternData = {
+ objectNo,
+ //디스플레이 설정(다중)
+ allocDisplay: dataToSend.firstOption1[0].selected,
+ outlineDisplay: dataToSend.firstOption1[1].selected,
+ gridDisplay: dataToSend.firstOption1[2].selected,
+ lineDisplay: dataToSend.firstOption1[3].selected,
+ wordDisplay: dataToSend.firstOption1[4].selected,
+ circuitNumDisplay: dataToSend.firstOption1[5].selected,
+ flowDisplay: dataToSend.firstOption1[6].selected,
+ trestleDisplay: dataToSend.firstOption1[7].selected,
+ totalDisplay: dataToSend.firstOption1[8].selected,
+ //차수 표시(다건)
+ corridorDimension: dataToSend.firstOption3[0].selected,
+ realDimension: dataToSend.firstOption3[1].selected,
+ noneDimension: dataToSend.firstOption3[2].selected,
+ //화면 표시(다중)
+ onlyBorder: dataToSend.firstOption2[0].selected,
+ lineHatch: dataToSend.firstOption2[1].selected,
+ allPainted: dataToSend.firstOption2[2].selected,
+ //흡착범위 설정(단건)
+ adsorpRangeSmall: dataToSend.secondOption2[0].selected,
+ adsorpRangeSmallSemi: dataToSend.secondOption2[1].selected,
+ adsorpRangeMedium: dataToSend.secondOption2[2].selected,
+ adsorpRangeLarge: dataToSend.secondOption2[3].selected,
+ }
+
+ // HTTP POST 요청 보내기
+ await post({ url: `/api/canvas-management/canvas-settings`, data: patternData }).then((res) => {
+ swalFire({ text: getMessage(res.returnMessage) })
+ })
+ } catch (error) {
+ swalFire({ text: getMessage(res.returnMessage), icon: 'error' })
+ }
+ setAdsorptionRange(option.range)
}
return (
<>
{getMessage('modal.canvas.setting.font.plan.edit')}
- {settingsModalOptions.option1.map((item, index) => (
-
- {getMessage(item.name)}
-
- ))}
+ {settingModalSecondOptions &&
+ settingModalSecondOptions.option3.map((item) => (
+
+ {getMessage(item.name)}
+
+ ))}
{getMessage('modal.canvas.setting.font.plan.absorption')}
- {settingsModalOptions.option2.map((item, index) => (
- onClickOption(item)}>
-
- {getMessage(item.name)}
-
- ))}
+ {settingModalSecondOptions &&
+ settingModalSecondOptions.option4.map((item) => (
+ onClickOption(item)}>
+
+ {getMessage(item.name)}
+
+ ))}
@@ -78,6 +148,15 @@ export default function SecondOption() {
{getMessage('modal.canvas.setting.font.plan.absorption.plan.size.setting')}
+ {
+ setAdsorptionPointMode(!adsorptionPointMode)
+ }}
+ >
+ {getMessage('modal.canvas.setting.font.plan.absorption.point')}
+ {adsorptionPointMode ? 'ON' : 'OFF'}
+
>
diff --git a/src/components/floor-plan/modal/setting01/SettingModal01.jsx b/src/components/floor-plan/modal/setting01/SettingModal01.jsx
index 6ce186b7..293d29df 100644
--- a/src/components/floor-plan/modal/setting01/SettingModal01.jsx
+++ b/src/components/floor-plan/modal/setting01/SettingModal01.jsx
@@ -5,15 +5,16 @@ import FirstOption from './FirstOption'
import WithDraggable from '@/components/common/draggable/withDraggable'
import SecondOption from '@/components/floor-plan/modal/setting01/SecondOption'
import { useMessage } from '@/hooks/useMessage'
+import GridOption from '@/components/floor-plan/modal/setting01/GridOption'
export default function SettingModal01(props) {
- const { setShowCanvasSettingModal } = props
+ const { setShowCanvasSettingModal, setShowDotLineGridModal } = props
const [buttonAct, setButtonAct] = useState(1)
const { getMessage } = useMessage()
return (
-
-
+
+
{getMessage('modal.canvas.setting')}
setShowCanvasSettingModal(false)}>
@@ -29,9 +30,13 @@ export default function SettingModal01(props) {
setButtonAct(2)}>
{getMessage('modal.canvas.setting.font.plan')}
+ setButtonAct(3)}>
+ {getMessage('modal.canvas.setting.grid')}
+
{buttonAct === 1 &&
}
{buttonAct === 2 &&
}
+ {buttonAct === 3 &&
}
diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx
index e8a4e872..456cb09f 100644
--- a/src/components/header/Header.jsx
+++ b/src/components/header/Header.jsx
@@ -1,7 +1,12 @@
'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'
@@ -23,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')) {
@@ -31,6 +37,9 @@ export default function Header(props) {
// }
const [selected, setSelected] = useState('')
+ const dimmedState = useRecoilValue(dimmedStore)
+ const isDimmed = dimmedState ? 'opacity-50 bg-black' : ''
+
const SelectOptions = [
{ id: 0, name: 'オンライン保証シ', link: '' },
{ id: 1, name: 'ステム', link: '' },
@@ -60,6 +69,14 @@ export default function Header(props) {
},
]
+ const syncSession = useCallback(() => {
+ setSessionState({ ...userSession })
+ })
+
+ useEffect(() => {
+ syncSession()
+ }, [userSession])
+
const onChangeSelect = (option) => {
setSelected(option)
}
@@ -108,7 +125,7 @@ export default function Header(props) {
return (
!(pathName.includes('login') || pathName.includes('join')) && (
-