feat(#38): Add periodic local storage backup for application form
This commit is contained in:
97
legalconsenthub/app/composables/useLocalStorageBackup.ts
Normal file
97
legalconsenthub/app/composables/useLocalStorageBackup.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
import type { ApplicationFormDto } from '~~/.api-client'
|
||||
import { useLogger } from '~/composables/useLogger'
|
||||
|
||||
interface LocalStorageBackup {
|
||||
formId: string
|
||||
sectionIndex: number
|
||||
timestamp: number
|
||||
formData: ApplicationFormDto
|
||||
}
|
||||
|
||||
const STORAGE_KEY_PREFIX = 'lch-form-backup-'
|
||||
|
||||
export function useLocalStorageBackup(formId: string) {
|
||||
const storageKey = `${STORAGE_KEY_PREFIX}${formId}`
|
||||
const logger = useLogger().withTag('localStorageBackup')
|
||||
|
||||
const hasBackup = ref(false)
|
||||
const backupTimestamp = ref<Date | null>(null)
|
||||
const backupSectionIndex = ref<number | null>(null)
|
||||
|
||||
function checkForBackup(): boolean {
|
||||
if (import.meta.server) return false
|
||||
|
||||
try {
|
||||
const storedApplicationForm = localStorage.getItem(storageKey)
|
||||
if (storedApplicationForm) {
|
||||
const backup = JSON.parse(storedApplicationForm) as LocalStorageBackup
|
||||
hasBackup.value = true
|
||||
backupTimestamp.value = new Date(backup.timestamp)
|
||||
backupSectionIndex.value = backup.sectionIndex
|
||||
return true
|
||||
}
|
||||
} catch {
|
||||
clearBackup()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function saveBackup(formData: ApplicationFormDto, currentSectionIndex: number): void {
|
||||
if (import.meta.server) return
|
||||
|
||||
try {
|
||||
const backup: LocalStorageBackup = {
|
||||
formId,
|
||||
sectionIndex: currentSectionIndex,
|
||||
timestamp: Date.now(),
|
||||
formData
|
||||
}
|
||||
localStorage.setItem(storageKey, JSON.stringify(backup))
|
||||
hasBackup.value = true
|
||||
backupTimestamp.value = new Date(backup.timestamp)
|
||||
backupSectionIndex.value = currentSectionIndex
|
||||
} catch (e) {
|
||||
// localStorage might be full or unavailable
|
||||
logger.error('Error saving backup', e)
|
||||
}
|
||||
}
|
||||
|
||||
function loadBackup(): ApplicationFormDto | null {
|
||||
if (import.meta.server) return null
|
||||
|
||||
try {
|
||||
const stored = localStorage.getItem(storageKey)
|
||||
if (stored) {
|
||||
const backup = JSON.parse(stored) as LocalStorageBackup
|
||||
return backup.formData
|
||||
}
|
||||
} catch {
|
||||
clearBackup()
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function clearBackup(): void {
|
||||
if (import.meta.server) return
|
||||
|
||||
localStorage.removeItem(storageKey)
|
||||
hasBackup.value = false
|
||||
backupTimestamp.value = null
|
||||
backupSectionIndex.value = null
|
||||
}
|
||||
|
||||
// Call synchronously - import.meta.server guard handles SSR safety.
|
||||
// Do NOT use onMounted here: this composable is called after `await` in async setup(),
|
||||
// which means Vue's active component instance is gone and lifecycle hooks cannot be registered.
|
||||
checkForBackup()
|
||||
|
||||
return {
|
||||
hasBackup: readonly(hasBackup),
|
||||
backupTimestamp: readonly(backupTimestamp),
|
||||
backupSectionIndex: readonly(backupSectionIndex),
|
||||
saveBackup,
|
||||
loadBackup,
|
||||
clearBackup,
|
||||
checkForBackup
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user