Skip to content

WIP: Cleanup, restructure, improve #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
2,175 changes: 712 additions & 1,463 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"axios": "^0.19.2",
"react": "^16.13.1",
"react-animated-weather": "^4.0.1",
"react-dom": "^16.13.1",
Expand Down
20 changes: 7 additions & 13 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,6 @@ div#txt {
padding-left: 20px;
}

.today-weather ul li span {
float: right;
padding-right: 10px;
}

.today-weather ul li:nth-child(5) {
border-bottom: none;
}
Expand Down Expand Up @@ -621,8 +616,13 @@ div#txt {
position: relative;
z-index: 2;
}
.search-box .img-box {
background: rgb(255, 255, 255, 0.2);

.search-box button {
text-indent: -9999px;
background: url("https://images.avishkaar.cc/workflow/newhp/search-white.png") 0 0 rgba(255, 255, 255, 0.2);
background-repeat: no-repeat;
background-position: center center;
background-size: 50%;
border-radius: 50%;
height: 32px;
width: 35px;
Expand Down Expand Up @@ -652,19 +652,13 @@ div#txt {
transition: all 1s ease-in-out;
}
.mb-icon {
height: 100%;
position: absolute;
top: 34%;
left: 36%;
z-index: 1;
display: none;
}
.mb-icon p {
color: white;
width: fit-content;
position: relative;
left: 24%;
top: 2%;
font-size: 25px;
}
.footer-info {
Expand Down
18 changes: 8 additions & 10 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from "react";
import CurrentLocation from "./currentLocation";
import React from "react";
import CurrentLocation from "./CurrentLocation";
import "./App.css";

function App() {
Expand All @@ -9,15 +9,13 @@ function App() {
<CurrentLocation />
</div>
<div className="footer-info">
<a href="https://www.htmlhints.com/article/how-to-create-toggle-switch/93">
Download Source Code
</a>{" "}
| Developed by{" "}
<a target="_blank" href="https://www.gauravghai.dev/">
<a href="https://www.htmlhints.com/article/how-to-create-toggle-switch/93">Download Source Code</a>
<span> | Developed by </span>
<a target="_blank" rel="noopener noreferrer" href="https://www.gauravghai.dev/">
Gaurav Ghai
</a>{" "}
| Powered by{" "}
<a target="_blank" href="https://www.htmlhints.com/">
</a>
<span> | Powered by </span>
<a target="_blank" rel="noopener noreferrer" href="https://www.htmlhints.com/">
HTML HINTS
</a>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/App.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { render } from '@testing-library/react';
import App from './App';
import React from "react";
import { render } from "@testing-library/react";
import App from "./App";

test('renders learn react link', () => {
test("renders learn react link", () => {
const { getByText } = render(<App />);
const linkElement = getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
Expand Down
102 changes: 102 additions & 0 deletions src/CurrentLocation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from "react";
import Clock from "react-live-clock";

import AnimatedWeatherIcon from "./components/AnimatedWeather";
import Forcast from "./Forcast";
import loader from "./images/WeatherIcons.gif";
import { dateBuilder, getPosition, getWeatherByCoordinate } from "./utils";

const ONE_MINUTE_IN_MS = 60 * 1000;

export class Weather extends React.Component {
state = {
coords: {
latitude: undefined,
longitude: undefined,
},
errorMessage: undefined,
temperatureC: undefined,
temperatureF: undefined,
city: undefined,
country: undefined,
humidity: undefined,
description: undefined,
icon: "CLEAR_DAY",
sunrise: undefined,
sunset: undefined,
errorMsg: undefined,
timerID: undefined,
};

async updateWeather() {
const weather = await getWeatherByCoordinate(this.state.coords);
const timerID = setTimeout(this.updateWeather, 10 * ONE_MINUTE_IN_MS);
return this.setState({ ...this.state, timerID, ...weather });
}

async componentDidMount() {
if (!navigator.geolocation) {
return alert("Geolocation not available");
}

let position;

try {
position = await getPosition();
} catch (err) {
position = { coords: { latitude: 28.67, longitude: 77.22 } };
alert(
"You have disabled location service. Allow 'This APP' to access your location. " +
"Your current location will be used for calculating Real time weather."
);
}

return this.setState((prevState) => ({ ...prevState, coords: position.coords }), this.updateWeather);
}

componentWillUnmount() {
return clearTimeout(this.state.timerID);
}

render() {
if (!this.state.temperatureC) {
return (
<React.Fragment>
<img alt="loader" src={loader} style={{ width: "50%", WebkitUserDrag: "none" }} />
<h3 style={{ color: "white", fontSize: "22px", fontWeight: "600" }}>Detecting your location</h3>
<h3 style={{ color: "white", marginTop: "10px" }}>
Your current location wil be displayed on the App <br></br> & used for calculating Real time weather.
</h3>
</React.Fragment>
);
}
return (
<React.Fragment>
<div className="city">
<div className="title">
<h2>{this.state.city}</h2>
<h3>{this.state.country}</h3>
</div>
<AnimatedWeatherIcon className="mb-icon" icon={this.state.icon} title={this.state.main} />
<div className="date-time">
<div className="dmy">
<div id="txt"></div>
<div className="current-time">
<Clock format="HH:mm:ss" interval={1000} ticking={true} />
</div>
<div className="current-date">{dateBuilder(new Date())}</div>
</div>
<div className="temperature">
<p>
{this.state.temperatureC}°<span>C</span>
</p>
</div>
</div>
</div>
<Forcast icon={this.state.icon} weather={this.state.main} />
</React.Fragment>
);
}
}

export default Weather;
83 changes: 83 additions & 0 deletions src/Forcast.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React, { useEffect, useState, useCallback } from "react";

import AnimatedWeatherIcon from "./components/AnimatedWeather";
import { getWeatherByQuery } from "./utils";

export const Forcast = (props) => {
const [query, setQuery] = useState("");
const [error, setError] = useState("");
const [weather, setWeather] = useState({});

const search = useCallback(async (query) => {
try {
const weather = await getWeatherByQuery(query);
setWeather(weather);
setQuery("");
} catch (err) {
console.log("error", err);
setWeather({});
setQuery("");
setError({ message: "Not Found", query });
}
}, []);

useEffect(() => {
search("Delhi");
}, [search]);

return (
<div className="forecast">
<AnimatedWeatherIcon className="forecast-icon" icon={props.icon} />
<div className="today-weather">
<h3>{props.weather}</h3>
<form onSubmit={(e) => e.preventDefault() || search(query)} className="search-box">
<input
type="text"
className="search-bar"
placeholder="Search any city"
onChange={(e) => setQuery(e.target.value)}
value={query}
/>
<button type="submit">Search</button>
</form>
<ul>
{weather.main ? (
<React.Fragment>
<li className="cityHead">
<p>
{weather.city}, {weather.country}
</p>
<img
alt={`weather icon ${weather.icon}`}
className="temp"
src={`https://openweathermap.org/img/wn/${weather.icon}.png`}
/>
</li>
<li>
<span>Temperature </span>
<span className="temp">
{weather.temperatureC}°c ({weather.main})
</span>
</li>
<li>
Humidity <span className="temp">{Math.round(weather.humidity)}%</span>
</li>
<li>
Visibility <span className="temp">{Math.round(weather.visibility)} mi</span>
</li>
<li>
Wind Speed <span className="temp">{Math.round(weather.speed)} Km/h</span>
</li>
</React.Fragment>
) : (
<li>
{error.query} {error.message}
</li>
)}
</ul>
</div>
</div>
);
};

export default Forcast;
11 changes: 11 additions & 0 deletions src/components/AnimatedWeather.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from "react";
import ReactAnimatedWeather from "react-animated-weather";

export const AnimatedWeatherIcon = ({ icon, title, className }) => (
<div className={className}>
<ReactAnimatedWeather icon={icon} color="white" size={112} animate={true} />
{title && <p>{title}</p>}
</div>
);

export default AnimatedWeatherIcon;
Loading