-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added react router dom. Created Home and About page with basic navigation. Installed dependencies: yarn add react-router-dom
- Loading branch information
Showing
7 changed files
with
241 additions
and
139 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,27 @@ | ||
import React, {useEffect} from "react"; | ||
import React from "react"; | ||
import {Provider} from "react-redux"; | ||
import {useForm} from 'react-hook-form'; | ||
|
||
import './App.css'; | ||
import {Button, Card, CardActions, CardContent, CardMedia, Grid} from "@mui/material"; | ||
import CssBaseline from "@mui/material/CssBaseline"; | ||
import AppBar from '@mui/material/AppBar'; | ||
import LocalPostOfficeIcon from '@mui/icons-material/LocalPostOffice'; | ||
import Stack from '@mui/material/Stack'; | ||
import Box from '@mui/material/Box'; | ||
import Toolbar from '@mui/material/Toolbar'; | ||
import Typography from '@mui/material/Typography'; | ||
import Container from '@mui/material/Container'; | ||
import {createTheme, ThemeProvider} from '@mui/material/styles'; | ||
import {FormTextField} from "./libs/ui/FormTextField"; | ||
import * as Yup from 'yup'; | ||
import {yupResolver} from "@hookform/resolvers/yup"; | ||
import {useAppDispatch, useAppSelector} from "./redux/hooks"; | ||
import { | ||
postsActions, | ||
selectPosts | ||
} from "./redux/features/posts/posts.slice"; | ||
import {BrowserRouter} from "react-router-dom"; | ||
import {store} from "./redux/store"; | ||
|
||
import {createTheme} from '@mui/material/styles'; | ||
import AppRoutes from "./routes"; | ||
import {ThemeProvider} from "@emotion/react"; | ||
import {CssBaseline} from "@mui/material"; | ||
|
||
const theme = createTheme(); | ||
|
||
interface CreateFormInput { | ||
title: string; | ||
body: string; | ||
} | ||
|
||
const createFormDefaultValues = { | ||
title: "", | ||
body: "", | ||
}; | ||
|
||
const newPostValidationSchema = Yup.object().shape({ | ||
title: Yup.string().required('Title can\'t be empty').max(10, 'Title must not exceed 10 characters'), | ||
body: Yup.string().required('Body is required'), | ||
}); | ||
|
||
function PostApp() { | ||
const dispatch = useAppDispatch(); | ||
const posts = useAppSelector(selectPosts); | ||
|
||
useEffect(() => { | ||
dispatch(postsActions.fetchAll()); | ||
}, []); | ||
|
||
const methods = useForm<CreateFormInput>({defaultValues: createFormDefaultValues, resolver: yupResolver(newPostValidationSchema)}); | ||
const {handleSubmit, reset, control} = methods; | ||
|
||
const onAdd = (data: CreateFormInput) => dispatch(postsActions.create({title: data!.title, body: data!.body})); | ||
|
||
return ( | ||
<ThemeProvider theme={theme}> | ||
<CssBaseline/> | ||
<AppBar position="relative"> | ||
<Toolbar> | ||
<LocalPostOfficeIcon sx={{mr: 2}}/> | ||
<Typography variant="h6" color="inherit" noWrap> | ||
App | ||
</Typography> | ||
</Toolbar> | ||
</AppBar> | ||
|
||
<main> | ||
<Box | ||
sx={{ | ||
bgcolor: 'background.paper', | ||
pt: 6, | ||
pb: 6, | ||
}} | ||
> | ||
<Container maxWidth="xs"> | ||
<Typography | ||
component="h1" | ||
variant="h2" | ||
align="center" | ||
color="text.primary" | ||
gutterBottom | ||
> | ||
Posts | ||
</Typography> | ||
<Stack | ||
sx={{pt: 4}} | ||
direction="column" | ||
spacing={1} | ||
justifyContent="center" | ||
> | ||
<FormTextField name="title" label="title" control={control} /> | ||
<FormTextField name="body" label="body" control={control} /> | ||
<Button onClick={handleSubmit(onAdd)} variant={"contained"}>Add new Post</Button> | ||
<Button onClick={() => reset()} variant={"outlined"}>Reset</Button> | ||
</Stack> | ||
</Container> | ||
</Box> | ||
<Container sx={{py: 8}} maxWidth="md"> | ||
{/* End hero unit */} | ||
<Grid container spacing={4}> | ||
{posts.map((post) => ( | ||
<Grid item key={post.id} xs={12} sm={6} md={4}> | ||
<Card | ||
sx={{height: '100%', display: 'flex', flexDirection: 'column'}} | ||
> | ||
<CardMedia | ||
component="img" | ||
image="https://source.unsplash.com/random" | ||
alt="random" | ||
/> | ||
<CardContent sx={{flexGrow: 1}}> | ||
<Typography gutterBottom variant="h5" component="h2"> | ||
{post.title} | ||
</Typography> | ||
<Typography> | ||
{post.body} | ||
</Typography> | ||
</CardContent> | ||
<CardActions> | ||
<Button size="small" onClick={() => dispatch(postsActions.delete(post))}>Delete</Button> | ||
<Button size="small" onClick={() => dispatch(postsActions.update({ | ||
...post, | ||
body: `Updated at ${new Date().toISOString()}` | ||
}))}>Update</Button> | ||
</CardActions> | ||
</Card> | ||
</Grid> | ||
))} | ||
</Grid> | ||
</Container> | ||
</main> | ||
</ThemeProvider> | ||
); | ||
} | ||
|
||
function App() { | ||
return ( | ||
<Provider store={store}> | ||
<PostApp/> | ||
</Provider> | ||
); | ||
} | ||
const App = () => ( | ||
<> | ||
<BrowserRouter> | ||
<ThemeProvider theme={theme}> | ||
<Provider store={store}> | ||
<CssBaseline/> | ||
<AppRoutes/> | ||
</Provider> | ||
</ThemeProvider> | ||
</BrowserRouter> | ||
</> | ||
); | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import {Link} from "@mui/material"; | ||
import {NavLink as RouterNavLink} from "react-router-dom"; | ||
import React from "react"; | ||
import Typography from "@mui/material/Typography"; | ||
|
||
const About = () => { | ||
return ( | ||
<> | ||
<Typography | ||
component="h1" | ||
variant="h2" | ||
align="center" | ||
color="text.primary" | ||
gutterBottom | ||
> | ||
About Page | ||
</Typography> | ||
<Link | ||
component={RouterNavLink} | ||
to={'/'} | ||
variant="button" | ||
color="text.primary" | ||
sx={{ my: 1, mx: 1.5 }} | ||
>Back to Home</Link> | ||
</> | ||
); | ||
} | ||
export default About; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import React, {useEffect} from "react"; | ||
import {useForm} from 'react-hook-form'; | ||
|
||
import '../App.css'; | ||
import {Button, Card, CardActions, CardContent, CardMedia, Grid, Link} from "@mui/material"; | ||
import AppBar from '@mui/material/AppBar'; | ||
import Stack from '@mui/material/Stack'; | ||
import Box from '@mui/material/Box'; | ||
import Toolbar from '@mui/material/Toolbar'; | ||
import Typography from '@mui/material/Typography'; | ||
import Container from '@mui/material/Container'; | ||
import {FormTextField} from "../libs/ui/FormTextField"; | ||
import * as Yup from 'yup'; | ||
import {yupResolver} from "@hookform/resolvers/yup"; | ||
import {useAppDispatch, useAppSelector} from "../redux/hooks"; | ||
import {postsActions, selectPosts} from "../redux/features/posts/posts.slice"; | ||
import { NavLink as RouterLink } from 'react-router-dom'; | ||
|
||
|
||
|
||
interface CreateFormInput { | ||
title: string; | ||
body: string; | ||
} | ||
|
||
const createFormDefaultValues = { | ||
title: "", | ||
body: "", | ||
}; | ||
|
||
const newPostValidationSchema = Yup.object().shape({ | ||
title: Yup.string().required('Title can\'t be empty').max(10, 'Title must not exceed 10 characters'), | ||
body: Yup.string().required('Body is required'), | ||
}); | ||
|
||
function Home() { | ||
const dispatch = useAppDispatch(); | ||
const posts = useAppSelector(selectPosts); | ||
|
||
useEffect(() => { | ||
dispatch(postsActions.fetchAll()); | ||
}, []); | ||
|
||
const methods = useForm<CreateFormInput>({ | ||
defaultValues: createFormDefaultValues, | ||
resolver: yupResolver(newPostValidationSchema) | ||
}); | ||
const {handleSubmit, reset, control} = methods; | ||
|
||
const onAdd = (data: CreateFormInput) => dispatch(postsActions.create({title: data!.title, body: data!.body})); | ||
|
||
return ( | ||
<> | ||
<AppBar | ||
position="static" | ||
color="primary" | ||
elevation={0} | ||
sx={{ borderBottom: (theme) => `1px solid ${theme.palette.divider}` }} | ||
> | ||
<Toolbar sx={{ flexWrap: 'wrap' }}> | ||
<Typography variant="h6" color="inherit" noWrap sx={{ flexGrow: 1 }}> | ||
Company name | ||
</Typography> | ||
<nav> | ||
<Link | ||
component={RouterLink} | ||
to={'/'} | ||
variant="button" | ||
color="text.primary" | ||
sx={{ my: 1, mx: 1.5 }} | ||
> | ||
Home | ||
</Link> | ||
<Link | ||
component={RouterLink} | ||
to={'/about'} | ||
variant="button" | ||
color="text.primary" | ||
sx={{ my: 1, mx: 1.5 }} | ||
> | ||
About | ||
</Link> | ||
</nav> | ||
</Toolbar> | ||
</AppBar> | ||
<main> | ||
<Box | ||
sx={{ | ||
bgcolor: 'background.paper', | ||
pt: 6, | ||
pb: 6, | ||
}} | ||
> | ||
<Container maxWidth="xs"> | ||
<Typography | ||
component="h1" | ||
variant="h2" | ||
align="center" | ||
color="text.primary" | ||
gutterBottom | ||
> | ||
Posts | ||
</Typography> | ||
<Stack | ||
sx={{pt: 4}} | ||
direction="column" | ||
spacing={1} | ||
justifyContent="center" | ||
> | ||
<FormTextField name="title" label="title" control={control}/> | ||
<FormTextField name="body" label="body" control={control}/> | ||
<Button onClick={handleSubmit(onAdd)} variant={"contained"}>Add new Post</Button> | ||
<Button onClick={() => reset()} variant={"outlined"}>Reset</Button> | ||
</Stack> | ||
</Container> | ||
</Box> | ||
<Container sx={{py: 8}} maxWidth="md"> | ||
{/* End hero unit */} | ||
<Grid container spacing={4}> | ||
{posts.map((post) => ( | ||
<Grid item key={post.id} xs={12} sm={6} md={4}> | ||
<Card | ||
sx={{height: '100%', display: 'flex', flexDirection: 'column'}} | ||
> | ||
<CardMedia | ||
component="img" | ||
image="https://source.unsplash.com/random" | ||
alt="random" | ||
/> | ||
<CardContent sx={{flexGrow: 1}}> | ||
<Typography gutterBottom variant="h5" component="h2"> | ||
{post.title} | ||
</Typography> | ||
<Typography> | ||
{post.body} | ||
</Typography> | ||
</CardContent> | ||
<CardActions> | ||
<Button size="small" | ||
onClick={() => dispatch(postsActions.delete(post))}>Delete</Button> | ||
<Button size="small" onClick={() => dispatch(postsActions.update({ | ||
...post, | ||
body: `Updated at ${new Date().toISOString()}` | ||
}))}>Update</Button> | ||
</CardActions> | ||
</Card> | ||
</Grid> | ||
))} | ||
</Grid> | ||
</Container> | ||
</main> | ||
</> | ||
); | ||
} | ||
|
||
export default Home; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import {Route, Routes} from 'react-router-dom'; | ||
import Home from "../pages/Home"; | ||
import About from "../pages/About"; | ||
|
||
const AppRoutes = () => ( | ||
<> | ||
<Routes> | ||
<Route path='/' element={<Home/>}/> | ||
<Route path='/about' element={<About/>}/> | ||
</Routes> | ||
</> | ||
); | ||
|
||
export default AppRoutes; |
Oops, something went wrong.