react-native-surveys
Version:
Build your own forms, surveys and polls for your React Native apps.
236 lines (225 loc) • 6.08 kB
JavaScript
function _extends() {
_extends =
Object.assign ||
function(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
import React, { memo, useState, useEffect, Fragment } from "react";
import { View, StyleSheet, Text, Dimensions } from "react-native";
import { useDropzone } from "../../api/react-dropzone";
import { colors, MAX_FORM_WIDTH } from "../../theme";
import { UploadIcon } from "../../assets/icons";
import FilePreview from "../../components/FilePreview";
import QuestionHeader from "../../components/QuestionHeader";
import { config } from "../../config";
const { width } = Dimensions.get("window");
const FilesUpload = ({
block,
form,
isPreview,
currentPageIndex,
blockIndex,
allBlocks
}) => {
const [error, setError] = useState(false);
const [files, updateFiles] = useState(block.files || []);
const { accept } = block;
const onDrop = (acceptedFiles, rejectedFiles) => {
if (rejectedFiles.length > 0) {
setError(
rejectedFiles.filter(f => f.type.indexOf("image") < 0).length > 0
? "Sorry, you can only upload images."
: "File exceeded max 5mb size."
);
} else {
setError(false);
}
if (files.length + acceptedFiles.length > config.MAX_UPLOAD_FILES_NUMBER) {
setError(
`Files limit reached. Max ${config.MAX_UPLOAD_FILES_NUMBER} files.`
);
}
const updatedFiles = [
...files,
...acceptedFiles.map(file =>
Object.assign(file, {
preview: URL.createObjectURL(file)
})
)
].slice(0, config.MAX_UPLOAD_FILES_NUMBER);
block.files = block.files || [];
updatedFiles.forEach((file, i) => {
if (block.files[i] && block.files[i].name === file.name) return;
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
block.files[i] = {
name: file.name,
type: file.type,
base64: reader.result
};
};
});
block.value = returnFilesBlockValue(updatedFiles.length);
updateFiles(updatedFiles);
};
const removeFile = file => {
const updatedFiles = files.filter(f => f.name !== file.name);
block.files = block.files.filter(f => f.name !== file.name);
block.value = returnFilesBlockValue(updatedFiles.length);
updateFiles(updatedFiles);
setError(false);
};
const returnFilesBlockValue = (numberOfFiles = 0) => {
if (numberOfFiles <= 0) return "";
const noun = numberOfFiles === 1 ? "file" : "files";
return `Uploaded ${numberOfFiles} ${noun}`;
};
useEffect(
() => () => {
files.forEach(file => URL.revokeObjectURL(file.preview));
},
[files]
);
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
noKeyboard: true,
disabled: isPreview,
multiple: true,
accept: accept || "",
maxSize: 5000000
});
const dropStyle = {
cursor: isPreview ? "auto" : "pointer",
flexDirection: files.length > 0 ? "row" : "column",
justifyContent: files.length > 0 ? "flex-start" : "center",
backgroundColor: isDragActive ? `${colors.success}10` : colors.white,
borderWidth: 1,
borderStyle: "solid",
borderColor: isDragActive ? colors.success : colors.border,
position: "relative",
display: "flex",
alignItems: "center",
flexWrap: "wrap",
minHeight: 150,
padding: width <= 500 ? 16 : 24,
boxSizing: "border-box",
width: "100%",
borderRadius: 4
};
const placeholderStyle = {
fontSize: 13,
color: isDragActive ? colors.add : colors.darkgrey,
paddingTop: 8,
textAlign: "center"
};
return React.createElement(
View,
{
style: styles.container
},
React.createElement(QuestionHeader, {
form: form,
block: block,
currentPageIndex: currentPageIndex,
blockIndex: blockIndex,
allBlocks: allBlocks
}),
React.createElement(
View,
{
style: styles.inputContainer
},
React.createElement(
"div",
_extends(
{
style: dropStyle
},
getRootProps(),
{
className: "dropZone"
}
),
React.createElement(
"input",
_extends(
{
style: {
display: "none",
position: "absolute",
width: 0,
height: 0
}
},
getInputProps()
)
),
files.map((file, i) =>
React.createElement(FilePreview, {
removeFile: removeFile,
isPreview: isPreview,
file: file,
key: file.name + i
})
),
files.length === 0 &&
React.createElement(
Fragment,
null,
React.createElement(UploadIcon, {
size: 32
}),
React.createElement(
Text,
{
style: placeholderStyle
},
"Drop your files here or click to browse"
)
)
),
error &&
React.createElement(
Text,
{
style: styles.error
},
error
)
)
);
};
const styles = StyleSheet.create({
container: {
display: "flex",
flexDirection: "column",
alignItems: "center"
},
inputContainer: {
display: "flex",
width: "100%",
backgroundColor: "transparent",
alignItems: "flex-start",
maxWidth: MAX_FORM_WIDTH,
paddingHorizontal: 24,
paddingVertical: 24
},
error: {
fontSize: 14,
color: colors.error,
paddingVertical: 8,
paddingHorizontal: 4
}
});
export default memo(FilesUpload);