mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
feat: delete course from edit page
This commit is contained in:
parent
321149a1f2
commit
3db6174b8b
@ -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 (
|
||||||
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -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: () => {},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user