Weather Finder
This game can be a very nice brain exercise, which focuses on prompting your ability to arrange numbers in the right order in a very short time, this game depends on the level you choose. Start with 3 squares x 3, and see how it goes, then you can make it wider as you improve in this brain exercise.
Prepare Project for Weather Finder App
To create the example project for this example, open command prompt, navigate to a convenient location, and run the command as shown below :
create-react-app example9
Now navigate to the project folder and add the React Bootstrap package to the project as shown below :
cd example9
npm i bootstrap-4-react
src\App.js
import React, { Component } from "react";
import Weather from "./Weather";
import "./App.css";
import "bootstrap/dist/css/bootstrap.min.css";
const apiKey = "8ddceeacaf8b95fe943c88fc8389dee0";
const Title = () => {
return (
<div>
<h1 className="title-container__title">Weather Finder</h1>
<h3 className="title-container__subtitle">
Find out temperature, conditions and more...
</h3>
</div>
);
};
const Form = ({ onWeather }) => {
return (
<form onSubmit={e => onWeather(e)}>
<input type="text" name="city" placeholder="City..." />
<input type="text" name="country" placeholder="Country..." />
<button className="form-button">get Weather</button>
</form>
);
};
class App extends Component {
state = {
temperature: undefined,
city: undefined,
country: undefined,
humidity: undefined,
description: undefined,
error: undefined
};
getWeather = async e => {
e.preventDefault();
const city = e.currentTarget.elements.city.value;
const country = e.currentTarget.elements.country.value;
if (city && country) {
try {
const apiCall = await fetch(
`https://cors-anywhere.herokuapp.com/http://api.openweathermap.org/data/2.5/weather?q=${city},${country}&appid=${apiKey}&units=metric`
);
const { main, sys, name, weather } = await apiCall.json();
this.setState({
temperature: main.temp,
city: name,
country: sys.country,
humidity: main.humidity,
description: weather[0].description,
error: ""
});
} catch (ex) {
console.log(ex.message);
}
} else {
this.setState({
temperature: undefined,
city: undefined,
country: undefined,
humidity: undefined,
description: undefined,
error: "please enter a valid values."
});
}
};
render() {
return (
<div className="wrapper">
<div className="main">
<div className="container" style={{ width: "100%" }}>
<div className="row">
<div className="col-xs-5 title-container">
<Title />
</div>
<div className="col-xs-7 form-container">
<Form onWeather={this.getWeather} />
<Weather
temperature={this.state.temperature}
city={this.state.city}
country={this.state.country}
humidity={this.state.humidity}
description={this.state.description}
error={this.state.error}
/>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default App;
src\Weather.js
import React from "react";
const Weather = ({
city,
country,
temperature,
humidity,
description,
error
}) => {
return (
<div className="weather__info">
{city && country && (
<p className="weather__key">
Location:{" "}
<span className="weather__value">
{" "}
{city}, {country}
</span>
</p>
)}
{temperature && (
<p className="weather__key">
Temperature: <span className="weather__value"> {temperature}</span>
</p>
)}
{humidity && (
<p className="weather__key">
Humidity: <span className="weather__value"> {humidity} </span>
</p>
)}
{description && (
<p className="weather__key">
Condition: <span className="weather__value"> {description}</span>
</p>
)}
{error && <p className="weather__error">{error}</p>}
</div>
);
};
export default Weather;
src\App.css
Replace the placeholder content of App.css with given below content :
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,400');
body {
font-family: "Open Sans", serif;
background: linear-gradient(to right, #e67e22, #e74c3c);
}
.wrapper {
background: linear-gradient(to right, #e67e22, #e74c3c);
display: flex;
justify-content: center;
align-items: center;
}
.main {
height: 90vh;
background: #fff;
box-shadow: 0px 13px 40px -13px rgba(0, 0, 0, 0.75);
width: 80%;
margin: 25px auto;
}
.title-container {
height: 15vh;
min-height: 100%;
background-size: cover;
display: flex;
justify-content: center;
text-align: center;
color: #000;
}
.title-container__title {
font-size: 50px;
letter-spacing: 2px;
line-height: 1.3;
}
.title-container__subtitle {
font-style: italic;
font-weight: 100;
letter-spacing: 1px;
line-height: 1.5;
}
.form-container {
background-color: #2c3e50;
height: 70vh;
padding-top: 50px;
padding-left: 50px;
}
input[type="text"] {
background-color: transparent;
border: 0;
border-bottom: solid 1px #f16051;
width: 30%;
padding-bottom: 4px;
color: #fff !important;
font-weight: lighter;
letter-spacing: 2px;
margin-bottom: 30px;
margin-right: 20px;
font-size: 20px;
}
input[type="text"] {
outline: none;
}
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0 30px #2c3e50 inset;
-webkit-text-fill-color: #fff !important;
}
button {
border: 0;
padding: 8px 20px;
margin: 0 2px;
border-radius: 2px;
font-weight: lighter;
letter-spacing: 1px;
font-size: 15px;
cursor: pointer;
background-color: #f16051;
color: #fff;
font-weight: 100;
}
button:active {
outline: none;
}
button:hover {
cursor: pointer;
}
.weather__info {
width: 60%;
font-size: 20px;
font-weight: 200;
letter-spacing: 2px;
}
.weather__key {
color: #f16051;
border-bottom: solid 2px rgba(255, 255, 255, 0.06);
padding: 20px 0 20px 0;
font-weight: 400;
}
.weather__key:last-child {
border: 0;
}
.weather__value {
color: #fff;
font-weight: 200;
}
.weather__error {
color: #f16051;
font-size: 20px;
letter-spacing: 1px;
font-weight: 200;
}
@media screen and (max-width: 700px) {
.title-container__title {
font-size: 30px;
}
.title-container__subtitle {
font-size: 18px;
}
.form-container {
padding-top: 30px;
}
.weather__info {
width: unset;
font-size: unset;
}
.weather__key {
padding: 4px 0 4px 0;
}
input[type="text"] {
margin-bottom: 10px;
}
button {
padding: 4px 10px;
}
}
@media screen and (max-width: 500px) {
.title-container__title {
font-size: 25px;
}
.title-container__subtitle {
font-size: 14px;
}
button {
padding: 2px;
}
}