-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
571 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Weather App</title> | ||
<!-- TODO: Link Font --> | ||
<link rel="preconnect" href="https://fonts.googleapis.com" /> | ||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> | ||
<link | ||
href="https://fonts.googleapis.com/css2?family=Merriweather+Sans:wght@300;400;500;600;700&display=swap" | ||
rel="stylesheet" | ||
/> | ||
<!-- TODO: style.css link --> | ||
<link rel="stylesheet" href="style.css" /> | ||
</head> | ||
<body> | ||
<!-- Wrapper --> | ||
<div class="wrapper"> | ||
<h1>Weather App</h1> | ||
<div class="tabContainer"> | ||
<p class="tab currentTab" data-userWeather>Your Weather</p> | ||
<p class="tab" data-searchWeather>Search Weather</p> | ||
</div> | ||
|
||
<!-- Container --> | ||
<div class="container"> | ||
<!-- Search Container --> | ||
<form class="formContainer" data-searchForm> | ||
<input | ||
type="text" | ||
placeholder="Search for city..." | ||
data-searchInput | ||
/> | ||
<button class="btn" type="submit"> | ||
<img | ||
src="./images/search.png" | ||
width="20" | ||
height="20" | ||
loading="lazy" | ||
/> | ||
</button> | ||
</form> | ||
|
||
<!-- Grant Location Access --> | ||
<div class="grantLocationContainer subContainer"> | ||
<img | ||
src="./images/location.png" | ||
width="80" | ||
height="80" | ||
loading="lazy" | ||
/> | ||
<p>Grant Location Access</p> | ||
<p>Allow access to get weather information</p> | ||
<button class="btn" data-grantAccess>Grant Access</button> | ||
</div> | ||
|
||
<div class="subContainer loadingContainer"> | ||
<img src="./images/loading.gif" width="150" height="150" /> | ||
<p>Loading</p> | ||
</div> | ||
|
||
<!-- Weather Info --> | ||
<div class="userInfoContainer subContainer"> | ||
<div class="name"> | ||
<p data-cityName></p> | ||
<img data-countryFlag /> | ||
</div> | ||
|
||
<p data-weatherDesc></p> | ||
<img data-weatherIcon /> | ||
|
||
<p data-temp></p> | ||
|
||
<div class="parameterContainer"> | ||
<!-- Wind Speed --> | ||
<div class="parameter"> | ||
<img src="images/wind.png" alt="#" /> | ||
<p>windspeed</p> | ||
<p class="parameterValue" data-windspeed></p> | ||
</div> | ||
|
||
<!-- Humidity --> | ||
<div class="parameter"> | ||
<img src="images/humidity.png" alt="#" /> | ||
<p>humidity</p> | ||
<p class="parameterValue" data-humidity></p> | ||
</div> | ||
|
||
<!-- Wind Speed --> | ||
<div class="parameter"> | ||
<img src="images/cloud.png" alt="#" /> | ||
<p>clouds</p> | ||
<p class="parameterValue" data-clouds></p> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<!-- Location Not Found --> | ||
<div class="errorContainer subContainer"> | ||
<img src="./images/not-found.png" data-errorImg /> | ||
<p data-errorText></p> | ||
<button class="btn" data-errorButton>Retry Now</button> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- TODO: script js link --> | ||
<script src="script.js"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
// API Key | ||
const API_KEY = "94303a144ace0d258e29adcfc5f72bd8"; | ||
|
||
// Tab Switching | ||
// Tab Switching | ||
const userTab = document.querySelector("[data-userWeather]"); | ||
const searchTab = document.querySelector("[data-searchWeather]"); | ||
const searchForm = document.querySelector("[data-searchForm]"); | ||
const userInfoContainer = document.querySelector(".userInfoContainer"); | ||
const grantAccessContainer = document.querySelector( | ||
".grantLocationContainer" | ||
); | ||
const loadingContainer = document.querySelector('.loadingContainer'); | ||
|
||
const notFound = document.querySelector('.errorContainer'); | ||
const errorBtn = document.querySelector('[data-errorButton]'); | ||
const errorText = document.querySelector('[data-errorText]'); | ||
const errorImage = document.querySelector('[data-errorImg]'); | ||
|
||
let currentTab = userTab; | ||
currentTab.classList.add("currentTab"); | ||
getFromSessionStorage(); | ||
// console.log(userTab); | ||
// console.log(searchTab); | ||
|
||
function switchTab(newTab) { | ||
notFound.classList.remove("active"); | ||
// check if newTab is already selected or not | ||
if (currentTab != newTab) { | ||
currentTab.classList.remove("currentTab"); | ||
currentTab = newTab; | ||
currentTab.classList.add("currentTab"); | ||
|
||
// Check which TAb is Selected - search / your | ||
|
||
// If Search Form not contains active class then add [Search Weather] | ||
if (!searchForm.classList.contains("active")) { | ||
searchForm.classList.add("active"); | ||
userInfoContainer.classList.remove("active"); | ||
grantAccessContainer.classList.remove("active"); | ||
} | ||
// Your Weather | ||
else { | ||
searchForm.classList.remove("active"); | ||
userInfoContainer.classList.remove("active"); | ||
getFromSessionStorage(); | ||
} | ||
} | ||
} | ||
|
||
userTab.addEventListener('click', () => { | ||
switchTab(userTab); | ||
}); | ||
|
||
searchTab.addEventListener('click', () => { | ||
switchTab(searchTab); | ||
}); | ||
|
||
|
||
function getFromSessionStorage() { | ||
const localCoordinates = sessionStorage.getItem("userCoordinates"); | ||
// console.log(localCoordinates); | ||
|
||
// Local Coordinates Not present - Grant Access Container | ||
if (!localCoordinates) { | ||
grantAccessContainer.classList.add('active'); | ||
} | ||
else { | ||
const coordinates = JSON.parse(localCoordinates); | ||
fetchWeatherInfo(coordinates); | ||
} | ||
} | ||
|
||
async function fetchWeatherInfo(coordinates) { | ||
const { lat, lon } = coordinates; | ||
// Remove Active Class from the Grant access Container | ||
grantAccessContainer.classList.remove('active'); | ||
|
||
// loading | ||
loadingContainer.classList.add('active'); | ||
|
||
// try - catch Block | ||
try { | ||
const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${API_KEY}&units=metric`); | ||
|
||
const data = await response.json(); | ||
if (!data.sys) { | ||
throw data; | ||
} | ||
loadingContainer.classList.remove('active'); | ||
userInfoContainer.classList.add('active'); | ||
renderWeatherInfo(data); | ||
} | ||
catch (err) { | ||
loadingContainer.classList.remove('active'); | ||
notFound.classList.add('active'); | ||
errorImage.style.display = 'none'; | ||
errorText.innerText = `Error: ${err?.message}`; | ||
errorBtn.style.display = 'block'; | ||
errorBtn.addEventListener("click", fetchWeatherInfo); | ||
} | ||
} | ||
|
||
// Render Weather On UI | ||
function renderWeatherInfo(weatherInfo) { | ||
const cityName = document.querySelector('[data-cityName]'); | ||
const countryFlag = document.querySelector('[data-countryFlag]'); | ||
const description = document.querySelector('[data-weatherDesc]'); | ||
const weatherIcon = document.querySelector('[data-weatherIcon]'); | ||
const temp = document.querySelector('[data-temp]'); | ||
const windspeed = document.querySelector('[data-windspeed]'); | ||
const humidity = document.querySelector('[data-humidity]'); | ||
const clouds = document.querySelector('[data-clouds]'); | ||
|
||
cityName.innerText = weatherInfo?.name; | ||
countryFlag.src = `https://flagcdn.com/144x108/${weatherInfo?.sys?.country.toLowerCase()}.png`; | ||
description.innerText = weatherInfo?.weather?.[0]?.description; | ||
weatherIcon.src = `http://openweathermap.org/img/w/${weatherInfo?.weather?.[0]?.icon}.png`; | ||
temp.innerText = `${weatherInfo?.main?.temp.toFixed(2)} °C`; | ||
windspeed.innerText = `${weatherInfo?.wind?.speed.toFixed(2)} m/s`; | ||
humidity.innerText = `${weatherInfo?.main?.humidity.toFixed(2)} %`; | ||
clouds.innerText = `${weatherInfo?.clouds?.all.toFixed(2)} %`; | ||
} | ||
|
||
const grantAccessButton = document.querySelector('[data-grantAccess]'); | ||
|
||
function getLocation() { | ||
if (navigator.geolocation) { | ||
navigator.geolocation.getCurrentPosition(showPosition); | ||
} | ||
else { | ||
grantAccessButton.style.display = 'none'; | ||
} | ||
} | ||
|
||
function showPosition(position) { | ||
const userCoordinates = { | ||
lat: position.coords.latitude, | ||
lon: position.coords.longitude | ||
}; | ||
sessionStorage.setItem("userCoordinates", JSON.stringify(userCoordinates)); | ||
fetchWeatherInfo(userCoordinates); | ||
} | ||
|
||
grantAccessButton.addEventListener('click', getLocation); | ||
|
||
|
||
// Search for weather | ||
const searchInput = document.querySelector('[data-searchInput]'); | ||
|
||
searchForm.addEventListener('submit', (e) => { | ||
e.preventDefault(); | ||
if (searchInput.value === "") { | ||
return; | ||
} | ||
// console.log(searchInput.value); | ||
fetchSearchWeatherInfo(searchInput.value); | ||
searchInput.value = ""; | ||
}); | ||
|
||
|
||
async function fetchSearchWeatherInfo(city) { | ||
loadingContainer.classList.add("active"); | ||
userInfoContainer.classList.remove("active"); | ||
grantAccessContainer.classList.remove("active"); | ||
notFound.classList.remove("active"); | ||
try { | ||
const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${API_KEY}&units=metric`); | ||
|
||
const data = await response.json(); | ||
if (!data.sys) { | ||
throw data; | ||
} | ||
loadingContainer.classList.remove('active'); | ||
userInfoContainer.classList.add('active'); | ||
renderWeatherInfo(data); | ||
} | ||
catch (err) { | ||
loadingContainer.classList.remove('active'); | ||
userInfoContainer.classList.remove('active'); | ||
notFound.classList.add('active'); | ||
errorText.innerText = `${err?.message}`; | ||
errorBtn.style.display = "none"; | ||
} | ||
} |
Oops, something went wrong.