diff --git a/app.js b/app.js deleted file mode 100644 index be21b8d..0000000 --- a/app.js +++ /dev/null @@ -1,104 +0,0 @@ -const searchBox = document.querySelector(".search-box input"); -const searchBtn = document.querySelector("#search"); -const weatherIcon = document.querySelector(".weather-icon"); -const appContainer = document.querySelector(".app-container"); - - -const weatherApiKey = 'b2fa3271ab55c9c76e1b2a2d1afd0478'; -const weatherURL = `https://api.openweathermap.org/data/2.5/weather?units=metric&q=`; - - - -const imageApiKey ="2BsfBnNAfcAGF3oX4F_fRIlYnOXYBGYyJpeHfo8AWp4"; -const imageURL = "https://api.unsplash.com/search/photos?page=1&query="; - - - - -window.addEventListener('load', ()=>{ - setTimeout(()=>{ - document.querySelector("#preloader").style.display = "none"; - },1500) -}) - - -//Weather API call -async function checkWeather(city){ - const response = await fetch(weatherURL + city + `&appid=${weatherApiKey}`); - const data = await response.json(); - - - if(response.status === 404){ - document.querySelector(".error").style.display = 'block'; - document.querySelector(".weather").style.visibility = "hidden"; - appContainer.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)), url("images/weather.jpg")`; - } - else{ - setTimeout(()=>{ - updateData(data); - },500) - } -} - -async function updateData(data){ - - //Update the weather data - document.querySelector("#city").textContent = data.name; - document.querySelector("#temp").textContent = Math.round(data.main.temp) +"°c"; - document.querySelector(".humidity").textContent = data.main.humidity + '%'; - document.querySelector(".wind").textContent = data.wind.speed + "Km/h"; - - - //Change the Weather Icon - const weatherCondition = data.weather[0].main; - - if(weatherCondition == 'Clear'){ - weatherIcon.src = "images/clear.png" - document.querySelector("#condition").textContent = data.weather[0].main; - } - else if(weatherCondition == 'Clouds'){ - weatherIcon.src = "images/clouds.png" - document.querySelector("#condition").textContent = data.weather[0].main; - } - else if(weatherCondition == 'Haze'){ - weatherIcon.src = "images/drizzle.png" - document.querySelector("#condition").textContent = data.weather[0].main; - } - else if(weatherCondition == 'Mist'){ - weatherIcon.src = "images/mist.png" - document.querySelector("#condition").textContent = data.weather[0].main; - } - else if(weatherCondition == 'Rain'){ - weatherIcon.src = "images/rain.png" - document.querySelector("#condition").textContent = data.weather[0].main; - } - else if(weatherCondition == 'Snow'){ - weatherIcon.src = "images/snow.png" - document.querySelector("#condition").textContent = data.weather[0].main; - } - - document.querySelector(".weather").style.display = "block"; - document.querySelector(".error").style.display = 'none'; -} - -//Default Call -checkWeather("kolkata"); -generateImage("kolkata") - - -//Image API call -async function generateImage(city){ - const response = await fetch(imageURL + city + `&client_id=${imageApiKey}`) - const data = await response.json(); - - const img = data.results[0].urls.full; - - appContainer.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${img})`; - -} - - -searchBtn.addEventListener('click', (e)=>{ - generateImage(searchBox.value.trim()); - checkWeather(searchBox.value.trim()); -}) \ No newline at end of file diff --git a/index.html b/index.html index 9c78bd8..725d422 100644 --- a/index.html +++ b/index.html @@ -1,26 +1,23 @@ + Weather App - Find weather of any city - + - - - -
-
-
+
+

Invalid City Name

@@ -54,4 +51,5 @@

Kolkata

+ \ No newline at end of file diff --git a/readme.md b/readme.md deleted file mode 100644 index ccc99c3..0000000 --- a/readme.md +++ /dev/null @@ -1,40 +0,0 @@ -# Weather App Project - -![Weather App Demo](images/demo.png) - -## Overview - -This is a simple weather app project built using HTML, CSS, and JavaScript also fully Responsive. The app allows users to input a city and retrieves real-time weather data, including temperature, humidity, and wind speed, for that city. Additionally, the app displays dynamic city images that change with each search, enhancing the user experience (not all the time although). - -The project was developed as a beginner-level JavaScript project and serves as a practical application of basic web development concepts. - -## Features - -- Input field to enter the desired city -- Real-time weather data retrieval using APIs -- Display of temperature, humidity, and wind speed -- Dynamic city images that change with each search - -## How to Use - -1. Clone the repository to your local machine. -2. Open the `index.html` file in your web browser. -3. Enter the name of the city you want to check the weather for in the input field. -4. Press the "Search" button to retrieve weather data. - -## Technologies Used - - - HTML - - CSS - - JavaScript - -## APIs Used - -- [OpenWeather API](https://openweathermap.org/api) for weather data retrieval. -- [Unsplash API](https://unsplash.com/developers) for dynamic city images. - -## Credits - -- [**GreatStack**](https://www.youtube.com/@GreatStackDev) - - diff --git a/script.js b/script.js new file mode 100644 index 0000000..18b60e2 --- /dev/null +++ b/script.js @@ -0,0 +1,129 @@ +const searchBox = document.querySelector(".search-box input"); +const searchBtn = document.querySelector("#search"); +const weatherIcon = document.querySelector(".weather-icon"); +const appContainer = document.querySelector(".app-container"); + +const weatherApiKey = 'b2fa3271ab55c9c76e1b2a2d1afd0478'; +const weatherURL = `https://api.openweathermap.org/data/2.5/weather?units=metric&q=`; + +const imageApiKey = "2BsfBnNAfcAGF3oX4F_fRIlYnOXYBGYyJpeHfo8AWp4"; +const imageURL = "https://api.unsplash.com/search/photos?page=1&query="; + +let recentCities = []; + +// Weather API call +async function checkWeather(city) { + const response = await fetch(weatherURL + city + `&appid=${weatherApiKey}`); + const data = await response.json(); + + if (response.status === 404 || data.cod === '404') { + document.querySelector(".error").style.display = 'block'; + document.querySelector(".weather").style.visibility = "hidden"; + appContainer.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.5)), url("images/weather.jpg")`; + } else { + setTimeout(() => { + updateData(data); + }, 500); + } +} + +// Update DOM with weather data +async function updateData(data) { + document.querySelector("#city").textContent = data.name; + document.querySelector("#temp").textContent = Math.round(data.main.temp) + "°c"; + document.querySelector(".humidity").textContent = data.main.humidity + '%'; + document.querySelector(".wind").textContent = data.wind.speed + "Km/h"; + + const weatherCondition = data.weather[0].main; + + if (weatherCondition === 'Clear') { + weatherIcon.src = "images/clear.png"; + } else if (weatherCondition === 'Clouds') { + weatherIcon.src = "images/clouds.png"; + } else if (weatherCondition === 'Haze') { + weatherIcon.src = "images/drizzle.png"; + } else if (weatherCondition === 'Mist') { + weatherIcon.src = "images/mist.png"; + } else if (weatherCondition === 'Rain') { + weatherIcon.src = "images/rain.png"; + } else if (weatherCondition === 'Snow') { + weatherIcon.src = "images/snow.png"; + } + + document.querySelector("#condition").textContent = data.weather[0].main; + document.querySelector(".weather").style.display = "block"; + document.querySelector(".error").style.display = 'none'; +} + +// Unsplash Image API call +async function generateImage(city) { + try { + const response = await fetch(imageURL + city + `&client_id=${imageApiKey}`); + const data = await response.json(); + + if (data.results && data.results.length > 0) { + const img = data.results[0].urls.full; + appContainer.style.backgroundImage = `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${img})`; + } + } catch (err) { + console.error("Image load failed:", err); + } +} + +// Add a city to recent list and localStorage +function updateRecentCities(city) { + const formattedCity = city.toLowerCase(); + if (!formattedCity || recentCities.includes(formattedCity)) return; + + recentCities.unshift(formattedCity); + if (recentCities.length > 5) { + recentCities.pop(); + } + + localStorage.setItem("recentCities", JSON.stringify(recentCities)); + renderRecentCities(); +} + +// Render recent cities from array +function renderRecentCities() { + const recentBox = document.querySelector("#recent"); + if (!recentBox) return; + + recentBox.innerHTML = ''; + + recentCities.forEach(city => { + const btn = document.createElement("button"); + btn.textContent = city.charAt(0).toUpperCase() + city.slice(1); + btn.addEventListener("click", () => { + document.querySelector("#city-input").value = city; + generateImage(city); + checkWeather(city); + }); + recentBox.appendChild(btn); + }); +} + +// Load from localStorage on page load +function loadRecentCities() { + const saved = localStorage.getItem("recentCities"); + if (saved) { + recentCities = JSON.parse(saved); + renderRecentCities(); + } +} + +// Handle search +searchBtn.addEventListener('click', () => { + const city = searchBox.value.trim(); + if (city === '') return; + + generateImage(city); + checkWeather(city); + updateRecentCities(city); +}); + +// Initial load +loadRecentCities(); +checkWeather("kolkata"); +generateImage("kolkata"); +updateRecentCities("kolkata"); diff --git a/style.css b/style.css index 3ada020..add524e 100644 --- a/style.css +++ b/style.css @@ -57,6 +57,31 @@ html, body{ outline: none; } +.recent-box { + margin-top: 20px; + display: flex; + justify-content: center; + flex-wrap: wrap; + gap: 10px; +} + +.recent-box button { + padding: 8px 16px; + background: rgba(255, 255, 255, 0.15); + border: 1px solid rgba(255, 255, 255, 0.25); + color: #fff; + border-radius: 999px; + font-size: 0.9rem; + backdrop-filter: blur(6px); + cursor: pointer; + transition: all 0.3s ease; +} + +.recent-box button:hover { + background: rgba(255, 255, 255, 0.25); + transform: scale(1.05); +} + #search{ background-color: #ebfffc; border-radius: 50%;