refactor: layout

This commit is contained in:
Sergey Yarkov 2021-10-30 00:09:28 +03:00
parent 4d0fef3fb1
commit 82c9021389
21 changed files with 198 additions and 128 deletions

View File

@ -1,4 +1,4 @@
import React, { Suspense, useEffect } from 'react'; import React, { Suspense } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Redirect } from 'react-router'; import { Redirect } from 'react-router';
import { useErrorHandler } from 'react-error-boundary'; import { useErrorHandler } from 'react-error-boundary';
@ -20,6 +20,7 @@ import NavDesktop from '@educt/components/Nav/Desktop';
/** /**
* Hooks * Hooks
*/ */
import { useEffect } from 'react';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
type LayoutPropsType = { roles: UserRoleEnum[] | undefined }; type LayoutPropsType = { roles: UserRoleEnum[] | undefined };
@ -31,6 +32,9 @@ const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
const { userStore } = useRootStore(); const { userStore } = useRootStore();
const handleError = useErrorHandler(); const handleError = useErrorHandler();
/**
* Fetch authorized user handler
*/
useEffect(() => { useEffect(() => {
userStore.loadCurrentUserData().catch(error => handleError(error)); userStore.loadCurrentUserData().catch(error => handleError(error));
}, [handleError, userStore]); }, [handleError, userStore]);
@ -38,8 +42,8 @@ const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
return ( return (
<> <>
<Header /> <Header />
<Flex minH='100vh'>
<NavDesktop /> <NavDesktop />
<Flex minH='100vh' justifyContent='center'>
<Box <Box
as='main' as='main'
flex='1 0' flex='1 0'

View File

@ -3,7 +3,7 @@ import React from 'react';
const LoadingPage: React.FC = () => { const LoadingPage: React.FC = () => {
return ( return (
<Flex justifyContent='center' mt='40' maxW='950px'> <Flex justifyContent='center' mt='40'>
<Box mt='auto' mb='auto' textAlign='center'> <Box mt='auto' mb='auto' textAlign='center'>
<Spinner thickness='4px' speed='0.55s' emptyColor='gray.200' color='blue.500' size='xl' /> <Spinner thickness='4px' speed='0.55s' emptyColor='gray.200' color='blue.500' size='xl' />
<Text mt='2' color='gray.500' userSelect='none'> <Text mt='2' color='gray.500' userSelect='none'>

View File

@ -1,10 +1,18 @@
import config from '@educt/config';
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { Flex, Box, useColorMode } from '@chakra-ui/react'; import { Flex, Box, useColorMode } from '@chakra-ui/react';
import { useRootStore } from '@educt/hooks/useRootStore'; import config from '@educt/config';
/**
* Components
*/
import NavList from '../NavList'; import NavList from '../NavList';
/**
* Hooks
*/
import { useRootStore } from '@educt/hooks/useRootStore';
/** /**
* *
* Nav component * Nav component

View File

@ -1,16 +1,25 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { MdExitToApp } from 'react-icons/md';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useRootStore } from '@educt/hooks/useRootStore'; import { IconButton, Skeleton } from '@chakra-ui/react';
import { Avatar } from '@chakra-ui/avatar'; import { Avatar } from '@chakra-ui/avatar';
import { Flex, Box, Text } from '@chakra-ui/layout'; import { Flex, Box, Text } from '@chakra-ui/layout';
import { Drawer, DrawerOverlay, DrawerContent, DrawerBody } from '@chakra-ui/modal'; import { Drawer, DrawerOverlay, DrawerContent, DrawerBody } from '@chakra-ui/modal';
import { MdExitToApp } from 'react-icons/md';
import { HamburgerIcon } from '@chakra-ui/icons'; import { HamburgerIcon } from '@chakra-ui/icons';
import { useDisclosure, IconButton, useColorMode, Skeleton } from '@chakra-ui/react';
import NavList from '../NavList';
import config from '@educt/config'; import config from '@educt/config';
/**
* Components
*/
import NavList from '../NavList';
/**
* Hooks
*/
import useLogoutQuery from '@educt/hooks/useLogoutQuery'; import useLogoutQuery from '@educt/hooks/useLogoutQuery';
import { useRootStore } from '@educt/hooks/useRootStore';
import { useColorMode, useDisclosure } from '@chakra-ui/react';
const NavMobile: React.FC = () => { const NavMobile: React.FC = () => {
const { const {

View File

@ -1,9 +1,13 @@
import React from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { userContainRoles } from '@educt/helpers';
import { Box, useColorMode } from '@chakra-ui/react'; import { Box, useColorMode } from '@chakra-ui/react';
import type { LinkType } from '@educt/types'; import type { LinkType } from '@educt/types';
/**
* Hooks
*/
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { userContainRoles } from '@educt/helpers';
type NavLinkPropsType = { type NavLinkPropsType = {
link: LinkType; link: LinkType;

View File

@ -1,9 +1,21 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import { useHistory } from 'react-router-dom';
/**
* Types
*/
import { LinkType } from '@educt/types'; import { LinkType } from '@educt/types';
/**
* Components
*/
import NavLink from './NavLink'; import NavLink from './NavLink';
/**
* Hooks
*/
import { useHistory } from 'react-router-dom';
type NavListPropsType = { type NavListPropsType = {
links: LinkType[]; links: LinkType[];
onCloseDrawer?: () => void; onCloseDrawer?: () => void;

View File

@ -14,6 +14,9 @@ import AuthForm from './components/AuthForm';
const AuthPage: React.FC<IPageProps> = () => { const AuthPage: React.FC<IPageProps> = () => {
const { authStore } = useRootStore(); const { authStore } = useRootStore();
/**
* User already authorized
*/
if (authStore.isLoggedIn) { if (authStore.isLoggedIn) {
return <Redirect to='/' />; return <Redirect to='/' />;
} }

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import { MdAccountCircle, MdSchool, MdVpnKey } from 'react-icons/md';
import { import {
FormControl, FormControl,
FormLabel, FormLabel,
@ -12,9 +11,23 @@ import {
Flex, Flex,
Box, Box,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { SubmitHandler, useForm } from 'react-hook-form'; import { MdAccountCircle, MdSchool, MdVpnKey } from 'react-icons/md';
import { yupResolver } from '@hookform/resolvers/yup'; import { yupResolver } from '@hookform/resolvers/yup';
/**
* Types
*/
import type { SubmitHandler } from 'react-hook-form';
/**
* Hooks
*/
import { useForm } from 'react-hook-form';
import useLoginQuery from '@educt/hooks/useLoginQuery'; import useLoginQuery from '@educt/hooks/useLoginQuery';
/**
* Schema
*/
import LoginSchema from './AuthForm.validator'; import LoginSchema from './AuthForm.validator';
type AuthInputType = { type AuthInputType = {
@ -33,6 +46,9 @@ const AuthForm: React.FC = () => {
}); });
const { login, loading } = useLoginQuery(); const { login, loading } = useLoginQuery();
/**
* Login handler
*/
const onSubmit: SubmitHandler<AuthInputType> = data => { const onSubmit: SubmitHandler<AuthInputType> = data => {
login(data.login, data.password).finally(() => reset()); login(data.login, data.password).finally(() => reset());
}; };

View File

@ -1,4 +1,4 @@
import React, { useContext } from 'react'; import React from 'react';
import { Tag, TagLabel } from '@chakra-ui/react'; import { Tag, TagLabel } from '@chakra-ui/react';
/** /**
@ -11,6 +11,11 @@ import { ICategory } from '@educt/interfaces';
*/ */
import { CoursesPageContext } from '@educt/contexts'; import { CoursesPageContext } from '@educt/contexts';
/**
* Hooks
*/
import { useContext } from 'react';
type CategoryItemProps = { type CategoryItemProps = {
category: ICategory; category: ICategory;
}; };
@ -21,9 +26,7 @@ const CategoryItem: React.FC<CategoryItemProps> = ({ category }) => {
/** /**
* Handle click on change category * Handle click on change category
*/ */
const onCategoryChange = () => { const onCategoryChange = () => setSelectedCategory(category);
setSelectedCategory(category);
};
return ( return (
<Tag <Tag

View File

@ -1,15 +1,28 @@
import React, { useContext, useEffect } from 'react'; import React from 'react';
import { Box, Flex, Tag, TagLabel } from '@chakra-ui/react'; import { Box, Flex, Tag, TagLabel } from '@chakra-ui/react';
import { CoursesPageContext } from '@educt/contexts';
import CategoryItem from './CategoryItem'; /**
* Types
*/
import { ICategory } from '@educt/interfaces'; import { ICategory } from '@educt/interfaces';
/**
* Components
*/
import CategoryItem from './CategoryItem';
import CategoryListLoading from './CategoryListLoading'; import CategoryListLoading from './CategoryListLoading';
/**
* Contexts
*/
import { CoursesPageContext } from '@educt/contexts';
/** /**
* Hooks * Hooks
*/ */
import { useErrorHandler } from 'react-error-boundary'; import { useContext, useEffect } from 'react';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { useErrorHandler } from 'react-error-boundary';
type CategoryListPropsType = { type CategoryListPropsType = {
categories: ICategory[] | null; categories: ICategory[] | null;
@ -21,6 +34,9 @@ const CategoryList: React.FC<CategoryListPropsType> = ({ categories, isLoading }
const { selectedCategory, setSelectedCategory } = useContext(CoursesPageContext); const { selectedCategory, setSelectedCategory } = useContext(CoursesPageContext);
const handleError = useErrorHandler(); const handleError = useErrorHandler();
/**
* Fetch handler
*/
useEffect(() => { useEffect(() => {
categoryStore.loadCategories().catch(error => handleError(error)); categoryStore.loadCategories().catch(error => handleError(error));
}, [categoryStore, handleError]); }, [categoryStore, handleError]);
@ -42,9 +58,10 @@ const CategoryList: React.FC<CategoryListPropsType> = ({ categories, isLoading }
> >
<TagLabel>All categories</TagLabel> <TagLabel>All categories</TagLabel>
</Tag> </Tag>
{categories.map((category, i) => { {/* Render items */}
return <CategoryItem key={category.id} category={category} />; {categories.map((category, i) => (
})} <CategoryItem key={category.id} category={category} />
))}
</Flex> </Flex>
</Box> </Box>
); );

View File

@ -1,20 +1,9 @@
import React from 'react'; import React from 'react';
import { import { observer } from 'mobx-react';
Flex,
Box,
Heading,
Text,
Menu,
MenuButton,
Badge,
MenuItem,
MenuList,
Image,
Link,
IconButton,
} from '@chakra-ui/react';
import { Link as ReactRouterLink } from 'react-router-dom'; import { Link as ReactRouterLink } from 'react-router-dom';
import { Icon } from '@chakra-ui/react'; import { Badge, Image, Link, IconButton, Icon } from '@chakra-ui/react';
import { Flex, Box, Heading, Text } from '@chakra-ui/layout';
import { Menu, MenuButton, MenuItem, MenuList } from '@chakra-ui/menu';
import { MdNote, MdMoreHoriz, MdGroup, MdThumbUp, MdVideoLibrary } from 'react-icons/md'; import { MdNote, MdMoreHoriz, MdGroup, MdThumbUp, MdVideoLibrary } from 'react-icons/md';
import { CheckIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons'; import { CheckIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons';
@ -22,15 +11,18 @@ import { CheckIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons';
* Types * Types
*/ */
import { ICourse } from '@educt/interfaces'; import { ICourse } from '@educt/interfaces';
import { CourseStatusEnum } from '@educt/enums';
/**
* Components
*/
import CourseStatusBadge from '@educt/components/CourseStatusBadge';
/** /**
* Hooks * Hooks
*/ */
import { useColorMode } from '@chakra-ui/color-mode'; import { useColorMode } from '@chakra-ui/color-mode';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import CourseStatusBadge from '@educt/components/CourseStatusBadge';
import { CourseStatusEnum } from '@educt/enums';
import { observer } from 'mobx-react';
type CourseItemPropsType = { type CourseItemPropsType = {
course: Omit<ICourse, 'teacher' | 'students' | 'lessons'>; course: Omit<ICourse, 'teacher' | 'students' | 'lessons'>;
@ -51,6 +43,7 @@ const CourseItem: React.FC<CourseItemPropsType> = ({ course, onDelete, onSetStat
{(me.isAdmin || me.isTeacher) && ( {(me.isAdmin || me.isTeacher) && (
<Flex justifyContent='flex-end'> <Flex justifyContent='flex-end'>
<Box position='absolute' zIndex='1' padding='10px'> <Box position='absolute' zIndex='1' padding='10px'>
{/* Actions */}
<Menu isLazy> <Menu isLazy>
<MenuButton <MenuButton
as={IconButton} as={IconButton}

View File

@ -1,10 +1,11 @@
import React, { useContext, useEffect } from 'react'; import React from 'react';
import { Box, Grid, Text } from '@chakra-ui/react'; import { Box, Grid, Text } from '@chakra-ui/react';
/** /**
* Types * Types
*/ */
import { ICourse } from '@educt/interfaces'; import { ICourse } from '@educt/interfaces';
import { CourseStatusEnum } from '@educt/enums';
/** /**
* Components * Components
@ -16,6 +17,7 @@ import DeleteCourseDialog from '../DeleteCourseDialog';
/** /**
* Hooks * Hooks
*/ */
import { useContext, useEffect } from 'react';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { useDisclosure } from '@chakra-ui/hooks'; import { useDisclosure } from '@chakra-ui/hooks';
import { useToast } from '@chakra-ui/toast'; import { useToast } from '@chakra-ui/toast';
@ -25,7 +27,6 @@ import { useErrorHandler } from 'react-error-boundary';
* Contexts * Contexts
*/ */
import { CoursesPageContext } from '@educt/contexts'; import { CoursesPageContext } from '@educt/contexts';
import { CourseStatusEnum } from '@educt/enums';
type CourseListPropsType = { type CourseListPropsType = {
courses: Omit<ICourse, 'teacher' | 'students' | 'lessons'>[] | null; courses: Omit<ICourse, 'teacher' | 'students' | 'lessons'>[] | null;
@ -42,6 +43,9 @@ const CourseList: React.FC<CourseListPropsType> = ({ courses, isLoading }) => {
const handleError = useErrorHandler(); const handleError = useErrorHandler();
const toast = useToast(); const toast = useToast();
/**
* Fetch handler
*/
useEffect(() => { useEffect(() => {
if (me !== null) { if (me !== null) {
courseStore.loadCourses({ courseStore.loadCourses({
@ -84,18 +88,8 @@ const CourseList: React.FC<CourseListPropsType> = ({ courses, isLoading }) => {
<> <>
{deletingCourse && <DeleteCourseDialog onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />} {deletingCourse && <DeleteCourseDialog onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />}
{courses.length !== 0 ? ( {courses.length !== 0 ? (
<Grid <Grid templateColumns='repeat(auto-fill, minmax(400px, 1fr))' gap='6'>
templateColumns='repeat(3, minmax(0, 1fr))' {/* Render items */}
gap='6'
sx={{
'@media (max-width: 1280px)': {
gridTemplateColumns: 'repeat(2, 1fr)',
},
'@media (max-width: 768px)': {
gridTemplateColumns: 'repeat(1, 1fr)',
},
}}
>
{courses.map(course => ( {courses.map(course => (
<CourseItem key={course.id} course={course} onDelete={onDeleteCourse} onSetStatus={onSetStatus} /> <CourseItem key={course.id} course={course} onDelete={onDeleteCourse} onSetStatus={onSetStatus} />
))} ))}

View File

@ -1,4 +1,4 @@
import React, { useContext } from 'react'; import React from 'react';
import { Tabs, TabList, Tab } from '@chakra-ui/react'; import { Tabs, TabList, Tab } from '@chakra-ui/react';
/** /**
@ -11,6 +11,11 @@ import { CourseStatusEnum } from '@educt/enums';
*/ */
import { CoursesPageContext } from '@educt/contexts'; import { CoursesPageContext } from '@educt/contexts';
/**
* Hooks
*/
import { useContext } from 'react';
type CourseStatusTabsProps = {}; type CourseStatusTabsProps = {};
const CourseStatusTabs: React.FC<CourseStatusTabsProps> = () => { const CourseStatusTabs: React.FC<CourseStatusTabsProps> = () => {

View File

@ -16,12 +16,16 @@ import CategoryList from './components/CategoryList';
import CourseStatusTabs from './components/CourseStatusTabs'; import CourseStatusTabs from './components/CourseStatusTabs';
import LoadingPage from '@educt/components/LoadingPage'; import LoadingPage from '@educt/components/LoadingPage';
/**
* Providers
*/
import { CoursesPageContextProvider } from '@educt/providers';
/** /**
* Hooks * Hooks
*/ */
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { CoursesPageContextProvider } from '@educt/providers'; import { useHistory } from 'react-router';
import { useHistory, useLocation } from 'react-router';
/** /**
* Courses page * Courses page

View File

@ -1,9 +1,13 @@
import React from 'react'; import React from 'react';
import { Text, Link, Box, Flex } from '@chakra-ui/layout';
import { Link as ReactRouterLink } from 'react-router-dom'; import { Link as ReactRouterLink } from 'react-router-dom';
import { MdVideoLibrary, MdGroup, MdThumbUp } from 'react-icons/md';
import { UserCourseType } from '@educt/interfaces';
import { Tag, TagLabel } from '@chakra-ui/react'; import { Tag, TagLabel } from '@chakra-ui/react';
import { Text, Link, Box, Flex } from '@chakra-ui/layout';
import { MdVideoLibrary, MdGroup, MdThumbUp } from 'react-icons/md';
/**
* Types
*/
import { UserCourseType } from '@educt/interfaces';
type CourseItemPropsType = { type CourseItemPropsType = {
course: UserCourseType; course: UserCourseType;
@ -11,15 +15,20 @@ type CourseItemPropsType = {
const CourseItem: React.FC<CourseItemPropsType> = ({ course }) => { const CourseItem: React.FC<CourseItemPropsType> = ({ course }) => {
return ( return (
<Box borderWidth='1px' borderRadius='md' p='10px' boxShadow='sm'> <Flex flexDir='column' borderWidth='1px' borderRadius='lg' p='10px' boxShadow='sm' mb='3'>
<Flex justifyContent='space-between' alignItems='center'> <Tag colorScheme='purple' borderRadius='full' alignSelf='flex-start'>
<Link as={ReactRouterLink} to={`course/${course.id}`} fontWeight='bold' fontSize='2xl'>
{course.title}
</Link>
<Link as={ReactRouterLink} to={`category/${course.category.id}`}>
<Tag colorScheme='purple' borderRadius='full'>
<TagLabel>{course.category.title}</TagLabel> <TagLabel>{course.category.title}</TagLabel>
</Tag> </Tag>
<Flex justifyContent='space-between' alignItems='center'>
<Link
as={ReactRouterLink}
to={`course/${course.id}`}
overflowWrap='anywhere'
fontWeight='bold'
fontSize='xl'
mr='5'
>
{course.title}
</Link> </Link>
</Flex> </Flex>
<Text>{course.description}</Text> <Text>{course.description}</Text>
@ -37,7 +46,7 @@ const CourseItem: React.FC<CourseItemPropsType> = ({ course }) => {
{course.likes_count}&nbsp;likes {course.likes_count}&nbsp;likes
</Text> </Text>
</Flex> </Flex>
</Box> </Flex>
); );
}; };

View File

@ -1,16 +1,20 @@
import React from 'react'; import React from 'react';
import { Box, Text, Flex } from '@chakra-ui/layout';
/**
* Types
*/
import { IMe } from '@educt/interfaces'; import { IMe } from '@educt/interfaces';
import { Box, Text, Stack, StackDivider } from '@chakra-ui/layout';
/**
* Components
*/
import CourseItem from './CourseItem'; import CourseItem from './CourseItem';
type CourseListPropsType = { type CourseListPropsType = {
courses: IMe['courses']; courses: IMe['courses'];
}; };
/**
* Render the course list on profile page for STUDENT role
* in "Available courses" tab
*/
const CourseList: React.FC<CourseListPropsType> = ({ courses }) => { const CourseList: React.FC<CourseListPropsType> = ({ courses }) => {
if (courses === undefined) { if (courses === undefined) {
return null; return null;
@ -27,11 +31,11 @@ const CourseList: React.FC<CourseListPropsType> = ({ courses }) => {
} }
return ( return (
<Stack spacing='8' divider={<StackDivider />}> <Flex flexDirection='column'>
{courses.map(course => ( {courses.map(course => (
<CourseItem course={course} key={course.id} /> <CourseItem course={course} key={course.id} />
))} ))}
</Stack> </Flex>
); );
}; };

View File

@ -90,11 +90,8 @@ const UpdateUserContactsForm: React.FC<UpdateUserContactsFormPropsType> = ({ con
return ( return (
<Box> <Box>
<form onSubmit={handleSubmit(onSubmit)}> <form onSubmit={handleSubmit(onSubmit)}>
<Box boxShadow='sm' borderRadius='sm' borderWidth='1px' padding='20px'> <Box boxShadow='sm' borderRadius='lg' borderWidth='1px' padding='20px'>
<Heading as='h3' size='md'> <Stack spacing='5px'>
My Contacts
</Heading>
<Stack spacing='5px' margin='20px 0'>
<FormControl id='phone_number'> <FormControl id='phone_number'>
<FormHelperText color='gray.500'>Phone number with country code</FormHelperText> <FormHelperText color='gray.500'>Phone number with country code</FormHelperText>
<Input <Input

View File

@ -1,8 +1,21 @@
import React, { useContext } from 'react'; import React from 'react';
import { Box, Heading, Stack, Flex, StackDivider, Text, Button } from '@chakra-ui/react'; import { Box, Heading, Stack, Flex, StackDivider, Text, Button } from '@chakra-ui/react';
/**
* Types
*/
import { IUser } from '@educt/interfaces'; import { IUser } from '@educt/interfaces';
/**
* Contexts
*/
import { ProfilePageContext } from '@educt/contexts'; import { ProfilePageContext } from '@educt/contexts';
/**
* Hooks
*/
import { useContext } from 'react';
type UserAccountInfoPropsType = { type UserAccountInfoPropsType = {
user: IUser; user: IUser;
}; };
@ -11,11 +24,8 @@ const UserAccountInfo: React.FC<UserAccountInfoPropsType> = ({ user }) => {
const { setStatusPageView } = useContext(ProfilePageContext); const { setStatusPageView } = useContext(ProfilePageContext);
return ( return (
<Box borderRadius='md' borderWidth='1px' padding='20px' boxShadow='sm'> <Box borderRadius='lg' borderWidth='1px' padding='20px' boxShadow='sm'>
<Heading as='h3' size='md'> <Stack spacing='10px' divider={<StackDivider />}>
Account information
</Heading>
<Stack spacing='10px' mt='20px' divider={<StackDivider />}>
<Flex> <Flex>
<Box> <Box>
<Text as='small' color='gray.500'> <Text as='small' color='gray.500'>

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { Box, Heading, Flex, Avatar, Text, Tabs, TabList, Tab, TabPanels, TabPanel } from '@chakra-ui/react'; import { Box, Heading, Flex, Avatar, Text, Tabs, TabList, Tab, TabPanels, TabPanel, Button } from '@chakra-ui/react';
/** /**
* Components * Components
@ -12,6 +12,7 @@ import CourseList from '@educt/pages/profile/components/CourseList';
/** /**
* Hooks * Hooks
*/ */
import useLogoutQuery from '@educt/hooks/useLogoutQuery';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { useColorMode } from '@chakra-ui/color-mode'; import { useColorMode } from '@chakra-ui/color-mode';
@ -20,6 +21,7 @@ const MainContainer: React.FC = () => {
userStore: { me }, userStore: { me },
} = useRootStore(); } = useRootStore();
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const { logout } = useLogoutQuery();
if (me === null) return null; if (me === null) return null;
@ -29,47 +31,17 @@ const MainContainer: React.FC = () => {
<Text mt='2'>Update you contacts information or password here.</Text> <Text mt='2'>Update you contacts information or password here.</Text>
<Flex <Flex
alignItems='center' alignItems='center'
flexDir={{ base: 'column', md: 'row' }}
textAlign={{ base: 'center', md: 'left' }}
mt='20' mt='20'
sx={{
'@media (max-width: 768px)': {
flexDirection: 'column',
alignItems: 'center',
textAlign: 'center',
mt: '10',
},
}}
> >
<Box> <Box>
<Avatar border={`4px solid ${colorMode === 'dark' ? '#2D3748' : '#E2E8F0'}`} size='2xl' name={me.fullname} /> <Avatar border={`4px solid ${colorMode === 'dark' ? '#2D3748' : '#E2E8F0'}`} size='2xl' name={me.fullname} />
</Box> </Box>
<Flex <Flex ml={{ md: '50' }} mt={{ base: '2', md: '0' }} flexDirection='column'>
ml='50'
flexDirection='column'
sx={{
'@media (max-width: 768px)': {
ml: '0',
mt: '5',
},
}}
>
<Heading as='h2'>{me.fullname}</Heading> <Heading as='h2'>{me.fullname}</Heading>
<Flex <Flex alignItems='center' flexDir={{ base: 'column', md: 'row' }}>
alignItems='center' <Text mr='10px' mb={{ base: '2', md: '0' }}>
sx={{
'@media (max-width: 768px)': {
flexDirection: 'column',
},
}}
>
<Text
mr='10px'
sx={{
'@media (max-width: 768px)': {
mr: '0',
mb: '5px',
},
}}
>
{me.email} {me.email}
</Text> </Text>
<UserBadge roles={me.roles} /> <UserBadge roles={me.roles} />
@ -83,7 +55,7 @@ const MainContainer: React.FC = () => {
<Tab>My contacts</Tab> <Tab>My contacts</Tab>
{me.isStudent && <Tab>Available courses</Tab>} {me.isStudent && <Tab>Available courses</Tab>}
</TabList> </TabList>
<TabPanels> <TabPanels mt='2'>
<TabPanel> <TabPanel>
<UserAccountInfo user={me} /> <UserAccountInfo user={me} />
</TabPanel> </TabPanel>
@ -98,6 +70,11 @@ const MainContainer: React.FC = () => {
</TabPanels> </TabPanels>
</Tabs> </Tabs>
</Box> </Box>
<Box textAlign='center' mt='3'>
<Button onClick={logout} w={{ base: 'full', sm: '150px' }}>
Sign Out
</Button>
</Box>
</Box> </Box>
); );
}; };

View File

@ -1,4 +1,4 @@
import React, { useEffect } from 'react'; import React from 'react';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
/** /**
@ -22,6 +22,7 @@ import ConfirmEmailContainer from './containers/ConfirmEmailContainer';
/** /**
* Hooks * Hooks
*/ */
import { useEffect } from 'react';
import { useRootStore } from '@educt/hooks/useRootStore'; import { useRootStore } from '@educt/hooks/useRootStore';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';

View File

@ -121,7 +121,7 @@ const UserList: React.FC<UserListPropsType> = ({ users, pagination }) => {
</Stack> </Stack>
)} )}
</Box> </Box>
<Flex mt='auto' mb='6rem' flexDirection={{ base: 'column', sm: 'column', md: 'row' }}> <Flex margin='2rem 0' flexDirection={{ base: 'column', sm: 'column', md: 'row' }}>
<Box textAlign={{ base: 'center', sm: 'center', md: 'left' }} mb={{ base: '2', md: '0' }}> <Box textAlign={{ base: 'center', sm: 'center', md: 'left' }} mb={{ base: '2', md: '0' }}>
Page <b>{pagination.current_page}</b> of {pagesCount} Page <b>{pagination.current_page}</b> of {pagesCount}
</Box> </Box>