feat(#37): Add prompt when leaving with unsaved changes

This commit is contained in:
2026-01-19 17:28:22 +01:00
parent 0ce89daddf
commit 753d90dc64
4 changed files with 81 additions and 3 deletions

View File

@@ -97,6 +97,44 @@ const isReadOnly = computed(() => {
return applicationForm.value?.createdBy?.keycloakId !== user.value?.keycloakId
})
// Unsaved changes tracking
const originalFormJson = ref<string>('')
onMounted(() => {
originalFormJson.value = JSON.stringify(applicationForm.value)
window.addEventListener('beforeunload', handleBeforeUnload)
})
onUnmounted(() => {
window.removeEventListener('beforeunload', handleBeforeUnload)
})
const hasUnsavedChanges = computed(() => {
if (!originalFormJson.value) return false
return JSON.stringify(applicationForm.value) !== originalFormJson.value
})
function handleBeforeUnload(e: BeforeUnloadEvent) {
if (hasUnsavedChanges.value) {
e.preventDefault()
}
}
onBeforeRouteLeave((to, from, next) => {
// Allow navigation between sections of the same form
if (to.params.id === from.params.id) {
next()
return
}
if (hasUnsavedChanges.value) {
const answer = window.confirm($t('applicationForms.unsavedWarning'))
next(answer)
} else {
next()
}
})
const validationMap = ref<Map<FormElementId, ComplianceStatus> | undefined>()
const validationStatus = ref<ComplianceStatus>(ComplianceStatus.NonCritical)
@@ -126,6 +164,7 @@ async function onSave() {
const updated = await updateForm(applicationForm.value.id, applicationForm.value)
if (updated) {
updateApplicationForm(updated)
originalFormJson.value = JSON.stringify(updated)
toast.add({ title: $t('common.success'), description: $t('applicationForms.saved'), color: 'success' })
}
}

View File

@@ -82,6 +82,38 @@ const applicationFormTemplate = computed(
const validationMap = ref<Map<FormElementId, ComplianceStatus> | undefined>()
const validationStatus = ref<ComplianceStatus>(ComplianceStatus.NonCritical)
// Unsaved changes tracking
const originalFormJson = ref<string>('')
onMounted(() => {
originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
window.addEventListener('beforeunload', handleBeforeUnload)
})
onUnmounted(() => {
window.removeEventListener('beforeunload', handleBeforeUnload)
})
const hasUnsavedChanges = computed(() => {
if (!originalFormJson.value) return false
return JSON.stringify(applicationFormTemplate.value) !== originalFormJson.value
})
function handleBeforeUnload(e: BeforeUnloadEvent) {
if (hasUnsavedChanges.value) {
e.preventDefault()
}
}
onBeforeRouteLeave((_to, _from, next) => {
if (hasUnsavedChanges.value) {
const answer = window.confirm($t('applicationForms.unsavedWarning'))
next(answer)
} else {
next()
}
})
const allFormElements = computed(() => {
return (
applicationFormTemplate.value?.formElementSections?.flatMap((section: FormElementSectionDto) =>
@@ -105,8 +137,11 @@ watch(
async function onSave() {
const applicationForm = await prepareAndCreateApplicationForm()
if (applicationForm) {
if (applicationForm?.id) {
// Reset to prevent unsaved changes warning when navigating
originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
toast.add({ title: $t('common.success'), description: $t('applicationForms.saved'), color: 'success' })
await navigateTo(`/application-forms/${applicationForm.id}/0`)
}
}
@@ -114,6 +149,8 @@ async function onSubmit() {
const applicationForm = await prepareAndCreateApplicationForm()
if (applicationForm?.id) {
await submitApplicationForm(applicationForm.id)
// Reset to prevent unsaved changes warning when navigating
originalFormJson.value = JSON.stringify(applicationFormTemplate.value)
await navigateTo('/')
toast.add({ title: $t('common.success'), description: $t('applicationForms.submitted'), color: 'success' })
}