refactor(FormTimer.vue): change timer variable from let to ref for reactivity
refactor(OpenCompleteForm.vue): remove FormTimer component and related logic to simplify form submission feat(OpenForm.vue): reintroduce FormTimer component and manage timer start/stop on form events for better user experience
This commit is contained in:
parent
f65de634ee
commit
5020f9fa74
|
|
@ -1,5 +1,4 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted } from 'vue'
|
|
||||||
import { pendingSubmission as pendingSubmissionFun } from "~/composables/forms/pendingSubmission.js"
|
import { pendingSubmission as pendingSubmissionFun } from "~/composables/forms/pendingSubmission.js"
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|
@ -9,7 +8,7 @@ const props = defineProps({
|
||||||
const pendingSubmission = pendingSubmissionFun(props.form)
|
const pendingSubmission = pendingSubmissionFun(props.form)
|
||||||
const startTime = ref(null)
|
const startTime = ref(null)
|
||||||
const completionTime = ref(parseInt(pendingSubmission.getTimer() ?? null))
|
const completionTime = ref(parseInt(pendingSubmission.getTimer() ?? null))
|
||||||
let timer = null
|
const timer = ref(null)
|
||||||
|
|
||||||
watch(() => completionTime.value, () => {
|
watch(() => completionTime.value, () => {
|
||||||
if (completionTime.value) {
|
if (completionTime.value) {
|
||||||
|
|
@ -21,16 +20,16 @@ const startTimer = () => {
|
||||||
if (!startTime.value) {
|
if (!startTime.value) {
|
||||||
startTime.value = parseInt(pendingSubmission.getTimer() ?? 1)
|
startTime.value = parseInt(pendingSubmission.getTimer() ?? 1)
|
||||||
completionTime.value = startTime.value
|
completionTime.value = startTime.value
|
||||||
timer = setInterval(() => {
|
timer.value = setInterval(() => {
|
||||||
completionTime.value += 1
|
completionTime.value += 1
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const stopTimer = () => {
|
const stopTimer = () => {
|
||||||
if (timer) {
|
if (timer.value) {
|
||||||
clearInterval(timer)
|
clearInterval(timer.value)
|
||||||
timer = null
|
timer.value = null
|
||||||
startTime.value = null
|
startTime.value = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,17 +39,9 @@ const resetTimer = () => {
|
||||||
completionTime.value = null
|
completionTime.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
document.addEventListener('input', startTimer)
|
|
||||||
})
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
document.removeEventListener('input', startTimer)
|
|
||||||
stopTimer()
|
|
||||||
})
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
completionTime,
|
completionTime,
|
||||||
|
startTimer,
|
||||||
stopTimer,
|
stopTimer,
|
||||||
resetTimer
|
resetTimer
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,6 @@
|
||||||
class="open-complete-form"
|
class="open-complete-form"
|
||||||
:style="{ '--font-family': form.font_family }"
|
:style="{ '--font-family': form.font_family }"
|
||||||
>
|
>
|
||||||
<FormTimer
|
|
||||||
ref="formTimer"
|
|
||||||
:form="form"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<link
|
<link
|
||||||
v-if="adminPreview && form.font_family"
|
v-if="adminPreview && form.font_family"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
|
|
@ -205,7 +200,6 @@
|
||||||
<script>
|
<script>
|
||||||
import OpenForm from './OpenForm.vue'
|
import OpenForm from './OpenForm.vue'
|
||||||
import OpenFormButton from './OpenFormButton.vue'
|
import OpenFormButton from './OpenFormButton.vue'
|
||||||
import FormTimer from './FormTimer.vue'
|
|
||||||
import VButton from '~/components/global/VButton.vue'
|
import VButton from '~/components/global/VButton.vue'
|
||||||
import FormCleanings from '../../pages/forms/show/FormCleanings.vue'
|
import FormCleanings from '../../pages/forms/show/FormCleanings.vue'
|
||||||
import VTransition from '~/components/global/transitions/VTransition.vue'
|
import VTransition from '~/components/global/transitions/VTransition.vue'
|
||||||
|
|
@ -214,7 +208,7 @@ import clonedeep from "clone-deep"
|
||||||
import ThemeBuilder from "~/lib/forms/themes/ThemeBuilder.js"
|
import ThemeBuilder from "~/lib/forms/themes/ThemeBuilder.js"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { VTransition, VButton, OpenFormButton, OpenForm, FormCleanings, FormTimer },
|
components: { VTransition, VButton, OpenFormButton, OpenForm, FormCleanings },
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
form: { type: Object, required: true },
|
form: { type: Object, required: true },
|
||||||
|
|
@ -281,14 +275,7 @@ export default {
|
||||||
if (form.busy) return
|
if (form.busy) return
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
// Stop the timer and get the completion time
|
form.post('/forms/' + this.form.slug + '/answer').then((data) => {
|
||||||
this.$refs.formTimer.stopTimer()
|
|
||||||
const completionTime = this.$refs.formTimer.completionTime
|
|
||||||
form.completion_time = completionTime
|
|
||||||
|
|
||||||
// this.closeAlert()
|
|
||||||
form.post('/forms/' + this.form.slug + '/answer')
|
|
||||||
.then((data) => {
|
|
||||||
useAmplitude().logEvent('form_submission', {
|
useAmplitude().logEvent('form_submission', {
|
||||||
workspace_id: this.form.workspace_id,
|
workspace_id: this.form.workspace_id,
|
||||||
form_id: this.form.id
|
form_id: this.form.id
|
||||||
|
|
@ -302,7 +289,7 @@ export default {
|
||||||
redirect_target_url: (this.form.is_pro && data.redirect && data.redirect_url) ? data.redirect_url : null
|
redirect_target_url: (this.form.is_pro && data.redirect && data.redirect_url) ? data.redirect_url : null
|
||||||
},
|
},
|
||||||
submission_data: form.data(),
|
submission_data: form.data(),
|
||||||
completion_time: completionTime
|
completion_time: form['completion_time']
|
||||||
})
|
})
|
||||||
|
|
||||||
if (this.isIframe) {
|
if (this.isIframe) {
|
||||||
|
|
@ -334,14 +321,12 @@ export default {
|
||||||
useAlert().error(error.data.message)
|
useAlert().error(error.data.message)
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$refs.formTimer.startTimer()
|
|
||||||
onFailure()
|
onFailure()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
restart () {
|
restart () {
|
||||||
this.submitted = false
|
this.submitted = false
|
||||||
this.$emit('restarted', true)
|
this.$emit('restarted', true)
|
||||||
this.$refs.formTimer.resetTimer() // Reset the timer
|
|
||||||
},
|
},
|
||||||
passwordEntered () {
|
passwordEntered () {
|
||||||
if (this.passwordForm.password !== '' && this.passwordForm.password !== null) {
|
if (this.passwordForm.password !== '' && this.passwordForm.password !== null) {
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@
|
||||||
:style="computedStyle"
|
:style="computedStyle"
|
||||||
@submit.prevent=""
|
@submit.prevent=""
|
||||||
>
|
>
|
||||||
|
<FormTimer
|
||||||
|
ref="form-timer"
|
||||||
|
:form="form"
|
||||||
|
/>
|
||||||
<template v-if="form.show_progress_bar">
|
<template v-if="form.show_progress_bar">
|
||||||
<div
|
<div
|
||||||
v-if="isIframe"
|
v-if="isIframe"
|
||||||
|
|
@ -134,10 +138,11 @@ import {pendingSubmission} from "~/composables/forms/pendingSubmission.js"
|
||||||
import FormLogicPropertyResolver from "~/lib/forms/FormLogicPropertyResolver.js"
|
import FormLogicPropertyResolver from "~/lib/forms/FormLogicPropertyResolver.js"
|
||||||
import {computed} from "vue"
|
import {computed} from "vue"
|
||||||
import CachedDefaultTheme from "~/lib/forms/themes/CachedDefaultTheme.js"
|
import CachedDefaultTheme from "~/lib/forms/themes/CachedDefaultTheme.js"
|
||||||
|
import FormTimer from './FormTimer.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'OpenForm',
|
name: 'OpenForm',
|
||||||
components: {draggable, OpenFormField, OpenFormButton, VueHcaptcha},
|
components: {draggable, OpenFormField, OpenFormButton, VueHcaptcha, FormTimer},
|
||||||
props: {
|
props: {
|
||||||
form: {
|
form: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
@ -328,6 +333,7 @@ export default {
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initForm()
|
this.initForm()
|
||||||
|
this.$refs['form-timer'].startTimer()
|
||||||
if (import.meta.client && window.location.href.includes('auto_submit=true')) {
|
if (import.meta.client && window.location.href.includes('auto_submit=true')) {
|
||||||
this.isAutoSubmit = true
|
this.isAutoSubmit = true
|
||||||
this.submitForm()
|
this.submitForm()
|
||||||
|
|
@ -349,12 +355,16 @@ export default {
|
||||||
this.dataForm.submission_id = this.form.submission_id
|
this.dataForm.submission_id = this.form.submission_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.$refs['form-timer'].stopTimer()
|
||||||
|
this.dataForm.completion_time = this.$refs['form-timer'].completionTime
|
||||||
|
|
||||||
this.$emit('submit', this.dataForm, this.onSubmissionFailure)
|
this.$emit('submit', this.dataForm, this.onSubmissionFailure)
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* If more than one page, show first page with error
|
* If more than one page, show first page with error
|
||||||
*/
|
*/
|
||||||
onSubmissionFailure() {
|
onSubmissionFailure() {
|
||||||
|
this.$refs['form-timer'].startTimer()
|
||||||
this.isAutoSubmit = false
|
this.isAutoSubmit = false
|
||||||
if (this.fieldGroups.length > 1) {
|
if (this.fieldGroups.length > 1) {
|
||||||
// Find first mistake and show page
|
// Find first mistake and show page
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue