mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
feat: added courses page store
This commit is contained in:
parent
9fb8b18b23
commit
d1d345ca88
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ButtonProps, Button } from '@chakra-ui/button';
|
import { ButtonProps, Button } from '@chakra-ui/button';
|
||||||
import { AddIcon, EditIcon } from '@chakra-ui/icons';
|
import { AddIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons';
|
||||||
import { MdSave } from 'react-icons/md';
|
import { MdSave } from 'react-icons/md';
|
||||||
|
|
||||||
export const CreateButton: React.FC<ButtonProps> = props => (
|
export const CreateButton: React.FC<ButtonProps> = props => (
|
||||||
@ -9,6 +9,12 @@ export const CreateButton: React.FC<ButtonProps> = props => (
|
|||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const DeleteButton: React.FC<ButtonProps> = props => (
|
||||||
|
<Button variant='outline' leftIcon={<DeleteIcon />} colorScheme='red' size='sm' {...props}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
export const EditButton: React.FC<ButtonProps> = props => (
|
export const EditButton: React.FC<ButtonProps> = props => (
|
||||||
<Button leftIcon={<EditIcon />} variant='outline' size='sm' {...props}>
|
<Button leftIcon={<EditIcon />} variant='outline' size='sm' {...props}>
|
||||||
Edit
|
Edit
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
import SetCourseStatusButton from './SetCourseStatusButton';
|
|
||||||
|
|
||||||
export default SetCourseStatusButton;
|
|
||||||
@ -15,19 +15,23 @@ import { CoursesPageContext } from '@educt/contexts';
|
|||||||
* Hooks
|
* Hooks
|
||||||
*/
|
*/
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
|
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||||
|
|
||||||
export type CategoryItemPropsType = {
|
export type CategoryItemPropsType = {
|
||||||
category: ICategory;
|
category: ICategory;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CategoryItem: React.FC<CategoryItemPropsType> = ({ category }) => {
|
const CategoryItem: React.FC<CategoryItemPropsType> = ({ category }) => {
|
||||||
const { selectedCategory, setSelectedCategory } = useContext(CoursesPageContext);
|
const {
|
||||||
const isSelected = selectedCategory?.id === category.id;
|
pageStore: { coursesStore },
|
||||||
|
} = useRootStore();
|
||||||
|
|
||||||
|
const isSelected = coursesStore.selectedCategory?.id === category.id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle click on change category
|
* Handle click on change category
|
||||||
*/
|
*/
|
||||||
const onCategoryChange = () => setSelectedCategory(category);
|
const onCategoryChange = () => coursesStore.setSelectedCategory(category);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tag
|
<Tag
|
||||||
|
|||||||
@ -29,8 +29,10 @@ type CategoryListPropsType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CategoryList: React.FC<CategoryListPropsType> = ({ render: Item }) => {
|
const CategoryList: React.FC<CategoryListPropsType> = ({ render: Item }) => {
|
||||||
const { categoryStore } = useRootStore();
|
const {
|
||||||
const { selectedCategory, setSelectedCategory } = useContext(CoursesPageContext);
|
categoryStore,
|
||||||
|
pageStore: { coursesStore },
|
||||||
|
} = useRootStore();
|
||||||
const handleError = useErrorHandler();
|
const handleError = useErrorHandler();
|
||||||
const { categories, isLoading } = categoryStore;
|
const { categories, isLoading } = categoryStore;
|
||||||
|
|
||||||
@ -51,11 +53,11 @@ const CategoryList: React.FC<CategoryListPropsType> = ({ render: Item }) => {
|
|||||||
<Flex sx={{ columnGap: '7px', rowGap: '5px' }} flexWrap='wrap'>
|
<Flex sx={{ columnGap: '7px', rowGap: '5px' }} flexWrap='wrap'>
|
||||||
<Tag
|
<Tag
|
||||||
borderRadius='full'
|
borderRadius='full'
|
||||||
variant={selectedCategory === undefined ? 'solid' : 'outline'}
|
variant={coursesStore.selectedCategory === null ? 'solid' : 'outline'}
|
||||||
cursor='pointer'
|
cursor='pointer'
|
||||||
transition='all .1s'
|
transition='all .1s'
|
||||||
_hover={{ opacity: '.8' }}
|
_hover={{ opacity: '.8' }}
|
||||||
onClick={() => setSelectedCategory(undefined)}
|
onClick={() => coursesStore.setSelectedCategory(null)}
|
||||||
>
|
>
|
||||||
<TagLabel>All categories</TagLabel>
|
<TagLabel>All categories</TagLabel>
|
||||||
</Tag>
|
</Tag>
|
||||||
|
|||||||
@ -36,12 +36,12 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
|
|||||||
const {
|
const {
|
||||||
userStore: { me },
|
userStore: { me },
|
||||||
courseStore,
|
courseStore,
|
||||||
|
pageStore: { coursesStore },
|
||||||
} = useRootStore();
|
} = useRootStore();
|
||||||
const [deleting, setDeleting] = useState<Pick<ICourse, 'id' | 'title'> | null>(null);
|
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, loadCourses } = courseStore;
|
||||||
|
|
||||||
const handleDeleteCourse = (course: Pick<ICourse, 'id' | 'title'>) => {
|
const handleDeleteCourse = (course: Pick<ICourse, 'id' | 'title'>) => {
|
||||||
setDeleting(course);
|
setDeleting(course);
|
||||||
@ -54,11 +54,11 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (me !== null) {
|
if (me !== null) {
|
||||||
courseStore.loadCourses({
|
courseStore.loadCourses({
|
||||||
category_id: selectedCategory?.id,
|
category_id: coursesStore.selectedCategory?.id,
|
||||||
status: me.isAdmin || me.isTeacher ? courseStatus : CourseStatusEnum.PUBLISHED,
|
status: me.isAdmin || me.isTeacher ? coursesStore.showedStatus : CourseStatusEnum.PUBLISHED,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [courseStore, selectedCategory, courseStatus]);
|
}, [courseStore, coursesStore.selectedCategory, coursesStore.showedStatus]);
|
||||||
|
|
||||||
if (courses === null || isLoading) return <LoadingList />;
|
if (courses === null || isLoading) return <LoadingList />;
|
||||||
|
|
||||||
@ -80,9 +80,9 @@ const CourseList: React.FC<CourseListPropsType> = ({ render: Item }) => {
|
|||||||
<Box textAlign='center' mt='10' userSelect='none'>
|
<Box textAlign='center' mt='10' userSelect='none'>
|
||||||
<Text color='gray.500'>
|
<Text color='gray.500'>
|
||||||
There are no courses
|
There are no courses
|
||||||
{!selectedCategory && !courseStatus
|
{!coursesStore.selectedCategory && !coursesStore.showedStatus
|
||||||
? 'in the system yet'
|
? 'in the system yet'
|
||||||
: `in this category${courseStatus ? ' or with this status' : ''}`}
|
: `in this category${coursesStore.showedStatus ? ' or with this status' : ''}`}
|
||||||
.
|
.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import { Tabs, TabList, Tab } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Types
|
|
||||||
*/
|
|
||||||
import { CourseStatusEnum } from '@educt/enums';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contexts
|
|
||||||
*/
|
|
||||||
import { CoursesPageContext } from '@educt/contexts';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hooks
|
|
||||||
*/
|
|
||||||
import { useContext } from 'react';
|
|
||||||
|
|
||||||
type CourseStatusTabsProps = {};
|
|
||||||
|
|
||||||
const CourseStatusTabs: React.FC<CourseStatusTabsProps> = () => {
|
|
||||||
const { setCourseStatus } = useContext(CoursesPageContext);
|
|
||||||
const handleChangeStatus = (status: CourseStatusEnum | undefined) => setCourseStatus(status);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tabs variant='solid-rounded'>
|
|
||||||
<TabList justifyContent='center'>
|
|
||||||
<Tab onClick={() => handleChangeStatus(undefined)}>All</Tab>
|
|
||||||
<Tab onClick={() => handleChangeStatus(CourseStatusEnum.PUBLISHED)}>Published</Tab>
|
|
||||||
<Tab onClick={() => handleChangeStatus(CourseStatusEnum.DRAFT)}>Unpublished Drafts</Tab>
|
|
||||||
</TabList>
|
|
||||||
</Tabs>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default CourseStatusTabs;
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
import CourseStatusTabs from './CourseStatusTabs';
|
|
||||||
|
|
||||||
export default CourseStatusTabs;
|
|
||||||
31
src/pages/courses/components/index.tsx
Normal file
31
src/pages/courses/components/index.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { BoxProps, Box } from '@chakra-ui/layout';
|
||||||
|
import { Tabs, TabList, Tab } from '@chakra-ui/tabs';
|
||||||
|
import { CourseStatusEnum } from '@educt/enums';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks
|
||||||
|
*/
|
||||||
|
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||||
|
|
||||||
|
export const CoursesTabs: React.FC<BoxProps> = props => {
|
||||||
|
const {
|
||||||
|
userStore: { me },
|
||||||
|
pageStore: { coursesStore },
|
||||||
|
} = useRootStore();
|
||||||
|
|
||||||
|
return (
|
||||||
|
me &&
|
||||||
|
(me.isAdmin || me.isTeacher ? (
|
||||||
|
<Box {...props}>
|
||||||
|
<Tabs variant='solid-rounded'>
|
||||||
|
<TabList justifyContent='center' {...props}>
|
||||||
|
<Tab onClick={() => coursesStore.setShowedStatus(undefined)}>All</Tab>
|
||||||
|
<Tab onClick={() => coursesStore.setShowedStatus(CourseStatusEnum.PUBLISHED)}>Published</Tab>
|
||||||
|
<Tab onClick={() => coursesStore.setShowedStatus(CourseStatusEnum.DRAFT)}>Unpublished Drafts</Tab>
|
||||||
|
</TabList>
|
||||||
|
</Tabs>
|
||||||
|
</Box>
|
||||||
|
) : null)
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box } from '@chakra-ui/react';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types
|
* Types
|
||||||
@ -10,22 +9,19 @@ import { IPageProps } from '@educt/interfaces';
|
|||||||
* Components
|
* Components
|
||||||
*/
|
*/
|
||||||
import { PageWrapper, PageHeading, PageContent } from '@educt/components/PageElements';
|
import { PageWrapper, PageHeading, PageContent } from '@educt/components/PageElements';
|
||||||
|
import { CreateButton } from '@educt/components/Buttons';
|
||||||
import LoadingPage from '@educt/components/LoadingPage';
|
import LoadingPage from '@educt/components/LoadingPage';
|
||||||
import CourseList from './components/CourseList';
|
import CourseList from './components/CourseList';
|
||||||
import CategoryList from './components/CategoryList';
|
import CategoryList from './components/CategoryList';
|
||||||
import CourseStatusTabs from './components/CourseStatusTabs';
|
|
||||||
import CategoryItem from './components/CategoryList/CategoryItem';
|
import CategoryItem from './components/CategoryList/CategoryItem';
|
||||||
import CourseItem from './components/CourseList/CourseItem';
|
import CourseItem from './components/CourseList/CourseItem';
|
||||||
|
|
||||||
/**
|
|
||||||
* Providers
|
|
||||||
*/
|
|
||||||
import { CoursesPageContextProvider } from '@educt/providers';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hooks
|
* Hooks
|
||||||
*/
|
*/
|
||||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||||
|
import { useHistory } from 'react-router';
|
||||||
|
import { CoursesTabs } from './components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Courses page
|
* Courses page
|
||||||
@ -34,22 +30,20 @@ const CoursesPage: React.FC<IPageProps> = () => {
|
|||||||
const {
|
const {
|
||||||
userStore: { me },
|
userStore: { me },
|
||||||
} = useRootStore();
|
} = useRootStore();
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
if (me === null) return <LoadingPage />;
|
if (me === null) return <LoadingPage />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CoursesPageContextProvider>
|
<PageWrapper>
|
||||||
<PageWrapper>
|
<PageHeading heading='Courses' description='List of all courses' />
|
||||||
<PageHeading heading='Courses' description='List of all courses' />
|
{(me.isAdmin || me.isTeacher) && <CreateButton onClick={() => history.push('/courses/create')} />}
|
||||||
<PageContent mt='10'>
|
<PageContent mt='10'>
|
||||||
{(me.isAdmin || me.isTeacher) && <CourseStatusTabs />}
|
<CoursesTabs mb='7' />
|
||||||
<Box mt='5'>
|
<CategoryList render={CategoryItem} />
|
||||||
<CategoryList render={CategoryItem} />
|
<CourseList render={CourseItem} />
|
||||||
<CourseList render={CourseItem} />
|
</PageContent>
|
||||||
</Box>
|
</PageWrapper>
|
||||||
</PageContent>
|
|
||||||
</PageWrapper>
|
|
||||||
</CoursesPageContextProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,20 +1,21 @@
|
|||||||
import React, { useState } from 'react';
|
import React from 'react';
|
||||||
import { Button } from '@chakra-ui/react';
|
import { ButtonProps, Button } from '@chakra-ui/button';
|
||||||
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai';
|
|
||||||
import { CourseStatusEnum } from '@educt/enums';
|
import { CourseStatusEnum } from '@educt/enums';
|
||||||
|
import { AiOutlineEye, AiOutlineEyeInvisible } from 'react-icons/ai';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks
|
||||||
|
*/
|
||||||
|
import { useState } from 'react';
|
||||||
import { useSetCourseStatus } from '@educt/hooks/queries';
|
import { useSetCourseStatus } from '@educt/hooks/queries';
|
||||||
|
|
||||||
type SetCourseStatusButtonPropsType = {
|
interface IStatusButtonProps extends ButtonProps {
|
||||||
courseId: string;
|
courseId: string;
|
||||||
currentStatus: CourseStatusEnum;
|
currentStatus: CourseStatusEnum;
|
||||||
loadingText?: string | undefined;
|
loadingText?: string | undefined;
|
||||||
};
|
}
|
||||||
|
export const StatusButton: React.FC<IStatusButtonProps> = props => {
|
||||||
const SetCourseStatusButton: React.FC<SetCourseStatusButtonPropsType> = ({
|
const { courseId, currentStatus, loadingText, ...btnProps } = props;
|
||||||
courseId,
|
|
||||||
currentStatus,
|
|
||||||
loadingText = 'Wait a second...',
|
|
||||||
}) => {
|
|
||||||
const [status, setStatus] = useState<keyof typeof CourseStatusEnum>(currentStatus);
|
const [status, setStatus] = useState<keyof typeof CourseStatusEnum>(currentStatus);
|
||||||
const { setCourseStatus, isLoading } = useSetCourseStatus();
|
const { setCourseStatus, isLoading } = useSetCourseStatus();
|
||||||
|
|
||||||
@ -28,8 +29,11 @@ const SetCourseStatusButton: React.FC<SetCourseStatusButtonPropsType> = ({
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => handleChangeStatus(CourseStatusEnum.DRAFT)}
|
onClick={() => handleChangeStatus(CourseStatusEnum.DRAFT)}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
loadingText={loadingText}
|
loadingText={loadingText || 'Saving...'}
|
||||||
leftIcon={<AiOutlineEyeInvisible />}
|
leftIcon={<AiOutlineEyeInvisible />}
|
||||||
|
size='sm'
|
||||||
|
variant='outline'
|
||||||
|
{...btnProps}
|
||||||
>
|
>
|
||||||
Mark as Draft
|
Mark as Draft
|
||||||
</Button>
|
</Button>
|
||||||
@ -38,8 +42,11 @@ const SetCourseStatusButton: React.FC<SetCourseStatusButtonPropsType> = ({
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => handleChangeStatus(CourseStatusEnum.PUBLISHED)}
|
onClick={() => handleChangeStatus(CourseStatusEnum.PUBLISHED)}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
loadingText={loadingText}
|
loadingText={loadingText || 'Saving...'}
|
||||||
leftIcon={<AiOutlineEye />}
|
leftIcon={<AiOutlineEye />}
|
||||||
|
size='sm'
|
||||||
|
variant='outline'
|
||||||
|
{...btnProps}
|
||||||
>
|
>
|
||||||
Publish course
|
Publish course
|
||||||
</Button>
|
</Button>
|
||||||
@ -48,5 +55,3 @@ const SetCourseStatusButton: React.FC<SetCourseStatusButtonPropsType> = ({
|
|||||||
|
|
||||||
return Components[status];
|
return Components[status];
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SetCourseStatusButton;
|
|
||||||
@ -1,8 +1,7 @@
|
|||||||
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, Button } from '@chakra-ui/react';
|
import { Box, Heading, Text, Tab, TabList, Flex, Tabs, TabPanels, TabPanel } from '@chakra-ui/react';
|
||||||
import { DeleteIcon } from '@chakra-ui/icons';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types
|
* Types
|
||||||
@ -14,7 +13,6 @@ import type { IPageProps } from '@educt/interfaces';
|
|||||||
*/
|
*/
|
||||||
import LoadingPage from '@educt/components/LoadingPage';
|
import LoadingPage from '@educt/components/LoadingPage';
|
||||||
import { EditCourseForm } from '@educt/components/Forms/CourseForm';
|
import { EditCourseForm } from '@educt/components/Forms/CourseForm';
|
||||||
import SetCourseStatusButton from '@educt/components/SetCourseStatusButton';
|
|
||||||
import DeleteCourseDialog from '@educt/components/Dialogs/DeleteCourseDialog';
|
import DeleteCourseDialog from '@educt/components/Dialogs/DeleteCourseDialog';
|
||||||
import { StudentTableList, StudentTableRow } from './components/StudentTableList';
|
import { StudentTableList, StudentTableRow } from './components/StudentTableList';
|
||||||
import LessonList from './components/LessonList';
|
import LessonList from './components/LessonList';
|
||||||
@ -26,6 +24,9 @@ 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';
|
import { useDisclosure } from '@chakra-ui/hooks';
|
||||||
|
import { PageContent, PageWrapper } from '@educt/components/PageElements';
|
||||||
|
import { DeleteButton } from '@educt/components/Buttons';
|
||||||
|
import { StatusButton } from './components';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Course editor
|
* Course editor
|
||||||
@ -53,55 +54,58 @@ const EditCoursePage: React.FC<IPageProps> = () => {
|
|||||||
if (!course || isLoading) return <LoadingPage />;
|
if (!course || isLoading) return <LoadingPage />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<PageWrapper>
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>Editing {course.title}</title>
|
<title>Editing {course.title}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
|
|
||||||
<DeleteCourseDialog course={course} onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />
|
<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>
|
||||||
<Text mt='2'>{course.title}</Text>
|
<Text mt='2'>{course.title}</Text>
|
||||||
</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} />
|
<StatusButton courseId={course.id} currentStatus={course.status} />
|
||||||
<Button onClick={onOpenDeleteDialog} ml='2' variant='outline' leftIcon={<DeleteIcon />} colorScheme='red'>
|
<DeleteButton onClick={onOpenDeleteDialog} ml='2' />
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box>
|
|
||||||
<Tabs isLazy mt='8'>
|
|
||||||
<TabList>
|
|
||||||
<Tab>Info</Tab>
|
|
||||||
<Tab>Lessons</Tab>
|
|
||||||
<Tab>Students</Tab>
|
|
||||||
</TabList>
|
|
||||||
|
|
||||||
<TabPanels>
|
<PageContent>
|
||||||
<TabPanel>
|
<Box>
|
||||||
<Box>
|
<Tabs isLazy mt='8'>
|
||||||
<EditCourseForm
|
<TabList>
|
||||||
defaultValues={{
|
<Tab>Info</Tab>
|
||||||
title: course.title,
|
<Tab>Lessons</Tab>
|
||||||
description: course.description,
|
<Tab>Students</Tab>
|
||||||
category_id: course.category.id,
|
</TabList>
|
||||||
teacher_id: course.teacher.id,
|
|
||||||
image: undefined,
|
<TabPanels>
|
||||||
}}
|
<TabPanel>
|
||||||
/>
|
<Box>
|
||||||
</Box>
|
<EditCourseForm
|
||||||
</TabPanel>
|
defaultValues={{
|
||||||
<TabPanel>
|
title: course.title,
|
||||||
<LessonList course={course} />
|
description: course.description,
|
||||||
</TabPanel>
|
category_id: course.category.id,
|
||||||
<TabPanel>
|
teacher_id: course.teacher.id,
|
||||||
<StudentTableList render={StudentTableRow} students={course.students} />
|
image: undefined,
|
||||||
</TabPanel>
|
}}
|
||||||
</TabPanels>
|
/>
|
||||||
</Tabs>
|
</Box>
|
||||||
</Box>
|
</TabPanel>
|
||||||
</>
|
<TabPanel>
|
||||||
|
<LessonList course={course} />
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel>
|
||||||
|
<StudentTableList render={StudentTableRow} students={course.students} />
|
||||||
|
</TabPanel>
|
||||||
|
</TabPanels>
|
||||||
|
</Tabs>
|
||||||
|
</Box>
|
||||||
|
</PageContent>
|
||||||
|
</PageWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
import { makeAutoObservable } from 'mobx';
|
import { makeAutoObservable } from 'mobx';
|
||||||
|
import CoursesStore from './pages/CoursesStore';
|
||||||
import EditCourseStore from './pages/EditCourseStore';
|
import EditCourseStore from './pages/EditCourseStore';
|
||||||
import RootStore from './RootStore';
|
import RootStore from './RootStore';
|
||||||
|
|
||||||
export default class PageStore {
|
export default class PageStore {
|
||||||
public root: RootStore;
|
public root: RootStore;
|
||||||
|
|
||||||
|
public coursesStore: CoursesStore;
|
||||||
|
|
||||||
public editCourseStore: EditCourseStore;
|
public editCourseStore: EditCourseStore;
|
||||||
|
|
||||||
constructor(root: RootStore) {
|
constructor(root: RootStore) {
|
||||||
@ -13,6 +16,7 @@ export default class PageStore {
|
|||||||
/**
|
/**
|
||||||
* Pages
|
* Pages
|
||||||
*/
|
*/
|
||||||
|
this.coursesStore = new CoursesStore(this);
|
||||||
this.editCourseStore = new EditCourseStore(this);
|
this.editCourseStore = new EditCourseStore(this);
|
||||||
|
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
|
|||||||
30
src/stores/pages/CoursesStore.ts
Normal file
30
src/stores/pages/CoursesStore.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { makeAutoObservable } from 'mobx';
|
||||||
|
import { CourseStatusEnum } from '@educt/enums';
|
||||||
|
import PageStore from '../PageStore';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Types
|
||||||
|
*/
|
||||||
|
import type { ICategory } from '@educt/interfaces';
|
||||||
|
|
||||||
|
export default class CoursesStore {
|
||||||
|
public pageStore: PageStore;
|
||||||
|
|
||||||
|
public selectedCategory: ICategory | null = null;
|
||||||
|
|
||||||
|
public showedStatus: CourseStatusEnum | undefined;
|
||||||
|
|
||||||
|
constructor(pageStore: PageStore) {
|
||||||
|
this.pageStore = pageStore;
|
||||||
|
|
||||||
|
makeAutoObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public setSelectedCategory(category: ICategory | null): void {
|
||||||
|
this.selectedCategory = category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public setShowedStatus(newStatus: CourseStatusEnum | undefined): void {
|
||||||
|
this.showedStatus = newStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user