mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 16:31:12 -05:00
59 lines
1.3 KiB
TypeScript
59 lines
1.3 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import { useDebounce } from './useDebounce';
|
|
|
|
export type AutoSaveOptions<T> = {
|
|
data: T;
|
|
onSave: (data: T) => Promise<void>;
|
|
debounceMs?: number;
|
|
enabled?: boolean;
|
|
isValid?: boolean;
|
|
};
|
|
|
|
export const useAutoSave = <T,>({
|
|
data,
|
|
onSave,
|
|
debounceMs = 3000,
|
|
enabled = true,
|
|
isValid = true
|
|
}: AutoSaveOptions<T>) => {
|
|
const [isSaving, setIsSaving] = useState(false);
|
|
const [lastSaved, setLastSaved] = useState<Date | null>(null);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const debouncedData = useDebounce(data, debounceMs);
|
|
const initialRender = useRef(true);
|
|
|
|
useEffect(() => {
|
|
// Skip initial render
|
|
if (initialRender.current) {
|
|
initialRender.current = false;
|
|
return;
|
|
}
|
|
|
|
// Skip if disabled or invalid
|
|
if (!enabled || !isValid) return;
|
|
|
|
const save = async () => {
|
|
setIsSaving(true);
|
|
setError(null);
|
|
|
|
try {
|
|
await onSave(debouncedData);
|
|
setLastSaved(new Date());
|
|
} catch (err) {
|
|
setError(err instanceof Error ? err.message : 'Failed to auto-save');
|
|
} finally {
|
|
setIsSaving(false);
|
|
}
|
|
};
|
|
|
|
save();
|
|
}, [debouncedData, enabled, isValid, onSave]);
|
|
|
|
return {
|
|
isSaving,
|
|
lastSaved,
|
|
error,
|
|
resetError: () => setError(null)
|
|
};
|
|
};
|