mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
feat: added course list in profile page
This commit is contained in:
parent
6a5f0ee305
commit
e8ca606a20
@ -19,6 +19,9 @@ export interface ICourse {
|
|||||||
category: ICategory;
|
category: ICategory;
|
||||||
lessons: ILesson[];
|
lessons: ILesson[];
|
||||||
students: Pick<IUser, 'id' | 'first_name' | 'last_name' | 'email'>;
|
students: Pick<IUser, 'id' | 'first_name' | 'last_name' | 'email'>;
|
||||||
|
students_count: string;
|
||||||
|
likes_count: string;
|
||||||
|
lessons_count: string;
|
||||||
created_at: string;
|
created_at: string;
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
}
|
}
|
||||||
@ -36,6 +39,22 @@ export interface ICategory {
|
|||||||
description: string;
|
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 {
|
export interface IUser {
|
||||||
id: string;
|
id: string;
|
||||||
fullname: string;
|
fullname: string;
|
||||||
@ -44,7 +63,7 @@ export interface IUser {
|
|||||||
email: string;
|
email: string;
|
||||||
roles: IUserRole[];
|
roles: IUserRole[];
|
||||||
contacts: IUserContacts | null;
|
contacts: IUserContacts | null;
|
||||||
courses: Pick<ICourse, 'id' | 'title' | 'description' | 'created_at' | 'updated_at'>[];
|
courses: UserCourseType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUserContacts {
|
export interface IUserContacts {
|
||||||
|
|||||||
43
src/pages/profile/components/CourseList/CourseItem.tsx
Normal file
43
src/pages/profile/components/CourseList/CourseItem.tsx
Normal 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} lessons
|
||||||
|
</Text>
|
||||||
|
<MdGroup />
|
||||||
|
<Text pl='1' pr='4'>
|
||||||
|
{course.students_count} students
|
||||||
|
</Text>
|
||||||
|
<MdThumbUp />
|
||||||
|
<Text pl='1' pr='4'>
|
||||||
|
{course.likes_count} likes
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CourseItem;
|
||||||
24
src/pages/profile/components/CourseList/CourseList.tsx
Normal file
24
src/pages/profile/components/CourseList/CourseList.tsx
Normal 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;
|
||||||
3
src/pages/profile/components/CourseList/index.ts
Normal file
3
src/pages/profile/components/CourseList/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import CourseList from './CourseList';
|
||||||
|
|
||||||
|
export default CourseList;
|
||||||
@ -52,7 +52,7 @@ const UpdateUserContactsForm: React.FC<UpdateUserContactsFormProps> = ({ contact
|
|||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<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'>
|
<Heading as='h3' size='lg'>
|
||||||
My Contacts
|
My Contacts
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|||||||
@ -11,7 +11,7 @@ const UserAccountInfo: React.FC<UserAccountInfoPropsType> = ({ user }) => {
|
|||||||
const { setStatusPageView } = useContext(ProfilePageViewContext);
|
const { setStatusPageView } = useContext(ProfilePageViewContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box borderRadius='md' borderWidth='1px' padding='20px'>
|
<Box borderRadius='md' borderWidth='1px' padding='20px' boxShadow='sm'>
|
||||||
<Heading as='h3' size='lg'>
|
<Heading as='h3' size='lg'>
|
||||||
Account information
|
Account information
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { observer } from 'mobx-react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Heading,
|
Heading,
|
||||||
@ -11,24 +12,42 @@ import {
|
|||||||
Tab,
|
Tab,
|
||||||
TabPanels,
|
TabPanels,
|
||||||
TabPanel,
|
TabPanel,
|
||||||
Stack,
|
|
||||||
StackDivider,
|
|
||||||
} from '@chakra-ui/react';
|
} 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';
|
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 UserBadge from 'components/UserBadge';
|
||||||
import LoadingPage from './components/LoadingPage';
|
import LoadingPage from './components/LoadingPage';
|
||||||
import UserAccountInfo from './components/UserAccountInfo';
|
import UserAccountInfo from './components/UserAccountInfo';
|
||||||
import UpdateUserContactsForm from './components/UpdateUserContactsForm';
|
import UpdateUserContactsForm from './components/UpdateUserContactsForm';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Containers
|
||||||
|
*/
|
||||||
import UpdatePasswordContainer from './containers/UpdatePasswordContainer';
|
import UpdatePasswordContainer from './containers/UpdatePasswordContainer';
|
||||||
import UpdateEmailContainer from './containers/UpdateEmailContainer';
|
import UpdateEmailContainer from './containers/UpdateEmailContainer';
|
||||||
import ConfirmEmailContainer from './containers/ConfirmEmailContainer';
|
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
|
* Profile page
|
||||||
@ -117,35 +136,15 @@ const ProfilePage: React.FC<IPageProps> = () => {
|
|||||||
{isStudent && <Tab>Available courses</Tab>}
|
{isStudent && <Tab>Available courses</Tab>}
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel padding='10px 0' mt='20px'>
|
<TabPanel>
|
||||||
<UserAccountInfo user={userStore.me} />
|
<UserAccountInfo user={userStore.me} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel padding='10px 0' mt='20px'>
|
<TabPanel>
|
||||||
<UpdateUserContactsForm contacts={userStore.me.contacts} />
|
<UpdateUserContactsForm contacts={userStore.me.contacts} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
{isStudent && (
|
{isStudent && (
|
||||||
<TabPanel padding='10px 0' mt='20px'>
|
<TabPanel>
|
||||||
<Box>
|
<CourseList courses={userStore.me.courses} />
|
||||||
<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>
|
</TabPanel>
|
||||||
)}
|
)}
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export default class UserStore {
|
|||||||
data: { id, first_name, last_name, email, roles, contacts, courses },
|
data: { id, first_name, last_name, email, roles, contacts, courses },
|
||||||
} = result;
|
} = result;
|
||||||
|
|
||||||
console.log(result);
|
console.log(`[UserStore]: Fetched authorized user data.`, result);
|
||||||
|
|
||||||
runInAction(() => {
|
runInAction(() => {
|
||||||
this.me = {
|
this.me = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user