2026-01-28 16:46:14 +00:00
|
|
|
import { isEqual } from 'es-toolkit'
|
2025-08-28 15:11:35 -07:00
|
|
|
import type { ComputedRef, Ref } from 'vue'
|
|
|
|
|
import { computed, ref } from 'vue'
|
|
|
|
|
|
|
|
|
|
export function useSavable<T extends Record<string, unknown>>(
|
|
|
|
|
data: () => T,
|
2026-01-28 16:46:14 +00:00
|
|
|
save: (changes: Partial<T>) => void | Promise<void>,
|
2025-08-28 15:11:35 -07:00
|
|
|
): {
|
|
|
|
|
saved: ComputedRef<T>
|
|
|
|
|
current: Ref<T>
|
2026-01-28 16:46:14 +00:00
|
|
|
changes: ComputedRef<Partial<T>>
|
|
|
|
|
hasChanges: ComputedRef<boolean>
|
|
|
|
|
saving: Ref<boolean>
|
2025-08-28 15:11:35 -07:00
|
|
|
reset: () => void
|
2026-01-28 16:46:14 +00:00
|
|
|
save: () => Promise<void>
|
2025-08-28 15:11:35 -07:00
|
|
|
} {
|
|
|
|
|
const savedValues = computed(data)
|
|
|
|
|
const currentValues = ref({ ...data() }) as Ref<T>
|
2026-01-28 16:46:14 +00:00
|
|
|
const saving = ref(false)
|
|
|
|
|
|
2025-08-28 15:11:35 -07:00
|
|
|
const changes = computed<Partial<T>>(() => {
|
|
|
|
|
const values: Partial<T> = {}
|
|
|
|
|
const keys = Object.keys(currentValues.value) as (keyof T)[]
|
|
|
|
|
for (const key of keys) {
|
2026-01-28 16:46:14 +00:00
|
|
|
if (!isEqual(savedValues.value[key], currentValues.value[key])) {
|
2025-08-28 15:11:35 -07:00
|
|
|
values[key] = currentValues.value[key]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return values
|
|
|
|
|
})
|
|
|
|
|
|
2026-01-28 16:46:14 +00:00
|
|
|
const hasChanges = computed(() => Object.keys(changes.value).length > 0)
|
|
|
|
|
|
2025-08-28 15:11:35 -07:00
|
|
|
const reset = () => {
|
|
|
|
|
currentValues.value = data()
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-28 16:46:14 +00:00
|
|
|
const saveInternal = async () => {
|
|
|
|
|
if (!hasChanges.value) return
|
|
|
|
|
saving.value = true
|
|
|
|
|
try {
|
|
|
|
|
await save(changes.value)
|
|
|
|
|
} finally {
|
|
|
|
|
saving.value = false
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-08-28 15:11:35 -07:00
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
saved: savedValues,
|
|
|
|
|
current: currentValues,
|
2026-01-28 16:46:14 +00:00
|
|
|
changes,
|
|
|
|
|
hasChanges,
|
|
|
|
|
saving,
|
2025-08-28 15:11:35 -07:00
|
|
|
reset,
|
|
|
|
|
save: saveInternal,
|
|
|
|
|
}
|
|
|
|
|
}
|