Repush
This commit is contained in:
19
README.md
Normal file
19
README.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Simple Weather App
|
||||
|
||||
This app allows users to search for the weather in a given location. It consists of an HTML file and a JavaScript file. Check it out [here](https://andrewtrieu.github.io/weather-deploy/).
|
||||
|
||||
## Instructions
|
||||
|
||||
To use the app, simply enter a location (city, state, and country) in the form and click the "Get Weather" button. The app will display the details of the current weather of that location. If no location is provided, the app will display the weather for the user's current location as determined by their IP address.
|
||||
|
||||
However, due to the nature of GitHub Pages, the deployment will not work correctly. Please test it locally as the link above is for reference purpose only. Actual usage is demonstrated in the following video:
|
||||
|
||||
[New video.webm](https://user-images.githubusercontent.com/68151686/210859583-0eaa11bd-1ba7-4f54-9de2-866a99fc65d8.webm)
|
||||
|
||||
## API
|
||||
|
||||
This app uses the OpenWeatherMap API to retrieve weather data and the Rest Countries API to retrieve country names. It also uses the ipapi API to determine the user's current location.
|
||||
|
||||
## Notes
|
||||
|
||||
This app was built using Bootstrap for styling and layout. It also utilizes fetch() and async/await to handle API calls.
|
||||
130
app.js
Normal file
130
app.js
Normal file
@@ -0,0 +1,130 @@
|
||||
const apiKey = "YOUR_API_KEY";
|
||||
const weatherForm = document.querySelector("#weather-form");
|
||||
const weatherInfo = document.querySelector("#weather-info");
|
||||
|
||||
fetchCurrent = async () => {
|
||||
const current = {};
|
||||
await fetch("https://ipapi.co/json/")
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
current["city"] = data.city;
|
||||
current["state"] = data.region;
|
||||
current["country"] = data.country_name;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
weatherInfo.innerHTML = "<p>An error occurred</p>";
|
||||
});
|
||||
return current;
|
||||
};
|
||||
|
||||
fetchCountry = async (country_code) => {
|
||||
let country;
|
||||
await fetch(`https://restcountries.com/v3.1/alpha/${country_code}`)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
country = data[0];
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
weatherInfo.innerHTML = "<p>An error occurred</p>";
|
||||
});
|
||||
return country.name.common;
|
||||
};
|
||||
|
||||
fetchLocation = async (city, region, country_name, apiKey) => {
|
||||
let location;
|
||||
await fetch(
|
||||
`http://api.openweathermap.org/geo/1.0/direct?q=${city},${region},${country_name}&appid=${apiKey}`
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
location = data[0];
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
weatherInfo.innerHTML = "<p>An error occurred</p>";
|
||||
});
|
||||
if (!location) {
|
||||
location = { lat: 0, lon: 0 };
|
||||
} else {
|
||||
location["country"] = await fetchCountry(location.country);
|
||||
}
|
||||
return location;
|
||||
};
|
||||
|
||||
fetchWeather = async (city, region, country_name, apiKey) => {
|
||||
const location = await fetchLocation(city, region, country_name, apiKey);
|
||||
let weather;
|
||||
await fetch(
|
||||
`https://api.openweathermap.org/data/2.5/weather?lat=${location.lat}&lon=${location.lon}&units=metric&&appid=${apiKey}`
|
||||
)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
weather = data;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
weatherInfo.innerHTML = "<p>An error occurred</p>";
|
||||
});
|
||||
if (location.state)
|
||||
weather[
|
||||
"destination"
|
||||
] = `${location.name}, ${location.state}, ${location.country}`;
|
||||
else weather["destination"] = `${location.name}, ${location.country}`;
|
||||
return weather;
|
||||
};
|
||||
|
||||
weatherForm.addEventListener("submit", async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
let city = document.querySelector("#city").value;
|
||||
let state = document.querySelector("#state").value;
|
||||
let country = document.querySelector("#country").value;
|
||||
|
||||
if (city === "") {
|
||||
const current = await fetchCurrent();
|
||||
city = current.city;
|
||||
state = current.state;
|
||||
country = current.country;
|
||||
}
|
||||
const weather = await fetchWeather(city, state, country, apiKey);
|
||||
|
||||
if (weather.coord.lat === 0 && weather.coord.lon === 0) {
|
||||
weatherInfo.innerHTML = `
|
||||
<div class="card-header">
|
||||
<h2>Location not found!</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3 text-center">
|
||||
<img src="https://icons.veryicon.com/png/o/commerce-shopping/jkd_wap/no-result.png" alt="Not found" width="100" height="100">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
weatherInfo.innerHTML = `
|
||||
<div class="card-header">
|
||||
<h2>Weather in ${weather.destination}</h2>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-3 text-center">
|
||||
<img src="http://openweathermap.org/img/wn/${weather.weather[0].icon}.png" alt="Weather icon" width="100" height="100">
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<p>Weather: ${weather.weather[0].main} (${weather.weather[0].description})</p>
|
||||
<p>Temperature: ${weather.main.temp}°C</p>
|
||||
<p>Feels like: ${weather.main.feels_like}°C</p>
|
||||
<p>Pressure: ${weather.main.pressure}hPa</p>
|
||||
<p>Humidity: ${weather.main.humidity}%</p>
|
||||
<p>Visibility: ${weather.visibility}m</p>
|
||||
<p>Wind speed: ${weather.wind.speed}m/s</p>
|
||||
<p>Cloudiness: ${weather.clouds.all}%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
});
|
||||
38
index.html
Normal file
38
index.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Weather App</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<meta charset="utf-8">
|
||||
</head>
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background-color: lightgray;
|
||||
}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<a class="navbar-brand" href="#">Weather App</a>
|
||||
</nav>
|
||||
<div class="container mt-5">
|
||||
<form id="weather-form" class="form-inline justify-content-center">
|
||||
<label for="city" class="mr-2">Location:</label>
|
||||
<input type="text" id="city" name="city" class="form-control mr-2">
|
||||
<label for="state" class="mr-2">State:</label>
|
||||
<input type="text" id="state" name="state" class="form-control mr-2">
|
||||
<label for="country" class="mr-2">Country:</label>
|
||||
<input type="text" id="country" name="country" class="form-control mr-2">
|
||||
<button type="submit" class="btn btn-primary">Get Weather</button>
|
||||
</form>
|
||||
<div id="weather-info" class="mt-5"></div>
|
||||
</div>
|
||||
<script src="app.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user