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} formConfig - Reactive reference to the form configuration object. * @param {import('vue').ComputedRef} 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 } }