All files / src/components/UploadFile FileUploadMobileView.tsx

86.2% Statements 25/29
75% Branches 15/20
78.57% Functions 11/14
85.18% Lines 23/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 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157                      8x   8x   8x 8x           8x 8x       8x 7x   8x 7x 1x     7x 8x   7x     8x   10x         8x 7x     1x                                                               10x                               2x                 7x                                                                         7x                    
import { Box, CircularProgress, Stack, styled } from "@mui/material";
import { useEffect, useMemo, useState } from "react";
import UploadIconThick from "@assets/rebrandIcons/UploadIconThick";
import { Text } from "../common/Text";
import { useFileUploadContext } from "./FileUploadContext";
import { UploadCard } from "./FileUploadSnackbar";
import { Button } from "../common/Button";
import { FileUploadStatus, SnackbarFile } from "./types";
import ModalFactory from "@common/Modal/ModalFactory/ModalFactory";
 
export default function FileUploadMobileView() {
  const [openModal, setOpenModal] = useState(false);
  const { snackbarFiles, clearSnackbarFiles, isEveryFileUploaded } =
    useFileUploadContext();
 
  useEffect(() => {
    const timeoutID = setTimeout(() => {
      if (snackbarFiles.length > 0 && isEveryFileUploaded && !openModal) {
        clearSnackbarFiles();
      }
    }, 3000);
 
    return () => {
      clearTimeout(timeoutID);
    };
  }, [snackbarFiles, isEveryFileUploaded, openModal]);
 
  const fileUploadAverageProgress = useMemo(() => {
    const totalProgress = snackbarFiles.reduce((acc, curr) => {
      // If file is too large, it's progress shouldn't be accounted while calculating average progress
      if (curr.status !== FileUploadStatus.FILE_TOO_LARGE)
        return acc + curr.uploadProgress;
      return acc;
    }, 0);
    // Use the length of uploading files to calculate average progress
    const uploadingFiles = snackbarFiles.filter(
      (item) => item.status !== FileUploadStatus.FILE_TOO_LARGE,
    );
    return totalProgress / uploadingFiles.length || 0;
  }, [snackbarFiles]);
 
  const isUploadFailed = snackbarFiles.some(
    (file) =>
      file.status === FileUploadStatus.FAILED ||
      file.status === FileUploadStatus.FILE_NOT_SUPPORTED ||
      file.status === FileUploadStatus.FILE_TOO_LARGE,
  );
 
  if (snackbarFiles.length < 1) return null;
  return (
    <>
      <UploadStatusButton
        onClick={() => setOpenModal(true)}
        isUploadFailed={isUploadFailed}
        fileUploadAverageProgress={fileUploadAverageProgress}
      />
      <ModalFactory
        variant="dialog"
        renderMobile
        modalProps={{
          sx: { zIndex: 1300 },
          open: openModal,
          onClose: () => setOpenModal(false),
          DrawerProps: {
            dataTestId: "uploading-files-drawer",
          },
        }}
      >
        <Puller />
        <Text
          color="#575353"
          textAlign="center"
          fontWeight={"book"}
          fontSize="18px"
          pb={"20px"}
        >
          Uploads
        </Text>
        <Stack
          flex={1}
          gap={2}
          sx={{ overflowX: "scroll", px: "12px", pb: "90px", pt: "8px" }}
        >
          {snackbarFiles.map((file: SnackbarFile) => {
            return <UploadCard key={file.id} snackbarFile={file} />;
          })}
        </Stack>
        <Stack bottom="20px" position="absolute" pt="20px" width="100%">
          <Button
            onClick={() => setOpenModal(false)}
            sx={{ width: "170px", margin: "auto" }}
          >
            Close
          </Button>
        </Stack>
      </ModalFactory>
    </>
  );
}
 
const UploadStatusButton = ({
  onClick,
  isUploadFailed,
  fileUploadAverageProgress,
}: {
  onClick: () => void;
  isUploadFailed: boolean;
  fileUploadAverageProgress: number;
}) => {
  return (
    <Box
      onClick={onClick}
      position="fixed"
      bottom="60px"
      right="20px"
      zIndex={1301}
      data-testid="file-upload-floating-button"
    >
      <Box
        data-testid="file-upload-floating-button-data"
        sx={{
          height: "52px",
          width: "52px",
          backgroundColor: isUploadFailed ? "#F5E0DF" : "#E6EAF2",
          borderRadius: "26px",
          display: "flex",
          justifyContent: "center",
          alignItems: "center",
        }}
      >
        <Box sx={{ position: "absolute", top: "-5px" }}>
          <CircularProgress
            size="62px"
            variant="determinate"
            value={isUploadFailed ? 0 : fileUploadAverageProgress}
            sx={{ color: "#6D9CF8", strokeLinecap: "round" }}
            data-testid="file-upload-floating-button-progress"
          />
        </Box>
 
        <UploadIconThick fill={isUploadFailed ? "#D80D0D" : "#6D9CF8"} />
      </Box>
    </Box>
  );
};
 
const Puller = styled(Box)(() => ({
  width: 52,
  height: 4,
  backgroundColor: "#FDFDFD",
  borderRadius: 3,
  position: "absolute",
  top: "-12px",
  zIndex: 1500,
  left: "calc(50% - 26px)",
}));