File size: 2,651 Bytes
13face0
 
 
 
 
 
a8dfd23
13face0
 
 
 
 
a8dfd23
 
13face0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import {
  CloseSquareOutlined,
  InboxOutlined,
  SyncOutlined,
} from "@ant-design/icons";
import { Upload } from "antd";
import { useAtom, atom } from "jotai";
import imageCompression from "browser-image-compression";
import React, { useState } from "react";

const { Dragger } = Upload;

export const uploadImageAtom = atom<string | null>(null);

const Dropzone: React.FC = () => {
  const [file, setFile] = useAtom(uploadImageAtom);
  const [compressing, setCompressing] = useState(false);

  return (
    <div className="relative flex justify-center items-center w-[600px] h-[400px]">
      <>
        {compressing && (
          <div className="absolute top-0 w-full h-full flex justify-center items-center z-10">
            <SyncOutlined spin className="text-9xl text-gray-700 opacity-60" />
          </div>
        )}
        {file && (
          <>
            <CloseSquareOutlined
              className="absolute top-0 right-0 translate-x-[100%] pl-1 text-xl text-gray-800 opacity-60 hover:scale-125"
              onClick={() => setFile(null)}
            />
            <img className="object-contain w-full h-full" src={file} />
          </>
        )}
        <Dragger
          accept="image/*"
          className="absolute w-full h-full"
          name="file"
          multiple={false}
          showUploadList={false}
          maxCount={1}
          beforeUpload={async (file) => {
            console.log("file", file);

            let compressedFile: File;
            if (file.size / 1024 > 500) {
              setCompressing(true);
              compressedFile = await imageCompression(file, {
                maxSizeMB: 1,
                maxWidthOrHeight: 1920,
                useWebWorker: true,
              });
              console.log(`compress ratio ${compressedFile.size / file.size}`);
            }

            const base64 = await new Promise<string>((resolve, reject) => {
              const reader = new FileReader();
              reader.readAsDataURL(compressedFile || file);
              reader.onload = () => resolve(reader.result as string);
              reader.onerror = (error) => reject(error);
            });
            setFile(base64);
            setCompressing(false);
            return false;
          }}
        >
          {!file && (
            <>
              <p className="ant-upload-drag-icon">
                <InboxOutlined />
              </p>
              <p className="ant-upload-text">
                Click or drag file to this area to upload
              </p>
            </>
          )}
        </Dragger>
      </>
    </div>
  );
};

export default Dropzone;