Files
gremiumhub/legalconsenthub/app/composables/useLocalStorageBackup.ts

98 lines
2.7 KiB
TypeScript

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
}
}