feat: canvas plan의 저장되지 않은 변경사항을 확인하는 로직 추가

TODO: 신규 canvas plan 저장 시 데이터 동기화 필요
This commit is contained in:
Daseul Kim 2024-10-07 14:30:03 +09:00
parent 7fd9ded5f8
commit 5f4b178506
2 changed files with 80 additions and 26 deletions

View File

@ -12,7 +12,7 @@ import { sessionStore } from '@/store/commonAtom'
export default function CanvasLayout() { export default function CanvasLayout() {
const [objectNo, setObjectNo] = useState('test123240822001') // const [objectNo, setObjectNo] = useState('test123240822001') //
const [addCanvasPlans, setAddCanvasPlans] = useState([]) const [plans, setPlans] = useState([])
const [planNum, setPlanNum] = useState(0) const [planNum, setPlanNum] = useState(0)
const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState)
@ -21,25 +21,54 @@ export default function CanvasLayout() {
const { getMessage } = useMessage() const { getMessage } = useMessage()
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { getCanvasByObjectNo, delCanvasById } = usePlan() const { getCanvasByObjectNo, delCanvasById, checkModifiedCanvasPlan, saveCanvas } = usePlan()
const handleCurrentPlan = (newCurrentId) => { const handleCurrentPlan = (newCurrentId) => {
// console.log('currentPlan newCurrentId: ', newCurrentId)
if (!currentCanvasPlan?.id || currentCanvasPlan.id !== newCurrentId) { if (!currentCanvasPlan?.id || currentCanvasPlan.id !== newCurrentId) {
setInitCanvasPlans((plans) => if (currentCanvasPlan?.id && checkModifiedCanvasPlan()) {
plans.map((plan) => { swalFire({
return { ...plan, isCurrent: plan.id === newCurrentId } html: getMessage('common.message.confirm.save') + `</br>${currentCanvasPlan.name}`,
}), type: 'confirm',
) confirmFn: async () => {
setAddCanvasPlans((plans) => saveCanvas(sessionState.userId)
plans.map((plan) => { /**
return { ...plan, isCurrent: plan.id === newCurrentId } * 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(() => { useEffect(() => {
setCurrentCanvasPlan([...initCanvasPlans, ...addCanvasPlans].find((plan) => plan.isCurrent) || null) setCurrentCanvasPlan(plans.find((plan) => plan.isCurrent) || null)
}, [initCanvasPlans, addCanvasPlans]) }, [plans])
const handleDeletePlan = (e, id) => { const handleDeletePlan = (e, id) => {
e.stopPropagation() // e.stopPropagation() //
@ -48,20 +77,21 @@ export default function CanvasLayout() {
delCanvasById(id) delCanvasById(id)
.then((res) => { .then((res) => {
swalFire({ text: getMessage('common.message.delete') }) 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)) setInitCanvasPlans((initCanvasPlans) => initCanvasPlans.filter((plan) => plan.id !== id))
setPlans((plans) => plans.filter((plan) => plan.id !== id))
}) })
.catch((error) => { .catch((error) => {
swalFire({ text: error.message, icon: '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 { } else {
setAddCanvasPlans(addCanvasPlans.filter((plan) => plan.id !== id)) setPlans(plans.filter((plan) => plan.id !== id))
swalFire({ text: getMessage('common.message.delete') }) swalFire({ text: getMessage('common.message.delete') })
} }
// last // last
const lastPlan = [...initCanvasPlans, ...addCanvasPlans].filter((plan) => plan.id !== id).at(-1) const lastPlan = plans.filter((plan) => plan.id !== id).at(-1)
if (!lastPlan) { if (!lastPlan) {
setPlanNum(0) setPlanNum(0)
setCurrentCanvasPlan(null) setCurrentCanvasPlan(null)
@ -71,7 +101,7 @@ export default function CanvasLayout() {
} }
const addNewPlan = () => { const addNewPlan = () => {
setAddCanvasPlans([...addCanvasPlans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }]) setPlans([...plans, { id: planNum, name: `Plan ${planNum + 1}`, objectNo: `${objectNo}` }])
handleCurrentPlan(planNum) handleCurrentPlan(planNum)
setPlanNum(planNum + 1) setPlanNum(planNum + 1)
} }
@ -81,6 +111,7 @@ export default function CanvasLayout() {
console.log('canvas 목록 ', res) console.log('canvas 목록 ', res)
if (res.length > 0) { if (res.length > 0) {
setInitCanvasPlans(res) setInitCanvasPlans(res)
setPlans(res)
handleCurrentPlan(res.at(-1).id) // last handleCurrentPlan(res.at(-1).id) // last
setPlanNum(res.length) setPlanNum(res.length)
} else { } else {
@ -93,7 +124,7 @@ export default function CanvasLayout() {
<div className="canvas-layout"> <div className="canvas-layout">
<div className="canvas-page-list"> <div className="canvas-page-list">
<div className="canvas-plane-wrap"> <div className="canvas-plane-wrap">
{[...initCanvasPlans, ...addCanvasPlans].map((plan) => ( {plans.map((plan) => (
<button key={plan.id} className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`} onClick={() => handleCurrentPlan(plan.id)}> <button key={plan.id} className={`canvas-page-box ${plan.isCurrent === true ? 'on' : ''}`} onClick={() => handleCurrentPlan(plan.id)}>
<span>{plan.name}</span> <span>{plan.name}</span>
<i <i
@ -115,7 +146,7 @@ export default function CanvasLayout() {
<span></span> <span></span>
</button> </button>
</div> </div>
<CanvasFrame plan={[...initCanvasPlans, ...addCanvasPlans].find((plan) => plan.isCurrent === true)} /> <CanvasFrame plan={plans.find((plan) => plan.isCurrent === true)} />
</div> </div>
) )
} }

View File

@ -6,7 +6,7 @@ import { useSwal } from '@/hooks/useSwal'
export function usePlan() { export function usePlan() {
const [canvas, setCanvas] = useRecoilState(canvasState) const [canvas, setCanvas] = useRecoilState(canvasState)
const [currentCanvasPlan, setcurrentCanvasPlan] = useRecoilState(currentCanvasPlanState) const [currentCanvasPlan, setCurrentCanvasPlan] = useRecoilState(currentCanvasPlanState)
const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState) const [initCanvasPlans, setInitCanvasPlans] = useRecoilState(initCanvasPlansState)
const { swalFire } = useSwal() const { swalFire } = useSwal()
const { getMessage } = useMessage() const { getMessage } = useMessage()
@ -70,6 +70,24 @@ export function usePlan() {
// }, 1000) // }, 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에서 사용할 있도록 포맷화 * DB에 저장된 데이터를 canvas에서 사용할 있도록 포맷화
*/ */
@ -106,14 +124,14 @@ export function usePlan() {
await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData }) await promisePut({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => { .then((res) => {
swalFire({ text: getMessage('common.message.save') }) swalFire({ text: getMessage('common.message.save') })
console.log('[PUT] canvas-statuses res :::::::: %o', res) // console.log('[PUT] canvas-statuses res :::::::: %o', res)
setInitCanvasPlans((initCanvasPlans) => setInitCanvasPlans((initCanvasPlans) =>
initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)), initCanvasPlans.map((plan) => (plan.id === currentCanvasPlan.id ? { ...plan, canvasStatus: canvasStatus } : plan)),
) )
}) })
.catch((error) => { .catch((error) => {
swalFire({ text: error.message, icon: 'error' }) swalFire({ text: error.message, icon: 'error' })
console.error('[PUT] canvas-statuses error :::::::: %o', error) // console.error('[PUT] canvas-statuses error :::::::: %o', error)
}) })
} else { } else {
// canvas 신규 등록 // canvas 신규 등록
@ -127,11 +145,15 @@ export function usePlan() {
await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData }) await promisePost({ url: '/api/canvas-management/canvas-statuses', data: planData })
.then((res) => { .then((res) => {
swalFire({ text: getMessage('common.message.save') }) 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) => { .catch((error) => {
swalFire({ text: error.message, icon: '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, removeMouseLines,
saveCanvas, saveCanvas,
addCanvas, addCanvas,
checkModifiedCanvasPlan,
getCanvasByObjectNo, getCanvasByObjectNo,
delCanvasById, delCanvasById,
} }