Proyectos de Subversion LeadersLinked - SPA

Rev

Autoría | Ultima modificación | Ver Log |

import React, { useState, useCallback, useEffect, useRef } from 'react';
import { useDropzone } from 'react-dropzone';
import { IconButton, styled } from '@mui/material';
import Close from '@mui/icons-material/Close';

import { useMobile } from '@hooks';
import { shareModalTypes } from '@app/redux/share-modal/shareModal.types';

import FormErrorFeedback from '../UI/form/FormErrorFeedback';

const DragAndDropContainer = styled('div')`
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 2rem 0;
  border: 2px dashed #eee;
  border-radius: 2;
  background-color: #fafafa;
  color: #bdbdbd;
  outline: none;
  transition: border 0.24s ease-in-out;
  text-align: center;
  cursor: pointer;
`;

const PreviewContainer = styled('div')`
  display: flex;
  position: relative;
  justify-content: center;

  img,
  video,
  object {
    width: 80%;
    max-height: 200px;
    max-width: 350px;
    object-fit: contain;
    display: block;
    margin: 0 auto;
  }
`;

const CloseButton = styled(IconButton)`
  position: absolute;
  background-color: #000;
  color: #fff;
  right: 1rem;
  svg {
    font-size: 1rem;
  }
`;

const DropzoneComponent = ({ type, onUploaded, settedFile, recomendationText }) => {
  const [errors, setErrors] = useState([]);
  const [files, setFiles] = useState([]);
  const mobileFileInputRef = useRef();
  const isMobile = useMobile();

  const acceptedMimeTypes = (type = '') => {
    switch (type) {
      case shareModalTypes.IMAGE:
        return 'image/jpeg, image/png, image/jpg';
      case shareModalTypes.FILE:
        return 'application/pdf, application/vnd.openxmlformats-officedocument.presentationml.presentation';
      case shareModalTypes.VIDEO:
        return 'video/mp4, video/mpeg, video/webm, video/quicktime';
      case shareModalTypes.CHAT:
        return 'video/mp4, video/mpeg, video/webm, application/pdf, image/jpeg, image/png, image/jpg';

      default:
        return null;
    }
  };

  const onDropRejected = useCallback((rejectedFiles) => {
    rejectedFiles.forEach((fileRejection) => {
      switch (fileRejection.errors[0].code) {
        case 'too-many-files':
          setErrors([...errors, 'solo puedes agregar 1 archivo']);
          break;
        case 'file-invalid-type':
          setErrors([...errors, 'por favor seleccione un archivo valido']);
          break;
        default:
          setErrors(errors);
          break;
      }
    });
  }, []);

  const onDropAccepted = useCallback((acceptedFiles) => {
    onUploaded(acceptedFiles[0]);
    setFiles(acceptedFiles.map((file) => file));
  }, []);

  const { getRootProps, getInputProps } = useDropzone({
    accept: acceptedMimeTypes(type),
    multiple: false,
    onDrop: onDropAccepted,
    onDropRejected,
    onDropAccepted: () => {
      setErrors([]);
    },
    maxFiles: 1
  });

  const onDeleteFileHandler = () => {
    setFiles([]);
    onUploaded('');
  };

  useEffect(() => {
    if (!settedFile) return;
    setFiles([settedFile]);
  }, [settedFile]);

  const filePreviewTest = (file) => {
    switch (type) {
      case shareModalTypes.IMAGE:
        return <img src={URL.createObjectURL(file)} />;
      case shareModalTypes.VIDEO:
        return <video src={URL.createObjectURL(file)} width='400' height='300' controls muted />;
      case shareModalTypes.CHAT:
        switch (file.type) {
          case 'video/mp4':
          case 'video/mpeg':
          case 'video/webm':
            return (
              <video src={URL.createObjectURL(file)} width='400' height='300' controls muted />
            );
          case 'image/jpeg':
          case 'image/png':
          case 'image/jpg':
            return <img src={URL.createObjectURL(file)} />;
          case 'application/pdf':
            return (
              <object
                data={URL.createObjectURL(file)}
                type='application/pdf'
                width='400'
                height='200'
              />
            );
          default:
            break;
        }
        break;
      case shareModalTypes.FILE:
        switch (file.type) {
          case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
            return (
              <iframe
                src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(
                  file
                )}`}
                width='100%'
                height='600px'
              />
            );
          case 'application/pdf':
            return <object data={URL.createObjectURL(file)} type='application/pdf' />;
          default:
            break;
        }
    }
  };

  if (files.length) {
    return (
      <PreviewContainer>
        {files.map((file) => filePreviewTest(file))}
        <CloseButton onClick={() => onDeleteFileHandler()}>
          <Close />
        </CloseButton>
      </PreviewContainer>
    );
  }

  return (
    <>
      {isMobile ? (
        <DragAndDropContainer onClick={() => mobileFileInputRef.current.click()}>
          <input
            accept={acceptedMimeTypes(type)}
            ref={mobileFileInputRef}
            onChange={(e) => onDropAccepted(e.target.files)}
            type='file'
            hidden
          />
          <p>Arrastra el archivo aqui, o haga click para seleccionar</p>
          {recomendationText}
        </DragAndDropContainer>
      ) : (
        <DragAndDropContainer {...getRootProps()}>
          <input {...getInputProps()} />
          <p>Arrastra el archivo aqui, o haga click para seleccionar</p>
          {recomendationText}
        </DragAndDropContainer>
      )}

      {errors.map((error, index) => (
        <FormErrorFeedback key={index}>{error}</FormErrorFeedback>
      ))}
    </>
  );
};

const areEqual = (prevProps, nextProps) => {
  return prevProps.settedFile === nextProps.settedFile;
};

export default React.memo(DropzoneComponent, areEqual);