First stable application according to tutorial
This commit is contained in:
parent
f5e4be85c4
commit
8d451a87b6
33 changed files with 1090 additions and 113 deletions
BIN
frontend/src/components/.Navbar.js.swl
Normal file
BIN
frontend/src/components/.Navbar.js.swl
Normal file
Binary file not shown.
BIN
frontend/src/components/.Navbar.js.swn
Normal file
BIN
frontend/src/components/.Navbar.js.swn
Normal file
Binary file not shown.
44
frontend/src/components/Button.css
Normal file
44
frontend/src/components/Button.css
Normal file
|
@ -0,0 +1,44 @@
|
|||
:root {
|
||||
--primary: #fff;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 8px 20px;
|
||||
border-radius: 2px;
|
||||
outline: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn--primary {
|
||||
background-color: var(--primary);
|
||||
color: #242424;
|
||||
border: 1px solid var(--primary);
|
||||
}
|
||||
|
||||
.btn--outline {
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
padding: 8px 20px;
|
||||
border: 1px solid var(--primary);
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.btn--medium {
|
||||
padding: 8px 20px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.btn--large {
|
||||
padding: 12px 26px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.btn--large:hover,
|
||||
.btn--medium:hover {
|
||||
transition: all 0.3s ease-out;
|
||||
background: #fff;
|
||||
color: #242424;
|
||||
transition: 250ms;
|
||||
}
|
||||
|
32
frontend/src/components/Button.js
Normal file
32
frontend/src/components/Button.js
Normal file
|
@ -0,0 +1,32 @@
|
|||
import React from 'react';
|
||||
import './Button.css';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const STYLES = ['btn--primary', 'btn--outline'];
|
||||
|
||||
const SIZES = ['btn--medium', 'btn--large'];
|
||||
export const Button = ({
|
||||
children,
|
||||
type,
|
||||
onClick,
|
||||
buttonStyle,
|
||||
buttonSize
|
||||
}) => {
|
||||
const checkButtonStyle = STYLES.includes(buttonStyle)
|
||||
? buttonStyle
|
||||
: STYLES[0];
|
||||
|
||||
const checkButtonSize = SIZES.includes(buttonSize) ? buttonSize : SIZES[0];
|
||||
|
||||
return (
|
||||
<Link to='sign-up' className='btn-mobile'>
|
||||
<button
|
||||
className={`btn ${checkButtonStyle} ${checkButtonSize}`}
|
||||
onClick={onClick}
|
||||
type={type}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
</Link>
|
||||
);
|
||||
};
|
21
frontend/src/components/CardItem.js
Normal file
21
frontend/src/components/CardItem.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
import React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
function CardItem(props) {
|
||||
return (
|
||||
<>
|
||||
<li className="cards__item">
|
||||
<Link className="cards__item__link" to={props.path}>
|
||||
<figure className="cards__item__pic-wrap" data-category={props.label}>
|
||||
<img src={props.src} alt="Travel Image" className="cards__item__img" />
|
||||
</figure>
|
||||
<div className="cards__item__info">
|
||||
<h5 className="cards__item__text">{props.text}</h5>
|
||||
</div>
|
||||
</Link>
|
||||
</li>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CardItem
|
119
frontend/src/components/Cards.css
Normal file
119
frontend/src/components/Cards.css
Normal file
|
@ -0,0 +1,119 @@
|
|||
.cards {
|
||||
padding: 4rem;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.cards__container {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
max-width: 1120px;
|
||||
width: 90%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.cards__wrapper {
|
||||
position: relative;
|
||||
margin: 50px 0 45px;
|
||||
}
|
||||
|
||||
.cards__items {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.cards__item {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin: 0 1rem;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.cards__item__link {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
width: 100%;
|
||||
box-shadow: 0 6px 20px rgba(56, 125, 255, 0.17);
|
||||
-webkit-filter: drop-shadow(0 6px 20px rgba(56, 125, 255, 0.017));
|
||||
filter: drop-shadow(0 6px 20px rgba(56, 125, 255, 0.017));
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.cards__item__pic-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-top: 67%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fade-img {
|
||||
animation-name: fade-img;
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
.cards__item__pic-wrap::after {
|
||||
content: attr(data-category);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
margin-left: 10px;
|
||||
padding: 6px 8px;
|
||||
max-width: calc((100%) - 60px);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
background-color: #1f98f4;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cards__item__img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: cover;
|
||||
transition: all 0.2s linear;
|
||||
}
|
||||
|
||||
.cards__item__img:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.cards__item__info {
|
||||
padding: 20px 30px 30px;
|
||||
}
|
||||
|
||||
.cards__item__text {
|
||||
color: #252e48;
|
||||
font-size: 18px;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1200px) {
|
||||
.content__blog__container {
|
||||
width: 84%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1024px) {
|
||||
.cards__items {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1024px) {
|
||||
.cards__item {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
}
|
||||
|
51
frontend/src/components/Cards.js
Normal file
51
frontend/src/components/Cards.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
import React from 'react'
|
||||
import CardItem from './CardItem'
|
||||
import './Cards.css'
|
||||
|
||||
function Cards() {
|
||||
return (
|
||||
<div className='cards'>
|
||||
<h1>Check out these EPIC Destinations</h1>
|
||||
<div className="cards__container">
|
||||
<div className="cards__wrapper">
|
||||
<ul className="cards__items">
|
||||
<CardItem
|
||||
src="/images/img-4.jpg"
|
||||
text="Explore the hidden waterfall deep inside the Amazon Jungle"
|
||||
label="Adventure"
|
||||
path="/services"
|
||||
/>
|
||||
<CardItem
|
||||
src="/images/img-4.jpg"
|
||||
text="Travel through the Islands of Bali in a Private Cruise"
|
||||
label="Luxury"
|
||||
path="/services"
|
||||
/>
|
||||
</ul>
|
||||
<ul className="cards__items">
|
||||
<CardItem
|
||||
src="/images/img-4.jpg"
|
||||
text="Explore the hidden waterfall deep inside the Amazon Jungle"
|
||||
label="Adventure"
|
||||
path="/services"
|
||||
/>
|
||||
<CardItem
|
||||
src="/images/img-4.jpg"
|
||||
text="Travel through the Islands of Bali in a Private Cruise"
|
||||
label="Luxury"
|
||||
path="/services"
|
||||
/>
|
||||
<CardItem
|
||||
src="/images/img-4.jpg"
|
||||
text="Travel through the Islands of Bali in a Private Cruise"
|
||||
label="Luxury"
|
||||
path="/services"
|
||||
/>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Cards
|
72
frontend/src/components/HeroSection.css
Normal file
72
frontend/src/components/HeroSection.css
Normal file
|
@ -0,0 +1,72 @@
|
|||
video {
|
||||
object-fit: cover;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.hero-container {
|
||||
background: url("../images/img-home.jpg") center center/cover no-repeat;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-shadow: inset 0 0 0 1000px rgba(0, 0, 0, 0.2);
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.hero-container > h1 {
|
||||
color: #fff;
|
||||
font-size: 100px;
|
||||
margin-top: -100px;
|
||||
}
|
||||
|
||||
.hero-container > p {
|
||||
margin-top: 8px;
|
||||
color: #fff;
|
||||
font-size: 32px;
|
||||
font-family: "Trebuchet MS", "Lucida Sans Unicode", "Lucida Grande",
|
||||
"Lucida Sans", Arial, sans-serif;
|
||||
}
|
||||
|
||||
.hero-btns {
|
||||
margin-top: 32px;
|
||||
}
|
||||
|
||||
.hero-btns .btn {
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
.fa-play-cirecle {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
.hero-container > h1 {
|
||||
font-size: 70px;
|
||||
margin-top: -150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.hero-container > h1 {
|
||||
font-size: 50px;
|
||||
margin-top: -100px;
|
||||
}
|
||||
|
||||
.hero-container > p {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.btn-mobile {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
31
frontend/src/components/HeroSection.js
Normal file
31
frontend/src/components/HeroSection.js
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import '../App.css';
|
||||
import { Button } from './Button';
|
||||
import './HeroSection.css';
|
||||
|
||||
function HeroSection() {
|
||||
return (
|
||||
<div className='hero-container'>
|
||||
<h1>ADVENTURE AWAITS</h1>
|
||||
<p>What are you waiting for?</p>
|
||||
<div className="hero-btns">
|
||||
<Button
|
||||
className='btns'
|
||||
buttonStyle='btn--outline'
|
||||
buttonSize='btn--large'
|
||||
>
|
||||
GET STARTED
|
||||
</Button>
|
||||
<Button
|
||||
className='btns'
|
||||
buttonStyle='btn--primary'
|
||||
buttonSize='btn--large'
|
||||
>
|
||||
WATCH TRAILER <i className='far fa-play-circle' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HeroSection
|
158
frontend/src/components/Navbar.css
Normal file
158
frontend/src/components/Navbar.css
Normal file
|
@ -0,0 +1,158 @@
|
|||
.navbar {
|
||||
background: linear-gradient(90deg, rgb(28, 27, 27) 0%, rgb(26, 23, 23) 100%);
|
||||
height: 80px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-size: 1.2rem;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.navbar-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 80px;
|
||||
max-width: 1500px;
|
||||
}
|
||||
|
||||
.navbar-logo {
|
||||
color: #fff;
|
||||
justify-self: start;
|
||||
margin-left: 20px;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-size: 2rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.fa-typo3 {
|
||||
margin-left: 0.5rem;
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, auto);
|
||||
grid-gap: 10px;
|
||||
list-style: none;
|
||||
text-align: center;
|
||||
width: 60vw;
|
||||
justify-content: end;
|
||||
margin-right: 2rem;
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-decoration: none;
|
||||
padding: 0.5rem 1rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.nav-links:hover {
|
||||
border-bottom: 4px solid #fff;
|
||||
transition: all 0.2s ease-out;
|
||||
}
|
||||
|
||||
.fa-bars {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.nav-links-mobile {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 960px) {
|
||||
.NavbarItems {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 90vh;
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: -100%;
|
||||
opacity: 1;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.nav-menu.active {
|
||||
background: #242222;
|
||||
left: 0;
|
||||
opacity: 1;
|
||||
transition: all 0.5s ease;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.nav-links {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
width: 100%;
|
||||
display: table;
|
||||
}
|
||||
|
||||
.nav-links:hover {
|
||||
background-color: #fff;
|
||||
color: #242424;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.navbar-logo {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
transform: translate(25%, 50%);
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translate(-100%, 60%);
|
||||
font-size: 1.8rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fa-times {
|
||||
color: #fff;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.nav-links-mobile {
|
||||
display: block;
|
||||
text-align: center;
|
||||
margin: 2rem auto;
|
||||
border-radius: 4px;
|
||||
width: 80%;
|
||||
text-decoration: none;
|
||||
font-size: 1.5rem;
|
||||
background-color: transparent;
|
||||
color: #fff;
|
||||
padding: 14px 20px;
|
||||
border: 1px solid #fff;
|
||||
transition: all 0.3s ease-out;
|
||||
}
|
||||
|
||||
.nav-links-mobile:hover {
|
||||
background: #fff;
|
||||
color: #242424;
|
||||
transition: 250ms;
|
||||
}
|
||||
}
|
81
frontend/src/components/Navbar.js
Normal file
81
frontend/src/components/Navbar.js
Normal file
|
@ -0,0 +1,81 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Button } from './Button';
|
||||
import { Link } from 'react-router-dom';
|
||||
import './Navbar.css';
|
||||
|
||||
function Navbar() {
|
||||
const [click, setClick] = useState(false);
|
||||
const [button, setButton] = useState(true);
|
||||
|
||||
const handleClick = () => setClick(!click);
|
||||
const closeMobileMenu = () => setClick(false);
|
||||
|
||||
const showButton = () => {
|
||||
if (window.innerWidth <= 960) {
|
||||
setButton(false);
|
||||
} else {
|
||||
setButton(true);
|
||||
}
|
||||
};
|
||||
|
||||
/* Shows the button after resizing the screen */
|
||||
useEffect(() => {
|
||||
showButton();
|
||||
}, []);
|
||||
|
||||
window.addEventListener('resize', showButton);
|
||||
|
||||
return (
|
||||
<>
|
||||
<nav className='navbar'>
|
||||
<div className='navbar-container'>
|
||||
<Link to='/' className='navbar-logo' onClick={closeMobileMenu}>
|
||||
TRVL
|
||||
<i class='fab fa-typo3' />
|
||||
</Link>
|
||||
<div className='menu-icon' onClick={handleClick}>
|
||||
<i className={click ? 'fas fa-times' : 'fas fa-bars'} />
|
||||
</div>
|
||||
<ul className={click ? 'nav-menu active' : 'nav-menu'}>
|
||||
<li className='nav-item'>
|
||||
<Link to='/' className='nav-links' onClick={closeMobileMenu}>
|
||||
Home
|
||||
</Link>
|
||||
</li>
|
||||
<li className='nav-item'>
|
||||
<Link
|
||||
to='/services'
|
||||
className='nav-links'
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
Services
|
||||
</Link>
|
||||
</li>
|
||||
<li className='nav-item'>
|
||||
<Link
|
||||
to='/products'
|
||||
className='nav-links'
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
Products
|
||||
</Link>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<Link
|
||||
to='/sign-up'
|
||||
className='nav-links-mobile'
|
||||
onClick={closeMobileMenu}
|
||||
>
|
||||
Sign Up
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
{button && <Button buttonStyle='btn--outline'>SIGN UP</Button>}
|
||||
</div>
|
||||
</nav>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default Navbar;
|
17
frontend/src/components/pages/Home.js
Normal file
17
frontend/src/components/pages/Home.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from 'react';
|
||||
import '../../App.css'
|
||||
import HeroSection from '../HeroSection'
|
||||
import Cards from '../Cards'
|
||||
import Footer from '../../Footer';
|
||||
|
||||
function Home() {
|
||||
return (
|
||||
<>
|
||||
<HeroSection />
|
||||
<Cards />
|
||||
<Footer />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default Home;
|
8
frontend/src/components/pages/Products.js
Normal file
8
frontend/src/components/pages/Products.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import React from 'react'
|
||||
import '../../App.css'
|
||||
|
||||
export default function Products() {
|
||||
return (
|
||||
<h1 className='products'>PRODUCTS</h1>
|
||||
);
|
||||
}
|
6
frontend/src/components/pages/Services.js
Normal file
6
frontend/src/components/pages/Services.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import React from 'react'
|
||||
import '../../App.css'
|
||||
|
||||
export default function Services() {
|
||||
return <h1 className="services">SERVICES</h1>;
|
||||
}
|
6
frontend/src/components/pages/SignUp.js
Normal file
6
frontend/src/components/pages/SignUp.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import React from 'react'
|
||||
import '../../App.css'
|
||||
|
||||
export default function SignUp() {
|
||||
return <h1 className="sign-up">SIGN UP</h1>;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue