File size: 3,343 Bytes
f909d7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React from "react";
import { Modal, Group, Button, TextInput, Stack, Divider, ModalProps } from "@mantine/core";
import styled from "styled-components";
import toast from "react-hot-toast";
import { AiOutlineUpload } from "react-icons/ai";
import useFile from "src/store/useFile";

const StyledUploadWrapper = styled.label`
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background: ${({ theme }) => theme.GRID_BG_COLOR};
  border: 2px dashed ${({ theme }) => theme.BACKGROUND_TERTIARY};
  border-radius: 5px;
  min-height: 200px;
  padding: 16px;
  cursor: pointer;

  input[type="file"] {
    display: none;
  }
`;

const StyledFileName = styled.span`
  padding-top: 14px;
  color: ${({ theme }) => theme.INTERACTIVE_NORMAL};
`;

const StyledUploadMessage = styled.h3`
  color: ${({ theme }) => theme.INTERACTIVE_ACTIVE};
  margin-bottom: 0;
`;

export const ImportModal: React.FC<ModalProps> = ({ opened, onClose }) => {
  const setContents = useFile(state => state.setContents);
  const [url, setURL] = React.useState("");
  const [jsonFile, setJsonFile] = React.useState<File | null>(null);

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files) setJsonFile(e.target.files?.item(0));
  };

  const handleFileDrag = (e: React.DragEvent<HTMLLabelElement>) => {
    e.preventDefault();

    if (e.type === "drop" && e.dataTransfer.files.length) {
      if (e.dataTransfer.files[0].type === "application/json") {
        setJsonFile(e.dataTransfer.files[0]);
      } else {
        toast.error("Please upload JSON file!");
      }
    }
  };

  const handleImportFile = () => {
    if (url) {
      setJsonFile(null);

      toast.loading("Loading...", { id: "toastFetch" });
      return fetch(url)
        .then(res => res.json())
        .then(json => {
          setContents({ contents: JSON.stringify(json, null, 2) });
          onClose();
        })
        .catch(() => toast.error("Failed to fetch JSON!"))
        .finally(() => toast.dismiss("toastFetch"));
    }

    if (jsonFile) {
      const reader = new FileReader();

      reader.readAsText(jsonFile, "UTF-8");
      reader.onload = function (data) {
        if (typeof data.target?.result === "string") setContents({ contents: data.target?.result });
        onClose();
      };
    }
  };

  return (
    <Modal title="Import JSON" opened={opened} onClose={onClose} centered>
      <Stack py="sm">
        <TextInput
          value={url}
          onChange={e => setURL(e.target.value)}
          type="url"
          placeholder="URL of JSON to fetch"
          data-autofocus
        />
        <StyledUploadWrapper onDrop={handleFileDrag} onDragOver={handleFileDrag}>
          <input
            key={jsonFile?.name}
            onChange={handleFileChange}
            type="file"
            accept="application/JSON"
          />
          <AiOutlineUpload size={48} />
          <StyledUploadMessage>Click Here to Upload JSON</StyledUploadMessage>
          <StyledFileName>{jsonFile?.name ?? "None"}</StyledFileName>
        </StyledUploadWrapper>
      </Stack>
      <Divider my="xs" />
      <Group justify="right">
        <Button onClick={handleImportFile} disabled={!(jsonFile || url)}>
          Import
        </Button>
      </Group>
    </Modal>
  );
};