미저장 변경 이탈 확인 추가
This commit is contained in:
100
composables/useAdminUnsavedChangesGuard.js
Normal file
100
composables/useAdminUnsavedChangesGuard.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* 관리자 편집 화면의 미저장 변경 이탈을 막는다.
|
||||
* @param {import('vue').Ref<boolean> | import('vue').ComputedRef<boolean>} isDirty - 변경 여부
|
||||
* @param {{ onLeaveConfirmed?: () => void | Promise<void> }} options - 이탈 승인 옵션
|
||||
* @returns {{
|
||||
* isUnsavedModalOpen: import('vue').Ref<boolean>,
|
||||
* stayOnUnsavedPage: () => void,
|
||||
* leaveUnsavedPage: () => Promise<void>,
|
||||
* allowNextRouteLeave: () => void
|
||||
* }} 이탈 확인 상태와 동작
|
||||
*/
|
||||
export const useAdminUnsavedChangesGuard = (isDirty, options = {}) => {
|
||||
const isUnsavedModalOpen = ref(false)
|
||||
const pendingRoute = ref(null)
|
||||
const isNextRouteAllowed = ref(false)
|
||||
|
||||
/**
|
||||
* 현재 이탈을 막아야 하는지 확인한다.
|
||||
* @returns {boolean} 이탈 차단 여부
|
||||
*/
|
||||
const shouldBlockLeave = () => Boolean(unref(isDirty)) && !isNextRouteAllowed.value
|
||||
|
||||
/**
|
||||
* 다음 라우트 이동을 한 번 허용한다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const allowNextRouteLeave = () => {
|
||||
isNextRouteAllowed.value = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 페이지에 머문다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const stayOnUnsavedPage = () => {
|
||||
pendingRoute.value = null
|
||||
isUnsavedModalOpen.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 미저장 변경을 버리고 이동한다.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const leaveUnsavedPage = async () => {
|
||||
const route = pendingRoute.value
|
||||
pendingRoute.value = null
|
||||
isUnsavedModalOpen.value = false
|
||||
isNextRouteAllowed.value = true
|
||||
|
||||
await options.onLeaveConfirmed?.()
|
||||
|
||||
if (route?.fullPath) {
|
||||
await navigateTo(route.fullPath)
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeRouteLeave((to) => {
|
||||
if (isNextRouteAllowed.value) {
|
||||
isNextRouteAllowed.value = false
|
||||
return true
|
||||
}
|
||||
|
||||
if (!shouldBlockLeave()) {
|
||||
return true
|
||||
}
|
||||
|
||||
pendingRoute.value = to
|
||||
isUnsavedModalOpen.value = true
|
||||
return false
|
||||
})
|
||||
|
||||
/**
|
||||
* 브라우저 탭 닫기와 새로고침을 기본 확인창으로 막는다.
|
||||
* @param {BeforeUnloadEvent} event - 브라우저 이탈 이벤트
|
||||
* @returns {void}
|
||||
*/
|
||||
const handleBeforeUnload = (event) => {
|
||||
if (!shouldBlockLeave()) {
|
||||
return
|
||||
}
|
||||
|
||||
event.preventDefault()
|
||||
event.returnValue = ''
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
window.addEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('beforeunload', handleBeforeUnload)
|
||||
})
|
||||
|
||||
return {
|
||||
isUnsavedModalOpen,
|
||||
stayOnUnsavedPage,
|
||||
leaveUnsavedPage,
|
||||
allowNextRouteLeave
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user