feat: added layout

This commit is contained in:
Sergey Yarkov 2022-01-23 21:00:42 +03:00
parent 8999a36eaf
commit 5ad94b7b25
5 changed files with 232 additions and 6 deletions

View File

@ -0,0 +1,45 @@
import * as React from 'react';
import {
Stat as ChakraStat,
StatProps,
useColorModeValue,
StatLabel as ChakraStatLabel,
StatLabel as ChakraStatNumber,
StatLabelProps,
Icon,
FlexProps,
Flex,
} from '@chakra-ui/react';
import { IconType } from 'react-icons';
export const Stat: React.FC = (props: StatProps) => (
<ChakraStat
px={{ base: 4, sm: 6 }}
py='5'
bg={useColorModeValue('white', 'gray.700')}
shadow='base'
rounded='lg'
{...props}
/>
);
export const StatLabel: React.FC = (props: StatLabelProps) => (
<ChakraStatLabel fontWeight='medium' isTruncated color={useColorModeValue('gray.500', 'gray.400')} {...props} />
);
export const StatNumber: React.FC = (props: StatLabelProps) => (
<ChakraStatNumber mt='2' fontWeight='medium' fontSize={'5xl'} isTruncated {...props} />
);
type StatIconPropsType = {
icon: IconType;
};
export const StatIcon: React.FC<StatIconPropsType> = props => (
<Icon as={props.icon} color={useColorModeValue('gray.700', 'gray.300')} width={10} height={10} />
);
export const StatContent: React.FC<FlexProps> = props => (
<Flex justifyContent={'space-between'} alignItems={'flex-end'}>
{props.children}
</Flex>
);

View File

@ -13,6 +13,7 @@ const useUpdateCategory = () => {
const update = async (id: string, data: UpdateCategoryParamsType) => { const update = async (id: string, data: UpdateCategoryParamsType) => {
try { try {
const result = await CategoryServiceInstance.update(id, data); const result = await CategoryServiceInstance.update(id, data);
toast({ title: 'Category updated.', status: 'info' });
return result.data; return result.data;
} catch (error) { } catch (error) {
if (axios.isAxiosError(error)) { if (axios.isAxiosError(error)) {

View File

@ -0,0 +1,94 @@
import React from 'react';
import {
Box,
BoxProps,
TextProps,
Text,
FlexProps,
Flex,
Tag,
TagLabel,
Icon,
Button,
useColorModeValue,
SimpleGrid,
SimpleGridProps,
} from '@chakra-ui/react';
import { Card } from '@educt/components/Card';
import { MdOutlineVideoLibrary, MdOutlineGroup, MdOutlineThumbUpOffAlt, MdOutlinePlayCircle } from 'react-icons/md';
import { useHistory } from 'react-router-dom';
export const CourseCardList: React.FC<SimpleGridProps> = props => (
<SimpleGrid
mt='4'
templateColumns={{
base: '1fr',
md: 'repeat(auto-fill, minmax(320px, 1fr))',
}}
spacing={'6'}
{...props}
/>
);
export const CourseCard: React.FC<BoxProps> = props => <Card py='5' px='6' {...props} />;
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 CourseCardCategory: React.FC = props => (
<Flex mt='2'>
<Tag size='sm' borderRadius='full' variant={'solid'}>
<TagLabel>{props.children}</TagLabel>
</Tag>
</Flex>
);
export const CourseCardContent: React.FC<FlexProps> = props => <Flex mt='5' alignItems={'center'} {...props} />;
export const CourseCardCreated: React.FC<{ created: string }> = props => (
<Box lineHeight={'1.2rem'} mr='14'>
<Text fontWeight={'medium'} fontSize={'sm'} color={useColorModeValue('gray.500', 'gray.400')}>
Created
</Text>
<Box as='time' verticalAlign='middle' dateTime={props.created}>
{props.created}
</Box>
</Box>
);
export const CourseCardLessons: React.FC<{ count: string | number }> = props => (
<Box>
<Flex alignItems={'center'}>
<Icon as={MdOutlineVideoLibrary} w={5} h={5} mr='3' />
<Box>
<Text fontWeight={'medium'} fontSize={'sm'} color={useColorModeValue('gray.500', 'gray.400')}>
Total lessons
</Text>
<Text>{props.count}</Text>
</Box>
</Flex>
</Box>
);
export const CourseCardFooter: React.FC<FlexProps> = props => (
<Flex justifyContent={'space-between'} alignItems={'center'} mt='9' {...props} />
);
export const CourseCardStat: React.FC<{ students: string | number; likes: string | number }> = props => (
<Flex>
<Flex alignItems={'center'} mr='5'>
<Icon as={MdOutlineGroup} mr='2' w={4} h={4} />
<Text>{props.students}</Text>
</Flex>
<Flex alignItems={'center'}>
<Icon as={MdOutlineThumbUpOffAlt} mr='2' w={4} h={4} />
<Text>{props.likes}</Text>
</Flex>
</Flex>
);
export const CourseCardWatch: React.FC<{ id: string }> = props => {
const history = useHistory();
return (
<Box>
<Button onClick={() => history.push(`/courses/${props.id}`)} leftIcon={<MdOutlinePlayCircle />} size='sm'>
Watch
</Button>
</Box>
);
};

View File

@ -1,16 +1,102 @@
import React from 'react'; import React from 'react';
import { Box, Heading } from '@chakra-ui/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 { IPageProps } from '@educt/interfaces';
import { PageContent, PageHeading, PageWrapper } 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';
import LoadingPage from '@educt/components/LoadingPage';
import {
CourseCard,
CourseCardCategory,
CourseCardCreated,
CourseCardHeading,
CourseCardContent,
CourseCardLessons,
CourseCardTitle,
CourseCardFooter,
CourseCardWatch,
CourseCardStat,
CourseCardList,
} from './components';
/** /**
* Main page * Main page
*/ */
const MainPage: React.FC<IPageProps> = () => { const MainPage: React.FC<IPageProps> = () => {
const {
userStore: { me },
} = useRootStore();
if (me === null) return <LoadingPage />;
return ( return (
<Box> <PageWrapper>
<Heading as='h1'>Main page</Heading> <PageHeading heading={`👋 Hello ${me.first_name},`} description="This what we've got today for you." />
</Box> <PageContent>
<SimpleGrid columns={{ base: 1, md: 2, lg: 4 }} spacing='6'>
<Stat>
<StatLabel>Unread messages</StatLabel>
<StatContent>
<StatNumber>3</StatNumber>
<StatIcon icon={MdOutlineMessage} />
</StatContent>
</Stat>
<Stat>
<StatLabel>Registered students</StatLabel>
<StatContent>
<StatNumber>24</StatNumber>
<StatIcon icon={MdOutlineGroup} />
</StatContent>
</Stat>
<Stat>
<StatLabel>Courses</StatLabel>
<StatContent>
<StatNumber>7</StatNumber>
<StatIcon icon={MdOutlineCollectionsBookmark} />
</StatContent>
</Stat>
<Stat>
<StatLabel>Lessons</StatLabel>
<StatContent>
<StatNumber>42</StatNumber>
<StatIcon icon={MdOutlineVideoLibrary} />
</StatContent>
</Stat>
</SimpleGrid>
<Box my='8'>
<Flex justifyContent={'space-between'}>
<Text fontWeight={'medium'}>Recently added</Text>
<Link as={ReactRouterLink} fontWeight={'medium'} to='/courses'>
See all
</Link>
</Flex>
<CourseCardList>
<CourseCard>
<CourseCardHeading>
<CourseCardTitle>Javascript in a nutshell</CourseCardTitle>
<CourseCardCategory>Web Developing</CourseCardCategory>
</CourseCardHeading>
<CourseCardContent>
<CourseCardCreated created='29 Nov 2022' />
<CourseCardLessons count={26} />
</CourseCardContent>
<CourseCardFooter>
<CourseCardStat students={24} likes={14} />
<CourseCardWatch id='123' />
</CourseCardFooter>
</CourseCard>
</CourseCardList>
</Box>
<Divider />
</PageContent>
</PageWrapper>
); );
}; };

View File

@ -69,7 +69,7 @@ export const ProfileDescription: React.FC<IProfileDescriptionProps> = props => {
); );
}; };
export const ProfileSignOutButton: React.FC<ButtonProps> = props => { export const ProfileSignOutButton: React.FC<ButtonProps> = () => {
const { logout } = useLogout(); const { logout } = useLogout();
return ( return (