Proyectos de Subversion LeadersLinked - SPA

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
3719 stevensc 1
import React, { useState, useCallback, useEffect, useRef } from 'react';
2
import { useDropzone } from 'react-dropzone';
3
import { IconButton, styled } from '@mui/material';
4
import Close from '@mui/icons-material/Close';
5
 
6
import { useMobile } from '@hooks';
7
import { shareModalTypes } from '@app/redux/share-modal/shareModal.types';
8
 
9
import FormErrorFeedback from '../UI/form/FormErrorFeedback';
10
 
11
const DragAndDropContainer = styled('div')`
12
  display: flex;
13
  flex-direction: column;
14
  align-items: center;
15
  padding: 2rem 0;
16
  border: 2px dashed #eee;
17
  border-radius: 2;
18
  background-color: #fafafa;
19
  color: #bdbdbd;
20
  outline: none;
21
  transition: border 0.24s ease-in-out;
22
  text-align: center;
23
  cursor: pointer;
24
`;
25
 
26
const PreviewContainer = styled('div')`
27
  display: flex;
28
  position: relative;
29
  justify-content: center;
30
 
31
  img,
32
  video,
33
  object {
34
    width: 80%;
35
    max-height: 200px;
36
    max-width: 350px;
37
    object-fit: contain;
38
    display: block;
39
    margin: 0 auto;
40
  }
41
`;
42
 
43
const CloseButton = styled(IconButton)`
44
  position: absolute;
45
  background-color: #000;
46
  color: #fff;
47
  right: 1rem;
48
  svg {
49
    font-size: 1rem;
50
  }
51
`;
52
 
53
const DropzoneComponent = ({ type, onUploaded, settedFile, recomendationText }) => {
54
  const [errors, setErrors] = useState([]);
55
  const [files, setFiles] = useState([]);
56
  const mobileFileInputRef = useRef();
57
  const isMobile = useMobile();
58
 
59
  const acceptedMimeTypes = (type = '') => {
60
    switch (type) {
61
      case shareModalTypes.IMAGE:
62
        return 'image/jpeg, image/png, image/jpg';
63
      case shareModalTypes.FILE:
64
        return 'application/pdf, application/vnd.openxmlformats-officedocument.presentationml.presentation';
65
      case shareModalTypes.VIDEO:
66
        return 'video/mp4, video/mpeg, video/webm, video/quicktime';
67
      case shareModalTypes.CHAT:
68
        return 'video/mp4, video/mpeg, video/webm, application/pdf, image/jpeg, image/png, image/jpg';
69
 
70
      default:
71
        return null;
72
    }
73
  };
74
 
75
  const onDropRejected = useCallback((rejectedFiles) => {
76
    rejectedFiles.forEach((fileRejection) => {
77
      switch (fileRejection.errors[0].code) {
78
        case 'too-many-files':
79
          setErrors([...errors, 'solo puedes agregar 1 archivo']);
80
          break;
81
        case 'file-invalid-type':
82
          setErrors([...errors, 'por favor seleccione un archivo valido']);
83
          break;
84
        default:
85
          setErrors(errors);
86
          break;
87
      }
88
    });
89
  }, []);
90
 
91
  const onDropAccepted = useCallback((acceptedFiles) => {
92
    onUploaded(acceptedFiles[0]);
93
    setFiles(acceptedFiles.map((file) => file));
94
  }, []);
95
 
96
  const { getRootProps, getInputProps } = useDropzone({
97
    accept: acceptedMimeTypes(type),
98
    multiple: false,
99
    onDrop: onDropAccepted,
100
    onDropRejected,
101
    onDropAccepted: () => {
102
      setErrors([]);
103
    },
104
    maxFiles: 1
105
  });
106
 
107
  const onDeleteFileHandler = () => {
108
    setFiles([]);
109
    onUploaded('');
110
  };
111
 
112
  useEffect(() => {
113
    if (!settedFile) return;
114
    setFiles([settedFile]);
115
  }, [settedFile]);
116
 
117
  const filePreviewTest = (file) => {
118
    switch (type) {
119
      case shareModalTypes.IMAGE:
120
        return <img src={URL.createObjectURL(file)} />;
121
      case shareModalTypes.VIDEO:
122
        return <video src={URL.createObjectURL(file)} width='400' height='300' controls muted />;
123
      case shareModalTypes.CHAT:
124
        switch (file.type) {
125
          case 'video/mp4':
126
          case 'video/mpeg':
127
          case 'video/webm':
128
            return (
129
              <video src={URL.createObjectURL(file)} width='400' height='300' controls muted />
130
            );
131
          case 'image/jpeg':
132
          case 'image/png':
133
          case 'image/jpg':
134
            return <img src={URL.createObjectURL(file)} />;
135
          case 'application/pdf':
136
            return (
137
              <object
138
                data={URL.createObjectURL(file)}
139
                type='application/pdf'
140
                width='400'
141
                height='200'
142
              />
143
            );
144
          default:
145
            break;
146
        }
147
        break;
148
      case shareModalTypes.FILE:
149
        switch (file.type) {
150
          case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
151
            return (
152
              <iframe
153
                src={`https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(
154
                  file
155
                )}`}
156
                width='100%'
157
                height='600px'
158
              />
159
            );
160
          case 'application/pdf':
161
            return <object data={URL.createObjectURL(file)} type='application/pdf' />;
162
          default:
163
            break;
164
        }
165
    }
166
  };
167
 
168
  if (files.length) {
169
    return (
170
      <PreviewContainer>
171
        {files.map((file) => filePreviewTest(file))}
172
        <CloseButton onClick={() => onDeleteFileHandler()}>
173
          <Close />
174
        </CloseButton>
175
      </PreviewContainer>
176
    );
177
  }
178
 
179
  return (
180
    <>
181
      {isMobile ? (
182
        <DragAndDropContainer onClick={() => mobileFileInputRef.current.click()}>
183
          <input
184
            accept={acceptedMimeTypes(type)}
185
            ref={mobileFileInputRef}
186
            onChange={(e) => onDropAccepted(e.target.files)}
187
            type='file'
188
            hidden
189
          />
190
          <p>Arrastra el archivo aqui, o haga click para seleccionar</p>
191
          {recomendationText}
192
        </DragAndDropContainer>
193
      ) : (
194
        <DragAndDropContainer {...getRootProps()}>
195
          <input {...getInputProps()} />
196
          <p>Arrastra el archivo aqui, o haga click para seleccionar</p>
197
          {recomendationText}
198
        </DragAndDropContainer>
199
      )}
200
 
201
      {errors.map((error, index) => (
202
        <FormErrorFeedback key={index}>{error}</FormErrorFeedback>
203
      ))}
204
    </>
205
  );
206
};
207
 
208
const areEqual = (prevProps, nextProps) => {
209
  return prevProps.settedFile === nextProps.settedFile;
210
};
211
 
212
export default React.memo(DropzoneComponent, areEqual);