mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
feat: added Loading component
This commit is contained in:
parent
5dae2f5975
commit
248e57e548
@ -1,19 +1,31 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Redirect } from 'react-router';
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
import { userContainRoles } from 'helpers';
|
||||
import { Flex, Box } from '@chakra-ui/react';
|
||||
import { useRootStore } from 'hooks/useRootStore';
|
||||
|
||||
/**
|
||||
* Types
|
||||
*/
|
||||
import { UserRoleEnum } from 'enums';
|
||||
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
import LoadingPage from 'components/LoadingPage';
|
||||
import Header from 'components/Header';
|
||||
import NavDesktop from 'components/Nav/Desktop';
|
||||
import { UserRoleEnum } from 'enums';
|
||||
import { userContainRoles } from 'helpers';
|
||||
import { Redirect } from 'react-router';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useRootStore } from 'hooks/useRootStore';
|
||||
|
||||
type LayoutPropsType = { roles: UserRoleEnum[] | undefined };
|
||||
|
||||
/**
|
||||
* Layout component
|
||||
* Сomponent for rendering the current page.
|
||||
* Render the current page using layout
|
||||
*/
|
||||
const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
|
||||
const { userStore } = useRootStore();
|
||||
@ -53,7 +65,7 @@ const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
|
||||
*/
|
||||
if (roles) {
|
||||
const { me } = userStore;
|
||||
if (me === null) return null;
|
||||
if (me === null) return <LoadingPage />;
|
||||
|
||||
/**
|
||||
* The user does not have the required roles
|
||||
|
||||
17
src/components/LoadingPage/LoadingPage.tsx
Normal file
17
src/components/LoadingPage/LoadingPage.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { Flex, Box, Spinner, Text } from '@chakra-ui/react';
|
||||
import React from 'react';
|
||||
|
||||
const LoadingPage: React.FC = () => {
|
||||
return (
|
||||
<Flex justifyContent='center' mt='20' maxW='950px'>
|
||||
<Box mt='auto' mb='auto' textAlign='center'>
|
||||
<Spinner thickness='4px' speed='0.55s' emptyColor='gray.200' color='blue.500' size='xl' />
|
||||
<Text mt='2' color='gray.500' userSelect='none'>
|
||||
Loading...
|
||||
</Text>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default LoadingPage;
|
||||
3
src/components/LoadingPage/index.ts
Normal file
3
src/components/LoadingPage/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
import LoadingPage from './LoadingPage';
|
||||
|
||||
export default LoadingPage;
|
||||
@ -13,7 +13,9 @@ import config from 'config';
|
||||
import useLogoutQuery from 'hooks/useLogoutQuery';
|
||||
|
||||
const NavMobile: React.FC = () => {
|
||||
const { userStore } = useRootStore();
|
||||
const {
|
||||
userStore: { me },
|
||||
} = useRootStore();
|
||||
const { colorMode } = useColorMode();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const { logout } = useLogoutQuery();
|
||||
@ -29,38 +31,32 @@ const NavMobile: React.FC = () => {
|
||||
<Flex as='nav' flexDirection='column' alignItems='flex-start' textDecoration='none' mb='20px'>
|
||||
<NavList links={config.links} onCloseDrawer={onClose} />
|
||||
</Flex>
|
||||
{userStore.me ? (
|
||||
<Box pb='10px'>
|
||||
<Box
|
||||
minHeight='60px'
|
||||
padding='10px'
|
||||
borderRadius='md'
|
||||
marginTop='auto'
|
||||
backgroundColor={colorMode === 'dark' ? 'gray.700' : 'gray.100'}
|
||||
>
|
||||
<Flex alignItems='center'>
|
||||
<Avatar size='sm' name={`${userStore.me.first_name} ${userStore.me.last_name}`} marginRight={3} />
|
||||
<Flex flexDirection='column'>
|
||||
<Text as='span' mr={2} lineHeight='1.2'>
|
||||
{`${userStore.me.first_name} ${userStore.me.last_name}`}
|
||||
</Text>
|
||||
<Link
|
||||
to={`/profile`}
|
||||
style={{ fontSize: '13px', textDecoration: 'underline' }}
|
||||
onClick={onClose}
|
||||
>
|
||||
View profile
|
||||
</Link>
|
||||
</Flex>
|
||||
<IconButton
|
||||
onClick={logout}
|
||||
aria-label='Logout'
|
||||
backgroundColor={colorMode === 'dark' ? 'gray.600' : 'gray.200'}
|
||||
marginLeft='auto'
|
||||
icon={<MdExitToApp />}
|
||||
/>
|
||||
{me !== null ? (
|
||||
<Box
|
||||
minHeight='60px'
|
||||
padding='10px'
|
||||
borderRadius='md'
|
||||
marginTop='auto'
|
||||
backgroundColor={colorMode === 'dark' ? 'gray.700' : 'gray.100'}
|
||||
>
|
||||
<Flex alignItems='center'>
|
||||
<Avatar size='sm' name={me.fullname} marginRight={3} />
|
||||
<Flex flexDirection='column'>
|
||||
<Text as='span' mr={2} lineHeight='1.2'>
|
||||
{me.fullname}
|
||||
</Text>
|
||||
<Link to={`/profile`} style={{ fontSize: '13px', textDecoration: 'underline' }} onClick={onClose}>
|
||||
View profile
|
||||
</Link>
|
||||
</Flex>
|
||||
</Box>
|
||||
<IconButton
|
||||
onClick={logout}
|
||||
aria-label='Logout'
|
||||
backgroundColor={colorMode === 'dark' ? 'gray.600' : 'gray.200'}
|
||||
marginLeft='auto'
|
||||
icon={<MdExitToApp />}
|
||||
/>
|
||||
</Flex>
|
||||
</Box>
|
||||
) : (
|
||||
<Skeleton
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { IUser } from 'interfaces';
|
||||
import { Stack, StackDivider } from '@chakra-ui/layout';
|
||||
import { Box, Text, Stack, StackDivider } from '@chakra-ui/layout';
|
||||
import CourseItem from './CourseItem';
|
||||
|
||||
type CourseListPropsType = {
|
||||
@ -16,6 +16,16 @@ const CourseList: React.FC<CourseListPropsType> = ({ courses }) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (courses.length === 0) {
|
||||
return (
|
||||
<Box textAlign='center' mt='10'>
|
||||
<Text color='gray.500' userSelect='none'>
|
||||
You are not a member of any course
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack spacing='8' divider={<StackDivider />}>
|
||||
{courses.map(course => (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user