feat: added course list in profile page

This commit is contained in:
Sergey Yarkov 2021-09-09 20:52:55 +03:00
parent 6a5f0ee305
commit e8ca606a20
8 changed files with 125 additions and 37 deletions

View File

@ -19,6 +19,9 @@ export interface ICourse {
category: ICategory;
lessons: ILesson[];
students: Pick<IUser, 'id' | 'first_name' | 'last_name' | 'email'>;
students_count: string;
likes_count: string;
lessons_count: string;
created_at: string;
updated_at: string;
}
@ -36,6 +39,22 @@ export interface ICategory {
description: string;
}
/**
* User with available course
*/
export type UserCourseType = Pick<
ICourse,
| 'id'
| 'title'
| 'description'
| 'category'
| 'students_count'
| 'likes_count'
| 'lessons_count'
| 'created_at'
| 'updated_at'
>;
export interface IUser {
id: string;
fullname: string;
@ -44,7 +63,7 @@ export interface IUser {
email: string;
roles: IUserRole[];
contacts: IUserContacts | null;
courses: Pick<ICourse, 'id' | 'title' | 'description' | 'created_at' | 'updated_at'>[];
courses: UserCourseType[];
}
export interface IUserContacts {

View File

@ -0,0 +1,43 @@
import React from 'react';
import { Text, Badge, Link, Box, Flex } from '@chakra-ui/layout';
import { Link as ReactRouterLink } from 'react-router-dom';
import { MdVideoLibrary, MdGroup, MdThumbUp } from 'react-icons/md';
import { UserCourseType } from 'interfaces';
type CourseItemPropsType = {
course: UserCourseType;
};
const CourseItem: React.FC<CourseItemPropsType> = ({ course }) => {
return (
<Box key={course.id} borderWidth='1px' borderRadius='md' p='10px' boxShadow='sm'>
<Flex justifyContent='space-between' alignItems='center'>
<Link as={ReactRouterLink} to={`course/${course.id}`} fontWeight='bold' fontSize='2xl'>
{course.title}
</Link>
<Badge colorScheme='purple'>
<Link as={ReactRouterLink} to={`category/${course.category.id}`}>
{course.category.title}
</Link>
</Badge>
</Flex>
<Text>{course.description}</Text>
<Flex mt='5' alignItems='center'>
<MdVideoLibrary />
<Text pl='1' pr='4'>
{course.lessons_count}&nbsp;lessons
</Text>
<MdGroup />
<Text pl='1' pr='4'>
{course.students_count}&nbsp;students
</Text>
<MdThumbUp />
<Text pl='1' pr='4'>
{course.likes_count}&nbsp;likes
</Text>
</Flex>
</Box>
);
};
export default CourseItem;

View File

@ -0,0 +1,24 @@
import React from 'react';
import { IUser } from 'interfaces';
import { Stack, StackDivider } from '@chakra-ui/layout';
import CourseItem from './CourseItem';
type CourseListPropsType = {
courses: IUser['courses'];
};
/**
* Render the course list on profile page
* in "Available courses" tab
*/
const CourseList: React.FC<CourseListPropsType> = ({ courses }) => {
return (
<Stack spacing='8' divider={<StackDivider />}>
{courses.map(course => (
<CourseItem course={course} key={course.id} />
))}
</Stack>
);
};
export default CourseList;

View File

@ -0,0 +1,3 @@
import CourseList from './CourseList';
export default CourseList;

View File

@ -52,7 +52,7 @@ const UpdateUserContactsForm: React.FC<UpdateUserContactsFormProps> = ({ contact
return (
<Box>
<form onSubmit={handleSubmit(onSubmit)}>
<Box borderRadius='md' borderWidth='1px' padding='20px'>
<Box boxShadow='sm' borderRadius='sm' borderWidth='1px' padding='20px'>
<Heading as='h3' size='lg'>
My Contacts
</Heading>

View File

@ -11,7 +11,7 @@ const UserAccountInfo: React.FC<UserAccountInfoPropsType> = ({ user }) => {
const { setStatusPageView } = useContext(ProfilePageViewContext);
return (
<Box borderRadius='md' borderWidth='1px' padding='20px'>
<Box borderRadius='md' borderWidth='1px' padding='20px' boxShadow='sm'>
<Heading as='h3' size='lg'>
Account information
</Heading>

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react';
import { observer } from 'mobx-react';
import {
Box,
Heading,
@ -11,24 +12,42 @@ import {
Tab,
TabPanels,
TabPanel,
Stack,
StackDivider,
} from '@chakra-ui/react';
import { IPageProps } from 'interfaces';
import { ProfilePageStatusType } from 'types';
import { useRootStore } from 'hooks/useRootStore';
import { useHistory } from 'react-router-dom';
import { observer } from 'mobx-react';
import { ProfilePageViewContext } from 'contexts';
import { userHasRoles } from 'helpers';
/**
* Types
*/
import { ProfilePageStatusType } from 'types';
import { IPageProps } from 'interfaces';
import { UserRoleEnum } from 'enums';
/**
* Components
*/
import CourseList from './components/CourseList';
import UserBadge from 'components/UserBadge';
import LoadingPage from './components/LoadingPage';
import UserAccountInfo from './components/UserAccountInfo';
import UpdateUserContactsForm from './components/UpdateUserContactsForm';
/**
* Containers
*/
import UpdatePasswordContainer from './containers/UpdatePasswordContainer';
import UpdateEmailContainer from './containers/UpdateEmailContainer';
import ConfirmEmailContainer from './containers/ConfirmEmailContainer';
import { UserRoleEnum } from 'enums';
/**
* Hooks
*/
import { useRootStore } from 'hooks/useRootStore';
import { useHistory } from 'react-router-dom';
/**
* Contexts
*/
import { ProfilePageViewContext } from 'contexts';
/**
* Profile page
@ -117,35 +136,15 @@ const ProfilePage: React.FC<IPageProps> = () => {
{isStudent && <Tab>Available courses</Tab>}
</TabList>
<TabPanels>
<TabPanel padding='10px 0' mt='20px'>
<TabPanel>
<UserAccountInfo user={userStore.me} />
</TabPanel>
<TabPanel padding='10px 0' mt='20px'>
<TabPanel>
<UpdateUserContactsForm contacts={userStore.me.contacts} />
</TabPanel>
{isStudent && (
<TabPanel padding='10px 0' mt='20px'>
<Box>
<Stack spacing='8' divider={<StackDivider />}>
{userStore.me.courses.map(course => (
<Box
key={course.id}
borderWidth='1px'
borderRadius='md'
p='10px'
cursor='pointer'
onClick={() => {
history.push(`/course/${course.id}`);
}}
>
<Heading as='h3' size='md'>
{course.title}
</Heading>
<Text>{course.description}</Text>
</Box>
))}
</Stack>
</Box>
<TabPanel>
<CourseList courses={userStore.me.courses} />
</TabPanel>
)}
</TabPanels>

View File

@ -47,7 +47,7 @@ export default class UserStore {
data: { id, first_name, last_name, email, roles, contacts, courses },
} = result;
console.log(result);
console.log(`[UserStore]: Fetched authorized user data.`, result);
runInAction(() => {
this.me = {