125 lines
4.0 KiB
JavaScript
125 lines
4.0 KiB
JavaScript
import { hash } from "~/lib/utils.js"
|
|
import { useStorage, watchThrottled } from "@vueuse/core"
|
|
import { computed, toValue } from 'vue'
|
|
|
|
/**
|
|
* Composable for managing pending form submission data and timer in localStorage.
|
|
* Includes throttled auto-saving of form data.
|
|
*
|
|
* @param {import('vue').Ref<Object>} formConfig - Reactive reference to the form configuration object.
|
|
* @param {import('vue').ComputedRef<Object>} formDataRef - Computed reference to the reactive form data object.
|
|
*/
|
|
export function usePendingSubmission(formConfig, formDataRef) {
|
|
const config = computed(() => toValue(formConfig)) // Ensure reactivity to config changes
|
|
|
|
const formPendingSubmissionKey = computed(() => {
|
|
const currentConfig = config.value
|
|
return currentConfig && typeof window !== 'undefined'
|
|
? currentConfig.form_pending_submission_key + "-" + hash(window.location.href)
|
|
: ""
|
|
})
|
|
|
|
const formPendingSubmissionTimerKey = computed(() => {
|
|
return formPendingSubmissionKey.value ? formPendingSubmissionKey.value + "-timer" : ""
|
|
})
|
|
|
|
const enabled = computed(() => {
|
|
// Auto-save is enabled if the feature is turned on in the config
|
|
return config.value?.auto_save ?? false
|
|
})
|
|
|
|
// Internal function to save data to localStorage
|
|
const saveData = (value) => {
|
|
if (import.meta.server || !enabled.value || !formPendingSubmissionKey.value) return
|
|
try {
|
|
useStorage(formPendingSubmissionKey.value).value =
|
|
value === null ? null : JSON.stringify(value)
|
|
} catch (e) {
|
|
console.error("Error saving pending submission to localStorage:", e)
|
|
}
|
|
}
|
|
|
|
// Internal function to retrieve data from localStorage
|
|
const retrieveData = (defaultValue = {}) => {
|
|
if (import.meta.server || !enabled.value || !formPendingSubmissionKey.value) return defaultValue
|
|
try {
|
|
const storageValue = useStorage(formPendingSubmissionKey.value).value
|
|
return storageValue ? JSON.parse(storageValue) : defaultValue
|
|
} catch (e) {
|
|
console.error("Error reading pending submission from localStorage:", e)
|
|
// Attempt to clear corrupted data
|
|
remove()
|
|
return defaultValue
|
|
}
|
|
}
|
|
|
|
// Watch formDataRef with throttling
|
|
watchThrottled(
|
|
formDataRef,
|
|
(newData) => {
|
|
// Only save if enabled and on client
|
|
if (import.meta.client && enabled.value) {
|
|
saveData(newData)
|
|
}
|
|
},
|
|
{ deep: true, throttle: 1000 } // Throttle saving to once per second
|
|
)
|
|
|
|
// --- Exposed Methods ---
|
|
|
|
const remove = () => {
|
|
// Clear the data from storage
|
|
saveData(null)
|
|
}
|
|
|
|
const get = (defaultValue = {}) => {
|
|
// Retrieve the currently stored data
|
|
return retrieveData(defaultValue)
|
|
}
|
|
|
|
const setSubmissionHash = (hash) => {
|
|
if (!enabled.value) return
|
|
const currentData = retrieveData()
|
|
saveData({
|
|
...currentData,
|
|
submission_hash: hash
|
|
})
|
|
}
|
|
|
|
const getSubmissionHash = () => {
|
|
return retrieveData()?.submission_hash ?? null
|
|
}
|
|
|
|
const setTimer = (value) => {
|
|
if (import.meta.server || !formPendingSubmissionTimerKey.value) return
|
|
useStorage(formPendingSubmissionTimerKey.value).value = value
|
|
}
|
|
|
|
const removeTimer = () => {
|
|
setTimer(null)
|
|
}
|
|
|
|
const getTimer = (defaultValue = null) => {
|
|
if (import.meta.server || !formPendingSubmissionTimerKey.value) return defaultValue
|
|
return useStorage(formPendingSubmissionTimerKey.value, defaultValue).value
|
|
}
|
|
|
|
const clear = () => {
|
|
remove()
|
|
removeTimer()
|
|
}
|
|
|
|
return {
|
|
formPendingSubmissionKey, // Keep for potential external use (e.g., partial submission hash map key)
|
|
enabled,
|
|
get, // Method to retrieve stored data
|
|
remove, // Method to clear stored data
|
|
setSubmissionHash, // Method to specifically set the submission hash
|
|
getSubmissionHash, // Method to specifically get the submission hash
|
|
setTimer, // Method to set the timer value
|
|
removeTimer, // Method to clear the timer value
|
|
getTimer, // Method to get the timer value
|
|
clear, // Method to clear both data and timer
|
|
}
|
|
}
|