All files / src/components/UploadFile/hooks useUploadFiles.tsx

3.44% Statements 1/29
0% Branches 0/8
0% Functions 0/7
3.7% Lines 1/27

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 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114                                                                                46x                                                                                                                                                  
import { customInstance } from "@services/api";
import axios from "axios";
import { debounce, isEmpty } from "lodash";
import { useState } from "react";
 
export type TFileAttachmentType =
  | "bank_account"
  | "legal_principal"
  | "account_member"
  | "underwriting_profile"
  | "account_owner"
  | "account_owner_selfie"
  | "conversation_message";
 
export type UploadProgressParams = {
  fileId: string;
  progress: number;
  identifier?: number | string; // can be id or url
};
 
export type TUploadFilePayload = {
  attachmentType?: TFileAttachmentType;
  label?: string;
  tag?: string;
  list: { file: File; id: string }[];
  merchantId: number;
  resourceID: number;
  isCustomerUpload?: boolean;
  isSignatureUpload?: boolean;
  onSuccess?: () => void;
  clearSnackbarFiles?: () => void;
  onUploadProgress(params: UploadProgressParams): void;
  onUploadFinish(params: { identifiers: (number | string)[] }): void;
  onUploadFailed(params: { fileIds: string[] }): void;
};
 
export type TUploadedFile = { id: number; isUploaded: true };
 
export type HandleUploadReturnType = "upload_failed" | TUploadedFile[];
 
export const useUploadFiles = () => {
  const [isLoading, setIsLoading] = useState(false);
 
  const handleUpload = async (
    payload: TUploadFilePayload,
    challengeSlugParam?: string,
  ): Promise<HandleUploadReturnType> => {
    if (isEmpty(payload.list)) return [];
    setIsLoading(true);
 
    const customDocumentList = payload.list.map((item) => {
      return {
        attachmentType: payload.attachmentType,
        fileName: item.file.name,
        label: payload.label,
        tag: payload.tag,
        resourceID: payload.resourceID,
      };
    });
    try {
      const res = await customInstance({
        url: `accounts/${payload.merchantId}/files`,
        method: "POST",
        data: { list: customDocumentList },
        params: { challenge_slug: challengeSlugParam },
      });
 
      if (!res?.total || res?.total < 1) return "upload_failed";
      for (const [index, document] of res.data.entries()) {
        await axios.put(document.fileURL, payload.list[index].file, {
          onUploadProgress: debounce((progressEvent: ProgressEvent) => {
            payload.onUploadProgress({
              fileId: payload.list[index].id,
              progress: (progressEvent.loaded * 100) / progressEvent.total,
              identifier: document.id,
            });
          }, 100) as any,
        });
      }
 
      const confirmedUploadedList: TUploadedFile[] = res.data.map(
        (item: any): TUploadedFile => ({
          id: item.id,
          isUploaded: true,
        }),
      );
      await customInstance({
        url: `accounts/${payload.merchantId}/files/confirm`,
        method: "POST",
        data: { list: confirmedUploadedList },
      });
 
      payload.onUploadFinish({
        identifiers: confirmedUploadedList.map((item: any) => item.id),
      });
 
      if (payload.onSuccess) {
        payload.onSuccess();
      }
 
      setIsLoading(false);
      return confirmedUploadedList;
    } catch (e) {
      payload.onUploadFailed({
        fileIds: payload.list.map((item) => item.id),
      });
      setIsLoading(false);
      return "upload_failed";
    }
  };
 
  return { handleUpload, isLoading };
};