From 9521a1b3f84427d297e2f84474fcdb9337fe3d8a Mon Sep 17 00:00:00 2001 From: Dhananjoy Date: Sun, 2 Oct 2022 12:57:49 +0530 Subject: [PATCH] -Added Icons, responsiveness Changed the alignment of the components so that they can be centered. Added Icons For Better User Experience. Added Responsiveness for better vivibility in Different device with different size. --- Weather Forecast Webapp/css/style.css | 309 +++++++++++++++------ Weather Forecast Webapp/index.html | 81 ++++-- Weather Forecast Webapp/js/icons/clear.svg | 105 +++++++ Weather Forecast Webapp/js/icons/cloud.svg | 1 + Weather Forecast Webapp/js/icons/haze.svg | 1 + Weather Forecast Webapp/js/icons/rain.svg | 1 + Weather Forecast Webapp/js/icons/snow.svg | 1 + Weather Forecast Webapp/js/icons/storm.svg | 1 + Weather Forecast Webapp/js/script.js | 126 +++++---- 9 files changed, 458 insertions(+), 168 deletions(-) create mode 100644 Weather Forecast Webapp/js/icons/clear.svg create mode 100644 Weather Forecast Webapp/js/icons/cloud.svg create mode 100644 Weather Forecast Webapp/js/icons/haze.svg create mode 100644 Weather Forecast Webapp/js/icons/rain.svg create mode 100644 Weather Forecast Webapp/js/icons/snow.svg create mode 100644 Weather Forecast Webapp/js/icons/storm.svg diff --git a/Weather Forecast Webapp/css/style.css b/Weather Forecast Webapp/css/style.css index bbb96a3d..3e08acd8 100644 --- a/Weather Forecast Webapp/css/style.css +++ b/Weather Forecast Webapp/css/style.css @@ -1,95 +1,224 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap'); *{ - margin: 0; - padding: 0; - } - - body { - background:linear-gradient(90deg,#614385, #516395); - line-height: 1.5; - font-size: 125%; - display: flex; - } - - /*--------------------------------------- CARD ------------------------------------------*/ - - .container { - position: relative; - background: rgba( 255, 255, 255, 0.25 ); -box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); -backdrop-filter: blur( 4px ); --webkit-backdrop-filter: blur( 4px ); -border-radius: 10px; -border: 1px solid rgba( 255, 255, 255, 0.18 ); - padding: 0 1em 1em; - margin: 150px 500px 400px auto; - -webkit-filter: drop-shadow(0 1em 1em rgba(226, 91, 91, 0.1)); - filter: drop-shadow(0 1em 1em rgba(226, 91, 91, 0.1)); - border-radius: 10px; - -webkit-border-radius: 10px; - -moz-border-radius: 10px; - -ms-border-radius: 10px; - -o-border-radius: 10px; - overflow: hidden; + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Poppins', sans-serif; } +body{ + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + background:linear-gradient(90deg,#614385, #516395); +} +::selection{ + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.wrapper{ + width: 400px; + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); + border: 1px solid rgba( 255, 255, 255, 0.18 ); + -webkit-filter: drop-shadow(0 1em 1em rgba(226, 91, 91, 0.1)); + filter: drop-shadow(0 1em 1em rgba(226, 91, 91, 0.1)); +} +.wrapper header{ + display: flex; + font-size: 21px; + font-weight: 500; - /*-------------------------------- FOR THE TILTED CARD------------------------------------ */ - - - - /* ------------------------------------------------------------------------------------------*/ - - .content { - position: relative; - margin: 0 60px auto; - padding: 0 1em; - } + padding: 16px 15px; + align-items: center; + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +header i{ + font-size: 0em; + cursor: pointer; + margin-right: 8px; +} +.wrapper.active header i{ + margin-left: 5px; + font-size: 30px; +} +.wrapper .input-part{ + margin: 20px 25px 30px; +} +.wrapper.active .input-part{ + display: none; +} +.input-part .info-txt{ + display: none; + font-size: 17px; + text-align: center; + padding: 12px 10px; + border-radius: 7px; + margin-bottom: 15px; +} +.input-part .info-txt.error{ + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.input-part .info-txt.pending{ + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.input-part :where(input, button){ + width: 100%; + height: 55px; + border: none; + outline: none; + font-size: 18px; + border-radius: 7px; +} +.input-part input{ + text-align: center; + padding: 0 15px; + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.input-part input:is(:focus, :valid){ + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.input-part input::placeholder{ + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.input-part .separator{ + height: 1px; + width: 100%; + margin: 25px 0; + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); + position: relative; + display: flex; + align-items: center; + justify-content: center; +} +.separator::before{ + content: "or"; + border: 1px solid rgba( 255, 255, 255, 0.18 ); + font-size: 19px; + padding: 0 15px; + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); +} +.input-part button{ - h1 { - border-bottom: 4px solid rebeccapurple; - padding-bottom: 0.25em; - margin-bottom: 0.25em; - text-align: center; - font-family: Verdana, Geneva, Tahoma, sans-serif; + cursor: pointer; + background: rgba( 255, 255, 255, 0.25 ); + box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); + backdrop-filter: blur( 4px ); + -webkit-backdrop-filter: blur( 4px ); + transition: 0.3s ease; +} +.input-part button:hover{ + background: rgba(98, 80, 149, 0.25); +} - } - - /*----------------------------------- INPUT BOX---------------------------------------*/ - - .input { - width: 100%; - border: none; - outline: none; - font-size: 1.4rem; - height: 50px; - padding: 10px 10px; - text-align: center; - font-weight: bold; - background: rgba( 255, 255, 255, 0.25 ); -box-shadow: 0 8px 32px 0 rgba( 31, 38, 135, 0.37 ); -backdrop-filter: blur( 4px ); --webkit-backdrop-filter: blur( 4px ); -border-radius: 10px; -border: 1px solid rgba( 255, 255, 255, 0.18 ); - } - - /*------------------------------------DETAILS----------------------------------------- */ - - .main-weather { - display: none; - padding: 20px; - line-height: 2.2rem; - border-radius: 10px; - height: 30vh; - text-align: center; - color: #23313E; - font-weight: bold; - } - - .temp { - - margin: 25px ; - font-size:40pt; - font-weight: 700; - } - - /*---------------------------------------------------------------------------------------*/ \ No newline at end of file +.wrapper .weather-part{ + display: none; + margin: 30px 0 0; + align-items: center; + justify-content: center; + flex-direction: column; +} +.wrapper.active .weather-part{ + display: flex; +} +.weather-part img{ + max-width: 125px; +} +.weather-part .temp{ + display: flex; + font-weight: 500; + font-size: 72px; +} +.weather-part .temp .numb{ + font-weight: 600; +} +.weather-part .temp .deg{ + font-size: 40px; + display: block; + margin: 10px 5px 0 0; +} +.weather-part .weather{ + font-size: 21px; + text-align: center; + margin: -5px 20px 15px; +} +.weather-part .location{ + display: flex; + font-size: 19px; + padding: 0 20px; + text-align: center; + margin-bottom: 30px; + align-items: flex-start; +} +.location i{ + font-size: 22px; + margin: 4px 5px 0 0; +} +.weather-part .bottom-details{ + display: flex; + width: 100%; + justify-content: space-between; + border-top: 1px solid #ccc; +} +.bottom-details .column{ + display: flex; + width: 100%; + padding: 15px 0; + align-items: center; + justify-content: center; +} +.column i{ + color: #5449a7; + font-size: 40px; +} +.column.humidity{ + border-left: 1px solid rgb(145, 139, 185); +} +.column .details{ + margin-left: 3px; +} +.details .temp, .humidity span{ + font-size: 18px; + font-weight: 500; + margin-top: -3px; +} +.details .temp .deg{ + margin: 0; + font-size: 17px; + padding: 0 2px 0 1px; +} +.column .details p{ + font-size: 14px; + margin-top: -6px; +} +.humidity i{ + font-size: 37px; +} \ No newline at end of file diff --git a/Weather Forecast Webapp/index.html b/Weather Forecast Webapp/index.html index f6553fd1..664487e5 100644 --- a/Weather Forecast Webapp/index.html +++ b/Weather Forecast Webapp/index.html @@ -1,38 +1,59 @@ - + + - - - - - - Weather + + Weather App + + + + - - -
-
-

WEATHER APP

- -
- -
-

Date

-
City
-
Temp
-
Min and Max Temp
-
Sunny
-
+
+
Weather App
+
+

+
+ +
+ +
+
+
+ Weather Icon +
+ _ + °C +
+
_ _
+
+ + _, _ +
+
+
+ +
+
+ _ + °C +
+

Feels like

+
+
+
+ +
+ _ +

Humidity

+
+
+
+
+ + - \ No newline at end of file diff --git a/Weather Forecast Webapp/js/icons/clear.svg b/Weather Forecast Webapp/js/icons/clear.svg new file mode 100644 index 00000000..371d7c38 --- /dev/null +++ b/Weather Forecast Webapp/js/icons/clear.svg @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Weather Forecast Webapp/js/icons/cloud.svg b/Weather Forecast Webapp/js/icons/cloud.svg new file mode 100644 index 00000000..39616667 --- /dev/null +++ b/Weather Forecast Webapp/js/icons/cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Weather Forecast Webapp/js/icons/haze.svg b/Weather Forecast Webapp/js/icons/haze.svg new file mode 100644 index 00000000..8f41e2c0 --- /dev/null +++ b/Weather Forecast Webapp/js/icons/haze.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Weather Forecast Webapp/js/icons/rain.svg b/Weather Forecast Webapp/js/icons/rain.svg new file mode 100644 index 00000000..b843ef96 --- /dev/null +++ b/Weather Forecast Webapp/js/icons/rain.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Weather Forecast Webapp/js/icons/snow.svg b/Weather Forecast Webapp/js/icons/snow.svg new file mode 100644 index 00000000..157e07eb --- /dev/null +++ b/Weather Forecast Webapp/js/icons/snow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Weather Forecast Webapp/js/icons/storm.svg b/Weather Forecast Webapp/js/icons/storm.svg new file mode 100644 index 00000000..64c19aef --- /dev/null +++ b/Weather Forecast Webapp/js/icons/storm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Weather Forecast Webapp/js/script.js b/Weather Forecast Webapp/js/script.js index 9cfc9612..a60848d6 100644 --- a/Weather Forecast Webapp/js/script.js +++ b/Weather Forecast Webapp/js/script.js @@ -1,59 +1,89 @@ -/*---------------------------------------API--------------------------------------------*/ - -const api = { - key: "", /* <=== ENTER YOU API KEY WITHIN THE QUOTES*/ - base: "https://api.openweathermap.org/data/2.5/weather?", -} - -/*-------------------FUNCTION TO DISPLAY DATE AND TIME USING MOMENT.JS-------------------*/ - -const date = moment(); -document.getElementById("date").innerHTML = date.format("Mo MMM YYYY dddd, h:mm:ss"); - - -/*-----------------------FUNCTION TO TAKE THE VALUES WHEN ENTERED------------------------*/ - - const Input = document.getElementById('input'); - - Input.addEventListener('keypress', (event) => { - - if(event.keyCode == 13) { - getWeather(Input.value); //passing the input value to getWeather function - document.querySelector('.main-weather').style.display = "block"; //used to show the details as intially the display is set as none +const wrapper = document.querySelector(".wrapper"), +inputPart = document.querySelector(".input-part"), +infoTxt = inputPart.querySelector(".info-txt"), +inputField = inputPart.querySelector("input"), +locationBtn = inputPart.querySelector("button"), +weatherPart = wrapper.querySelector(".weather-part"), +wIcon = weatherPart.querySelector("img"), +arrowBack = wrapper.querySelector("header i"); + +let api; + +inputField.addEventListener("keyup", e =>{ + if(e.key == "Enter" && inputField.value != ""){ + requestApi(inputField.value); } }); -/*-------------------------------FUNCTION TO GET WEATHER--------------------------------*/ - - -function getWeather(city) { - fetch(`${api.base}q=${city}&appid=${api.key}&units=metric`) // format for calling api is given on the web docs - // units=metric used for celcius, if you remove it the temperature would be in Fahrenheit - .then(details => { - return details.json(); // Sending all details to showWeather function in form of json +locationBtn.addEventListener("click", () =>{ + if(navigator.geolocation){ + navigator.geolocation.getCurrentPosition(onSuccess, onError); + }else{ + alert("Your browser not support geolocation api"); + } +}); - }).then(showWeather); +function requestApi(city){ + api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${'de1400a8c4500ee4e0ebe2e706f9d077'}`; + fetchData(); } -/*-------------------------------FUNCTION TO SHOW WEATHER--------------------------------*/ - - -function showWeather(details){ //Taking the received values from API into this function - - // console.log(details); - - let city = document.getElementById('city'); - city.innerHTML = `${details.name}, ${details.sys.country}`; - - let temperature = document.getElementById('temp'); - temperature.innerHTML = `${Math.round(details.main.temp)}°C`; //Rounding off the temp using math function +function onSuccess(position){ + const {latitude, longitude} = position.coords; + api = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&units=metric&appid=${'de1400a8c4500ee4e0ebe2e706f9d077'}`; + fetchData(); +} - let minMax = document.getElementById('min-max'); - minMax.innerHTML = `${Math.round(details.main.temp_min)}°C (Min) and ${Math.round(details.main.temp_max)}°C (Max) `; //Rounding off the temp using math function +function onError(error){ + infoTxt.innerText = error.message; + infoTxt.classList.add("error"); +} - let weatherType = document.getElementById('weather-type'); - weatherType.innerHTML = `${details.weather[0].main}`; +function fetchData(){ + infoTxt.innerText = "Getting weather details..."; + infoTxt.classList.add("pending"); + fetch(api).then(res => res.json()).then(result => weatherDetails(result)).catch(() =>{ + infoTxt.innerText = "Something went wrong"; + infoTxt.classList.replace("pending", "error"); + }); } -/*----------------------------------------------------------------------------------------*/ +function weatherDetails(info){ + if(info.cod == "404"){ + infoTxt.classList.replace("pending", "error"); + infoTxt.innerText = `${inputField.value} isn't a valid city name`; + }else{ + const city = info.name; + const country = info.sys.country; + const {description, id} = info.weather[0]; + const {temp, feels_like, humidity} = info.main; + + if(id == 800){ + wIcon.src = "icons/clear.svg"; + }else if(id >= 200 && id <= 232){ + wIcon.src = "icons/storm.svg"; + }else if(id >= 600 && id <= 622){ + wIcon.src = "icons/snow.svg"; + }else if(id >= 701 && id <= 781){ + wIcon.src = "icons/haze.svg"; + }else if(id >= 801 && id <= 804){ + wIcon.src = "icons/cloud.svg"; + }else if((id >= 500 && id <= 531) || (id >= 300 && id <= 321)){ + wIcon.src = "icons/rain.svg"; + } + + weatherPart.querySelector(".temp .numb").innerText = Math.floor(temp); + weatherPart.querySelector(".weather").innerText = description; + weatherPart.querySelector(".location span").innerText = `${city}, ${country}`; + weatherPart.querySelector(".temp .numb-2").innerText = Math.floor(feels_like); + weatherPart.querySelector(".humidity span").innerText = `${humidity}%`; + infoTxt.classList.remove("pending", "error"); + infoTxt.innerText = ""; + inputField.value = ""; + wrapper.classList.add("active"); + } +} +arrowBack.addEventListener("click", ()=>{ + wrapper.classList.remove("active"); +}); \ No newline at end of file