mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 02:09:08 +03:00
feat: fetch lesson hook
This commit is contained in:
parent
eb1fd5d084
commit
44cc8f47ec
@ -22,7 +22,11 @@ export const PageHeading: React.FC<IPageHeadingProps> = props => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageContent: React.FC<BoxProps> = props => <Box {...props}>{props.children}</Box>;
|
export const PageContent: React.FC<BoxProps> = props => (
|
||||||
|
<Box mt='4' {...props}>
|
||||||
|
{props.children}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
export const PageFooter: React.FC<BoxProps> = props => (
|
export const PageFooter: React.FC<BoxProps> = props => (
|
||||||
<Box mt='4' {...props}>
|
<Box mt='4' {...props}>
|
||||||
|
|||||||
21
src/hooks/queries/lesson/useFetchLesson.ts
Normal file
21
src/hooks/queries/lesson/useFetchLesson.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import useAsync from '@educt/hooks/useAsync';
|
||||||
|
import { ILesson } from '@educt/interfaces';
|
||||||
|
import { LessonServiceInstance } from '@educt/services';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
const useFetchLesson = (id: string) => {
|
||||||
|
const fetch = async (id: string) => {
|
||||||
|
const { data } = await LessonServiceInstance.fetchLessonById(id);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const { execute: fetchLessonById, ...state } = useAsync<ILesson, Parameters<typeof fetch>>(fetch);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchLessonById(id);
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
return { ...state };
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useFetchLesson };
|
||||||
@ -124,9 +124,9 @@ const CoursePage: React.FC<IPageProps> = () => {
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider mt='5' />
|
<Divider mt='5' mb='5' />
|
||||||
|
|
||||||
<Box mt='4'>
|
<Box>
|
||||||
<Flex alignItems={'center'} justifyContent={'space-between'}>
|
<Flex alignItems={'center'} justifyContent={'space-between'}>
|
||||||
<Text fontSize={'2xl'} fontWeight={'medium'}>
|
<Text fontSize={'2xl'} fontWeight={'medium'}>
|
||||||
Content
|
Content
|
||||||
|
|||||||
@ -188,10 +188,7 @@ export const LessonItem: React.FC<ILessonItemProps> = props => {
|
|||||||
display={'flex'}
|
display={'flex'}
|
||||||
fontSize={'sm'}
|
fontSize={'sm'}
|
||||||
justifyContent={'space-between'}
|
justifyContent={'space-between'}
|
||||||
pl='5'
|
p='5'
|
||||||
pr='5'
|
|
||||||
pb='5'
|
|
||||||
pt='5'
|
|
||||||
minH='85px'
|
minH='85px'
|
||||||
borderRadius={'xl'}
|
borderRadius={'xl'}
|
||||||
transition={'ease-in-out .1s'}
|
transition={'ease-in-out .1s'}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Box, Heading } from '@chakra-ui/react';
|
import moment from 'moment';
|
||||||
|
import { Flex, Box, Button, Divider, Heading, Text, Grid, GridItem, Stack, Icon, IconButton } from '@chakra-ui/react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types
|
* Types
|
||||||
@ -9,18 +10,98 @@ import { IPageProps } from '@educt/interfaces';
|
|||||||
/**
|
/**
|
||||||
* Hooks
|
* Hooks
|
||||||
*/
|
*/
|
||||||
import { useParams } from 'react-router-dom';
|
import { Redirect, useParams } from 'react-router-dom';
|
||||||
|
import { PageContent, PageHeading, PageWrapper } from '@educt/components/PageElements';
|
||||||
|
import { useFetchLesson } from '@educt/hooks/queries/lesson/useFetchLesson';
|
||||||
|
import LoadingPage from '@educt/components/LoadingPage';
|
||||||
|
import { MdCheckCircle, MdOutlineFilePresent, MdSkipNext, MdSkipPrevious } from 'react-icons/md';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lesson Page
|
* Lesson Page
|
||||||
*/
|
*/
|
||||||
const LessonPage: React.FC<IPageProps> = () => {
|
const LessonPage: React.FC<IPageProps> = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
|
const { error, data: lesson, isLoading } = useFetchLesson(id);
|
||||||
|
|
||||||
|
if (error?.response?.status === 404) {
|
||||||
|
return <Redirect to='/404' />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lesson || isLoading) return <LoadingPage />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<PageWrapper>
|
||||||
<Heading as='h1'>Lesson {id}</Heading>
|
<PageHeading heading={lesson.title}>
|
||||||
</Box>
|
<Box mt='3'>
|
||||||
|
<Text fontSize={'sm'}>~{moment.duration(lesson.duration, 'minutes').humanize()}</Text>
|
||||||
|
</Box>
|
||||||
|
</PageHeading>
|
||||||
|
<PageContent>
|
||||||
|
<Grid templateColumns={{ base: '1fr', xl: '3fr 1fr' }} gap={'7'}>
|
||||||
|
<GridItem>
|
||||||
|
<Box>
|
||||||
|
<Box bg={lesson.color?.hex} minH={'500px'} />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Flex justifyContent={'flex-end'} mt='3'>
|
||||||
|
<IconButton aria-label='prev-lesson' icon={<MdSkipPrevious />} size='sm' mr='2' />
|
||||||
|
<Button aria-label='next-lesson' leftIcon={<MdSkipNext />} size='sm'>
|
||||||
|
Next lesson
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
|
|
||||||
|
<Box mt='7'>
|
||||||
|
<Heading as='h2' fontSize={'2xl'} fontWeight={'medium'}>
|
||||||
|
Description
|
||||||
|
</Heading>
|
||||||
|
<Text mt='3'>{lesson.description}</Text>
|
||||||
|
|
||||||
|
<Divider mt='4' />
|
||||||
|
</Box>
|
||||||
|
</GridItem>
|
||||||
|
<GridItem>
|
||||||
|
<Box>
|
||||||
|
<Stack maxH={'445px'} overflowY={'scroll'}>
|
||||||
|
{Array(50)
|
||||||
|
.fill(1)
|
||||||
|
.map((n, i) => (
|
||||||
|
<Flex key={i} alignItems={'center'} borderRadius={'xl'}>
|
||||||
|
<Icon as={MdCheckCircle} color='green.500' w={7} h={7} mr='2' />
|
||||||
|
<Box>
|
||||||
|
<Text as='small' color='gray.500'>
|
||||||
|
Lesson {i + 1}
|
||||||
|
</Text>
|
||||||
|
<Text fontSize='sm' fontWeight={'medium'}>
|
||||||
|
Lorem ipsum dolor sit amet consectetur adipisicing elit. Vel, eaque.
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
|
||||||
|
<Divider mt='5' mb='5' />
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
<Text fontSize={'2xl'} fontWeight={'medium'}>
|
||||||
|
Materials
|
||||||
|
</Text>
|
||||||
|
<Stack>
|
||||||
|
{[1, 2, 3].map(n => (
|
||||||
|
<Flex key={n} alignItems={'center'} mt='5' p='3' bg='gray.50' borderRadius={'lg'}>
|
||||||
|
<Icon as={MdOutlineFilePresent} mr='2' h={4} w={4} />
|
||||||
|
<Text fontSize={'sm'} fontWeight={'medium'} lineHeight={'1rem'}>
|
||||||
|
lesson-1_sourse-code.zip <br />
|
||||||
|
<Text as='small'>190kB</Text>
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</GridItem>
|
||||||
|
</Grid>
|
||||||
|
</PageContent>
|
||||||
|
</PageWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,17 @@ class LessonService {
|
|||||||
this.api = api;
|
this.api = api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get lesson by id
|
||||||
|
*
|
||||||
|
* @param id Lesson id
|
||||||
|
* @returns Lesson
|
||||||
|
*/
|
||||||
|
public async fetchLessonById(id: string): Promise<IApiRespose<ILesson>> {
|
||||||
|
const result = await this.api.get(`/v1/lessons/${id}`);
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete lesson by id
|
* Delete lesson by id
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user