feat: added materials uploader

This commit is contained in:
Sergey Yarkov 2022-01-05 01:29:44 +03:00
parent 359deec3bc
commit 03c8e3b8cc
4 changed files with 33 additions and 44 deletions

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React from 'react';
import * as helpres from '@educt/helpers'; import * as helpres from '@educt/helpers';
import { Stack, Flex, Box, Icon, Text, Input, IconButton, Button } from '@chakra-ui/react'; import { Stack, Flex, Box, Icon, Text, Input, IconButton, Button } from '@chakra-ui/react';
import { MdOutlineFilePresent } from 'react-icons/md'; import { MdOutlineFilePresent } from 'react-icons/md';
@ -12,12 +12,11 @@ import { FileSupportedFormatsEnum } from '@educt/enums';
type FilesUploaderPropsType = { type FilesUploaderPropsType = {
onChange: (files: File[]) => void; onChange: (files: File[]) => void;
files?: Array<File> | undefined; files?: File[] | undefined;
}; };
const FilesUploader: React.FC<FilesUploaderPropsType> = ({ onChange, files }) => { const FilesUploader: React.FC<FilesUploaderPropsType> = ({ onChange, files }) => {
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
const [selectedFiles, setSelectedFiles] = useState<Array<File>>([]);
const onSelectFileHandler = () => { const onSelectFileHandler = () => {
if (fileInputRef.current) { if (fileInputRef.current) {
@ -28,12 +27,9 @@ const FilesUploader: React.FC<FilesUploaderPropsType> = ({ onChange, files }) =>
/** /**
* Detach file * Detach file
*/ */
const onRemoveSelectedFileHandler = (selectedFile: File) => () => const onRemoveSelectedFileHandler = (selectedFile: File) => () => {
setSelectedFiles(selectedFiles => { onChange([...Array.from(files?.filter(file => file.name !== selectedFile.name) || [])]);
const updated = selectedFiles.filter(file => file.name !== selectedFile.name); };
onChange(updated);
return updated;
});
/** /**
* Attach file * Attach file
@ -41,20 +37,13 @@ const FilesUploader: React.FC<FilesUploaderPropsType> = ({ onChange, files }) =>
const onChangeFileHandler = (e: React.ChangeEvent<HTMLInputElement>) => { const onChangeFileHandler = (e: React.ChangeEvent<HTMLInputElement>) => {
e.preventDefault(); e.preventDefault();
const { files } = e.target; if (e.target.files && e.target.files.length !== 0) {
const isAlreadySelected = (files || []).find(selectedFile =>
if (files && files.length !== 0) { Array.from(e.target.files || []).some(file => file.name === selectedFile.name)
const isAlreadySelected = selectedFiles.find(selectedFile =>
Array.from(files).some(file => file.name === selectedFile.name)
); );
if (isAlreadySelected) return; if (isAlreadySelected) return;
onChange([...Array.from(files || []), ...e.target.files]);
setSelectedFiles(selectedFiles => {
const updated = [...selectedFiles, ...Array.from(files)];
onChange(updated);
return updated;
});
} }
}; };
@ -72,7 +61,7 @@ const FilesUploader: React.FC<FilesUploaderPropsType> = ({ onChange, files }) =>
/> />
{files && ( {files && (
<Stack> <Stack>
{selectedFiles.map((file, index) => ( {files.map((file, index) => (
<Flex <Flex
key={index} key={index}
alignItems={'center'} alignItems={'center'}

View File

@ -37,7 +37,6 @@ const LessonForm: React.FC<LessonFormPropsType> = ({ onSubmit, buttonLabel, isLo
const { const {
control, control,
register, register,
watch,
formState: { errors, isDirty }, formState: { errors, isDirty },
} = reactHookForm; } = reactHookForm;
@ -104,7 +103,7 @@ const LessonForm: React.FC<LessonFormPropsType> = ({ onSubmit, buttonLabel, isLo
)} )}
/> />
<Text as='small' color='red.500'> <Text as='small' color='red.500'>
{errors.materials?.map(m => m.message)} {errors.materials?.message}
</Text> </Text>
<FormHelperText> <FormHelperText>
Supported formats:{' '} Supported formats:{' '}

View File

@ -1,8 +1,8 @@
import { VideoSupportedFormatsEnum } from '@educt/enums'; import * as helpers from '@educt/helpers';
import yup from '@educt/schema'; import yup from '@educt/schema';
const VIDEO_FILE_SIZE = 5000 * 1024 * 1024; const VIDEO_FILE_SIZE = 5000 * 1024 * 1024;
const MATERIAL_FILE_SIZE = 10000 * 1024; const MATERIAL_FILE_SIZE = 100000 * 1024;
const LessonFormSchema = yup.object().shape({ const LessonFormSchema = yup.object().shape({
title: yup.string().required('Title field name is required').max(90, 'Title must be at most 90 characters'), title: yup.string().required('Title field name is required').max(90, 'Title must be at most 90 characters'),
@ -13,25 +13,26 @@ const LessonFormSchema = yup.object().shape({
duration: yup.string().required('Duration field name is required'), duration: yup.string().required('Duration field name is required'),
video: yup video: yup
.mixed() .mixed()
.test('fileSize', 'File size is too large', (value: File) => { .test(
'fileSize',
`File size is too large, maximum size is ${helpers.transformBytes(VIDEO_FILE_SIZE)}`,
(value: File) => {
if (!value) return true; if (!value) return true;
return value && value.size <= VIDEO_FILE_SIZE; return value && value.size <= VIDEO_FILE_SIZE;
}) }
.test('fileFormat', 'This file format is not supported', (value: File) => { )
if (!value) return true;
return value && Object.values(VideoSupportedFormatsEnum).includes(value.type as VideoSupportedFormatsEnum);
})
.required('Video field name is required'), .required('Video field name is required'),
// materials: yup materials: yup
// .mixed() .mixed()
// .test('fileSize', 'File size is too large', (value: File) => { .test(
// if (!value) return true; 'fileSize',
// return value && value.size <= VIDEO_FILE_SIZE; `File size is too large, maximum size is ${helpers.transformBytes(MATERIAL_FILE_SIZE)}`,
// }) (values: File[]) => {
// .test('fileFormat', 'This file format is not supported', (value: File) => { if (!values) return true;
// if (!value) return true; return values && values.every(value => value.size <= MATERIAL_FILE_SIZE);
// return value && VIDEO_SUPPORTED_FORMATS.includes(value.type); }
// }), )
.optional(),
}); });
export default LessonFormSchema; export default LessonFormSchema;

View File

@ -19,7 +19,7 @@ export enum VideoSupportedFormatsEnum {
export enum FileSupportedFormatsEnum { export enum FileSupportedFormatsEnum {
PDF = 'application/pdf', PDF = 'application/pdf',
ZIP = 'application/zip', ZIP = 'application/x-zip-compressed',
RAR = 'application/x-rar-compressed', RAR = 'application/x-rar-compressed',
DOC = 'application/msword', DOC = 'application/msword',
DOCX = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', DOCX = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',