import { useEffect, useRef, useState } from 'react' import { API_URL } from '../../config' import { isLiteralUnion } from '../../utils/types' import { handleHTTPErrors } from '../../utils' const addErrors = ['Не удалось опубликовать объявление', 'Неверный ответ от сервера', 'Неизвестная ошибка'] as const type AddError = typeof addErrors[number] const isAddError = (obj: unknown): obj is AddError => ( isLiteralUnion(obj, addErrors) ) const buttonStates = ['Опубликовать', 'Загрузка...', 'Опубликовано', 'Отменено'] as const type ButtonState = typeof buttonStates[number] | AddError type AddResponse = { Answer: boolean } const isAddResponse = (obj: unknown): obj is AddResponse => ( typeof obj === 'object' && obj !== null && typeof Reflect.get(obj, 'Answer') === 'boolean' ) const useAddAnnouncement = () => { const [status, setStatus] = useState('Опубликовать') const timerIdRef = useRef() const abortControllerRef = useRef() const doAdd = async (formData: FormData) => { if (status === 'Загрузка...') { abortControllerRef.current?.abort() setStatus('Отменено') timerIdRef.current = setTimeout(() => setStatus('Опубликовать'), 3000) return } setStatus('Загрузка...') const abortController = new AbortController() abortControllerRef.current = abortController try { const res = await fetch(API_URL + '/announcement', { method: 'PUT', body: formData, signal: abortController.signal }) handleHTTPErrors(res) const data: unknown = await res.json() if (!isAddResponse(data)) throw new Error('Неверный ответ от сервера') if (!data.Answer) { throw new Error('Не удалось опубликовать объявление') } setStatus('Опубликовано') } catch (err) { setStatus(isAddError(err) ? err : 'Неизвестная ошибка') timerIdRef.current = setTimeout(() => setStatus('Опубликовать'), 10000) } } useEffect(() => { const abortController = abortControllerRef.current return () => { clearTimeout(timerIdRef.current) abortController?.abort() } }) return { doAdd, status } } export default useAddAnnouncement