feat: delete course from edit page

This commit is contained in:
Sergey Yarkov 2021-12-03 00:19:04 +03:00
parent 321149a1f2
commit 3db6174b8b
7 changed files with 53 additions and 26 deletions

View File

@ -1,4 +1,4 @@
import React, { useContext } from 'react'; import React from 'react';
/** /**
* Types * Types
@ -10,15 +10,12 @@ import { ICourse } from '@educt/interfaces';
*/ */
import ConfirmDialog from '@educt/components/ConfirmDialog/ConfirmDialog'; import ConfirmDialog from '@educt/components/ConfirmDialog/ConfirmDialog';
/**
* Contexts
*/
import { CoursesPageContext } from '@educt/contexts';
/** /**
* Hooks * Hooks
*/ */
import { useDeleteCourse } from '@educt/hooks/queries/course/useDeleteCourse'; import { useDeleteCourse } from '@educt/hooks/queries/course/useDeleteCourse';
import { useHistory, useLocation } from 'react-router';
import useIsMountedRef from '@educt/hooks/useIsMountedRef';
type DeleteCourseDialogPropsType = { type DeleteCourseDialogPropsType = {
course: Pick<ICourse, 'id' | 'title'>; course: Pick<ICourse, 'id' | 'title'>;
@ -27,24 +24,29 @@ type DeleteCourseDialogPropsType = {
}; };
const DeleteCourseDialog: React.FC<DeleteCourseDialogPropsType> = ({ onClose, isOpen, course }) => { const DeleteCourseDialog: React.FC<DeleteCourseDialogPropsType> = ({ onClose, isOpen, course }) => {
const { setDeletingCourse } = useContext(CoursesPageContext);
const { deleteCourse, isLoading } = useDeleteCourse(); const { deleteCourse, isLoading } = useDeleteCourse();
const isMountedRef = useIsMountedRef();
const history = useHistory();
const location = useLocation();
const handleDelete = async (isConfirmed: boolean, id: string) => { const handleDelete = async (isConfirmed: boolean, id: string) => {
if (isConfirmed) { if (isConfirmed) {
try { try {
await deleteCourse(id); await deleteCourse(id);
if (isMountedRef.current && location.pathname !== '/courses') {
history.push('/courses');
}
} catch (error: any) { } catch (error: any) {
console.error(error); console.error(error);
} finally {
setDeletingCourse(undefined);
} }
} }
if (isMountedRef.current) {
/** /**
* Close dialog * Close dialog
*/ */
onClose(); onClose();
}
}; };
return ( return (

View File

@ -21,6 +21,7 @@ type DeleteLessonDialogPropsType = {
onClose: () => void; onClose: () => void;
}; };
//TODO pass lesson by prop
const DeleteLessonDialog: React.FC<DeleteLessonDialogPropsType> = ({ isOpen, onClose }) => { const DeleteLessonDialog: React.FC<DeleteLessonDialogPropsType> = ({ isOpen, onClose }) => {
const { const {
pageStore: { pageStore: {
@ -31,7 +32,11 @@ const DeleteLessonDialog: React.FC<DeleteLessonDialogPropsType> = ({ isOpen, onC
const handleDelete = async (isConfirmed: boolean) => { const handleDelete = async (isConfirmed: boolean) => {
if (isConfirmed && deletingLesson) { if (isConfirmed && deletingLesson) {
try {
await deleteLesson(deletingLesson.id); await deleteLesson(deletingLesson.id);
} catch (error: any) {
console.error(error);
}
} }
/** /**

View File

@ -29,6 +29,8 @@ export const CoursesPageContext = createContext<CoursesPageContextType>({
setSelectedCategory: () => {}, setSelectedCategory: () => {},
courseStatus: undefined, courseStatus: undefined,
setCourseStatus: () => {}, setCourseStatus: () => {},
//TODO: remove
deletingCourse: undefined, deletingCourse: undefined,
setDeletingCourse: () => {}, setDeletingCourse: () => {},
}); });

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useState } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Box, Grid, Text } from '@chakra-ui/react'; import { Box, Grid, Text } from '@chakra-ui/react';
@ -11,7 +11,7 @@ import { CourseItemPropsType } from './CourseItem';
/** /**
* Components * Components
*/ */
import DeleteCourseDialog from '../DeleteCourseDialog'; import DeleteCourseDialog from '@educt/components/Dialogs/DeleteCourseDialog';
import LoadingList from '@educt/components/LoadingList'; import LoadingList from '@educt/components/LoadingList';
/** /**
@ -26,6 +26,7 @@ import { useDisclosure } from '@chakra-ui/hooks';
* Contexts * Contexts
*/ */
import { CoursesPageContext } from '@educt/contexts'; import { CoursesPageContext } from '@educt/contexts';
import { ICourse } from '@educt/interfaces';
type CourseListPropsType = { type CourseListPropsType = {
render: React.FC<CourseItemPropsType>; render: React.FC<CourseItemPropsType>;
@ -36,11 +37,17 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
userStore: { me }, userStore: { me },
courseStore, courseStore,
} = useRootStore(); } = useRootStore();
const { selectedCategory, courseStatus, deletingCourse, setDeletingCourse } = useContext(CoursesPageContext); const [deleting, setDeleting] = useState<Pick<ICourse, 'id' | 'title'> | null>(null);
const { selectedCategory, courseStatus } = useContext(CoursesPageContext);
const { onOpen: onOpenDeleteDialog, onClose: onCloseDeleteDialog, isOpen: isOpenDeleteDialog } = useDisclosure(); const { onOpen: onOpenDeleteDialog, onClose: onCloseDeleteDialog, isOpen: isOpenDeleteDialog } = useDisclosure();
const { setCourseStatus } = useSetCourseStatus(); const { setCourseStatus } = useSetCourseStatus();
const { courses, isLoading } = courseStore; const { courses, isLoading } = courseStore;
const deleteHandler = (course: Pick<ICourse, 'id' | 'title'>) => {
setDeleting(course);
onOpenDeleteDialog();
};
/** /**
* Fetch courses handler * Fetch courses handler
*/ */
@ -57,19 +64,14 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
return ( return (
<Box> <Box>
{deletingCourse && ( {deleting && <DeleteCourseDialog course={deleting} onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />}
<DeleteCourseDialog course={deletingCourse} onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />
)}
{courses.length !== 0 ? ( {courses.length !== 0 ? (
<Grid templateColumns={{ sm: 'repeat(auto-fill, minmax(400px, 1fr))' }} gap='4'> <Grid templateColumns={{ sm: 'repeat(auto-fill, minmax(400px, 1fr))' }} gap='4'>
{courses.map(course => ( {courses.map(course => (
<Item <Item
key={course.id} key={course.id}
course={course} course={course}
onDelete={() => { onDelete={() => deleteHandler({ id: course.id, title: course.title })}
setDeletingCourse(course);
onOpenDeleteDialog();
}}
onSetStatus={setCourseStatus} onSetStatus={setCourseStatus}
/> />
))} ))}

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import Helmet from 'react-helmet'; import Helmet from 'react-helmet';
import { Redirect } from 'react-router-dom'; import { Redirect } from 'react-router-dom';
import { Box, Heading, Text, Tab, TabList, Flex, Tabs, TabPanels, TabPanel } from '@chakra-ui/react'; import { Box, Heading, Text, Tab, TabList, Flex, Tabs, TabPanels, TabPanel, Button } from '@chakra-ui/react';
import { DeleteIcon } from '@chakra-ui/icons';
/** /**
* Types * Types
@ -16,6 +17,7 @@ import { EditCourseForm } from '@educt/components/Forms/CourseForm';
import SetCourseStatusButton from '@educt/components/SetCourseStatusButton'; import SetCourseStatusButton from '@educt/components/SetCourseStatusButton';
import LessonList from './components/LessonList'; import LessonList from './components/LessonList';
import { StudentList, StudentItem } from './components/StudentList'; import { StudentList, StudentItem } from './components/StudentList';
import DeleteCourseDialog from '@educt/components/Dialogs/DeleteCourseDialog';
/** /**
* Hooks * Hooks
@ -23,6 +25,7 @@ import { StudentList, StudentItem } from './components/StudentList';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { useFetchCourse } from '@educt/hooks/queries'; import { useFetchCourse } from '@educt/hooks/queries';
import { useDisclosure } from '@chakra-ui/hooks';
/** /**
* Course editor * Course editor
@ -35,6 +38,7 @@ const EditCoursePage: React.FC<IPageProps> = () => {
}, },
} = useRootStore(); } = useRootStore();
const { error, isLoading } = useFetchCourse(params.id); const { error, isLoading } = useFetchCourse(params.id);
const { onOpen: onOpenDeleteDialog, onClose: onCloseDeleteDialog, isOpen: isOpenDeleteDialog } = useDisclosure();
/** /**
* Not Found * Not Found
@ -53,6 +57,7 @@ const EditCoursePage: React.FC<IPageProps> = () => {
<Helmet> <Helmet>
<title>Editing {course.title}</title> <title>Editing {course.title}</title>
</Helmet> </Helmet>
<DeleteCourseDialog course={course} onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />
<Flex justifyContent='space-between' alignItems='center' flexWrap='wrap'> <Flex justifyContent='space-between' alignItems='center' flexWrap='wrap'>
<Box mr='3'> <Box mr='3'>
<Heading as='h1'>Course editor</Heading> <Heading as='h1'>Course editor</Heading>
@ -60,6 +65,9 @@ const EditCoursePage: React.FC<IPageProps> = () => {
</Box> </Box>
<Box ml='auto' alignSelf='flex-end' justifySelf='flex-end' mt={{ base: '7', md: '0' }}> <Box ml='auto' alignSelf='flex-end' justifySelf='flex-end' mt={{ base: '7', md: '0' }}>
<SetCourseStatusButton courseId={course.id} currentStatus={course.status} /> <SetCourseStatusButton courseId={course.id} currentStatus={course.status} />
<Button onClick={onOpenDeleteDialog} ml='2' variant='outline' leftIcon={<DeleteIcon />} colorScheme='red'>
Delete
</Button>
</Box> </Box>
</Flex> </Flex>
<Box> <Box>

View File

@ -10,6 +10,10 @@ export default class EditCourseStore {
public course: Omit<ICourse, 'students_count' | 'likes_count' | 'lessons_count'> | null = null; public course: Omit<ICourse, 'students_count' | 'likes_count' | 'lessons_count'> | null = null;
public isDeleting: boolean = false;
public deletingCourse: Pick<ICourse, 'id' | 'title'> | undefined;
public deletingLesson: ILesson | undefined; public deletingLesson: ILesson | undefined;
constructor(pageStore: PageStore) { constructor(pageStore: PageStore) {
@ -72,7 +76,11 @@ export default class EditCourseStore {
} }
} }
setDeletingLesson(lesson: ILesson) { public setDeletingLesson(lesson: ILesson) {
this.deletingLesson = lesson; this.deletingLesson = lesson;
} }
public setDeletingCourse(course: Pick<ICourse, 'id' | 'title'> | undefined) {
this.deletingCourse = course;
}
} }