From 5f4b1785069fea8bb7fea08226e373b864136823 Mon Sep 17 00:00:00 2001 From: Daseul Kim Date: Mon, 7 Oct 2024 14:30:03 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20canvas=20plan=EC=9D=98=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=EB=90=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=82=AC=ED=95=AD=EC=9D=84=20=ED=99=95=EC=9D=B8?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TODO: 신규 canvas plan 저장 시 데이터 동기화 필요 --- src/components/floor-plan/CanvasLayout.jsx | 73 +++++++++++++++------- src/hooks/usePlan.js | 33 ++++++++-- 2 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx index 3abebd85..98f5f36d 100644 --- a/src/components/floor-plan/CanvasLayout.jsx +++ b/src/components/floor-plan/CanvasLayout.jsx @@ -12,7 +12,7 @@ import { sessionStore } from '@/store/commonAtom' export default function CanvasLayout() { const [objectNo, setObjectNo] = useState('test123240822001') // 이후 삭제 필요 - const [addCanvasPlans, setAddCanvasPlans] = useState([]) + const [plans, setPlans] = useState([]) const [planNum, setPlanNum] = useState(0) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) @@ -21,25 +21,54 @@ export default function CanvasLayout() { const { getMessage } = useMessage() const { swalFire } = useSwal() - const { getCanvasByObjectNo, delCanvasById } = usePlan() + const { getCanvasByObjectNo, delCanvasById, checkModifiedCanvasPlan, saveCanvas } = usePlan() const handleCurrentPlan = (newCurrentId) => { + // console.log('currentPlan newCurrentId: ', 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 } - }), - ) + if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) { + swalFire({ + html: getMessage('common.message.confirm.save') + `
${currentCanvasPlan.name}`, + type: 'confirm', + confirmFn: async () => { + saveCanvas(sessionState.userId) + /** + * TODO: 신규 canvas plan 저장 시 id, name 등 데이터 동기화 필요 (40~51Line) + */ + initCanvasPlans.map((initPlan) => { + if ('isNew' in initPlan) { + // console.log('================ isNew initPlan: ', initPlan) + setPlans((plans) => + plans.map((plan) => { + initPlan.isNew === plan.id + ? { ...plan, id: initPlan.id, name: initPlan.name, canvasStatus: initPlan.canvasStatus, isCurrent: plan.id === newCurrentId } + : { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + } + }) + }, + denyFn: () => { + setPlans((plans) => + plans.map((plan) => { + return { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + }, + }) + } else { + setPlans((plans) => + plans.map((plan) => { + return { ...plan, isCurrent: plan.id === newCurrentId } + }), + ) + } } } useEffect(() => { - setCurrentCanvasPlan([...initCanvasPlans, ...addCanvasPlans].find((plan) => plan.isCurrent) || null) - }, [initCanvasPlans, addCanvasPlans]) + setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null) + }, [plans]) const handleDeletePlan = (e, id) => { e.stopPropagation() // 이벤트 버블링 방지 @@ -48,20 +77,21 @@ export default function CanvasLayout() { delCanvasById(id) .then((res) => { swalFire({ text: getMessage('common.message.delete') }) - console.log('[DELETE] canvas-statuses res :::::::: %o', res) + // console.log('[DELETE] canvas-statuses res :::::::: %o', res) setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id)) + setPlans((plans) => plans.filter((plan) => plan.id !== id)) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) - console.error('[DELETE] canvas-statuses res error :::::::: %o', error) + // console.error('[DELETE] canvas-statuses res error :::::::: %o', error) }) } else { - setAddCanvasPlans(addCanvasPlans.filter((plan) => plan.id !== id)) + setPlans(plans.filter((plan) => plan.id !== id)) swalFire({ text: getMessage('common.message.delete') }) } // 삭제 후 last 데이터에 포커싱 - const lastPlan = [...initCanvasPlans, ...addCanvasPlans].filter((plan) => plan.id !== id).at(-1) + const lastPlan = plans.filter((plan) => plan.id !== id).at(-1) if (!lastPlan) { setPlanNum(0) setCurrentCanvasPlan(null) @@ -71,7 +101,7 @@ export default function CanvasLayout() { } const addNewPlan = () => { - setAddCanvasPlans([...addCanvasPlans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }]) + setPlans([...plans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }]) handleCurrentPlan(planNum) setPlanNum(planNum + 1) } @@ -81,6 +111,7 @@ export default function CanvasLayout() { console.log('canvas 목록 ', res) if (res.length > 0) { setInitCanvasPlans(res) + setPlans(res) handleCurrentPlan(res.at(-1).id) // last 데이터에 포커싱 setPlanNum(res.length) } else { @@ -93,7 +124,7 @@ export default function CanvasLayout() {
- {[...initCanvasPlans, ...addCanvasPlans].map((plan) => ( + {plans.map((plan) => (
- plan.isCurrent === true)} /> + plan.isCurrent === true)} />
) } diff --git a/src/hooks/usePlan.js b/src/hooks/usePlan.js index c719ba24..e861f9f8 100644 --- a/src/hooks/usePlan.js +++ b/src/hooks/usePlan.js @@ -6,7 +6,7 @@ import { useSwal } from '@/hooks/useSwal' export function usePlan() { const [canvas, setCanvas] = useRecoilState(canvasState) - const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) + const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const { swalFire } = useSwal() const { getMessage } = useMessage() @@ -70,6 +70,24 @@ export function usePlan() { // }, 1000) } + /** + * 실시간 캔버스 상태와 DB에 저장된 캔버스 상태를 비교하여 수정 여부를 판단 + */ + const checkModifiedCanvasPlan = () => { + removeMouseLines() + const canvasStr = addCanvas() + const canvasStatus = dbToCanvasFormat(canvasToDbFormat(canvasStr)) + if (JSON.parse(canvasStr).objects.length === 0 && currentCanvasPlan.canvasStatus === undefined) { + // 빈 캔버스 + return false + } else if (canvasStatus === currentCanvasPlan.canvasStatus) { + // 변경사항 없는 캔버스 + return false + } else { + return true + } + } + /** * DB에 저장된 데이터를 canvas에서 사용할 수 있도록 포맷화 */ @@ -106,14 +124,14 @@ export function usePlan() { await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { swalFire({ text: getMessage('common.message.save') }) - console.log('[PUT] canvas-statuses res :::::::: %o', res) + // console.log('[PUT] canvas-statuses res :::::::: %o', res) setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)), ) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) - console.error('[PUT] canvas-statuses error :::::::: %o', error) + // console.error('[PUT] canvas-statuses error :::::::: %o', error) }) } else { // canvas 신규 등록 @@ -127,11 +145,15 @@ export function usePlan() { await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) .then((res) => { swalFire({ text: getMessage('common.message.save') }) - console.log('[POST] canvas-statuses response :::::::: %o', res) + setInitCanvasPlans([ + ...initCanvasPlans, + { id: res.data, name: currentCanvasPlan.objectNo + '-' + res.data, userId: userId, canvasStatus: canvasStatus, isNew: currentCanvasPlan.id }, + ]) + // console.log('[POST] canvas-statuses response :::::::: %o', res) }) .catch((error) => { swalFire({ text: error.message, icon: 'error' }) - console.error('[POST] canvas-statuses res error :::::::: %o', error) + // console.error('[POST] canvas-statuses res error :::::::: %o', error) }) } } @@ -170,6 +192,7 @@ export function usePlan() { removeMouseLines, saveCanvas, addCanvas, + checkModifiedCanvasPlan, getCanvasByObjectNo, delCanvasById, }