Skip to content
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.
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
# 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.
to build a simple weather dashboard that uses a weather API to tell today's weather and temperature and a 4-day forecast. We also had to make the design as similar as possible to the ones that were provided

## 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?
I followed the steps from the past live sessions and from youtube, I had problems with the styling trying to make it as similar as possible, and displaying the sunset/sunrise in a correct format.

If I had more time I would like to make the live-time work correctly, and add the option to see other cities weather, also improve more 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.
https://shiny-sopapillas-ecb62f.netlify.app
Binary file added assets/.DS_Store
Binary file not shown.
Binary file added assets/design-1/.DS_Store
Binary file not shown.
Binary file added assets/design-1/clouds.jpg
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 assets/design-1/search.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!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>
<link rel="stylesheet" href="style.css">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap" rel="stylesheet">
</head>
<body>
<div class="main-weather-container">
<!-- Search Icon -->
<div class="search-icon">
<img src="assets/design-1/search.png" alt="Search-icon">
</div>

<!-- Current Weather Information -->
<div class="current-weather">
<div id="temp" class="temp">8°C</div>
<div id="city" class="city">Stockholm</div>
<div id="time" class="time">Time: 17:40</div>
<div id="weather-condition" class="weather-condition">Heavy Intensity Rain</div>
<div id="weather-icon" class="weather-icon">
<img src="assets/design-1/Group16.png" alt="Cloudy">
</div>
<div id="sun-info" class="sun-info">
<div id="sunrise" class="sunrise">Sunrise: 06:46</div>
<div id="sunset" class="sunset">Sunset: 18:30</div>
</div>
</div>

<!-- Forecast Section -->
<div class="forecast-container">
<div id="forecast"></div>
</div>
</div>

<script src="./script.js"></script>
</body>
</html>
117 changes: 117 additions & 0 deletions script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
const apiKey = '15e8eef35aa52c93aeef1018b9732a74';
const baseUrl = "https://api.openweathermap.org/data/2.5/";
const city = "Stockholm,Sweden";
const units = "metric";
const apiUrl = `${baseUrl}weather?q=${city}&units=${units}&APPID=${apiKey}`;
const forecastApiUrl = `${baseUrl}forecast?q=${city}&units=${units}&APPID=${apiKey}`;

function convertTo24HourTime(timestamp, timezoneOffset) {
const utcTime = new Date(timestamp * 1000);

const options = {
hour: '2-digit',
minute: '2-digit',
hour12: false,
timeZone: 'Europe/Stockholm'
};

return new Intl.DateTimeFormat('en-GB', options).format(utcTime);
}

function capitalizeFirstLetter(text) {
return text.charAt(0).toUpperCase() + text.slice(1);
}

async function checkWeather() {
try {
const response = await fetch(apiUrl);
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
const data = await response.json();

console.log(data);

document.getElementById('city').innerHTML = data.name;
document.getElementById('temp').innerHTML = `${data.main.temp.toFixed(1)}°C`;

document.getElementById('sunrise').innerHTML = convertTo24HourTime(data.sys.sunrise, data.timezone);
document.getElementById('sunset').innerHTML = convertTo24HourTime(data.sys.sunset, data.timezone);
document.getElementById('time').innerHTML = `Local Time: ${convertTo24HourTime(data.dt, data.timezone)}`;

document.getElementById('weather-condition').innerHTML = capitalizeFirstLetter(data.weather[0].description);
const weatherIcon = document.getElementById('weather-icon').querySelector('img');
weatherIcon.src = `http://openweathermap.org/img/wn/${data.weather[0].icon}@2x.png`;
weatherIcon.alt = data.weather[0].description;

} catch (error) {
console.error('Error fetching weather data:', error);
}
}

document.addEventListener('DOMContentLoaded', () => {
checkWeather();
getWeatherForecast();
});

// Fetch and process the weather forecast
async function getWeatherForecast() {
try {
const response = await fetch(forecastApiUrl);
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);

const forecastData = await response.json();
console.log('Forecast API Response:', forecastData);

// Store daily forecast (only for 12:00 PM each day)
const dailyForecasts = {};

forecastData.list.forEach(item => {
const date = item.dt_txt.split(' ')[0]; // Extract YYYY-MM-DD
const time = item.dt_txt.split(' ')[1]; // Extract HH:MM:SS

// Only use forecast entries for 12:00 PM
if (time === '12:00:00') {
dailyForecasts[date] = {
date: new Date(date).toLocaleDateString('en-US', { weekday: 'long', day: 'numeric', month: 'short' }),
temp: item.main.temp.toFixed(1), // ✅ Only display temperature
icon: item.weather[0].icon,
description: capitalizeFirstLetter(item.weather[0].description) // Capitalize description
};
}
});

// Convert object to array and limit to the next 4 days
const forecastArray = Object.values(dailyForecasts).slice(0, 4);
console.log("Final 4-day forecast:", forecastArray); // ✅ Debugging step

displayForecast(forecastArray);
} catch (error) {
console.error('Error fetching forecast data:', error);
}
}

// Display the forecast data
function displayForecast(dailyForecasts) {
const forecastContainer = document.getElementById('forecast');
forecastContainer.innerHTML = ''; // Clear previous content

const header = document.createElement('h3');
header.textContent = 'Forecast at 12:00';
forecastContainer.appendChild(header);

dailyForecasts.forEach(day => {
const forecastCard = document.createElement('div');
forecastCard.classList.add('forecast-day');

forecastCard.innerHTML = `
<div class="day">${day.date}</div>
<img src="http://openweathermap.org/img/wn/${day.icon}.png" alt="${day.description}">
<div class="temp">${day.temp}°C</div> <!-- ✅ Only showing temperature -->
<div class="description">${day.description}</div>
`;

forecastContainer.appendChild(forecastCard);
});
}

// Call the function to get the forecast
getWeatherForecast();
110 changes: 110 additions & 0 deletions style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/* General Styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'poppins', sans-serif;
}

body {
background: url('assets/design-1/clouds.jpg') no-repeat center center fixed;
background-size: cover;
}

.main-weather-container {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100vh;
padding: 5px 35px 15px;
width: 90%;
max-width: 470px;
margin: 10px auto 10px;
}

/* Search Icon */
.search-icon {
position: relative;
top: 20px;
left: 20px;
padding: 5px;
}

.search-icon img {
width: 24px;
cursor: pointer;
}

/* Current Weather Section */
.current-weather {
text-align: center;
color: #f1f1f1;
}

.temp {
font-size: 96px;
font-weight: bold;
}

.city {
font-size: 36px;
margin: 10px 0;
}

.time {
font-size: 20px;
margin-bottom: 10px;
}

.weather-condition {
font-size: 24px;
}

.weather-icon img {
width: 50px;
margin-top: 10px;
}

.sun-info {
display: flex;
justify-content: space-between;
margin-top: 10px;
font-size: 18px;
}

.sunrise, .sunset {
text-align: center;
}

/* Forecast Section */
.forecast-container {
background-color: rgba(107, 107, 107, 0.3);
color: rgb(255, 255, 255);
padding: 50px 50px 50px 50px;
border-radius: 20px;
margin-top: 20px;
font-family: 'Roboto', sans-serif;
}

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

.forecast-day img {
width: 40px;
}

.forecast-day .day {
flex: 1;
font-size: 18px;
font-weight: bold;
}

.forecast-day .temp {
font-size: 18px;
font-weight: bold;
}