Skip to content

Commit e7cdaf5

Browse files
authored
Merge pull request #11 from atlp-rwanda/ft-landing-page-182234874
#182234874 (Feature): Implement landing page
2 parents aeb2942 + 7b49241 commit e7cdaf5

33 files changed

+1129
-82
lines changed

.eslintrc.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
}
2222
],
2323
"react/jsx-no-undef": "off",
24+
"react/jsx-props-no-spreading": "off",
25+
"react/require-default-props": "off",
2426
"react/jsx-filename-extension": "off",
2527
"react/jsx-wrap-multilines": "off",
2628
"no-undef": "off"

jest.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
module.exports = {
22
setupFilesAfterEnv: ['<rootDir>/config/setUpTests.js'],
3+
moduleNameMapper: {
4+
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
5+
'<rootDir>/config/setUpTests.js',
6+
'\\.(css|less)$': '<rootDir>/config/setUpTests.js',
7+
},
38
};

package.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@
77
"license": "MIT",
88
"scripts": {
99
"dev": "webpack serve --mode development --open --hot",
10-
"test": "jest --env=jsdom",
10+
"test": "jest --env=jsdom react-scripts test -u",
1111
"build": "webpack --mode production",
1212
"lint": "eslint src/**/*.jsx --fix",
1313
"prepare": "husky install"
1414
},
1515
"dependencies": {
1616
"@reduxjs/toolkit": "^1.8.1",
17+
"@emotion/react": "^11.9.0",
18+
"@emotion/styled": "^11.8.1",
19+
"@mui/material": "^5.8.0",
20+
"@mui/styled-engine-sc": "^5.8.0",
21+
"prop-types": "^15.8.1",
1722
"react": "^18.1.0",
1823
"react-dom": "^18.1.0",
1924
"react-redux": "^8.0.1",
2025
"react-router-dom": "^6.3.0",
2126
"redux": "^4.2.0",
2227
"redux-persist": "^6.0.0",
23-
"sass": "^1.51.0"
28+
"react-test-renderer": "^18.1.0",
29+
"sass": "^1.51.0",
30+
"styled-components": "^5.3.5"
2431
},
2532
"devDependencies": {
2633
"@babel/core": "^7.17.10",

src/App.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { Route, Routes } from 'react-router-dom';
3-
import Home from './components/home/Home';
3+
import Home from './pages/index';
44
import Welcome from './components/Welcome';
55
import AboutPage from './components/about/About';
66

src/components/home/AppBar.jsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import * as React from 'react';
2+
import Box from '@mui/material/Box';
3+
import Link from '@mui/material/Link';
4+
import Button from '@mui/material/Button';
5+
import AppBar from './AppBarLayout';
6+
import Toolbar from './ToolBar';
7+
import Theme from '../../styles/muiTheme';
8+
9+
const rightLink = {
10+
fontSize: 16,
11+
color: 'common.white',
12+
ml: 3,
13+
};
14+
15+
function AppAppBar() {
16+
return (
17+
<div>
18+
<AppBar position="fixed" sx={{ bgcolor: Theme.bgcolor }}>
19+
<Toolbar sx={{ justifyContent: 'space-between' }}>
20+
<Box sx={{ flex: 1 }} />
21+
<Link
22+
variant="h6"
23+
underline="none"
24+
color="inherit"
25+
href="/"
26+
sx={{ fontSize: 24 }}
27+
>
28+
Barefoot Nomad
29+
</Link>
30+
<Box sx={{ flex: 1, display: 'flex', justifyContent: 'flex-end' }}>
31+
<Link
32+
color="inherit"
33+
variant="h6"
34+
underline="none"
35+
href="/"
36+
sx={rightLink}
37+
>
38+
<Button
39+
sx={{ color: 'common.white' }}
40+
color="secondary"
41+
variant="outlined"
42+
>
43+
Login
44+
</Button>
45+
</Link>
46+
<Link
47+
variant="h6"
48+
underline="none"
49+
href="/"
50+
sx={{ ...rightLink, color: 'common.white' }}
51+
>
52+
<Button
53+
sx={{ color: 'common.white' }}
54+
color="secondary"
55+
variant="outlined"
56+
>
57+
Register
58+
</Button>
59+
</Link>
60+
</Box>
61+
</Toolbar>
62+
</AppBar>
63+
<Toolbar />
64+
</div>
65+
);
66+
}
67+
68+
export default AppAppBar;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable react/jsx-props-no-spreading */
2+
import * as React from 'react';
3+
import MuiAppBar from '@mui/material/AppBar';
4+
5+
function AppBar(props) {
6+
return <MuiAppBar elevation={0} position="fixed" {...props} />;
7+
}
8+
9+
export default AppBar;

src/components/home/AppFooter.jsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* eslint-disable react/forbid-prop-types */
2+
import React from 'react';
3+
import Box from '@mui/material/Box';
4+
import Link from '@mui/material/Link';
5+
import Typography from '@mui/material/Typography';
6+
7+
function Footer() {
8+
return (
9+
<Box sx={{ bgcolor: 'background.paper', p: 6 }} component="footer">
10+
<Typography
11+
variant="subtitle1"
12+
align="center"
13+
color="text.secondary"
14+
component="p"
15+
>
16+
Barefoot Nomad
17+
</Typography>
18+
<Typography variant="body2" color="text.secondary" align="center">
19+
Copyright ©
20+
<Link color="inherit" href="/">
21+
Barefoot Nomad
22+
</Link>{' '}
23+
{new Date().getFullYear()}.
24+
</Typography>
25+
</Box>
26+
);
27+
}
28+
29+
export default Footer;

src/components/home/Button.jsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import * as React from 'react';
2+
import { experimentalStyled as styled } from '@mui/material/styles';
3+
import MuiButton from '@mui/material/Button';
4+
5+
const ButtonRoot = styled(MuiButton)(({ theme, size }) => ({
6+
borderRadius: 0,
7+
fontWeight: theme.typography.fontWeightMedium,
8+
fontFamily: theme.typography.h1.fontFamily,
9+
padding: theme.spacing(2, 4),
10+
fontSize: theme.typography.pxToRem(14),
11+
boxShadow: 'none',
12+
'&:active, &:focus': {
13+
boxShadow: 'none',
14+
},
15+
...(size === 'small' && {
16+
padding: theme.spacing(1, 3),
17+
fontSize: theme.typography.pxToRem(13),
18+
}),
19+
...(size === 'large' && {
20+
padding: theme.spacing(2, 5),
21+
fontSize: theme.typography.pxToRem(16),
22+
}),
23+
}));
24+
25+
function Button(props) {
26+
return <ButtonRoot {...props} />;
27+
}
28+
29+
export default Button;

src/components/home/Home.jsx

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,51 @@
1-
/* eslint-disable jsx-a11y/no-autofocus */
2-
import React from 'react';
3-
import { useDispatch, useSelector } from 'react-redux';
4-
import {
5-
setDarkMode,
6-
setLightMode,
7-
selectBackgroundColor,
8-
} from '../../redux/features/color/colorSlice';
9-
import {
10-
changeVisibility,
11-
selectVisibility,
12-
} from '../../redux/features/visibility/visibilitySlice';
13-
import './home.scss';
1+
import * as React from 'react';
2+
import Button from './Button';
3+
import Typography from './Typography';
4+
import ProductLayout from './PageLayout';
5+
import Theme from '../../styles/muiTheme';
146

15-
function Home() {
16-
const backgroundColor = useSelector(selectBackgroundColor);
17-
const visibility = useSelector(selectVisibility);
18-
const dispatch = useDispatch();
7+
const backgroundImage =
8+
'https://images.unsplash.com/photo-1534854638093-bada1813ca19?auto=format&fit=crop&w=1400&q=80';
199

10+
export default function Home() {
2011
return (
21-
<div className="welcome" style={{ backgroundColor }}>
22-
<b>
23-
Welcome to <i>BAREFOOT NOMAD.</i>
24-
</b>
25-
<button
26-
onClick={() => {
27-
dispatch(setDarkMode());
28-
dispatch(changeVisibility());
29-
}}
30-
type="button"
31-
autoFocus={visibility}
12+
<ProductLayout
13+
sxBackground={{
14+
backgroundImage: `url(${backgroundImage})`,
15+
backgroundColor: Theme.imageColor, // Average color of the background image.
16+
backgroundPosition: 'center',
17+
}}
18+
>
19+
{/* Increase the network loading priority of the background image. */}
20+
<img
21+
style={{ display: 'none' }}
22+
src={backgroundImage}
23+
alt="increase priority"
24+
/>
25+
<Typography color="inherit" align="center" variant="h2" marked="center">
26+
Welcome to Barefoot Nomad
27+
</Typography>
28+
<Typography
29+
color="inherit"
30+
align="center"
31+
variant="h5"
32+
sx={{ mb: 4, mt: { sx: 4, sm: 10 } }}
3233
>
33-
Dark mode
34-
</button>
35-
<button
36-
onClick={() => {
37-
dispatch(setLightMode());
38-
dispatch(changeVisibility());
39-
}}
40-
type="button"
41-
autoFocus={!visibility}
34+
Best Travel Service Provider
35+
</Typography>
36+
<Button
37+
color="secondary"
38+
size="large"
39+
variant="contained"
40+
component="a"
41+
href="/"
42+
sx={{ mt: 8 }}
4243
>
43-
Light mode
44-
</button>
45-
</div>
44+
Get started
45+
</Button>
46+
<Typography variant="body2" color="inherit" sx={{ mt: 2 }}>
47+
Discover the experience
48+
</Typography>
49+
</ProductLayout>
4650
);
4751
}
48-
49-
export default Home;

src/components/home/PageLayout.jsx

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/* eslint-disable react/require-default-props */
2+
import * as React from 'react';
3+
import PropTypes from 'prop-types';
4+
import { styled } from '@mui/material/styles';
5+
6+
import Container from '@mui/material/Container';
7+
import Box from '@mui/material/Box';
8+
import Wonder from '../../../static/productHeroWonder.png';
9+
import Arrow from '../../../static/productHeroArrowDown.png';
10+
11+
const ProductHeroLayoutRoot = styled('section')(({ theme }) => ({
12+
color: theme.palette.common.white,
13+
position: 'relative',
14+
display: 'flex',
15+
alignItems: 'center',
16+
[theme.breakpoints.up('sm')]: {
17+
height: '80vh',
18+
minHeight: 500,
19+
maxHeight: 1300,
20+
},
21+
}));
22+
23+
const Background = styled(Box)({
24+
position: 'absolute',
25+
left: 0,
26+
right: 0,
27+
top: 0,
28+
bottom: 0,
29+
backgroundSize: 'cover',
30+
backgroundRepeat: 'no-repeat',
31+
zIndex: -2,
32+
});
33+
34+
function ProductHeroLayout(props) {
35+
const { sxBackground, children } = props;
36+
37+
const scrolToSection = (id) => {
38+
const anchor = document.getElementById(id);
39+
anchor.scrollIntoView({
40+
behavior: 'smooth',
41+
block: 'center',
42+
});
43+
};
44+
45+
return (
46+
<ProductHeroLayoutRoot>
47+
<Container
48+
sx={{
49+
mt: 3,
50+
mb: 14,
51+
display: 'flex',
52+
flexDirection: 'column',
53+
alignItems: 'center',
54+
}}
55+
>
56+
<img src={Wonder} alt="wonder" width="147" height="80" />
57+
{children}
58+
<Box
59+
sx={{
60+
position: 'absolute',
61+
left: 0,
62+
right: 0,
63+
top: 0,
64+
bottom: 0,
65+
backgroundColor: 'common.black',
66+
opacity: 0.5,
67+
zIndex: -1,
68+
}}
69+
/>
70+
<Background sx={sxBackground} />
71+
<Box
72+
component="img"
73+
src={Arrow}
74+
height="16"
75+
width="12"
76+
alt="arrow down"
77+
onClick={() => scrolToSection('main')}
78+
sx={{
79+
position: 'absolute',
80+
bottom: 32,
81+
'&:hover': {
82+
cursor: 'pointer',
83+
'& .addIcon': {
84+
color: 'purple',
85+
},
86+
},
87+
}}
88+
/>
89+
</Container>
90+
</ProductHeroLayoutRoot>
91+
);
92+
}
93+
94+
ProductHeroLayout.propTypes = {
95+
children: PropTypes.node,
96+
sxBackground: PropTypes.oneOfType([
97+
PropTypes.arrayOf(
98+
PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])
99+
),
100+
PropTypes.func,
101+
PropTypes.object,
102+
]),
103+
};
104+
105+
export default ProductHeroLayout;

0 commit comments

Comments
 (0)