All files / app/src/shared/hooks useUpload.ts

23.07% Statements 12/52
100% Branches 1/1
50% Functions 1/2
23.07% Lines 12/52

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 751x                             1x 13x   13x 13x   13x                                                                                             13x 13x 13x 13x 13x 13x  
import { AxiosError, AxiosRequestConfig, AxiosResponse, Cancel } from 'axios'
import { RcFile, UploadRequestError, UploadRequestOption } from 'rc-upload/lib/interface'
import { useRef, useState } from 'react'
import { FileModel, HydraError, Nullable } from '@/shared/@types'
import { notify, uploadFiles, useTranslate } from '@/shared/lib'
import { ulid } from 'ulid'
 
export interface UploadHookProps {
  multiple?: boolean
  optimistic?: boolean
  withOffline?: boolean
  // Изменить возвращаемое значение в зависимости с бэком
  customRequest?: (file: RcFile, config?: AxiosRequestConfig<RcFile>) => Promise<AxiosResponse<FileModel>>
}
 
export const useUpload = ({ multiple, optimistic, withOffline, customRequest }: UploadHookProps) => {
  const { t } = useTranslate(['common'])
 
  const [isLoading, setIsLoading] = useState(false)
  const abortController = useRef<Nullable<AbortController>>(null)
 
  const upload = async ({
    file,
    onSuccess,
    onError,
  }: UploadRequestOption<Partial<FileModel> & { uid: string; loading: boolean }>) => {
    const rcFile = file as RcFile
    const fileUlid = ulid()
 
    try {
      setIsLoading(true)
      if (!multiple && abortController.current) {
        abortController.current.abort()
      }
      abortController.current = new AbortController()
 
      const optimisticFileData = {
        uid: rcFile.uid,
        name: rcFile.name,
        path: rcFile.name,
        id: fileUlid,
      }
 
      optimistic &&
        onSuccess?.({
          ...optimisticFileData,
          loading: true,
        })
 
      const request = customRequest || uploadFiles
 
      const response = await request(rcFile, {
        signal: abortController.current.signal,
        withOffline,
      })
      onSuccess?.({ ...response.data, loading: false, uid: rcFile.uid })
    } catch (error) {
      onError?.(error as UploadRequestError)
      if ((error as Cancel).message === 'canceled') return
      if ((error as AxiosError<HydraError>).response?.data?.['hydra:description'] === 'unsupported file format') {
        return notify(t('Unsupported file format'), { status: 'error' })
      }
      notify(t('fileUploadError'), { status: 'error' })
    } finally {
      setIsLoading(false)
    }
  }
 
  return {
    isLoading,
    setIsLoading,
    upload,
  }
}