parent
ce21ceead6
commit
6821f7c680
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,45 @@
|
||||
<div align="center">
|
||||
<h1> 30 Days Of React: Projects</h1>
|
||||
<a class="header-badge" target="_blank" href="https://www.linkedin.com/in/asabeneh/">
|
||||
<img src="https://img.shields.io/badge/style--5eba00.svg?label=LinkedIn&logo=linkedin&style=social">
|
||||
</a>
|
||||
<a class="header-badge" target="_blank" href="https://twitter.com/Asabeneh">
|
||||
<img alt="Twitter Follow" src="https://img.shields.io/twitter/follow/asabeneh?style=social">
|
||||
</a>
|
||||
|
||||
<sub>Author:
|
||||
<a href="https://www.linkedin.com/in/asabeneh/" target="_blank">Asabeneh Yetayeh</a><br>
|
||||
<small> October, 2020</small>
|
||||
</sub>
|
||||
|
||||
</div>
|
||||
|
||||
[<< Day 17](../17_React_Router/17_react_router.md) | [Day 19>>]()
|
||||
|
||||

|
||||
|
||||
- [Projects](#projects)
|
||||
- [Exercises](#exercises)
|
||||
- [Exercises: Level 1](#exercises-level-1)
|
||||
- [Exercises: Level 2](#exercises-level-2)
|
||||
- [Exercises: Level 3](#exercises-level-3)
|
||||
|
||||
# Projects
|
||||
|
||||
Congratulations for making it to this far. Now, you have a solid understanding of React. I believe we have cover most of the feature of React and your are ready to work on projects. What we have cover so far is the old version of React. Starting from Day 20 we will learn React Hooks. In the next three days you will work on only projects.
|
||||
|
||||
# Exercises
|
||||
|
||||
## Exercises: Level 1
|
||||
|
||||
## Exercises: Level 2
|
||||
|
||||
coming
|
||||
|
||||
## Exercises: Level 3
|
||||
|
||||
coming
|
||||
|
||||
🎉 CONGRATULATIONS ! 🎉
|
||||
|
||||
[<< Day 17](../17_React_Router/17_react_router.md) | [Day 19>>]()
|
@ -0,0 +1,23 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
@ -0,0 +1,5 @@
|
||||
# 30 Days of React App: Day 17
|
||||
|
||||
In the project directory, you can run to start the project
|
||||
|
||||
### `npm start`
|
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "30-days-of-react",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-scripts": "3.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Montserrat:300,400,500|Roboto:300,400,500&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-react-app"
|
||||
/>
|
||||
|
||||
<title>30 Days Of React App</title>
|
||||
<style>
|
||||
|
||||
/* == General style === */
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
line-height: 1.5;
|
||||
font-family: 'Montserrat';
|
||||
font-weight: 300;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.root {
|
||||
min-height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.header-wrapper,
|
||||
.main-wrapper,
|
||||
.footer-wrapper {
|
||||
width: 85%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.header-wrapper,
|
||||
.main-wrapper {
|
||||
padding: 10px;
|
||||
margin: 2px auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 70px;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #61dbfb;
|
||||
padding: 25;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 10px;
|
||||
padding-bottom: 60px;
|
||||
/* Height of the footer */
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
ul li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
footer {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
/* Height of the footer */
|
||||
background: #6cf;
|
||||
}
|
||||
|
||||
.footer-wrapper {
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
line-height: 60px;
|
||||
}
|
||||
.user-card {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.user-card > img {
|
||||
border-radius: 50%;
|
||||
width: 14%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,13 @@
|
||||
export const tenHighestPopulation = [
|
||||
{ country: 'World', population: 7693165599 },
|
||||
{ country: 'China', population: 1377422166 },
|
||||
{ country: 'India', population: 1295210000 },
|
||||
{ country: 'United States of America', population: 323947000 },
|
||||
{ country: 'Indonesia', population: 258705000 },
|
||||
{ country: 'Brazil', population: 206135893 },
|
||||
{ country: 'Pakistan', population: 194125062 },
|
||||
{ country: 'Nigeria', population: 186988000 },
|
||||
{ country: 'Bangladesh', population: 161006790 },
|
||||
{ country: 'Russian Federation', population: 146599183 },
|
||||
{ country: 'Japan', population: 126960000 },
|
||||
]
|
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 82 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 40 KiB |
@ -0,0 +1,303 @@
|
||||
import React, { Component } from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Route,
|
||||
Switch,
|
||||
NavLink,
|
||||
Redirect,
|
||||
Prompt,
|
||||
} from 'react-router-dom'
|
||||
|
||||
// Home component
|
||||
const Home = (props) => <h1>Welcome Home</h1>
|
||||
// About component
|
||||
const About = (props) => <h1>About Us</h1>
|
||||
// Contact component
|
||||
const Contact = (props) => <h1>Contact us</h1>
|
||||
// Challenge component
|
||||
|
||||
const challenges = [
|
||||
{
|
||||
name: '30 Days Of Python',
|
||||
description:
|
||||
'30 Days of Python challenge is a step by step guide to learn Python in 30 days.',
|
||||
status: 'completed',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '20 Nov 2019 - 20 Dec 2019',
|
||||
slug: 'pyhton',
|
||||
url:
|
||||
'https://github.com/https://https://github.com/Asabeneh/30-Days-Of-Python.com/Asabeneh/30-Days-Of-JavaScript/30-Days-Of-React',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '30 Days Of JavaScript',
|
||||
description:
|
||||
'30 Days of JavaScript challenge is a step by step guide to learn JavaScript in 30 days.',
|
||||
status: 'completed',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '1 Jan 2020 - 30 Jan 2020',
|
||||
slug: 'javascript',
|
||||
url: 'https://github.com/Asabeneh/30-Days-Of-JavaScript',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '30 Days Of React',
|
||||
description:
|
||||
'30 Days of React challenge is a step by step guide to learn React in 30 days.',
|
||||
status: 'ongoing',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '1 Oct 2020- 30 Oct 2020',
|
||||
slug: 'react',
|
||||
url: 'https://github.com/Asabeneh/30-Days-Of-React',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '30 HTML and CSS',
|
||||
description:
|
||||
'30 Days of HTML and CSS challenge is a step by step guide to learn HTML and CSS in 30 days.',
|
||||
|
||||
status: 'coming',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '',
|
||||
slug: 'html-and-css',
|
||||
url: '',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '30 ReactNative',
|
||||
description:
|
||||
'30 Days of ReactNative challenge is a step by step guide to learn ReactNative in 30 days.',
|
||||
status: 'coming',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '',
|
||||
slug: 'reactnative',
|
||||
url: '',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '30 Data Analysis',
|
||||
description:
|
||||
'30 Days of Data Analysis challenge is a step by step guide to learn about data, data visualization and data analysis in 30 days.',
|
||||
status: 'coming',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '',
|
||||
slug: 'data-analysis',
|
||||
url: '',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '30 Machine Learning',
|
||||
description:
|
||||
'30 Days of Machine learning challenge is a step by step guide to learn data cleaning, machine learning models and predictions in 30 days.',
|
||||
status: 'coming',
|
||||
days: 30,
|
||||
level: 'Beginners to Advanced',
|
||||
duration: '',
|
||||
slug: 'machine-learning',
|
||||
url: '',
|
||||
author: {
|
||||
firstName: 'Asabeneh',
|
||||
lastName: 'Yetayeh',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
const Challenge = ({
|
||||
challenge: {
|
||||
name,
|
||||
description,
|
||||
status,
|
||||
days,
|
||||
level,
|
||||
duration,
|
||||
author: { firstName, lastName },
|
||||
},
|
||||
}) => (
|
||||
<div>
|
||||
<h1>{name}</h1>
|
||||
<p>{level}</p>
|
||||
<p>
|
||||
Author: {firstName} {lastName}
|
||||
</p>
|
||||
{duration && (
|
||||
<>
|
||||
{' '}
|
||||
<small>{duration}</small> <br />
|
||||
</>
|
||||
)}
|
||||
<small>Number of days: {days}</small>
|
||||
|
||||
<p>{description}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
const Challenges = (props) => {
|
||||
const path = props.location.pathname
|
||||
const slug = path.split('/').slice(path.split('/').length - 1)[0]
|
||||
const challenge = challenges.find((challenge) => challenge.slug === slug)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>30 Days Of React Challenge</h1>
|
||||
<ul>
|
||||
{challenges.map(({ name, slug }) => (
|
||||
<li key={slug}>
|
||||
<NavLink to={`/challenges/${slug}`}>{name}</NavLink>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path={'/challenges'}
|
||||
component={() => <h1>Choose any of the challenges</h1>}
|
||||
/>
|
||||
<Route
|
||||
path={path}
|
||||
component={(props) => <Challenge challenge={challenge} />}
|
||||
/>
|
||||
</Switch>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const NotFound = (props) => <h1>The page your looking for not found</h1>
|
||||
const Navbar = ({ username }) => (
|
||||
<ul>
|
||||
<li>
|
||||
<NavLink to='/'>Home</NavLink>
|
||||
</li>
|
||||
<li>
|
||||
<NavLink to='/about'>About</NavLink>
|
||||
</li>
|
||||
<li>
|
||||
<NavLink to='/contact'>Contact</NavLink>
|
||||
</li>
|
||||
<li>
|
||||
<NavLink to={`/user/${username}`}>User</NavLink>
|
||||
</li>
|
||||
<li>
|
||||
<NavLink to='/challenges'>Challenges</NavLink>
|
||||
</li>
|
||||
</ul>
|
||||
)
|
||||
|
||||
const User = ({ match, isLoggedIn, handleLogin }) => {
|
||||
const username = match.params.username
|
||||
return (
|
||||
<div>
|
||||
{isLoggedIn ? (
|
||||
<>
|
||||
<h1>Welcome {username} to the challenge</h1>
|
||||
<small>Now, you can navigate through all the challenges</small> <br />
|
||||
</>
|
||||
) : (
|
||||
<p>Please login in to access the challenges </p>
|
||||
)}
|
||||
<button onClick={handleLogin}>{isLoggedIn ? 'Logout' : 'Login'}</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Welcome = ({ handleLogin, isLoggedIn }) => {
|
||||
return (
|
||||
<div>
|
||||
{isLoggedIn ? 'Welcome to the challenge' : <p>Please login in </p>}
|
||||
<button onClick={handleLogin}>{isLoggedIn ? 'Logout' : 'Login'}</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
class App extends Component {
|
||||
state = {
|
||||
isLoggedIn: false,
|
||||
firstName: 'Asabeneh',
|
||||
}
|
||||
handleLogin = () => {
|
||||
this.setState({
|
||||
isLoggedIn: !this.state.isLoggedIn,
|
||||
})
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<Router>
|
||||
<div className='App'>
|
||||
<Navbar username={this.state.firstName} />
|
||||
|
||||
<Prompt
|
||||
message={({ pathname }) => {
|
||||
return this.state.isLoggedIn &&
|
||||
pathname.includes('/user/Asabeneh')
|
||||
? 'Are you sure you want to logout?'
|
||||
: true
|
||||
}}
|
||||
/>
|
||||
|
||||
<Switch>
|
||||
<Route path='/about' component={About} />
|
||||
<Route path='/contact' component={Contact} />
|
||||
<Route
|
||||
path='/user/:username'
|
||||
component={(props) => (
|
||||
<User
|
||||
{...props}
|
||||
isLoggedIn={this.state.isLoggedIn}
|
||||
handleLogin={this.handleLogin}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path='/login'
|
||||
component={(props) => (
|
||||
<Welcome
|
||||
{...props}
|
||||
isLoggedIn={this.state.isLoggedIn}
|
||||
handleLogin={this.handleLogin}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path='/challenges'
|
||||
component={(props) => {
|
||||
return this.state.isLoggedIn ? (
|
||||
<Challenges {...props} />
|
||||
) : (
|
||||
<Redirect to='/user/asabeneh' />
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Route exact path='/' component={Home} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</div>
|
||||
</Router>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const rootElement = document.getElementById('root')
|
||||
ReactDOM.render(<App />, rootElement)
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue