From 88a1194e1c721d3320e3e7daa3f943d64de5a4e0 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 28 Oct 2024 13:48:21 +0900 Subject: [PATCH 1/7] =?UTF-8?q?offset=EC=9A=A9=20=EB=8B=A8=EC=9C=84,=20flo?= =?UTF-8?q?w=EC=9A=A9=20=EB=8B=A8=EC=9C=84=20=EB=8B=A4=EB=A6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/common/useCanvasConfigInitialize.js | 16 ++++++++++++---- src/hooks/roofcover/useRoofShapeSetting.js | 8 +++++++- src/hooks/useLine.js | 16 +++++++++++++--- src/store/canvasAtom.js | 11 +++++++++++ 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/hooks/common/useCanvasConfigInitialize.js b/src/hooks/common/useCanvasConfigInitialize.js index 2b31bbda..f49b4cb9 100644 --- a/src/hooks/common/useCanvasConfigInitialize.js +++ b/src/hooks/common/useCanvasConfigInitialize.js @@ -1,7 +1,7 @@ import { useEffect } from 'react' import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil' import { basicSettingState, roofDisplaySelector, settingModalFirstOptionsState } from '@/store/settingAtom' -import { canvasState, dotLineGridSettingState, pitchText, pitchTextSelector } from '@/store/canvasAtom' +import { canvasState, dotLineGridSettingState, pitchText, pitchTextSelector, showAngleUnitSelector } from '@/store/canvasAtom' import { getChonByDegree, getDegreeByChon, setSurfaceShapePattern } from '@/util/canvas-util' import { useFont } from '@/hooks/common/useFont' import { useGrid } from '@/hooks/common/useGrid' @@ -16,6 +16,7 @@ export function useCanvasConfigInitialize() { const setGlobalFonts = useSetRecoilState(globalFontAtom) const setDotLineGridSetting = useSetRecoilState(dotLineGridSettingState) const pitchText = useRecoilValue(pitchTextSelector) + const angleUnit = useRecoilValue(showAngleUnitSelector) const {} = useFont() const {} = useGrid() const {} = useRoof() @@ -33,15 +34,22 @@ export function useCanvasConfigInitialize() { useEffect(() => { if (!canvas) return - const texts = canvas.getObjects().filter((obj) => obj.name === 'pitchText' || obj.name === 'flowText') + const offsetTexts = canvas.getObjects().filter((obj) => obj.name === 'pitchText') + const flowTexts = canvas.getObjects().filter((obj) => obj.name === 'flowText') if (basicSetting.roofAngleSet === 'slope') { - texts.forEach((obj) => { + offsetTexts.forEach((obj) => { + obj.set({ text: `${obj.originText}-∠${obj.pitch}${angleUnit}` }) + }) + flowTexts.forEach((obj) => { obj.set({ text: `${obj.originText}-∠${obj.pitch}${pitchText}` }) }) } if (basicSetting.roofAngleSet === 'flat') { - texts.forEach((obj) => { + offsetTexts.forEach((obj) => { + obj.set({ text: `${obj.originText}-∠${getDegreeByChon(obj.pitch)}${angleUnit}` }) + }) + flowTexts.forEach((obj) => { obj.set({ text: `${obj.originText}-∠${getDegreeByChon(obj.pitch)}${pitchText}` }) }) } diff --git a/src/hooks/roofcover/useRoofShapeSetting.js b/src/hooks/roofcover/useRoofShapeSetting.js index 9aab5da7..e0d850f4 100644 --- a/src/hooks/roofcover/useRoofShapeSetting.js +++ b/src/hooks/roofcover/useRoofShapeSetting.js @@ -38,6 +38,8 @@ export function useRoofShapeSetting(id) { const setCurrentMenu = useSetRecoilState(currentMenuState) const outerLineFix = useRecoilValue(outerLineFixState) + const isFixRef = useRef(false) + const pitchRef = useRef(null) const jerkinHeadPitchRef = useRef(null) @@ -60,6 +62,10 @@ export function useRoofShapeSetting(id) { } return () => { + if (!isFixRef.current) { + return + } + const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const pitchTexts = canvas.getObjects().filter((obj) => obj.name === 'pitchText') canvas.remove(...pitchTexts) @@ -83,7 +89,6 @@ export function useRoofShapeSetting(id) { }) addPitchText(line) - line.setViewLengthText(false) } }) canvas.renderAll() @@ -388,6 +393,7 @@ export function useRoofShapeSetting(id) { canvas?.renderAll() roof.drawHelpLine() // setShowRoofShapeSettingModal(false) + isFixRef.current = true closePopup(id) } diff --git a/src/hooks/useLine.js b/src/hooks/useLine.js index 62ec937a..7bf01a47 100644 --- a/src/hooks/useLine.js +++ b/src/hooks/useLine.js @@ -1,5 +1,13 @@ import { useRecoilValue } from 'recoil' -import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, fontFamilyState, fontSizeState } from '@/store/canvasAtom' +import { + ANGLE_TYPE, + canvasState, + currentAngleTypeSelector, + fontFamilyState, + fontSizeState, + pitchTextSelector, + showAngleUnitSelector, +} from '@/store/canvasAtom' import { QLine } from '@/components/fabric/QLine' import { getChonByDegree, getDegreeByChon } from '@/util/canvas-util' @@ -8,6 +16,8 @@ export const useLine = () => { const fontSize = useRecoilValue(fontSizeState) const fontFamily = useRecoilValue(fontFamilyState) const currentAngleType = useRecoilValue(currentAngleTypeSelector) + const pitchText = useRecoilValue(pitchTextSelector) + const angleUnit = useRecoilValue(showAngleUnitSelector) const addLine = (points = [], options) => { const line = new QLine(points, { @@ -81,8 +91,8 @@ export const useLine = () => { const textStr = currentAngleType === ANGLE_TYPE.SLOPE - ? `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + attributes.pitch : ''}` - : `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + getDegreeByChon(attributes.pitch) : ''}` + ? `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + attributes.pitch + angleUnit : ''}` + : `${attributes.offset ? attributes.offset * 10 : attributes.width * 10}${attributes.pitch ? '-∠' + getDegreeByChon(attributes.pitch) + angleUnit : ''}` if (direction === 'top') { left = (startPoint.x + endPoint.x) / 2 diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js index 2eade854..bdce5876 100644 --- a/src/store/canvasAtom.js +++ b/src/store/canvasAtom.js @@ -353,3 +353,14 @@ export const pitchTextSelector = selector({ return roofAngleSet === 'slope' ? '寸' : '度' }, }) + +//각도 표시, offset 길이에서는 각도가 한자가 아닌 도형으로 표시되어야 한다. +export const showAngleUnitSelector = selector({ + key: 'showAngleUnitSelector', + get: ({ get }) => { + const basicSettingStateValue = get(basicSettingState) + const roofAngleSet = basicSettingStateValue.roofAngleSet + + return roofAngleSet === 'slope' ? '寸' : '°' + }, +}) From 74b6792d96bb0ab867363c370f1965a2ab3aeb01 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 28 Oct 2024 13:58:37 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=EC=A0=80=EC=9E=A5=EC=8B=9C=20properties=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20db=20=3D>=20canvas=20=EC=8B=9C=20replace?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/usePlan.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 8ed84af4..4c655e86 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -65,6 +65,7 @@ export function usePlan() { 'text', 'pitch', 'uuid', + 'originText', ]) const str = JSON.stringify(objs) @@ -144,7 +145,7 @@ export function usePlan() { * DB에 저장된 데이터를 canvas에서 사용할 수 있도록 포맷화 */ const dbToCanvasFormat = (cs) => { - return cs.replace(/##/g, '"').replace(/∠/g, '∠') + return cs.replace(/##/g, '"').replace(/∠/g, '∠').replace(/°/g, '°') } /** From e7ab754b59a3092d1009026ed985946425c74b55 Mon Sep 17 00:00:00 2001 From: basssy Date: Mon, 28 Oct 2024 14:52:19 +0900 Subject: [PATCH 3/7] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=20=EA=B2=AC=EC=A0=81?= =?UTF-8?q?=EC=84=9C=20=ED=99=94=EB=A9=B4=EC=9D=B4=EB=8F=99=EC=8B=9C=20?= =?UTF-8?q?=EB=AC=BC=EA=B1=B4=EB=B2=88=ED=98=B8=20=EA=B4=80=EB=A0=A8=20ato?= =?UTF-8?q?m=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/management/StuffDetail.jsx | 10 ++++++++-- src/components/management/StuffSubHeader.jsx | 7 ++++--- src/store/floorPlanObjectAtom.js | 9 +++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 src/store/floorPlanObjectAtom.js diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index 4b15c8a0..e8104548 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -10,15 +10,18 @@ import { globalLocaleStore } from '@/store/localeAtom' import { isEmptyArray, isNotEmptyArray, isObjectNotEmpty } from '@/util/common-utils' import { useMessage } from '@/hooks/useMessage' import { useForm } from 'react-hook-form' -import { useRecoilValue } from 'recoil' +import { useRecoilValue, useSetRecoilState } from 'recoil' import { sessionStore } from '@/store/commonAtom' import FindAddressPop from './popup/FindAddressPop' import PlanRequestPop from './popup/PlanRequestPop' import WindSelectPop from './popup/WindSelectPop' import { useCommonCode } from '@/hooks/common/useCommonCode' import StuffPlanQGrid from './StuffPlanQGrid' +import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' export default function StuffDetail() { + const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) //견적서 화면용 물건번호리코일 + const inputReceiveUserEl = useRef(null) //담당자ref const inputObjectNameEl = useRef(null) //물건명ref const inputZipNoEl = useRef(null) //우편번호ref @@ -1077,6 +1080,7 @@ export default function StuffDetail() { //상세화면으로 전환 if (res.status === 201) { alert(getMessage('stuff.detail.save')) + setFloorPlanObjectNo({ floorPlanObjectNo: objectNo }) router.push(`/management/stuff/detail?objectNo=${res.data.objectNo.toString()}`) } }) @@ -1085,6 +1089,7 @@ export default function StuffDetail() { await promisePut({ url: apiUrl, data: params }).then((res) => { if (res.status === 201) { alert(getMessage('stuff.detail.save')) + setFloorPlanObjectNo({ floorPlanObjectNo: objectNo }) router.refresh() } }) @@ -1153,7 +1158,8 @@ export default function StuffDetail() { alert(getMessage('stuff.detail.delete.message1')) } else { if (confirm(getMessage('common.message.data.delete'))) { - del({ url: `/api/object/${objectNo}` }).then((res) => { + del({ url: `/api/object/${objectNo}` }).then(() => { + setFloorPlanObjectNo({ floorPlanObjectNo: '' }) router.push('/management/stuff') }) } diff --git a/src/components/management/StuffSubHeader.jsx b/src/components/management/StuffSubHeader.jsx index 1b10a149..f1103143 100644 --- a/src/components/management/StuffSubHeader.jsx +++ b/src/components/management/StuffSubHeader.jsx @@ -5,14 +5,15 @@ import Link from 'next/link' import Image from 'next/image' import { useMessage } from '@/hooks/useMessage' import { useRouter, useSearchParams } from 'next/navigation' -import { stuffSearchState } from '@/store/stuffAtom' +import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' import { useSetRecoilState } from 'recoil' export default function StuffSubHeader({ type }) { const { getMessage } = useMessage() const router = useRouter() - const setSchObjectNo = useSetRecoilState(stuffSearchState) + const setFloorPlanObjectNo = useSetRecoilState(floorPlanObjectState) + useEffect(() => { window.scrollTo(0, 0) }, []) @@ -22,7 +23,7 @@ export default function StuffSubHeader({ type }) { // url에 물건번호로 도면작성화면으로 이동 const moveFloorPlan = () => { - setSchObjectNo(objectNo) + setFloorPlanObjectNo({ floorPlanObjectNo: objectNo }) router.push('/floor-plan') } diff --git a/src/store/floorPlanObjectAtom.js b/src/store/floorPlanObjectAtom.js new file mode 100644 index 00000000..50cdccf4 --- /dev/null +++ b/src/store/floorPlanObjectAtom.js @@ -0,0 +1,9 @@ +import { atom } from 'recoil' +import { v1 } from 'uuid' +export const floorPlanObjectState = atom({ + key: `floorPlanObjectState/${v1()}`, + default: { + objectNo: '', //물건번호 + }, + dangerouslyAllowMutability: true, +}) From 7a8b575b8e5b9f52c090e775a11d4b681a12dd37 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 28 Oct 2024 14:56:36 +0900 Subject: [PATCH 4/7] refactor: canvas layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 예외 메뉴를 위한 레이아웃 분리 --- src/app/floor-plan/[mid]/[pid]/page.jsx | 3 +++ src/app/floor-plan/layout.js | 8 +++++++- src/app/floor-plan/page.jsx | 3 ++- src/components/floor-plan/CanvasFrame.jsx | 14 +++++++------- src/components/floor-plan/CanvasLayout.jsx | 8 +++++--- src/components/floor-plan/FloorPlan.jsx | 10 +++++----- src/hooks/common/useCanvasMenu.js | 10 ++++++++++ src/hooks/usePlan.js | 3 +++ 8 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 src/app/floor-plan/[mid]/[pid]/page.jsx create mode 100644 src/hooks/common/useCanvasMenu.js diff --git a/src/app/floor-plan/[mid]/[pid]/page.jsx b/src/app/floor-plan/[mid]/[pid]/page.jsx new file mode 100644 index 00000000..473897dc --- /dev/null +++ b/src/app/floor-plan/[mid]/[pid]/page.jsx @@ -0,0 +1,3 @@ +export default function EstimatePage() { + return
이자리....
+} diff --git a/src/app/floor-plan/layout.js b/src/app/floor-plan/layout.js index 829599af..782bc51e 100644 --- a/src/app/floor-plan/layout.js +++ b/src/app/floor-plan/layout.js @@ -1,11 +1,17 @@ 'use client' +import FloorPlan from '@/components/floor-plan/FloorPlan' import { FloorPlanProvider } from './FloorPlanProvider' +import CanvasLayout from '@/components/floor-plan/CanvasLayout' export default function FloorPlanLayout({ children }) { console.log('FloorPlanLayout') return ( <> - {children} + + + {children} + + ) } diff --git a/src/app/floor-plan/page.jsx b/src/app/floor-plan/page.jsx index f503099e..b38a7ef0 100644 --- a/src/app/floor-plan/page.jsx +++ b/src/app/floor-plan/page.jsx @@ -1,9 +1,10 @@ +import CanvasFrame from '@/components/floor-plan/CanvasFrame' import FloorPlan from '@/components/floor-plan/FloorPlan' export default function FloorPlanPage() { return ( <> - + ) } diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx index c2a73b63..9dfd3ac8 100644 --- a/src/components/floor-plan/CanvasFrame.jsx +++ b/src/components/floor-plan/CanvasFrame.jsx @@ -15,7 +15,7 @@ import { useCanvasConfigInitialize } from '@/hooks/common/useCanvasConfigInitial import { MENU } from '@/common/common' import PanelBatchStatistics from '@/components/floor-plan/modal/panelBatch/PanelBatchStatistics' -export default function CanvasFrame({ plan }) { +export default function CanvasFrame() { const canvasRef = useRef(null) const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState) const { canvas } = useCanvas('canvas') @@ -24,14 +24,14 @@ export default function CanvasFrame({ plan }) { const currentObject = useRecoilValue(currentObjectState) const currentMenu = useRecoilValue(currentMenuState) const { contextMenu, handleClick, handleKeyup } = useContextMenu() - const { checkCanvasObjectEvent, checkUnsavedCanvasPlan, resetModifiedPlans } = usePlan() + const { selectedPlan, checkCanvasObjectEvent, checkUnsavedCanvasPlan, resetModifiedPlans } = usePlan() useEvent() const loadCanvas = () => { if (canvas) { canvas?.clear() // 캔버스를 초기화합니다. - if (plan?.canvasStatus) { - canvas?.loadFromJSON(JSON.parse(plan.canvasStatus), function () { + if (selectedPlan?.canvasStatus) { + canvas?.loadFromJSON(JSON.parse(selectedPlan.canvasStatus), function () { canvasLoadInit() //config된 상태로 캔버스 객체를 그린다 canvas?.renderAll() // 캔버스를 다시 그립니다. }) @@ -41,15 +41,15 @@ export default function CanvasFrame({ plan }) { } useEffect(() => { - if (modifiedPlanFlag && plan?.id) { - checkCanvasObjectEvent(plan.id) + if (modifiedPlanFlag && selectedPlan?.id) { + checkCanvasObjectEvent(selectedPlan.id) } }, [modifiedPlanFlag]) useEffect(() => { loadCanvas() resetModifiedPlans() - }, [plan, canvas]) + }, [selectedPlan, canvas]) return (
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index ac247f6b..ea3292c0 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -9,9 +9,11 @@ import { usePlan } from '@/hooks/usePlan' import { modifiedPlansState } from '@/store/canvasAtom' import { globalLocaleStore } from '@/store/localeAtom' import { SessionContext } from '@/app/SessionProvider' +import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' -export default function CanvasLayout(props) { - const { menuNumber } = props +export default function CanvasLayout({ children }) { + // const { menuNumber } = props + const { menuNumber } = useCanvasMenu() const { session } = useContext(SessionContext) const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요 const [modifiedPlans, setModifiedPlans] = useRecoilState(modifiedPlansState) // 변경된 canvas plan @@ -60,7 +62,7 @@ export default function CanvasLayout(props) { )}
- plan.isCurrent === true)} /> + {children} ) } diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index bc95d9b3..caf9a2d7 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -7,16 +7,18 @@ import { globalLocaleStore } from '@/store/localeAtom' import { settingModalFirstOptionsState, settingModalSecondOptionsState } from '@/store/settingAtom' import CanvasMenu from '@/components/floor-plan/CanvasMenu' import CanvasLayout from '@/components/floor-plan/CanvasLayout' +import { useCanvasMenu } from '@/hooks/common/useCanvasMenu' import '@/styles/contents.scss' -export default function FloorPlan() { +export default function FloorPlan({ children }) { const globalLocaleState = useRecoilValue(globalLocaleStore) const { get } = useAxios(globalLocaleState) const [settingModalFirstOptions, setSettingModalFirstOptions] = useRecoilState(settingModalFirstOptionsState) const [settingModalSecondOptions, setSettingModalSecondOptions] = useRecoilState(settingModalSecondOptionsState) const [objectNo, setObjectNo] = useState('test123240912001') // 이후 삭제 필요 - const [menuNumber, setMenuNumber] = useState(null) + // const [menuNumber, setMenuNumber] = useState(null) + const { menuNumber, setMenuNumber } = useCanvasMenu() const modalProps = { menuNumber, @@ -57,9 +59,7 @@ export default function FloorPlan() { <>
-
- -
+
{children}
) diff --git a/src/hooks/common/useCanvasMenu.js b/src/hooks/common/useCanvasMenu.js new file mode 100644 index 00000000..23f594d9 --- /dev/null +++ b/src/hooks/common/useCanvasMenu.js @@ -0,0 +1,10 @@ +import { useState } from 'react' + +export const useCanvasMenu = () => { + const [menuNumber, setMenuNumber] = useState(null) + + return { + menuNumber, + setMenuNumber, + } +} diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index 4c655e86..1cced0f0 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -8,6 +8,7 @@ import { useSwal } from '@/hooks/useSwal' export function usePlan() { const [planNum, setPlanNum] = useState(0) + const [selectedPlan, setSelectedPlan] = useState(null) const [canvas, setCanvas] = useRecoilState(canvasState) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) @@ -279,6 +280,7 @@ export function usePlan() { } useEffect(() => { setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) + setSelectedPlan(plans.find((plan) => plan.isCurrent)) }, [plans]) /** @@ -366,6 +368,7 @@ export function usePlan() { return { canvas, plans, + selectedPlan, modifiedPlans, checkCanvasObjectEvent, resetModifiedPlans, From b71afc04925648d9321209ff8b7ad67eecf3a540 Mon Sep 17 00:00:00 2001 From: "hyojun.choi" Date: Mon, 28 Oct 2024 14:56:51 +0900 Subject: [PATCH 5/7] =?UTF-8?q?lengthText=20=EC=83=9D=EC=84=B1=20=EC=8B=9C?= =?UTF-8?q?=20=EA=B8=80=EA=BC=B4=20=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80?= 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 | 2 +- src/hooks/useCanvasEvent.js | 15 +++++++++------ 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/components/fabric/QLine.js b/src/components/fabric/QLine.js index 37c9a75f..4ee9535a 100644 --- a/src/components/fabric/QLine.js +++ b/src/components/fabric/QLine.js @@ -152,7 +152,7 @@ export const QLine = fabric.util.createClass(fabric.Line, { getLength() { //10배 곱해진 값 return - return Number(this.length.toFixed(2) * 10) + return Number(this.length.toFixed(1)) * 10 }, setViewLengthText(bool) { diff --git a/src/components/fabric/QPolygon.js b/src/components/fabric/QPolygon.js index 31076b69..8068a772 100644 --- a/src/components/fabric/QPolygon.js +++ b/src/components/fabric/QPolygon.js @@ -183,7 +183,7 @@ export const QPolygon = fabric.util.createClass(fabric.Polygon, { const end = points[(i + 1) % points.length] const dx = end.x - start.x const dy = end.y - start.y - const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(2)) * 10 + const length = Number(Math.sqrt(dx * dx + dy * dy).toFixed(1)) * 10 let midPoint diff --git a/src/hooks/useCanvasEvent.js b/src/hooks/useCanvasEvent.js index 0df650c0..ab283a08 100644 --- a/src/hooks/useCanvasEvent.js +++ b/src/hooks/useCanvasEvent.js @@ -11,6 +11,7 @@ import { modifiedPlanFlagState, } from '@/store/canvasAtom' import { QPolygon } from '@/components/fabric/QPolygon' +import { fontSelector } from '@/store/fontAtom' // 캔버스에 필요한 이벤트 export function useCanvasEvent() { @@ -22,6 +23,7 @@ export function useCanvasEvent() { const fontFamily = useRecoilValue(fontFamilyState) const [canvasZoom, setCanvasZoom] = useRecoilState(canvasZoomState) const [modifiedPlanFlag, setModifiedPlanFlag] = useRecoilState(modifiedPlanFlagState) + const lengthTextOption = useRecoilValue(fontSelector('lengthText')) // 기본적인 이벤트 필요시 추가 const attachDefaultEventOnCanvas = () => { @@ -108,16 +110,17 @@ export function useCanvasEvent() { }) } - if (target.type.toLowerCase().includes('text')) { - target.set({ fontSize }) - target.set({ fontFamily }) - } - - if (target.name === 'lengthText') { + if (target.name === 'lengthText' && target.type.toLowerCase().includes('text') > 0) { const x = target.left const y = target.top target.lockMovementX = false target.lockMovementY = false + + target.fill = lengthTextOption.fontColor.value + target.fontFamily = lengthTextOption.fontFamily.value + target.fontSize = lengthTextOption.fontSize.value + target.fontWeight = lengthTextOption.fontWeight.value + // Add a property to store the previous value const previousValue = target.text target.on('selected', (e) => { From d65f27c036304c6037cd1e8714dbc552e87cd0de Mon Sep 17 00:00:00 2001 From: basssy Date: Mon, 28 Oct 2024 15:19:25 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=EB=AC=BC=EA=B1=B4=ED=98=84=ED=99=A9=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C=20=EA=B2=AC=EC=A0=81?= =?UTF-8?q?=EC=84=9C=EB=A1=9C=20=EC=9D=B4=EB=8F=99.=20=EA=B2=AC=EC=A0=81?= =?UTF-8?q?=EC=84=9C=20=ED=99=94=EB=A9=B4=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/floor-plan/[mid]/[pid]/page.jsx | 8 +- src/components/estimate/Estimate.jsx | 307 +++++++++++++++++++ src/components/management/StuffDetail.jsx | 7 +- src/components/management/StuffPlanQGrid.jsx | 4 +- src/locales/ja.json | 26 +- src/locales/ko.json | 26 +- 6 files changed, 372 insertions(+), 6 deletions(-) create mode 100644 src/components/estimate/Estimate.jsx diff --git a/src/app/floor-plan/[mid]/[pid]/page.jsx b/src/app/floor-plan/[mid]/[pid]/page.jsx index 473897dc..80eae575 100644 --- a/src/app/floor-plan/[mid]/[pid]/page.jsx +++ b/src/app/floor-plan/[mid]/[pid]/page.jsx @@ -1,3 +1,9 @@ +import Estimate from '@/components/estimate/Estimate' + export default function EstimatePage() { - return
이자리....
+ return ( + <> + + + ) } diff --git a/src/components/estimate/Estimate.jsx b/src/components/estimate/Estimate.jsx new file mode 100644 index 00000000..e1a453fe --- /dev/null +++ b/src/components/estimate/Estimate.jsx @@ -0,0 +1,307 @@ +'use client' +import { useEffect, useState } from 'react' +import { useMessage } from '@/hooks/useMessage' +import SingleDatePicker from '../common/datepicker/SingleDatePicker' +import { useRecoilValue } from 'recoil' +import { floorPlanObjectState } from '@/store/floorPlanObjectAtom' + +export default function Estimate() { + const { getMessage } = useMessage() + const objectRecoil = useRecoilValue(floorPlanObjectState) + console.log('견적서화면이군요', objectRecoil.floorPlanObjectNo) + return ( +
+
+ {/* 물건번호, 견적서번호, 등록일, 변경일시 시작 */} +
+
+
+
+
{getMessage('estimate.detail.objectNo')}
+
RX524231020006 (Plan No: 1)
+
+
+
{getMessage('estimate.detail.estimateNo')}
+
5242310200065242
+
+
+
{getMessage('estimate.detail.createDatetime')}
+
9999.09.28
+
+
+
{getMessage('estimate.detail.lastEditDatetime')}
+
9999.09.28 06:36
+
+
+
+
+ {/* 물건번호, 견적서번호, 등록일, 변경일시 끝 */} + {/* 기본정보 시작 */} +
+
+
+
+

{getMessage('estimate.detail.header.title')}

+
+
+
+ + + + + + + + + + {/* 1차 판매점명 */} + + + {/* 견적일 */} + + + + + {/* 2차 판매점명 */} + + + {/* 담당자 */} + + + + + {/* 안건명 */} + + + + + {/* 메모 */} + + + + + {/* 주문분류 */} + + + + + {/* 지붕재・사양시공 최대4개*/} + + + + + {/* 비고 */} + + + + +
{getMessage('estimate.detail.saleStoreId')} + {getMessage('estimate.detail.estimateDate')} * + +
+ +
+
{getMessage('estimate.detail.otherSaleStoreId')} + {getMessage('estimate.detail.receiveUser')} * + +
+ +
+
+ {getMessage('estimate.detail.title')} * + +
+
+ +
+
+ +
+
+
{getMessage('estimate.detail.remarks')}물건정보에서 입력한 메모 표시
+ 注文分類/주문분류 * + +
+
屋根材・仕様施工 / 지붕재・사양시공 +
+
+ +
+
+ +
+
+
+
+ {/* 마지막div엔 mb5 제외 */} +
+
備考 /비고 +
+ +
+
+
+ {/* 파일첨부 시작 */} +
+
+

{getMessage('estimate.detail.header.fileList1')}

+
+ + +
+
+
+
+ + + + + + + + + + + +
{getMessage('estimate.detail.header.fileList1')} +
+
+ +
+
+

Drag file here

+
    +
    +
    +
    +
    + {/* 첨부파일 목록 시작 */} +
    + + + + + + + + + + +
    {getMessage('estimate.detail.header.fileList2')}
    +
    + {/* 첨부파일 목록 끝 */} + {/* 파일첨부 끝 */} + {/* 견적특이사항 시작 */} +
    +
    +

    {getMessage('estimate.detail.header.specialEstimate')}

    +
    {getMessage('estimate.detail.header.specialEstimateProductInfo')}
    +
    +
    + {/* 공통코드영역시작 */} +
    + {/* 공통코드영역끝 */} + {/* 견적특이사항 내용영역시작 */} +
    + {/* 견적특이사항 내용영역끝 */} + {/* 견적특이사항 끝 */} + {/* 제품정보 시작 */} +
    +
    +

    {getMessage('estimate.detail.header.specialEstimateProductInfo')}

    +
    +
    +
    +
    +
    +
    수량 (PCS)
    +
    74
    +
    +
    +
    용량 (Kw)
    +
    8300
    +
    +
    +
    공급가액
    +
    6,798,900
    +
    +
    +
    부가세 (10%)
    +
    679,890
    +
    +
    +
    총액
    +
    7,478,790
    +
    +
    +
    + {/* YJOD면 아래영역 숨김 */} +
    + + + + + + + + + + + + + + + + + + + +
    + {getMessage('estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice')} + * + +
    + +
    +
    {getMessage('estimate.detail.sepcialEstimateProductInfo.pkgWeight')}(모듈수량 * 수량) / 100){getMessage('estimate.detail.sepcialEstimateProductInfo.pkgPrice')}PKG단가(W) * PKG용량(W)
    +
    + {/* 제품정보 끝 */} + {/* 가격표시영역시작 */} +
    +
    +
    {getMessage('estimate.detail.header.showPrice')}
    +
    + +
    +
    +
    +
    + + {getMessage('estimate.detail.showPrice.description')} +
    +
    +
    + + +
    +
    +
    + {/* 가격표시영역끝 */} + {/* html테이블시작 */} +
    + {/* html테이블끝 */} +
    +
    + {/* 기본정보끝 */} +
    +
    + ) +} diff --git a/src/components/management/StuffDetail.jsx b/src/components/management/StuffDetail.jsx index e8104548..9960fb1f 100644 --- a/src/components/management/StuffDetail.jsx +++ b/src/components/management/StuffDetail.jsx @@ -257,7 +257,9 @@ export default function StuffDetail() { type="button" className="grid-btn" onClick={() => { - console.log('견적서조회버튼클릭') + //mid:5(견적서), /pid:플랜번호 + setFloorPlanObjectNo({ floorPlanObjectNo: params.data.objectNo }) + router.push(`/floor-plan/5/${params.data.planNo}`) }} > @@ -270,7 +272,8 @@ export default function StuffDetail() { console.log('엑셀버튼클릭') }} > - Excel + + {getMessage('stuff.detail.planGrid.btn2')} diff --git a/src/components/management/StuffPlanQGrid.jsx b/src/components/management/StuffPlanQGrid.jsx index 1c8b88ba..c1e2c605 100644 --- a/src/components/management/StuffPlanQGrid.jsx +++ b/src/components/management/StuffPlanQGrid.jsx @@ -1,4 +1,5 @@ import { useState, useMemo, useCallback, useEffect } from 'react' +import { useMessage } from '@/hooks/useMessage' import { AgGridReact } from 'ag-grid-react' import 'ag-grid-community/styles/ag-grid.css' import 'ag-grid-community/styles/ag-theme-quartz.css' @@ -8,7 +9,7 @@ export default function StuffPlanQGrid(props) { const [rowData, setRowData] = useState(null) // const [gridApi, setGridApi] = useState(null) const [colDefs, setColDefs] = useState(planGridColumns) - + const { getMessage } = useMessage() const defaultColDef = useMemo(() => { return { flex: 1, @@ -46,6 +47,7 @@ export default function StuffPlanQGrid(props) { pagination={isPageable} domLayout="autoHeight" suppressCellFocus={true} + overlayNoRowsTemplate={`${getMessage('stuff.grid.noData')}`} /> ) diff --git a/src/locales/ja.json b/src/locales/ja.json index 97e20595..8c6d1208 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -707,5 +707,29 @@ "surface.shape.validate.size.1to23": "①길이는 ②+③보다 큰 값을 넣어주세요.", "surface.shape.validate.size.2to3": "②길이는 ③보다 큰 값을 넣어주세요.", "surface.shape.validate.size.3to4": "③길이는 ④보다 큰 값을 넣어주세요.", - "surface.shape.validate.size.4to5": "④길이는 ⑤보다 큰 값을 넣어주세요." + "surface.shape.validate.size.4to5": "④길이는 ⑤보다 큰 값을 넣어주세요.", + "estimate.detail.header.title": "基本情報", + "estimate.detail.objectNo": "品番", + "estimate.detail.estimateNo": "見積書番号", + "estimate.detail.createDatetime": "登録日", + "estimate.detail.lastEditDatetime": "変更日時", + "estimate.detail.saleStoreId": "一次販売店名", + "estimate.detail.estimateDate": "見積日", + "estimate.detail.otherSaleStoreId": "二次販売店名", + "estimate.detail.receiveUser": "担当者 ", + "estimate.detail.title": "案件名", + "estimate.detail.remarks": "メモ", + "estimate.detail.header.fileList1": "ファイル添付", + "estimate.detail.fileList.btn": "ファイル選択", + "estimate.detail.header.fileList2": "添付ファイル一覧", + "estimate.detail.header.specialEstimate": "見積もりの具体的な", + "estimate.detail.header.specialEstimateProductInfo": "製品情報", + "estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "住宅PKG単価 (W)", + "estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG容量 (Kw)", + "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG金額", + "estimate.detail.header.showPrice": "価格表示", + "estimate.detail.showPrice.btn1": "Pricing", + "estimate.detail.showPrice.description": "クリックして製品の特異性を確認する", + "estimate.detail.showPrice.btn2": "製品を追加", + "estimate.detail.showPrice.btn3": "製品削除" } diff --git a/src/locales/ko.json b/src/locales/ko.json index cc47a03d..cecdf4af 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -712,5 +712,29 @@ "surface.shape.validate.size.1to23": "①길이는 ②+③보다 큰 값을 넣어주세요.", "surface.shape.validate.size.2to3": "②길이는 ③보다 큰 값을 넣어주세요.", "surface.shape.validate.size.3to4": "③길이는 ④보다 큰 값을 넣어주세요.", - "surface.shape.validate.size.4to5": "④길이는 ⑤보다 큰 값을 넣어주세요." + "surface.shape.validate.size.4to5": "④길이는 ⑤보다 큰 값을 넣어주세요.", + "estimate.detail.header.title": "기본정보", + "estimate.detail.objectNo": "물건번호", + "estimate.detail.estimateNo": "견적서 번호", + "estimate.detail.createDatetime": "등록일", + "estimate.detail.lastEditDatetime": "변경일시", + "estimate.detail.saleStoreId": "1차 판매점명", + "estimate.detail.estimateDate": "견적일", + "estimate.detail.otherSaleStoreId": "2차 판매점명", + "estimate.detail.receiveUser": "담당자", + "estimate.detail.title": "안건명", + "estimate.detail.remarks": "메모", + "estimate.detail.header.fileList1": "파일첨부", + "estimate.detail.fileList.btn": "파일선택", + "estimate.detail.header.fileList2": "첨부파일 목록", + "estimate.detail.header.specialEstimate": "견적특이사항", + "estimate.detail.header.specialEstimateProductInfo": "제품정보", + "estimate.detail.sepcialEstimateProductInfo.pkgUnitPrice": "주택PKG단가 (W)", + "estimate.detail.sepcialEstimateProductInfo.pkgWeight": "PKG 용량 (Kw)", + "estimate.detail.sepcialEstimateProductInfo.pkgPrice": "PKG 금액", + "estimate.detail.header.showPrice": "가격표시", + "estimate.detail.showPrice.btn1": "Pricing", + "estimate.detail.showPrice.description": "클릭하여 제품 특이사항 확인", + "estimate.detail.showPrice.btn2": "제품추가", + "estimate.detail.showPrice.btn3": "제품삭제" } From caa642b65b35090f1542dc2516f614b5fed73feb Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Mon, 28 Oct 2024 15:48:52 +0900 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20menuNumber=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/FloorPlan.jsx | 5 ++++- src/hooks/common/useCanvasMenu.js | 5 +++-- src/store/menuAtom.js | 6 ++++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100644 src/store/menuAtom.js diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx index caf9a2d7..adee1b60 100644 --- a/src/components/floor-plan/FloorPlan.jsx +++ b/src/components/floor-plan/FloorPlan.jsx @@ -25,10 +25,13 @@ export default function FloorPlan({ children }) { setMenuNumber, } useEffect(() => { - console.log('FloorPlan useEffect 실행') fetchSettings() }, [objectNo]) + useEffect(() => { + setMenuNumber(1) + }, []) + // Canvas Setting 조회 const fetchSettings = async () => { try { diff --git a/src/hooks/common/useCanvasMenu.js b/src/hooks/common/useCanvasMenu.js index 23f594d9..f8758e3e 100644 --- a/src/hooks/common/useCanvasMenu.js +++ b/src/hooks/common/useCanvasMenu.js @@ -1,7 +1,8 @@ -import { useState } from 'react' +import { menuNumberState } from '@/store/menuAtom' +import { useRecoilState } from 'recoil' export const useCanvasMenu = () => { - const [menuNumber, setMenuNumber] = useState(null) + const [menuNumber, setMenuNumber] = useRecoilState(menuNumberState) return { menuNumber, diff --git a/src/store/menuAtom.js b/src/store/menuAtom.js new file mode 100644 index 00000000..b86ecbd0 --- /dev/null +++ b/src/store/menuAtom.js @@ -0,0 +1,6 @@ +import { atom } from 'recoil' + +export const menuNumberState = atom({ + key: 'menuNumberState', + default: null, +})