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

Project Weather App #429

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9c2478e
Add a HTML file with a basic structure. Add a JS file with DOM select…
joheri1 Sep 27, 2024
6789ee9
Remove example of what an API key looks like and how it should be use…
joheri1 Sep 27, 2024
9d17817
Fetch data for City name, weather description, sunrise, sunset and te…
joheri1 Sep 27, 2024
b7ec8bb
Fetch data for forecast using async. Add variables for latitud and lo…
joheri1 Sep 27, 2024
a8a5a26
Update console log text. Remove test data.
joheri1 Sep 27, 2024
b0f7e29
Make the function fetchTodayWeatherAsync dynamic by removing City as …
joheri1 Sep 28, 2024
85b4e96
HTML: Add HTML element for five-day forecast. Delete element Weekday …
joheri1 Sep 29, 2024
70c33e6
Add Math.round to today and forecast temperature to display a whole n…
joheri1 Sep 29, 2024
d1998e0
Convert Sunset/Sunrise from seconds to milliseconds by multiplying by…
joheri1 Sep 29, 2024
ca9a504
Add CSS styling. Adapt app do different screen sizes. Add weather ico…
joheri1 Sep 29, 2024
2ede3e4
Copy folder with images to the code folder. Update paths to icons i t…
joheri1 Sep 29, 2024
6f7212d
Update weather icaon paths
joheri1 Sep 29, 2024
13277fd
Add more CSS Styling
joheri1 Sep 29, 2024
ed47e82
Change weekdays array to start with Sun
joheri1 Sep 29, 2024
d1063b3
Adapt site to desktop
joheri1 Sep 30, 2024
8fe39b2
Add cnt=32 to forecastURL to display 4 day forecast instead of default
joheri1 Sep 30, 2024
9d83dc2
Add padding and margin to CSS. Change background color.
joheri1 Sep 30, 2024
1b94468
Update code
joheri1 Sep 30, 2024
2ced24f
Remove todays forcast in the forecastDate filter. Add a const for tod…
joheri1 Sep 30, 2024
74d16ec
Add README-file. Update the BASE_URL and forecastBaseURL for better U…
joheri1 Sep 30, 2024
85b8cae
Update README file. Fix height issues on container for Desktop.
joheri1 Sep 30, 2024
eafc9ec
Add margin and padding on body for desktop
joheri1 Sep 30, 2024
f6411c9
Add footer to the HTML
joheri1 Sep 30, 2024
c637333
Add more css to footer
joheri1 Sep 30, 2024
a41b834
Give sunrise and sunset the correct local time zone
joheri1 Oct 10, 2024
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
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
}
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
# 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 assignment is to fetch data from an API using fetch() in JavaScript and create an app should have a city name, current temperature, weather description, sunrise/sunset time, and a 4-day forecast. The data should be presented in a user-friendly format, and the app should be responsive to different devices.

## The problem

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?
## Time
This project was fun to work with and I wish I had more time.

I made a plan, and stuck to it, which was good. The plan was the following:
1. Create HTML File: Set up an HTML file with (the required) fields for city name, current temperature, weather description, sunrise and sunset times, and placeholders for the forecast.
2. Add API URL and Endpoints: Create API URL and endpoints in the JavaScript file, and set up the DOM Selectors.
3. Fetch today’s weather: Use async/await to fetch today's weather, convert the response to json format, populate the innerHTML, and add the error handling. When all fields for today's weather are fetched and displayed, start with the forecast.
4. Fetch and display Forecast: Retrieve and display the forecast dataFetch and display the Forecast data.
5. Format the data: Ensure the data is correctly formatted.
6. Design and responsiveness: Work on the design and make the site responsive.

All went smoothly until I began working on the forecast. I had go back in the material (especially the Live sessions) multiple times just to get a hang of what I was expected to do next. On top of that there were so many JavaScript default behaviors that I needed to find solutions for, such as JavaScript weeks start on Sunday and the need to convert sunset times from seconds to milliseconds. These were fun challenges but I needed more time. As a result, the design part isn't fully completed.

## If I had more time
I would improve my code by create a constant for updating the HTML to keep the functions clean, and find a way to combine the "calls" for today’s weather and the forecast into a single "call". Fetch and display lowest and highest temperature. Use images from the API, instead of using only the three that came along in the assets. And of course, pay more attention to the design.

## 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.
LINK: https://project-weather-app-by-joe.netlify.app/
Binary file added code/.DS_Store
Binary file not shown.
Binary file added code/assets/design-1/Group16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added code/assets/design-1/Group34.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added code/assets/design-1/Group36.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added code/assets/design-1/Group37.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added code/assets/design-1/Group38.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions code/assets/design-2/noun_Cloud_1188486.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions code/assets/design-2/noun_Sunglasses_2055147.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions code/assets/design-2/noun_Umbrella_2030530.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 30 additions & 0 deletions code/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Project Weather App</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<div class="current-container">
<img id="weather-icon" src="" alt="Current Weather Icon"/>
<h1 id="temperature">Temperature</h1>
<h2 id="city">City</h2>
<h3 id="description">Weather description</h3>
<p id="sunrise" class="sunrise_sunset">Sunrise: </p>
<p id="sunset" class="sunrise_sunset">Sunset: </p>
</div>
<div class="forecast-container">
<div id="four-day-forecast"></div>
<div class="day-container">
</div>
</div>
<div>
<footer>2024-09-29 Johanna Eriksson</footer>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
100 changes: 100 additions & 0 deletions code/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//API URL and Endpoints
const BASE_URL = "https://api.openweathermap.org/data/2.5/"
const api_key = "617b18d1663716ef276314bb0808d62b"

// DOM Selectors
const cityName = document.getElementById("city")
const description = document.getElementById("description")
const temperature = document.getElementById("temperature")
const sunriseTime = document.getElementById("sunrise")
const sunsetTime = document.getElementById("sunset")
const fourDayForecast = document.getElementById('four-day-forecast')

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

// Get today's date for comparison in forecast
const today = new Date().getDate()

const weatherIcons = {
"scattered clouds": "./assets/design-1/Group16.png", // Cloudy
"few clouds": "./assets/design-1/Group34.png", // Few clouds
"clear sky": "./assets/design-1/Group37.png", // Sunny
}

//Fetch todays weather
const fetchTodaysWeatherAsync = async (city) => {
const todayURL = `${BASE_URL}weather?q=${city}&units=metric&APPID=${api_key}`
// units=metric to get temperatures in Celcius
try {
const response = await fetch(`${todayURL}`)
if (!response.ok) {
throw new Error("Failed to fetch today's weather data")
}
//convert response to JSON
const data = await response.json()

//Update DOM with today's weather data
cityName.innerHTML = data.name
temperature.innerHTML = `${Math.round(data.main.temp)} °C`
description.innerHTML = data.weather[0].description

const weatherDescription = data.weather[0].description

//Weather icon
const weatherIconURL = weatherIcons[weatherDescription] || "./assets/design-1/Group16.png"; // Default icon
console.log("Weather icon path:", weatherIconURL)
document.getElementById("weather-icon").src = weatherIconURL


//Sunset/Sunrise

//Convert Time zone and Sunset / Sunrise from seconds to milliseconds by multiplying by 1000, which the date object requires
const localTimezone = data.timezone * 1000
const sunrise = new Date((data.sys.sunrise * 1000) + localTimezone).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })
const sunset = new Date((data.sys.sunset * 1000) + localTimezone).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })

sunriseTime.innerHTML = `Sunrise: ${sunrise}`
sunsetTime.innerHTML = `Sunset: ${sunset}`

} catch (error) {
//Handle any errors
console.error("Error when fetching Today's weather", error)
}
}
fetchTodaysWeatherAsync("Las Vegas")

//Fetch forecast weather
const fetchForecastWeatherAsync = async (city) => {
const forecastURL = `${BASE_URL}forecast?q=${city}&units=metric&cnt=40&appid=${api_key}`
// units=metric to get temperatures in Celcius and cnt=40 for a 5 day forecast, then we remove todays forecast
try {
const response = await fetch(`${forecastURL}`)
if (!response.ok) {
throw new Error("Failed to fetch forecast weather data")
}
//convert response to JSON
const data = await response.json()

//Filter forecast on 12:00
const filteredForecast = data.list.filter(forecast => {
const forecastDate = new Date(forecast.dt_txt)
return forecastDate.getHours() === 12 && forecastDate.getDate() !== today
})
filteredForecast.forEach(forecast => {
let forecastDate = new Date(forecast.dt_txt)//Convert date to Date const
let dayName = weekdays[forecastDate.getDay()] // Get weekday
// Get weather icon
const weatherDescription = forecast.weather[0].description

//Update HTML with weekday, temperture and icon
const forecastIconURL = weatherIcons[weatherDescription] || "./assets/design-1/Group16.png"; // Default icon
fourDayForecast.innerHTML += `<p>${dayName}: <img src="${forecastIconURL}" alt="weather icon"> ${Math.round(forecast.main.temp)} °C</p>`

})
} catch (error) {
//Handle any errors
console.error("Error when fetching the forecast", error)
}
}
fetchForecastWeatherAsync("Las Vegas")
139 changes: 139 additions & 0 deletions code/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/*Ensure images adapts well to all devices*/
img {
display: block;
max-width: 100%;
}

/*Mobile*/
@media screen and (max-width: 600px) {
.container {
padding: 10px;
margin-top: 10px;
max-width: 100%;
max-height: 100%;
}
footer {
width: 300px;
}
}
/* Tablet */

@media screen and (min-width: 501px) and (max-width: 1024px) {
body {
padding: 10px;
margin: 40px;
}
.container {
width: 800px;
margin-top: 40px;
padding: 50px;
}
.temperature h1 {
font-size: 60px;
}

.forecast p {
font-size: 16px;
}
}
/* Desktop */
@media screen and (min-width: 1025px) {
body {
padding: 10px;
margin: 40px;
}
.container {
width: 100%;
}
.temperature h1 {
font-size: 72px;
}
.forecast p {
font-size: 18px;
}
}
body {
font-family: 'Arial', sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #d1c4e9;
}

.container {
background: linear-gradient(to bottom, #d1c4e9, #fff);
border-radius: 20px;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.1);
margin-top: 40px;
padding: 50px;
width: 320px;
height: 100%;
text-align: center;
overflow-y: auto
}

#weather-icon {
display: block;
margin: 0 auto;
width: 100px;
}
.temperature h1 {
font-size: 72px;
font-weight: bold;
color: #fff;
}

.sunrise_sunset {
font-size: 14px;
color: grey;
opacity: 0.6;
}

.forecast {
margin-top: 20px;
}

#four-day-forecast {
display: flex;
flex-direction: column;
align-items: center;
}

.forecast #four-day-forecast {
text-align: center;
margin: 5px;
}

.forecast #four-day-forecast p {
font-size: 14px;
color: #333;
margin: 5px 0;
display: flex;
justify-content: space-between;
}

.forecast-day {
display: flex;
align-items: center;
justify-content: center;
padding: 10px 0;
border-bottom: 1px solid #ddd;
}

.forecast-day img {
margin-right: 10px;
}

footer {
display: flex;
justify-content: center;
margin-top: 20px;
color: #fff;
background-color: #d1c4e9;
border-radius: 20px;
border-style: dotted;
padding: 10px;
margin-top: 20px;
}

2 changes: 1 addition & 1 deletion instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Start out with signing up for a [free Open Weather Map](https://home.openweather
For example, to get the current weather in Stockholm, you can use the URL below. Remember to replace YOUR_API_KEY with the API key you copied from your dashboard.

```
https://api.openweathermap.org/data/2.5/weather?q=Stockholm,Sweden&units=metric&APPID=YOUR_API_KEY
https://api.openweathermap.org/data/2.5/weather?q=Stockholm,Sweden&units=metric&APPID=xxxxx
```

The response should look something like this (this has been run through jsonlint.com to add newlines and indentation):
Expand Down