elements constructor улучшен

This commit is contained in:
2025-07-22 10:33:21 +03:00
parent ac8be1a347
commit 553da77a87
7 changed files with 688 additions and 253 deletions

111
src/hook/useDelayedSave.ts Normal file
View File

@@ -0,0 +1,111 @@
import { useCallback, useEffect, useRef, useState } from 'react'
interface UseDelayedSaveOptions<T> {
onSave: (data: T) => Promise<void>
onSuccess?: (data: T) => void // Коллбек после успешного сохранения
delay?: number // Задержка в миллисекундах (по умолчанию 2000мс)
}
interface UseDelayedSaveReturn<T> {
hasUnsavedChanges: boolean
isSaving: boolean
lastSaveError: string | null
updateData: (data: T) => void
manualSave: () => Promise<void>
clearError: () => void
}
export function useDelayedSave<T>({
onSave,
onSuccess,
delay = 2000,
}: UseDelayedSaveOptions<T>): UseDelayedSaveReturn<T> {
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
const [isSaving, setIsSaving] = useState(false)
const [lastSaveError, setLastSaveError] = useState<string | null>(null)
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
const pendingDataRef = useRef<T | null>(null)
// Очистка таймера при размонтировании компонента
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
}
}, [])
const clearError = useCallback(() => {
setLastSaveError(null)
}, [])
const performSave = useCallback(
async (data: T) => {
if (isSaving) return
setIsSaving(true)
setLastSaveError(null)
try {
await onSave(data)
setHasUnsavedChanges(false)
pendingDataRef.current = null
// Вызываем коллбек успешного сохранения
onSuccess?.(data)
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Неизвестная ошибка'
setLastSaveError(errorMessage)
console.error('Ошибка при сохранении:', error)
} finally {
setIsSaving(false)
}
},
[onSave, onSuccess, isSaving]
)
const updateData = useCallback(
(data: T) => {
// Отменяем предыдущий таймер
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
}
// Сохраняем данные для отложенного сохранения
pendingDataRef.current = data
setHasUnsavedChanges(true)
setLastSaveError(null)
// Устанавливаем новый таймер
timeoutRef.current = setTimeout(() => {
if (pendingDataRef.current) {
performSave(pendingDataRef.current)
}
}, delay)
},
[delay, performSave]
)
const manualSave = useCallback(async () => {
// Отменяем автоматическое сохранение
if (timeoutRef.current) {
clearTimeout(timeoutRef.current)
timeoutRef.current = null
}
// Сохраняем немедленно, если есть несохранённые данные
if (pendingDataRef.current) {
await performSave(pendingDataRef.current)
}
}, [performSave])
return {
hasUnsavedChanges,
isSaving,
lastSaveError,
updateData,
manualSave,
clearError,
}
}