feat: added new field to course model

This commit is contained in:
Sergey Yarkov 2021-12-18 21:01:53 +03:00
parent 329995fcda
commit eb1fd5d084
12 changed files with 53 additions and 20 deletions

View File

@ -31,6 +31,7 @@ export type InputFields = {
image?: File | undefined;
category_id: string;
description: string;
education_description: string | null;
teacher_id: string;
};
@ -84,6 +85,7 @@ const CourseForm: React.FC<CourseFormPropsType> = ({ onSubmit, buttonLabel, isLo
const watchTitle = watch('title');
const watchDescription = watch('description');
const watchEducationDescription = watch('education_description');
return (
<form onSubmit={onSubmit}>
@ -117,6 +119,26 @@ const CourseForm: React.FC<CourseFormPropsType> = ({ onSubmit, buttonLabel, isLo
</Flex>
</FormControl>
<FormControl id='education_description' isInvalid={!!errors.education_description}>
<FormLabel>What you&apos;ll learn section</FormLabel>
<Textarea resize='none' minH='80px' {...register('education_description')} />
<Flex justifyContent='space-between'>
<Text as='small' color='red.500'>
{errors.education_description?.message}
</Text>
{watchEducationDescription && (
<Text
as='small'
color={
!!errors.education_description || watchEducationDescription.length > 250 ? 'red.500' : 'gray.500'
}
>
{watchEducationDescription.length || 0}/250
</Text>
)}
</Flex>
</FormControl>
<Flex justifyContent='space-between' flexDirection={{ base: 'column', lg: 'row' }}>
<Box flexGrow={1} flexBasis='0' mr={{ base: '0', lg: '7' }}>
<Stack spacing='5'>

View File

@ -9,6 +9,7 @@ const CreateCourseSchema = yup.object().shape({
.string()
.required('Description field name is required')
.max(250, 'Description must be at most 250 characters'),
education_description: yup.string().max(250, 'This section must be at most 250 characters').nullable(),
image: yup
.mixed()
.test('fileSize', 'File size is too large', (value: File) => {

View File

@ -39,6 +39,7 @@ const CreateFormCourse: React.FC = () => {
const course = await createCourse({
title: data.title,
description: data.description,
education_description: data.education_description,
teacher_id: data.teacher_id,
category_id: data.category_id,
image: data.image,

View File

@ -32,6 +32,7 @@ type EditFormCoursePropsType = {
image?: File | undefined;
category_id?: string | undefined;
description?: string | undefined;
education_description?: string | null | undefined;
teacher_id?: string | undefined;
}
| undefined;
@ -43,6 +44,7 @@ const EditFormCourse: React.FC<EditFormCoursePropsType> = ({ defaultValues }) =>
defaultValues: {
title: defaultValues?.title || '',
description: defaultValues?.description || '',
education_description: defaultValues?.education_description || '',
category_id: defaultValues?.category_id || '',
teacher_id: defaultValues?.teacher_id || '',
image: undefined,
@ -56,16 +58,17 @@ const EditFormCourse: React.FC<EditFormCoursePropsType> = ({ defaultValues }) =>
*/
const onSubmit: SubmitHandler<InputFields> = async data => {
try {
const updated = await updateCourse(id, data);
const updatedCourse = await updateCourse(id, data);
/**
* Update fields with new values
*/
form.reset({
title: updated.title,
description: updated.description,
teacher_id: updated.teacher.id,
category_id: updated.category.id,
title: updatedCourse.title,
description: updatedCourse.description,
education_description: updatedCourse.education_description,
teacher_id: updatedCourse.teacher.id,
category_id: updatedCourse.category.id,
image: undefined,
});
} catch (error) {

View File

@ -1,9 +1,9 @@
import React from 'react';
import { observer } from 'mobx-react';
import { Link } from 'react-router-dom';
import { Link as ReactRouterLink } from 'react-router-dom';
import { IconButton, Skeleton } from '@chakra-ui/react';
import { Avatar } from '@chakra-ui/avatar';
import { Flex, Box, Text } from '@chakra-ui/layout';
import { Flex, Box, Text, Link } from '@chakra-ui/layout';
import { Drawer, DrawerOverlay, DrawerContent, DrawerBody } from '@chakra-ui/modal';
import { MdExitToApp } from 'react-icons/md';
import { HamburgerIcon } from '@chakra-ui/icons';
@ -55,20 +55,20 @@ const NavMobile: React.FC = () => {
<Flex alignItems='center'>
<Avatar size='sm' name={me.fullname} marginRight={3} />
<Flex flexDirection='column'>
<Text as='span' mr={2} lineHeight='1.2'>
<Text as='span' fontWeight={'semibold'} fontSize={'sm'} mr={2} lineHeight='1.2'>
{me.fullname}
</Text>
<Link to={`/profile`} style={{ fontSize: '13px', textDecoration: 'underline' }} onClick={onClose}>
<Link
as={ReactRouterLink}
fontSize={'sm'}
to={`/profile`}
style={{ fontSize: '13px', textDecoration: 'underline' }}
onClick={onClose}
>
View profile
</Link>
</Flex>
<IconButton
onClick={logout}
aria-label='Logout'
backgroundColor={colorMode === 'dark' ? 'gray.600' : 'gray.200'}
marginLeft='auto'
icon={<MdExitToApp />}
/>
<IconButton onClick={logout} aria-label='Logout' marginLeft='auto' icon={<MdExitToApp />} />
</Flex>
</Box>
) : (

View File

@ -31,6 +31,7 @@ export function userContainRoles(userRoles: IUserRole[], roles: UserRoleEnum[]):
* @returns Clean object that don't have null values
*/
export function removeEmptyValues(obj: object) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return Object.fromEntries(Object.entries(obj).filter(([_, value]) => value !== null));
}
@ -47,7 +48,7 @@ export function transformToFormData(data: object): FormData {
* Append value to form-data format
*/
Object.entries(data).forEach(([key, value]) => {
if (value) {
if (value !== undefined) {
if (Array.isArray(value)) {
value.forEach((v, i) => formData.append(`${key}[${i}]`, v));
return;

View File

@ -17,6 +17,7 @@ const useCreateCourse = () => {
const result = await CourseServiceInstance.create({
title: data.title,
description: data.description,
education_description: data.education_description,
teacher_id: data.teacher_id,
category_id: data.category_id,
image: data.image,

View File

@ -16,6 +16,7 @@ const useUpdateCourse = () => {
const result = await CourseServiceInstance.update(id, {
title: data.title,
description: data.description,
education_description: data.education_description,
teacher_id: data.teacher_id,
category_id: data.category_id,
image: data.image,

View File

@ -23,6 +23,7 @@ export interface ICourse {
image: AttachmentFileType | null;
title: string;
description: string;
education_description: string | null;
status: CourseStatusEnum;
teacher: Pick<IUser, 'id' | 'first_name' | 'fullname' | 'last_name' | 'email' | 'created_at' | 'updated_at'>;
category: ICategory;

View File

@ -114,14 +114,13 @@ const CoursePage: React.FC<IPageProps> = () => {
<Divider mt='5' />
</GridItem>
<GridItem borderRadius={'lg'} minWidth={'290px'} h='550px'>
<GridItem borderRadius={'lg'} minWidth={'290px'} h='550px' p={{ base: '4', xl: '0px' }}>
<Box>
<Text fontSize={'2xl'} fontWeight={'medium'}>
What you&apos;ll learn.
</Text>
<Text fontSize={'sm'} mt='2'>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Iste temporibus harum eos praesentium hic,
sunt corporis deserunt impedit natus consequuntur?
{course.education_description}
</Text>
</Box>

View File

@ -75,6 +75,7 @@ const EditCoursePage: React.FC<IPageProps> = () => {
defaultValues={{
title: course.title,
description: course.description,
education_description: course.education_description,
category_id: course.category.id,
teacher_id: course.teacher.id,
image: undefined,

View File

@ -127,6 +127,7 @@ export type UpdateUserContactsParamsType = {
export type CreateCourseParamsType = {
title: string;
description: string;
education_description: string | null;
teacher_id: string;
category_id: string;
image?: File | undefined;
@ -136,6 +137,7 @@ export type CreateCourseParamsType = {
export type UpdateCourseParamsType = {
title?: string | undefined;
description?: string | undefined;
education_description?: string | null | undefined;
teacher_id?: string | undefined;
category_id?: string | undefined;
image?: File | undefined;