mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
feat: course status badge
This commit is contained in:
parent
962e43c81c
commit
02b2a4ee43
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,7 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
.env
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
|
||||
30
src/components/CourseStatusBadge/CourseStatusBadge.tsx
Normal file
30
src/components/CourseStatusBadge/CourseStatusBadge.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { Badge } from '@chakra-ui/layout';
|
||||
import { CourseStatusEnum } from 'enums';
|
||||
import React from 'react';
|
||||
|
||||
type CourseStatusBadgeProps = {
|
||||
status: CourseStatusEnum;
|
||||
};
|
||||
|
||||
const CourseStatusBadge: React.FC<CourseStatusBadgeProps> = ({ status }) => {
|
||||
return (
|
||||
<>
|
||||
{(() => {
|
||||
switch (status) {
|
||||
case CourseStatusEnum.PUBLISHED:
|
||||
return (
|
||||
<Badge variant='subtle' colorScheme='green'>
|
||||
Published
|
||||
</Badge>
|
||||
);
|
||||
case CourseStatusEnum.DRAFT:
|
||||
return <Badge variant='subtle'>Draft</Badge>;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
})()}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CourseStatusBadge;
|
||||
3
src/components/CourseStatusBadge/index.ts
Normal file
3
src/components/CourseStatusBadge/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import CourseStatusBadge from './CourseStatusBadge';
|
||||
|
||||
export default CourseStatusBadge;
|
||||
@ -4,6 +4,11 @@ import { CoursesPageContext } from 'contexts';
|
||||
import CategoryItem from './CategoryItem';
|
||||
import { ICategory } from 'interfaces';
|
||||
import CategoryListLoading from './CategoryListLoading';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
import { useRootStore } from 'hooks/useRootStore';
|
||||
|
||||
type CategoryListPropsType = {
|
||||
@ -12,16 +17,13 @@ type CategoryListPropsType = {
|
||||
};
|
||||
|
||||
const CategoryList: React.FC<CategoryListPropsType> = ({ categories, isLoading }) => {
|
||||
const { courseStore } = useRootStore();
|
||||
const { categoryStore } = useRootStore();
|
||||
const { selectedCategory, setSelectedCategory } = useContext(CoursesPageContext);
|
||||
const handleError = useErrorHandler();
|
||||
|
||||
/**
|
||||
* Handle on changing category
|
||||
*/
|
||||
useEffect(() => {
|
||||
console.log(`[LOG:] Selected category: ${selectedCategory?.title}`);
|
||||
courseStore.loadCourses({ category_id: selectedCategory?.id });
|
||||
}, [courseStore, selectedCategory]);
|
||||
categoryStore.loadCategories().catch(error => handleError(error));
|
||||
}, [categoryStore, handleError]);
|
||||
|
||||
if (isLoading || categories === null) {
|
||||
return <CategoryListLoading />;
|
||||
|
||||
@ -28,6 +28,7 @@ import { ICourse } from 'interfaces';
|
||||
*/
|
||||
import { useColorMode } from '@chakra-ui/color-mode';
|
||||
import { useRootStore } from 'hooks/useRootStore';
|
||||
import CourseStatusBadge from 'components/CourseStatusBadge';
|
||||
|
||||
type CourseItemPropsType = {
|
||||
course: Omit<ICourse, 'teacher' | 'students' | 'lessons'>;
|
||||
@ -97,7 +98,10 @@ const CourseItem: React.FC<CourseItemPropsType> = ({ course }) => {
|
||||
/>
|
||||
</Box>
|
||||
<Box p='0 10px' mt='10px' pb='20px'>
|
||||
<Badge colorScheme='blue'>{course.category.title}</Badge>
|
||||
<Flex justifyContent='space-between'>
|
||||
<Badge colorScheme='blue'>{course.category.title}</Badge>
|
||||
{(me.isAdmin || me.isTeacher) && <CourseStatusBadge status={course.status} />}
|
||||
</Flex>
|
||||
<Heading as='h2' fontSize='xl' mt='5px'>
|
||||
{course.title}
|
||||
</Heading>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Grid } from '@chakra-ui/react';
|
||||
import React, { useContext, useEffect } from 'react';
|
||||
import { Box, Grid, Text } from '@chakra-ui/react';
|
||||
|
||||
/**
|
||||
* Types
|
||||
@ -12,33 +12,58 @@ import { ICourse } from 'interfaces';
|
||||
import CourseItem from './CourseItem';
|
||||
import CourseListLoading from './CourseListLoading';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useRootStore } from 'hooks/useRootStore';
|
||||
|
||||
/**
|
||||
* Contexts
|
||||
*/
|
||||
import { CoursesPageContext } from 'contexts';
|
||||
|
||||
type CourseListPropsType = {
|
||||
courses: Omit<ICourse, 'teacher' | 'students' | 'lessons'>[] | null;
|
||||
isLoading: boolean;
|
||||
};
|
||||
|
||||
const CourseList: React.FC<CourseListPropsType> = ({ courses, isLoading }) => {
|
||||
const { courseStore } = useRootStore();
|
||||
const { selectedCategory } = useContext(CoursesPageContext);
|
||||
|
||||
useEffect(() => {
|
||||
courseStore.loadCourses({ category_id: selectedCategory?.id });
|
||||
}, [courseStore, selectedCategory]);
|
||||
|
||||
if (isLoading || courses === null) {
|
||||
return <CourseListLoading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Grid
|
||||
templateColumns='repeat(3, 1fr)'
|
||||
gap='6'
|
||||
sx={{
|
||||
'@media (max-width: 1280px)': {
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
},
|
||||
'@media (max-width: 768px)': {
|
||||
gridTemplateColumns: 'repeat(1, 1fr)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{courses.map(course => {
|
||||
return <CourseItem key={course.id} course={course} />;
|
||||
})}
|
||||
</Grid>
|
||||
<>
|
||||
{courses.length !== 0 ? (
|
||||
<Grid
|
||||
templateColumns='repeat(3, 1fr)'
|
||||
gap='6'
|
||||
sx={{
|
||||
'@media (max-width: 1280px)': {
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
},
|
||||
'@media (max-width: 768px)': {
|
||||
gridTemplateColumns: 'repeat(1, 1fr)',
|
||||
},
|
||||
}}
|
||||
>
|
||||
{courses.map(course => (
|
||||
<CourseItem key={course.id} course={course} />
|
||||
))}
|
||||
</Grid>
|
||||
) : (
|
||||
<Box textAlign='center' mt='10' userSelect='none'>
|
||||
<Text color='gray.500'>There are no courses in this category.</Text>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Flex, Tabs, TabList, Tab, Box, Heading, Text, Button } from '@chakra-ui/react';
|
||||
|
||||
@ -10,14 +10,13 @@ import { AddIcon } from '@chakra-ui/icons';
|
||||
*/
|
||||
import CourseList from './components/CourseList';
|
||||
import CategoryList from './components/CategoryList';
|
||||
import LoadingPage from 'components/LoadingPage';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useRootStore } from 'hooks/useRootStore';
|
||||
import { CoursesPageContextProvider } from 'providers';
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
import LoadingPage from 'components/LoadingPage';
|
||||
|
||||
/**
|
||||
* Courses page
|
||||
@ -28,14 +27,6 @@ const CoursesPage: React.FC<IPageProps> = ({ title }) => {
|
||||
categoryStore,
|
||||
courseStore,
|
||||
} = useRootStore();
|
||||
const handleError = useErrorHandler();
|
||||
|
||||
useEffect(() => {
|
||||
if (me !== null) {
|
||||
categoryStore.loadCategories().catch(error => handleError(error));
|
||||
// courseStore.loadCourses().catch(error => handleError(error));
|
||||
}
|
||||
}, [me, categoryStore, handleError]);
|
||||
|
||||
if (me === null) return <LoadingPage />;
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ const UpdateUserContactsForm: React.FC<UpdateUserContactsFormProps> = ({ contact
|
||||
<Box>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<Box boxShadow='sm' borderRadius='sm' borderWidth='1px' padding='20px'>
|
||||
<Heading as='h3' size='lg'>
|
||||
<Heading as='h3' size='md'>
|
||||
My Contacts
|
||||
</Heading>
|
||||
<Stack spacing='5px' margin='20px 0'>
|
||||
|
||||
@ -12,7 +12,7 @@ const UserAccountInfo: React.FC<UserAccountInfoPropsType> = ({ user }) => {
|
||||
|
||||
return (
|
||||
<Box borderRadius='md' borderWidth='1px' padding='20px' boxShadow='sm'>
|
||||
<Heading as='h3' size='lg'>
|
||||
<Heading as='h3' size='md'>
|
||||
Account information
|
||||
</Heading>
|
||||
<Stack spacing='10px' mt='20px' divider={<StackDivider />}>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user