Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Weather App #415

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 5501
}
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Weather App

Replace this readme with your own information about your project.

Start by briefly describing the assignment in a sentence or two. Keep it short and to the point.
The aim of this project was to fetch data from a weather API and implement the data into a website. The weather data includes name of city, rounded temperatures, weather description & images, sunrise and sunset times.

## The problem
One challenge in this project was to understand the data offered by the API and implement the data into the website. Convertion to local times and temperatures involved.

Right now, the weather forecast has been based on two time entry points to receive the temperature. To improve the accuracy of the shown data, it would be good to fetch more data.

Describe how you approached to problem, and what tools and techniques you used to solve it. How did you plan? What technologies did you use? If you had more time, what would be next?

## View it live

Every project should be deployed somewhere. Be sure to include the link to the deployed project so that the viewer can click around and see what it's all about.
https://gittes-weather-app.netlify.app
Binary file added assets/.DS_Store
Binary file not shown.
67 changes: 67 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie-edge">
<link rel="stylesheet" href="style.css">
<title>Weather App</title>
<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=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
rel="stylesheet">
</head>

<body id="body">
<header class="day-theme" id="header">
<div class="menu" id="hamburgerMenu">
<div class="hamburger-layer"></div>
<div class="hamburger-layer"></div>
<div class="hamburger-layer"></div>
</div>

<!-- Window to search for town -->

<div id="searchLocationWindow" class="search-location-window">
<div class="searchLocationContainer">
<span class="close-window-button" id="closeWindow">X</span>
<h2>Find current weather and four-day forecast</h2>
<input type="text" id="searchCity" class="search-city" placeholder="enter a city"></input>
<button class="search-button" id="searchLocationButton">Search</button>
</div>
</div>


<div class="weather-container">
<div class="temperature-container">
<div>
<h1 class="temperature" id="temp">
</h1>
</div>
<h2 id="cityName"></h2>
<h3 id="weather"></h3>
</div>
<div class="current-weather-image" id="currentWeatherImage">
</div>
</div>

<div class="sunrise-sunset">
<p>sunrise</p>
<p id="sunrise"></p>
<p>sunset</p>
<P id="sunset"></P>
</div>
</header>
<main>
<div class="weather-forecast-container" id="forecastContainer">

</div>

</main>

<script src="./script.js"></script>
</body>

</html>
196 changes: 196 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
const BASE_URL = "https://api.openweathermap.org/data/2.5/"
const API_KEY = "72e635da2875c352d9f726550253e2db"

const menu = document.getElementById('hamburgerMenu')
const searchWindow = document.getElementById('searchLocationWindow')
const closeWindow = document.getElementById('closeWindow')
const searchButton = document.getElementById('searchLocationButton')
const cityInput = document.getElementById('searchCity')
const temperature = document.getElementById('temp')
const weather = document.getElementById('weather')
const cityName = document.getElementById('cityName')
const sunrise = document.getElementById('sunrise')
const sunset = document.getElementById('sunset')
const iconCurrent = document.getElementById('currentWeatherImage')
const header = document.getElementById('header')


// function to create new URL for forecast based on the users input
const createForecastURL = (cityName) => {
return `${BASE_URL}forecast?q=${cityName}&units=metric&APPID=${API_KEY}`
}

// function to create new URL for current weather based on the users input
const createURL = (cityName) => {
return `${BASE_URL}weather?q=${cityName}&units=metric&APPID=${API_KEY}`
}

// function to convert Unix-time into hours:minutes
const convertUnixToTime = (unixTime, timeZone) => {
const time = unixTime * 1000
const date = new Date(time)
const localTime = new Date(date.getTime() + timeZone * 1000)

const hours = localTime.getUTCHours()
const minutes = "0" + localTime.getUTCMinutes()
return `${hours}:${minutes.substr(-2)}`
}


// to get the weather data for the current weather
const fetchWeatherData = async (cityName) => {
const URL = createURL(cityName)
try {
const response = await fetch(URL)
if (!response.ok) {
throw new Error('Failed to fetch weather data')
}
const data = await response.json()
// console.log(data)
updateHTML(data)

} catch (error) {
console.log(error)
}
}

// to get the forecast weather data
const fetchForecastData = async (cityName) => {
const URLForecast = createForecastURL(cityName)
try {
const response = await fetch(URLForecast)
if (!response.ok) {
throw new Error('Failed to fetch forecast weather data')
}
const dataForecast = await response.json()
console.log(dataForecast)
updateForecastHTML(dataForecast)

} catch (error) {
console.log(error)
}
}

// update HTML current weather

const updateHTML = (data) => {
console.log(data)

cityName.innerText = data.name
weather.innerText = data.weather[0].description

// method to round the temperatures
const roundedTemp = Math.round(data.main.temp)
temperature.innerText = `${roundedTemp}°C`

// the local time for the specific city

const sunriseTime = convertUnixToTime(data.sys.sunrise, data.timezone)
const sunsetTime = convertUnixToTime(data.sys.sunset, data.timezone)

sunrise.innerText = sunriseTime
sunset.innerText = sunsetTime

const currentTime = Math.floor(Date.now() / 1000)

// Icon
const iconCode = data.weather[0].icon
const iconUrl = `http://openweathermap.org/img/wn/${iconCode}@2x.png`

iconCurrent.innerHTML = `<img class="icon-big" src="${iconUrl}" alt="Weather Icon">`

// Day/Night Background Update
const nightBackground = (currentTime, sunriseTime, sunsetTime) => {
header.style.background = (currentTime < sunriseTime || currentTime > sunsetTime)
? "linear-gradient(90deg, #323667 50%, #6B6EA8 50%)"
: ""
}
nightBackground(currentTime, data.sys.sunrise, data.sys.sunset)
}

// update HTML for forecast weather

// Array with weekdays
const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

// Function for HTML inputs
const updateForecastHTML = (dataForecast) => {
console.log(dataForecast)

const forecasts = dataForecast.list

// filters the forecast for 12 AM (midnight) each day
const filteredMinForecasts = forecasts.filter(minForecast => {
const dateTime = new Date(minForecast.dt_txt)
return dateTime.getHours() === 0
})

// filters the forecast for 12AM each day
const filteredMaxForecasts = forecasts.filter(maxForecast => {
const dateTime = new Date(maxForecast.dt_txt)
return dateTime.getHours() === 12
})

let forecastHTML = ''

// Loops
for (let i = 0; i < 4; i++) {
const minTemp = Math.round(filteredMinForecasts[i].main.temp)
const maxTemp = Math.round(filteredMaxForecasts[i].main.temp)

// Get the icon for the forecast
const iconCode = filteredMinForecasts[i].weather[0].icon
const iconUrl = `http://openweathermap.org/img/wn/${iconCode}@2x.png`

// get weekdays

const dateTime = new Date(filteredMaxForecasts[i].dt_txt)
const dayOfWeek = weekdays[dateTime.getDay()]

forecastHTML += `
<div class="weather-day">
<p class="weekday">${dayOfWeek}</p>
<div class="forecast-image">
<img class="forecast-icon "src="${iconUrl}" alt="Weather Icon">
</div>
<p class="forecast-temperature">${minTemp}° / ${maxTemp}°C</p>
</div>
`
}
forecastContainer.innerHTML = forecastHTML
}

// Event Listener to open the search window
menu.addEventListener("click", () => {
searchWindow.style.display = "block"
cityInput.value = ""
})

// To close the search window users can either click on the X or somewhere else on the window

closeWindow.addEventListener("click", () => {
searchWindow.style.display = "none"
})

searchWindow.addEventListener("click", (event) => {
if (event.target == searchWindow) {
searchWindow.style.display = "none"
}
})

// Event-Listener to be able to search a cities

searchButton.addEventListener("click", () => {
// gets the name of the city from the input field
const city = cityInput.value
console.log(city)
if (city) {
fetchWeatherData(city)
fetchForecastData(city)
searchWindow.style.display = "none"
} else (
console.log("please enter a city name")
)
})


Loading