forked from polka_billy/porridger
Converted put(api/announcement) to use useSend
Added useSendButtonCaption hook Related to #19
This commit is contained in:
@ -1,79 +1,31 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { useCallback } 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'
|
||||
)
|
||||
import { useSend } from '..'
|
||||
import { composePutAnnouncementURL, processPutAnnouncement } from '../../api/putAnnouncement'
|
||||
import { isPutAnnouncementResponse } from '../../api/putAnnouncement/types'
|
||||
import useSendButtonCaption from '../useSendButtonCaption'
|
||||
|
||||
const useAddAnnouncement = () => {
|
||||
const [status, setStatus] = useState<ButtonState>('Опубликовать')
|
||||
const { doSend, loading, error } = useSend(
|
||||
composePutAnnouncementURL(),
|
||||
'PUT',
|
||||
true,
|
||||
isPutAnnouncementResponse,
|
||||
processPutAnnouncement,
|
||||
)
|
||||
|
||||
const timerIdRef = useRef<number>()
|
||||
const abortControllerRef = useRef<AbortController>()
|
||||
const { update, ...button } = useSendButtonCaption('Опубликовать', loading, error, 'Опубликовано')
|
||||
|
||||
const doAdd = async (formData: FormData) => {
|
||||
if (status === 'Загрузка...') {
|
||||
abortControllerRef.current?.abort()
|
||||
setStatus('Отменено')
|
||||
timerIdRef.current = setTimeout(() => setStatus('Опубликовать'), 3000)
|
||||
return
|
||||
}
|
||||
const doSendWithButton = useCallback(async (formData: FormData) => {
|
||||
const data = await doSend({}, {
|
||||
body: formData
|
||||
})
|
||||
update(data)
|
||||
|
||||
setStatus('Загрузка...')
|
||||
return data
|
||||
}, [doSend, update])
|
||||
|
||||
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 }
|
||||
return { doSend: doSendWithButton, button }
|
||||
}
|
||||
|
||||
export default useAddAnnouncement
|
||||
|
Reference in New Issue
Block a user