54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
|
|
import { t } from '@/i18n'
|
|
import { useLocalizedOverlay } from '@/i18n/presentation'
|
|
import ConfirmDialog from '@/components/ConfirmDialog.vue'
|
|
import { authRedirectPending } from '@/composables/useApi'
|
|
|
|
interface UnsavedChangesOptions {
|
|
isDirty: () => boolean
|
|
title: () => string
|
|
onDiscard?: () => void
|
|
}
|
|
|
|
export function useUnsavedChangesGuard({ isDirty, title, onDiscard }: UnsavedChangesOptions) {
|
|
const overlay = useLocalizedOverlay()
|
|
|
|
async function allowsLeaving() {
|
|
if (authRedirectPending.value || !isDirty()) {
|
|
return true
|
|
}
|
|
const confirmed = await overlay
|
|
.create(ConfirmDialog, {
|
|
props: {
|
|
get title() {
|
|
return t('Leave without saving?')
|
|
},
|
|
get description() {
|
|
return t("Your changes to \u0022{0}\u0022 haven't been saved.", [title()])
|
|
},
|
|
get confirmLabel() {
|
|
return t('Keep editing')
|
|
},
|
|
get cancelLabel() {
|
|
return t('Discard changes')
|
|
},
|
|
get pendingLabel() {
|
|
return t('Keep editing')
|
|
},
|
|
tone: 'neutral',
|
|
action: async () => {},
|
|
dismissResolvesTo: 'confirm',
|
|
},
|
|
})
|
|
.open()
|
|
if (confirmed) {
|
|
return false
|
|
}
|
|
onDiscard?.()
|
|
return true
|
|
}
|
|
|
|
onBeforeRouteLeave(allowsLeaving)
|
|
onBeforeRouteUpdate((to, from) => (to.params.id === from.params.id ? true : allowsLeaving()))
|
|
}
|