101 lines
2.5 KiB
JavaScript
101 lines
2.5 KiB
JavaScript
/**
|
|
* 관리자 편집 화면의 미저장 변경 이탈을 막는다.
|
|
* @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
|
|
}
|
|
}
|