mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
feat: dark mode & public route
This commit is contained in:
parent
d4703b97d3
commit
d28cb97d30
15
src/App.tsx
15
src/App.tsx
@ -1,8 +1,11 @@
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
|
||||
import { BrowserRouter as Router, Switch } from 'react-router-dom';
|
||||
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
import PrivateRoute from './components/PrivateRoute/PrivateRoute';
|
||||
import ErrorFallback from './components/ErrorFallback';
|
||||
import PublicRoute from './components/PublicRoute/PublicRoute';
|
||||
|
||||
/**
|
||||
* Pages
|
||||
@ -22,11 +25,11 @@ const App = () => {
|
||||
<PrivateRoute path='/courses' component={CoursesPage} title='Courses' />
|
||||
<PrivateRoute path='/messages' component={MessagesPage} title='Messages' />
|
||||
<PrivateRoute path='/profile' component={ProfilePage} title='Profile' />
|
||||
<Route path='/auth' component={AuthPage} />
|
||||
<Route component={NotFoundPage} />
|
||||
<PublicRoute path='/auth' component={AuthPage} />
|
||||
<PublicRoute component={NotFoundPage} />
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
|
||||
export default observer(App);
|
||||
export default App;
|
||||
|
||||
@ -6,10 +6,10 @@ const AppName: React.FC = () => {
|
||||
return (
|
||||
<Flex alignItems='center'>
|
||||
<Box mr='4'>
|
||||
<MdSchool fill='blue' size='36px' />
|
||||
<Box as={MdSchool} color='blue.500' size='36px' />
|
||||
</Box>
|
||||
<Box lineHeight='1'>
|
||||
<Heading as='p' fontSize='2xl' color='gray.700'>
|
||||
<Heading as='p' fontSize='2xl'>
|
||||
App name
|
||||
</Heading>
|
||||
<Text as='small'>App description</Text>
|
||||
|
||||
@ -8,7 +8,6 @@ const Header: React.FC = () => {
|
||||
return (
|
||||
<Box
|
||||
as='header'
|
||||
background='#fff'
|
||||
position='fixed'
|
||||
top={0}
|
||||
left={0}
|
||||
|
||||
@ -6,7 +6,8 @@ import { MdNotifications } from 'react-icons/md';
|
||||
const UserNotifications: React.FC = () => {
|
||||
return (
|
||||
<Button
|
||||
marginRight={3}
|
||||
mr={3}
|
||||
ml={3}
|
||||
variant='solid'
|
||||
outline='none'
|
||||
border='none'
|
||||
|
||||
@ -5,6 +5,7 @@ import Nav from '../Nav/Nav';
|
||||
import { observer } from 'mobx-react';
|
||||
import { useRootStore } from '../../hooks/useRootStore';
|
||||
import { useErrorHandler } from 'react-error-boundary';
|
||||
import { ColorModeSwitcher } from '../ColorModeSwitcher/ColorModeSwitcher';
|
||||
|
||||
/**
|
||||
*
|
||||
@ -27,10 +28,12 @@ const Layout: React.FC = ({ children }) => {
|
||||
<>
|
||||
<Header />
|
||||
<Nav />
|
||||
|
||||
<Flex minH='100vh' flexDirection='column'>
|
||||
<Box pl='18rem' mt='4rem' mb='4rem' flex='1 0 auto'>
|
||||
<Box as='main' mr='auto' ml='auto' maxW='85rem' pl={5} pr={5} pt='2rem' pb='2rem'>
|
||||
{children}
|
||||
<ColorModeSwitcher position='absolute' right={0} bottom={0} margin={5} />
|
||||
</Box>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
||||
@ -30,7 +30,7 @@ const Nav: React.FC = () => {
|
||||
alignItems='flex-start'
|
||||
textDecoration='none'
|
||||
height='calc(100vh - 4rem)'
|
||||
padding='1.5rem 1.2rem'
|
||||
padding='5'
|
||||
>
|
||||
{config.links.map((link, i) => (
|
||||
<NavLink
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import React from 'react';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { Box, useColorMode } from '@chakra-ui/react';
|
||||
import type { History } from 'history';
|
||||
import type { LinkType } from '../../interfaces';
|
||||
import type { ActiveLinkState } from './Nav';
|
||||
@ -28,6 +28,7 @@ const NavLink: React.FC<NavLinkProps> = ({
|
||||
activeLink,
|
||||
link,
|
||||
}) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const onMouseEnter = () => handleOnHoverLink(link.title);
|
||||
const onClick = () => handleRoute(link.location);
|
||||
|
||||
@ -46,8 +47,8 @@ const NavLink: React.FC<NavLinkProps> = ({
|
||||
cursor='pointer'
|
||||
>
|
||||
<Box
|
||||
color={history.location.pathname === link.location || activeLink.title === link.title ? 'blue.500' : ''}
|
||||
backgroundColor={activeLink.title === link.title ? '#EBF8FF' : ''}
|
||||
color={history.location.pathname === link.location || activeLink.title === link.title ? 'blue.400' : ''}
|
||||
backgroundColor={activeLink.title === link.title ? `${colorMode === 'dark' ? 'gray.700' : 'gray.100'}` : ''}
|
||||
alignItems='center'
|
||||
borderRadius='9999px'
|
||||
display='flex'
|
||||
|
||||
@ -12,7 +12,7 @@ import ErrorFallback from '../ErrorFallback';
|
||||
* Checks if the user is loggedIn by reactive variable and if not,
|
||||
* then a redirect to "/auth" route.
|
||||
*/
|
||||
const PrivateRoute: React.FC<IPrivateRouteProps> = ({ children, component: Component, title, ...options }) => {
|
||||
const PrivateRoute: React.FC<IPrivateRouteProps> = ({ component: Component, title, ...options }) => {
|
||||
const { authStore } = useRootStore();
|
||||
|
||||
return (
|
||||
|
||||
23
src/components/PublicRoute/PublicRoute.tsx
Normal file
23
src/components/PublicRoute/PublicRoute.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import { Route } from 'react-router-dom';
|
||||
import { IPublicRouteProps } from '../../interfaces';
|
||||
import ErrorFallback from '../ErrorFallback';
|
||||
|
||||
/**
|
||||
* Render public page
|
||||
*/
|
||||
const PublicRoute: React.FC<IPublicRouteProps> = ({ component: Component, title, ...options }) => {
|
||||
return (
|
||||
<Route
|
||||
{...options}
|
||||
render={props => (
|
||||
<ErrorBoundary FallbackComponent={ErrorFallback}>
|
||||
<Component {...props} title={title} />
|
||||
</ErrorBoundary>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default PublicRoute;
|
||||
@ -47,6 +47,11 @@ export interface IPageProps extends RouteComponentProps {
|
||||
}
|
||||
|
||||
export interface IPrivateRouteProps extends RouteProps {
|
||||
component: React.FC<any>;
|
||||
component: React.FC<IPageProps>;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface IPublicRouteProps extends RouteProps {
|
||||
component: React.FC<IPageProps>;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
@ -1,23 +1,28 @@
|
||||
import React from 'react';
|
||||
import Helmet from 'react-helmet';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Box, Heading, Button } from '@chakra-ui/react';
|
||||
import { MdError } from 'react-icons/md';
|
||||
import { Flex, Box, Heading, Text, useToast } from '@chakra-ui/react';
|
||||
|
||||
const NotFoundPage: React.FC = () => {
|
||||
const toast = useToast();
|
||||
|
||||
React.useEffect(() => {
|
||||
toast({ title: `Page not found`, duration: 10000, isClosable: true, status: 'warning' });
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>Error 404</title>
|
||||
</Helmet>
|
||||
<Box textAlign='center' mt={40}>
|
||||
<Flex justifyContent='center'>
|
||||
<MdError size='64px' />
|
||||
</Flex>
|
||||
<Heading display='block' as='h1' fontSize='6xl'>
|
||||
Error 404
|
||||
Page not found
|
||||
</Heading>
|
||||
<Link to='/'>
|
||||
<Button variant='link' colorScheme='blue'>
|
||||
Return to main page
|
||||
</Button>
|
||||
</Link>
|
||||
<Text mt='5'>Sorry the page you are looking for could not be found.</Text>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user