Added brackets for const lambdas Converted const lambdas with multiple instructions to functions
80 lines
2.6 KiB
TypeScript
80 lines
2.6 KiB
TypeScript
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<ButtonState>('Опубликовать')
|
||
|
||
const timerIdRef = useRef<number>()
|
||
const abortControllerRef = useRef<AbortController>()
|
||
|
||
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
|