This commit is contained in:
AndrewTrieu
2023-01-05 21:27:30 +02:00
commit 2ea1abec02
3 changed files with 187 additions and 0 deletions

19
README.md Normal file
View 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
View 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
View 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>