mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 02:09:08 +03:00
refactor: page
This commit is contained in:
parent
7f3eabe3e4
commit
a14ed5eff9
@ -53,7 +53,7 @@ const AddStudentsModal: React.FC<AddStudentsModalPropsType> = ({
|
||||
icon={MdGroup}
|
||||
heading='Add new students'
|
||||
description='Attach new students to current course.'
|
||||
confirmText='Add students'
|
||||
confirmText='Add'
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
onProceed={handleAttachStudents}
|
||||
|
||||
@ -1,17 +1,23 @@
|
||||
import React from 'react';
|
||||
import { BoxProps, Box, Flex, Heading, Text, Divider } from '@chakra-ui/react';
|
||||
|
||||
interface IPageHeadingProps extends BoxProps {
|
||||
interface IPageComposition {
|
||||
Heading: React.FC<IPageHeadingProps & BoxProps>;
|
||||
Content: React.FC<BoxProps>;
|
||||
Footer: React.FC<BoxProps>;
|
||||
}
|
||||
|
||||
const Page: React.FC<BoxProps> & IPageComposition = props => {
|
||||
return <Box {...props}>{props.children}</Box>;
|
||||
};
|
||||
|
||||
interface IPageHeadingProps {
|
||||
headingPrefix?: JSX.Element;
|
||||
heading: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
export const PageWrapper: React.FC<BoxProps> = props => {
|
||||
return <Box {...props}>{props.children}</Box>;
|
||||
};
|
||||
|
||||
export const PageHeading: React.FC<IPageHeadingProps> = props => {
|
||||
Page.Heading = props => {
|
||||
const { headingPrefix, heading, description, ...boxProps } = props;
|
||||
return (
|
||||
<Box {...boxProps}>
|
||||
@ -26,15 +32,17 @@ export const PageHeading: React.FC<IPageHeadingProps> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
export const PageContent: React.FC<BoxProps> = props => (
|
||||
Page.Content = props => (
|
||||
<Box mt='4' {...props}>
|
||||
{props.children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
export const PageFooter: React.FC<BoxProps> = props => (
|
||||
Page.Footer = props => (
|
||||
<Box mt='4' {...props}>
|
||||
<Divider m='20px 0' />
|
||||
{props.children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
export { Page };
|
||||
|
||||
@ -10,7 +10,7 @@ const Avatar: React.FC<IAvatarProps> = props => {
|
||||
return (
|
||||
<Flex flexDir={'column'} alignItems={'center'}>
|
||||
<ChakraAvatar border={`4px solid ${borderColor}`} borderColor={borderColor} name={name} size='2xl'>
|
||||
<ChakraAvatarBadge boxSize='0.75em' bg={onlineColor} />
|
||||
{isOnline && <ChakraAvatarBadge boxSize='0.75em' bg={onlineColor} />}
|
||||
</ChakraAvatar>
|
||||
{props.children}
|
||||
</Flex>
|
||||
|
||||
@ -3,7 +3,7 @@ import { ChatButton } from './ChatButton';
|
||||
|
||||
export interface IAvatarProps {
|
||||
name: string;
|
||||
isOnline: boolean;
|
||||
isOnline?: boolean | undefined;
|
||||
}
|
||||
|
||||
export interface IChatButtonProps {
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import React, { createContext } from 'react';
|
||||
import { BoxProps, Flex } from '@chakra-ui/react';
|
||||
import { IUser } from '@educt/interfaces';
|
||||
import React from 'react';
|
||||
import { BoxProps, Flex, FlexProps } from '@chakra-ui/react';
|
||||
import { Avatar, ChatButton, IAvatarProps, IChatButtonProps } from './Avatar';
|
||||
import { About, Details, Heading, IAboutProps, IDetailsProps, IHeadingProps, Info } from './Info';
|
||||
|
||||
@ -13,10 +12,12 @@ interface IUserProfileComposition {
|
||||
About: React.FC<IAboutProps>;
|
||||
}
|
||||
|
||||
export const UserProfileContext = createContext<IUser | undefined>(undefined);
|
||||
|
||||
const UserProfile: React.FC & IUserProfileComposition = props => {
|
||||
return <Flex flexDir={{ base: 'column', md: 'row' }}>{props.children}</Flex>;
|
||||
const UserProfile: React.FC<FlexProps> & IUserProfileComposition = props => {
|
||||
return (
|
||||
<Flex flexDir={{ base: 'column', md: 'row' }} {...props}>
|
||||
{props.children}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
UserProfile.Avatar = Avatar;
|
||||
|
||||
@ -8,7 +8,7 @@ import { MdError } from 'react-icons/md';
|
||||
* Types
|
||||
*/
|
||||
import { IPageProps } from '@educt/interfaces';
|
||||
import { PageContent, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
@ -28,8 +28,8 @@ const NotFoundPage: React.FC<IPageProps> = ({ title }) => {
|
||||
<Helmet>
|
||||
<title>{title}</title>
|
||||
</Helmet>
|
||||
<PageWrapper textAlign='center' mt={40}>
|
||||
<PageContent>
|
||||
<Page textAlign='center' mt={40}>
|
||||
<Page.Content>
|
||||
<Icon as={MdError} w='16' h='16' />
|
||||
<Heading display='block' as='h1' fontSize='6xl'>
|
||||
Page not found
|
||||
@ -38,8 +38,8 @@ const NotFoundPage: React.FC<IPageProps> = ({ title }) => {
|
||||
<Link as={ReactRouterLink} to='/' color='blue.500'>
|
||||
Return to main page
|
||||
</Link>
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import React from 'react';
|
||||
import { IPageProps } from '@educt/interfaces';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { CategoryTableList, CategoryTableRow } from '@educt/components/Tables/CategoryTableList';
|
||||
import { useFetchCategories } from '@educt/hooks/queries';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useFetchCategories } from '@educt/hooks/queries';
|
||||
|
||||
/**
|
||||
* Categories page
|
||||
*/
|
||||
@ -14,12 +18,12 @@ const CategoriesPage: React.FC<IPageProps> = () => {
|
||||
if (isLoading || categories === null) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<PageHeading heading='Categories' description='Edit categories in the system.' />
|
||||
<PageContent>
|
||||
<Page>
|
||||
<Page.Heading heading='Categories' description='Edit categories in the system.' />
|
||||
<Page.Content>
|
||||
<CategoryTableList categories={categories} render={CategoryTableRow} />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import type { IPageProps } from '@educt/interfaces';
|
||||
* Components
|
||||
*/
|
||||
import { CourseBackgroundImage, CourseHeader, CourseHeading, CourseInfo, LessonItem, LessonList } from '.';
|
||||
import { PageWrapper, PageContent } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
|
||||
/**
|
||||
@ -50,7 +50,7 @@ const CoursePage: React.FC<IPageProps> = () => {
|
||||
const handleEditCourse = () => history.push(`/courses/edit/${course.id}`);
|
||||
|
||||
return (
|
||||
<PageWrapper maxW='1200px'>
|
||||
<Page maxW='1200px'>
|
||||
<Helmet>
|
||||
<title>{course.title}</title>
|
||||
</Helmet>
|
||||
@ -64,7 +64,7 @@ const CoursePage: React.FC<IPageProps> = () => {
|
||||
/>
|
||||
</CourseHeader>
|
||||
|
||||
<PageContent mt={{ base: '5', sm: '2' }}>
|
||||
<Page.Content mt={{ base: '5', sm: '2' }}>
|
||||
<Grid templateColumns={{ base: '1fr', xl: '3fr 1fr' }} gap={'7'}>
|
||||
<GridItem>
|
||||
<Box>
|
||||
@ -158,8 +158,8 @@ const CoursePage: React.FC<IPageProps> = () => {
|
||||
</Box>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ import { IPageProps } from '@educt/interfaces';
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
import { PageWrapper, PageHeading, PageContent } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { CreateButton } from '@educt/components/Buttons';
|
||||
import { Box } from '@chakra-ui/layout';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
@ -38,18 +38,18 @@ const CoursesPage: React.FC<IPageProps> = () => {
|
||||
if (me === null) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<PageHeading heading='Courses' description='List of all courses'>
|
||||
<Page>
|
||||
<Page.Heading heading='Courses' description='List of all courses'>
|
||||
<Box mt='5'>
|
||||
{(me.isAdmin || me.isTeacher) && <CreateButton onClick={handleCreateCourse} ml='auto' display='block' />}
|
||||
</Box>
|
||||
</PageHeading>
|
||||
<PageContent mt='10'>
|
||||
</Page.Heading>
|
||||
<Page.Content mt='10'>
|
||||
<CoursesTabs mb='7' />
|
||||
<CategoryList render={CategoryItem} />
|
||||
<CourseList render={CourseItem} />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { IPageProps } from '@educt/interfaces';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import CreateLessonForm from '@educt/components/Forms/LessonForm/CreateLessonForm';
|
||||
import { Redirect, useParams } from 'react-router-dom';
|
||||
import { useFetchCourse } from '@educt/hooks/queries';
|
||||
@ -21,12 +21,12 @@ const CreateLessonPage: React.FC<IPageProps> = () => {
|
||||
if (!course || isLoading) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<PageHeading heading='Lesson Creation' description='Create new lesson' />
|
||||
<PageContent>
|
||||
<Page>
|
||||
<Page.Heading heading='Lesson Creation' description='Create new lesson' />
|
||||
<Page.Content>
|
||||
<CreateLessonForm />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { Flex, Box, Heading, Text } from '@chakra-ui/react';
|
||||
|
||||
/**
|
||||
* Types
|
||||
@ -11,23 +10,23 @@ import { IPageProps } from '@educt/interfaces';
|
||||
*/
|
||||
import PrevPageButton from '@educt/components/PrevPageButton';
|
||||
import { CreateCourseForm } from '@educt/components/Forms/CourseForm';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
|
||||
/**
|
||||
* Create course page
|
||||
*/
|
||||
const CreateCoursePage: React.FC<IPageProps> = () => {
|
||||
return (
|
||||
<PageWrapper>
|
||||
<PageHeading
|
||||
<Page>
|
||||
<Page.Heading
|
||||
headingPrefix={<PrevPageButton prevPage='/courses' />}
|
||||
heading='Course Creation'
|
||||
description='Fill in the required fields to create a new course'
|
||||
/>
|
||||
<PageContent>
|
||||
<Page.Content>
|
||||
<CreateCourseForm />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ import DeleteCourseDialog from '@educt/components/Dialogs/DeleteCourseDialog';
|
||||
import PrevPageButton from '@educt/components/PrevPageButton';
|
||||
import { DeleteButton } from '@educt/components/Buttons';
|
||||
import { StatusButton } from './components';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { StudentTableList, StudentTableRow } from './components/StudentTableList';
|
||||
import LessonList from './components/LessonList';
|
||||
|
||||
@ -43,13 +43,13 @@ const EditCoursePage: React.FC<IPageProps> = () => {
|
||||
if (!course || isLoading) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<Page>
|
||||
<Helmet>
|
||||
<title>Editing {course.title}</title>
|
||||
</Helmet>
|
||||
|
||||
<DeleteCourseDialog course={course} onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />
|
||||
<PageHeading
|
||||
<Page.Heading
|
||||
headingPrefix={<PrevPageButton prevPage='/courses' />}
|
||||
heading='Course editor'
|
||||
description={course.title}
|
||||
@ -58,8 +58,8 @@ const EditCoursePage: React.FC<IPageProps> = () => {
|
||||
<StatusButton courseId={course.id} currentStatus={course.status} />
|
||||
<DeleteButton onClick={onOpenDeleteDialog} ml='2' />
|
||||
</Flex>
|
||||
</PageHeading>
|
||||
<PageContent>
|
||||
</Page.Heading>
|
||||
<Page.Content>
|
||||
<Box>
|
||||
<Tabs mt='8'>
|
||||
<TabList>
|
||||
@ -91,8 +91,8 @@ const EditCoursePage: React.FC<IPageProps> = () => {
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</Box>
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ import {
|
||||
import ReactPlayer from 'react-player';
|
||||
import { MdOutlineCircle, MdCheckCircle, MdOutlineFilePresent, MdSkipNext, MdSkipPrevious } from 'react-icons/md';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
|
||||
/**
|
||||
* Types
|
||||
@ -138,17 +138,17 @@ const LessonPage: React.FC<IPageProps> = () => {
|
||||
if (me === null) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<Page>
|
||||
<Helmet>
|
||||
<title>{lesson.title}</title>
|
||||
</Helmet>
|
||||
<PageHeading heading={lesson.title}>
|
||||
<Page.Heading heading={lesson.title}>
|
||||
<Flex mt='3' alignItems={'center'} justifyContent={'space-between'}>
|
||||
<Text fontSize={'sm'}>~{moment.duration(lesson.duration, 'minutes').humanize()}</Text>
|
||||
{(me.isAdmin || me.isTeacher) && <EditButton onClick={handleEditLesson} />}
|
||||
</Flex>
|
||||
</PageHeading>
|
||||
<PageContent>
|
||||
</Page.Heading>
|
||||
<Page.Content>
|
||||
<Grid templateColumns={{ base: '1fr', xl: '3fr 1fr' }}>
|
||||
<GridItem>
|
||||
<Box>
|
||||
@ -270,8 +270,8 @@ const LessonPage: React.FC<IPageProps> = () => {
|
||||
</Box>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import { IPageProps } from '@educt/interfaces';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { Redirect, useParams } from 'react-router-dom';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
import { useFetchLesson } from '@educt/hooks/queries/lesson/useFetchLesson';
|
||||
import EditLessonForm from '@educt/components/Forms/LessonForm/EditLessonForm';
|
||||
import { useFetchLesson } from '@educt/hooks/queries/lesson/useFetchLesson';
|
||||
|
||||
/**
|
||||
* Create Lesson page
|
||||
@ -20,12 +20,12 @@ const EditLessonPage: React.FC<IPageProps> = () => {
|
||||
if (!lesson || isLoading) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<PageHeading heading='Lesson Editor' description={lesson.description} />
|
||||
<PageContent>
|
||||
<Page>
|
||||
<Page.Heading heading='Lesson Editor' description={lesson.description} />
|
||||
<Page.Content>
|
||||
<EditLessonForm lesson={lesson} />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -34,7 +34,7 @@ export const CourseCard: React.FC<BoxProps> = props => <Card py='5' px='6' {...p
|
||||
export const CourseCardHeading: React.FC<BoxProps> = props => (
|
||||
<Box borderLeftWidth={'5px'} borderColor={'blue.500'} pl='2' {...props} />
|
||||
);
|
||||
export const CourseCardTitle: React.FC<TextProps> = props => <Text fontSize={'2xl'} fontWeight={'bold'} {...props} />;
|
||||
export const CourseCardTitle: React.FC<TextProps> = props => <Text fontSize={'2xl'} fontWeight={'medium'} {...props} />;
|
||||
export const CourseCardCategory: React.FC = props => (
|
||||
<Flex mt='2'>
|
||||
<Tag size='sm' borderRadius='full' variant={'solid'}>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import { Flex, Box, Text, Link, SimpleGrid, Divider } from '@chakra-ui/react';
|
||||
import { Link as ReactRouterLink } from 'react-router-dom';
|
||||
import { IPageProps } from '@educt/interfaces';
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { Stat, StatContent, StatIcon, StatLabel, StatNumber } from '@educt/components/Stat';
|
||||
import { MdOutlineCollectionsBookmark, MdOutlineGroup, MdOutlineMessage, MdOutlineVideoLibrary } from 'react-icons/md';
|
||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||
@ -21,9 +21,13 @@ import {
|
||||
CourseCardList,
|
||||
} from './components';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
/**
|
||||
* Hooks
|
||||
*/
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useFetchCourses, useFetchStat } from '@educt/hooks/queries';
|
||||
import { useSocketEvent } from '@educt/hooks/useSocketEvent';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
/**
|
||||
* Main page
|
||||
@ -52,9 +56,9 @@ const MainPage: React.FC<IPageProps> = () => {
|
||||
if (me === null || courses === null || stat === null) return <LoadingPage />;
|
||||
|
||||
return (
|
||||
<PageWrapper>
|
||||
<PageHeading heading={`👋 Hello ${me.first_name},`} description="This what we've got today for you." />
|
||||
<PageContent>
|
||||
<Page>
|
||||
<Page.Heading heading={`👋 Hello ${me.first_name},`} description="This what we've got today for you." />
|
||||
<Page.Content>
|
||||
<SimpleGrid columns={{ base: 1, md: 2, lg: 4 }} spacing='6'>
|
||||
<Stat>
|
||||
<StatLabel>Online</StatLabel>
|
||||
@ -121,8 +125,8 @@ const MainPage: React.FC<IPageProps> = () => {
|
||||
</CourseCardList>
|
||||
</Box>
|
||||
<Divider />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Box, Heading, Breadcrumb, BreadcrumbItem, BreadcrumbLink, Grid } from '@chakra-ui/react';
|
||||
import { Box, Heading } from '@chakra-ui/react';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
|
||||
import { IPageProps } from '@educt/interfaces';
|
||||
|
||||
@ -8,9 +9,9 @@ import { IPageProps } from '@educt/interfaces';
|
||||
*/
|
||||
const MessagesPage: React.FC<IPageProps> = () => {
|
||||
return (
|
||||
<Box>
|
||||
<Heading as='h1'>Messages page</Heading>
|
||||
</Box>
|
||||
<Page>
|
||||
<Page.Heading heading='Messages' />
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -69,16 +69,6 @@ export const ProfileDescription: React.FC<IProfileDescriptionProps> = props => {
|
||||
);
|
||||
};
|
||||
|
||||
export const ProfileSignOutButton: React.FC<ButtonProps> = () => {
|
||||
const { logout } = useLogout();
|
||||
|
||||
return (
|
||||
<Button onClick={logout} size='sm' w={{ base: 'full', sm: '150px' }}>
|
||||
Sign Out
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProfileLoading: React.FC<BoxProps> = props => {
|
||||
return (
|
||||
<Box maxW='900px' {...props}>
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Avatar,
|
||||
Tabs,
|
||||
TabList,
|
||||
Tab,
|
||||
@ -23,8 +22,9 @@ import { IPageProps } from '@educt/interfaces';
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
import { PageHeading, PageContent, PageWrapper, PageFooter } from '@educt/components/PageElements';
|
||||
import { ProfileAvatar, ProfileBaseInfo, ProfileDescription, ProfileLoading, ProfileSignOutButton } from './components';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { ProfileLoading } from './components';
|
||||
import { UserProfile } from '@educt/components/UserProfile';
|
||||
import { CourseList } from './components/CourseList';
|
||||
import UpdateUserContactsForm from '@educt/pages/profile/components/UpdateUserContactsForm';
|
||||
|
||||
@ -33,6 +33,7 @@ import UpdateUserContactsForm from '@educt/pages/profile/components/UpdateUserCo
|
||||
*/
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
/**
|
||||
* Profile page
|
||||
@ -46,13 +47,17 @@ const ProfilePage: React.FC<IPageProps> = () => {
|
||||
if (me === null) return <ProfileLoading />;
|
||||
|
||||
return (
|
||||
<PageWrapper maxW='900px'>
|
||||
<PageHeading heading='My account' description='Update you contacts information or password here.' />
|
||||
<ProfileBaseInfo mt='20'>
|
||||
<ProfileAvatar name={me.fullname} />
|
||||
<ProfileDescription fullname={me.fullname} email={me.email} roles={me.roles} />
|
||||
</ProfileBaseInfo>
|
||||
<PageContent>
|
||||
<Page maxW={'900px'}>
|
||||
<Page.Heading heading='My account' description='Update you contacts information or password here.' />
|
||||
<Page.Content>
|
||||
<UserProfile mt='14'>
|
||||
<UserProfile.Avatar name={me.fullname} />
|
||||
<UserProfile.Info>
|
||||
<UserProfile.Heading fullname={me.fullname} roles={me.roles} />
|
||||
<UserProfile.Details registered={me.created_at} lastLogin={me.last_login} />
|
||||
<UserProfile.About about={me.about} />
|
||||
</UserProfile.Info>
|
||||
</UserProfile>
|
||||
<Tabs mt='7'>
|
||||
<TabList>
|
||||
<Tab>Account information</Tab>
|
||||
@ -116,12 +121,9 @@ const ProfilePage: React.FC<IPageProps> = () => {
|
||||
)}
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</PageContent>
|
||||
<PageFooter textAlign='center'>
|
||||
<ProfileSignOutButton />
|
||||
</PageFooter>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ProfilePage;
|
||||
export default observer(ProfilePage);
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { Redirect } from 'react-router-dom';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
import { PageContent, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { UserProfile } from '@educt/components/UserProfile';
|
||||
import type { IPageProps } from '@educt/interfaces';
|
||||
|
||||
@ -10,18 +11,27 @@ import type { IPageProps } from '@educt/interfaces';
|
||||
*/
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useFetchUser } from '@educt/hooks/queries/user/useFetchUser';
|
||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||
|
||||
const UserPage: React.FC<IPageProps> = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const { data: user, error, isLoading } = useFetchUser(id);
|
||||
const params = useParams<{ id: string }>();
|
||||
const {
|
||||
userStore: { me },
|
||||
} = useRootStore();
|
||||
const { data: user, error, isLoading } = useFetchUser(params.id);
|
||||
|
||||
if (error?.response?.status === 404) return <Redirect to='/404' />;
|
||||
|
||||
if (user === null || isLoading) return <LoadingPage />;
|
||||
if (user === null || me === null || isLoading) return <LoadingPage />;
|
||||
|
||||
/**
|
||||
* Redirect to profile page
|
||||
*/
|
||||
if (me.id === params.id) return <Redirect to='/profile' />;
|
||||
|
||||
return (
|
||||
<PageWrapper maxW='800px'>
|
||||
<PageContent>
|
||||
<Page>
|
||||
<Page.Content maxW={'900px'}>
|
||||
<UserProfile>
|
||||
<UserProfile.Avatar name={user.fullname} isOnline>
|
||||
<UserProfile.ChatButton userid={user.id} />
|
||||
@ -32,9 +42,9 @@ const UserPage: React.FC<IPageProps> = () => {
|
||||
<UserProfile.About about={user.about} />
|
||||
</UserProfile.Info>
|
||||
</UserProfile>
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserPage;
|
||||
export default observer(UserPage);
|
||||
|
||||
@ -8,7 +8,7 @@ import type { IPageProps } from '@educt/interfaces';
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||
import { Page } from '@educt/components/PageElements';
|
||||
import { UserList, UserItem } from './components/UserList';
|
||||
import LoadingPage from '@educt/components/LoadingPage';
|
||||
|
||||
@ -35,12 +35,12 @@ const UsersPage: React.FC<IPageProps> = () => {
|
||||
return (
|
||||
// TODO: delete page context for better performance
|
||||
<UsersPageContextProvider>
|
||||
<PageWrapper>
|
||||
<PageHeading heading='User management' description='You can add or delete users on this page.' />
|
||||
<PageContent mt='5'>
|
||||
<Page>
|
||||
<Page.Heading heading='User management' description='You can add or delete users on this page.' />
|
||||
<Page.Content mt='5'>
|
||||
<UserList render={UserItem} limit={6} />
|
||||
</PageContent>
|
||||
</PageWrapper>
|
||||
</Page.Content>
|
||||
</Page>
|
||||
</UsersPageContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@ -62,10 +62,25 @@ export default class UserStore {
|
||||
public async loadCurrentUserData() {
|
||||
const result = await UserServiceInstance.fetchMe();
|
||||
const {
|
||||
data: { id, first_name, last_name, fullname, email, roles, likes, contacts, courses, created_at, updated_at },
|
||||
data: {
|
||||
id,
|
||||
first_name,
|
||||
last_name,
|
||||
fullname,
|
||||
about,
|
||||
last_login,
|
||||
email,
|
||||
roles,
|
||||
likes,
|
||||
contacts,
|
||||
courses,
|
||||
created_at,
|
||||
updated_at,
|
||||
},
|
||||
} = result;
|
||||
|
||||
runInAction(() => {
|
||||
// TODO Fix this
|
||||
this.me = {
|
||||
id,
|
||||
first_name,
|
||||
@ -73,6 +88,8 @@ export default class UserStore {
|
||||
email,
|
||||
roles,
|
||||
fullname,
|
||||
about,
|
||||
last_login,
|
||||
likes,
|
||||
contacts,
|
||||
courses,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user