diff --git a/src/components/ErrorFallback.tsx b/src/components/ErrorFallback.tsx index 6a1cac2..eb76168 100644 --- a/src/components/ErrorFallback.tsx +++ b/src/components/ErrorFallback.tsx @@ -1,15 +1,22 @@ import React from 'react'; import Cookies from 'js-cookie'; -import { useToast, Flex, Box, Heading, Text } from '@chakra-ui/react'; +import { Flex, Box, Heading, Text } from '@chakra-ui/react'; import { MdError } from 'react-icons/md'; + +/** + * Hooks + */ +import { useEffect } from 'react'; +import { useToast } from '@chakra-ui/toast'; import { useRootStore } from '@educt/hooks/useRootStore'; +import { Redirect } from 'react-router'; const ErrorFallback: React.FC<{ error: any }> = props => { const { userStore, authStore } = useRootStore(); const { error } = props; const toast = useToast(); - React.useEffect(() => { + useEffect(() => { toast({ title: `${error.message}`, duration: 10000, isClosable: true, status: 'error' }); }); @@ -18,7 +25,7 @@ const ErrorFallback: React.FC<{ error: any }> = props => { userStore.me = null; authStore.setIsLoggedIn(false); Cookies.remove('logged_in'); - } + } else if (error.response.status === 404) return ; } return ( diff --git a/src/components/Forms/CourseForm/CourseForm.tsx b/src/components/Forms/CourseForm/CourseForm.tsx new file mode 100644 index 0000000..9183e10 --- /dev/null +++ b/src/components/Forms/CourseForm/CourseForm.tsx @@ -0,0 +1,210 @@ +import React from 'react'; +import { Button, Textarea, InputGroup, InputRightElement, Input } from '@chakra-ui/react'; +import { FormControl, FormLabel, FormHelperText } from '@chakra-ui/form-control'; +import { Flex, Box, Text, Divider, Stack } from '@chakra-ui/layout'; +import { Controller, UseFormReturn } from 'react-hook-form'; + +/** + * Types + */ +import { OptionType } from '@educt/types'; +import { UserRoleEnum } from '@educt/enums'; + +/** + * Components + */ +import AsyncSelect from '@educt/components/AsyncSelect'; +import FileSelect from '@educt/components/FileSelect'; + +/** + * Hooks + */ +import { useToast } from '@chakra-ui/toast'; +import { useRootStore } from '@educt/hooks/useRootStore'; +import { useErrorHandler } from 'react-error-boundary'; + +export type InputFields = { + title: string; + image?: File | undefined; + category_id: string; + description: string; + teacher_id: string; +}; + +export type CourseFormPropsType = { + onSubmit: () => Promise; + buttonLabel: string; + isLoading: boolean; + reactHookForm: UseFormReturn; +}; + +const CourseForm: React.FC = ({ onSubmit, buttonLabel, isLoading, reactHookForm }) => { + const { + control, + register, + watch, + formState: { errors, isDirty }, + } = reactHookForm; + + const { + userStore: { userService }, + categoryStore: { categoryService }, + } = useRootStore(); + const handleError = useErrorHandler(); + const toast = useToast(); + + /** + * Load users into select field + */ + const loadUsersOptions = async (): Promise => { + try { + const users = await userService.fetchAll({ limit: 12, role: UserRoleEnum.TEACHER }); + + return users.data.map(user => ({ + label: user.fullname, + value: user.id, + })); + } catch (error: any) { + if (error.response) { + toast({ title: 'Error' }); + } else { + handleError(error); + } + } + }; + + /** + * Load categories into select filed + */ + const loadCategoriesOptions = async (): Promise => { + try { + const categories = await categoryService.fetchAll(); + return categories.data.map(category => ({ + label: category.title, + value: category.id, + })); + } catch (error: any) { + if (error.response) { + toast({ title: 'Error' }); + } else { + handleError(error); + } + } + }; + + const watchTitle = watch('title'); + + return ( +
+ + + Name + + + 90 ? 'red.500' : 'gray.500'}> + {watchTitle?.length || 0}/90 + + } + /> + + e.g Web Development in Javascript + + {errors.title?.message} + + + + + Description +