Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9b15298
created app structure in html and styling in css
Nicolinabl Oct 14, 2025
b5e746b
added ts file and worked on fetching API
Nicolinabl Oct 15, 2025
542b0ad
added function for fetching and displaying todays weather
Nicolinabl Oct 16, 2025
2179629
experimented with new date() to try to display current temp and not t…
Nicolinabl Oct 17, 2025
a33ae1c
planning session, listed action points in readme
Nicolinabl Oct 20, 2025
f5f26a5
advice message in ts file and minor changes in structure(will look in…
Oct 20, 2025
45d8c13
Temps for forecasts 7 days forward
Nicolinabl Oct 21, 2025
c8b3e5e
changes to advice message
Oct 21, 2025
0a330d8
fix merge conflicts
Oct 21, 2025
164388b
Dynamically show weekdays, current day on top
Nicolinabl Oct 21, 2025
b3eec92
finished the advice message so i changed color and symbol depending o…
Oct 22, 2025
3615e90
weather-conditions-added
Oct 22, 2025
0b0d998
Merge pull request #2 from Nicolinabl/weather-conditions-added
Nicolinabl Oct 22, 2025
9e8acf5
Merge branch 'main' into weather-message/sunrise-sunset
Nicolinabl Oct 22, 2025
91f6929
Merge pull request #1 from Nicolinabl/weather-message/sunrise-sunset
Nicolinabl Oct 22, 2025
7919a2f
Merge branch 'main' into WeeklyForecast
Nicolinabl Oct 22, 2025
c988732
Merge pull request #3 from Nicolinabl/WeeklyForecast
Nicolinabl Oct 22, 2025
62a0228
fixed error, removed extra }
Nicolinabl Oct 22, 2025
4b70342
added rain data, displayed it in the browser and minor bug fixes
Oct 22, 2025
17ac2c7
made the website responsive
Oct 22, 2025
c7a0bc2
saved changes
Oct 22, 2025
b2fdc7f
minor bugfix in the showMessage function
Oct 23, 2025
50fa639
minor bugfix in showMessage
Oct 23, 2025
6d8367d
Merge pull request #5 from Nicolinabl/rain-probability-data
Nicolinabl Oct 23, 2025
c8df634
changed code
Nicolinabl Oct 23, 2025
8153b4a
fixed merge conflicts
Nicolinabl Oct 23, 2025
f635bb2
fixed the hr to look better
Oct 23, 2025
a48d1fc
Merge branch 'main' into CSS-fixes
Nicolinabl Oct 23, 2025
9a0f053
Merge pull request #6 from Nicolinabl/CSS-fixes
Nicolinabl Oct 23, 2025
0023479
removed code not in use, added typescript
Nicolinabl Oct 23, 2025
b10af1c
fixed the conditionals for the showMessage and changes symbol-code st…
Oct 23, 2025
5cba74b
saved changes: fixed the conditionals for the showMessage and changes…
Oct 23, 2025
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: 9 additions & 0 deletions Figma designs for students (1)/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.
Binary file added Figma designs for students (1)/[email protected]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Figma designs for students (2)/Group 8.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 Group 7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,32 @@
# js-project-weather-app
# js-project-weather-app

## Project requirements

### API
* location
* condition(symbol_code)
* 7 day forecast
* Air temperature. (air_temperature)

## Stretch goals
* sunrise/sunset

TO DOS
- !Connect weather symbol-code to string & icon -> Julia
- !Display dynamic temps in bottom weekly list -> Nicolina
- Add sunset/sunrise API - Carolina
- Add dynamic messages based of temperature
- Change color depending weather
- look into more paramaters from smhi api


Stretch goal options
Feature: Sunrise & Sunset 🌅 Use the sunrise/sunset API to display when the sun rises and sets.

Feature: More cities 🏙️ Give the user the option to choose between a couple of your favourite cities, or create a searchbar where the user can search for a specific city.

Feature: Use your location 🗺️ Use the Geolocation API that is built into your browser to fetch the city that you are located in at the moment and show the weather for your location.

Feature: Add more data 💽 Explore the API and use another endpoint of the API to include supplementary information.

Feature: CSS Animations ☀️ Add some CSS animations to your app, e.g. pulsating sun/raindrops.
55 changes: 55 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
>
<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=Cormorant:ital,wght@0,300..700;1,300..700&family=Montserrat:ital,wght@0,100..900;1,100..900&family=Nunito+Sans:ital,opsz,wght@0,6..12,200..1000;1,6..12,200..1000&family=Work+Sans:ital,wght@0,100..900;1,100..900&display=swap"
rel="stylesheet"
>
<link
rel="stylesheet"
href="style.css"
>
<title>Weather app</title>
</head>

<body>
<main>
<div id="weatherContainer">
</div>

<div id="rainContainer">
</div>

<div id="sunriseSunsetContainer">
</div>

<section id="adviceSection">
</section>


<section
class="weekly-temp"
id="weeklyTemp"
>
</section>
</main>

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

</html>
273 changes: 273 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,273 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
//----------------------------------
// Dom selectors
//----------------------------------
const weatherContainer = document.getElementById("weatherContainer");
const rainContainer = document.getElementById("rainContainer");
const weeklyTempContainer = document.getElementById("weeklyTemp");
const adviceContainer = document.getElementById("adviceSection");
//----------------------------------
// API link
//----------------------------------
const weatherURL = `https://opendata-download-metfcst.smhi.se/api/category/snow1g/version/1/geotype/point/lon/16.158/lat/58.5812/data.json?parameters=air_temperature,symbol_code,probability_of_precipitation`;
const sunriseSunset = `https://api.sunrisesunset.io/json?lat=58.5812&lng=16.158`;
//----------------------------------
// Fetch API function
//----------------------------------
let data;
let todayWeather;
const fetchData = () => __awaiter(void 0, void 0, void 0, function* () {
try {
const response = yield fetch(weatherURL);
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
data = yield response.json();
console.log(data);
displayWeeklyTemps();
todayForecast();
}
catch (error) {
console.log("catch an error");
}
});
let sunData;
const sunriseSunsetContainer = document.getElementById("sunriseSunsetContainer");
const fetchSunriseSunsetData = () => __awaiter(void 0, void 0, void 0, function* () {
try {
const response = yield fetch(sunriseSunset);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
sunData = yield response.json();
console.log(sunData);
displaySunTimes(sunData);
}
catch (error) {
console.error("An error:", error);
}
});
//----------------------------------
// Sunrise/sunset function
//----------------------------------
const displaySunTimes = (sunData) => {
const sunrise = sunData.results.sunrise;
const sunset = sunData.results.sunset;
sunriseSunsetContainer.innerHTML = `
<div class="top-info">
<p id="topSunrise">Sunrise</p>
<p id="sunriseTime">${sunrise}</p>
</div>

<div class="top-info">
<p id="topSunset">sunset</p>
<p id="sunsetTime">${sunset}</p>
</div>
`;
};
fetchSunriseSunsetData();
//Mapping codes and conditions:
const weatherSymbol = (code) => {
const mapping = {
1: "Clear sky",
2: "Nearly clear",
3: "Variable clouds",
4: "Half cloudy sky",
5: "Cloudy",
6: "Overcast",
7: "Fog",
8: "Light rain",
9: "Moderate rain",
10: "Heavy showers",
11: "Thunderstorm",
12: "Light sleet",
13: "Moderate sleet",
14: "Heavy sleet",
15: "Light snow",
16: "Moderate snow",
17: "Heavy snow",
18: "Light rain",
19: "Moderate rain",
20: "Heavy rain",
21: "Thunder",
22: "Light sleet",
23: "Moderate sleet",
24: "Heavy sleet",
25: "Light snow",
26: "Moderate snow",
27: "Heavy snow"
};
return mapping[Math.round(code)] || "Unknown";
};
//----------------------------------
// Show todays forecast function
//----------------------------------
const todayForecast = () => {
const current = data.timeSeries[0].data;
const airTemp = current.air_temperature;
const conditionCode = current.symbol_code;
const conditionLabel = weatherSymbol(conditionCode);
const rainData = current.probability_of_precipitation;
const condition = weatherSymbol(data.timeSeries[0].data.symbol_code);
todayWeather = {
condition,
airTemp,
rainData
};
weatherContainer.innerHTML = `
<div class="top-info">
<p id="topCondition">${todayWeather.condition}</p>
<hr>
<p id="topTemp">${todayWeather.airTemp}&deg;</p>
</div>
`;
rainContainer.innerHTML = `
<div class="top-info">
<p id="topRainData">Probability of rain: ${todayWeather.rainData}%</p>
</div>`;
showMessage(todayWeather, adviceContainer, weeklyTempContainer);
};
//----------------------------------
// Function for showing advice message, symbol and diffrent styling depending on weather
//----------------------------------
const showMessage = (data, adviceContainer, weeklyTempContainer) => {
const hrElement = document.querySelector("hr");
if (!weeklyTempContainer || !adviceContainer)
return;
adviceContainer.innerHTML = ``;
const condition = data.condition.toLowerCase();
// --- SUNNY ---
if (condition.includes("clear") ||
condition.includes("nearly clear")) {
document.body.style.backgroundColor = "#F7E9B9";
document.body.style.color = "#2A5510";
hrElement.style.borderColor = "#2A5510";
adviceContainer.innerHTML = `
<img class="advice-img" src="Group 7.png" alt="sunny icon">
<h1>Get your sunglasses on. Stockholm is amazing!</h1>`;
}
// --- CLOUDY / OVERCAST / FOG ---
else if (condition.includes("cloud") ||
condition.includes("overcast") ||
condition.includes("fog") ||
condition.includes("variable") ||
condition.includes("half cloudy sky")) {
document.body.style.backgroundColor = "#FFFFFF";
document.body.style.color = "#F47775";
hrElement.style.borderColor = "#F47775";
adviceContainer.innerHTML = `
<img class="advice-img" src="./Figma designs for students (2)/Group [email protected]" alt="cloudy icon">
<h1>Light a fire and get cosy. Stockholm is looking grey today.</h1>`;
}
// --- RAIN / SLEET ---
else if (condition.includes("rain") ||
condition.includes("sleet") ||
condition.includes("shower")) {
document.body.style.backgroundColor = "#BDE8FA";
document.body.style.color = "#164A68";
hrElement.style.borderColor = "#164A68";
adviceContainer.innerHTML = `
<img class="advice-img" src="./Figma designs for students (1)/[email protected]" alt="rainy icon">
<h1>Don't forget your umbrella. It's wet in Stockholm today.</h1>`;
}
// --- SNOW ---
else if (condition.includes("snow")) {
document.body.style.backgroundColor = "#EAF4FF";
document.body.style.color = "#1B3A57";
hrElement.style.borderColor = "#1B3A57";
adviceContainer.innerHTML = `
<img class="advice-img" src="./snow-icon.png" alt="snow icon">
<h1>Wrap up warm — it's snowing in Stockholm!</h1>`;
}
// --- THUNDER / STORM ---
else if (condition.includes("thunder") ||
condition.includes("storm")) {
document.body.style.backgroundColor = "#B3B8C4";
document.body.style.color = "#2A2A2A";
hrElement.style.borderColor = "#2A2A2A";
adviceContainer.innerHTML = `
<img class="advice-img" src="./storm-icon.png" alt="storm icon">
<h1>Stay safe — there’s a storm in Stockholm.</h1>`;
}
// --- FALLBACK ---
else {
document.body.style.backgroundColor = "#EEE";
document.body.style.color = "#333";
hrElement.style.borderColor = "#000";
adviceContainer.innerHTML = `<h1>Anything could happen, you better be prepared!</h1>`;
}
};
fetchData();
//----------------------------------
// Display weekly temps bottom part function
//----------------------------------
const weekDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; /* Array of weekdays. To be used for displaying weekdays dynamically */
let weatherForecast; /* Defining weatherForecast object */
const displayWeeklyTemps = () => {
const rotateWeekdays = () => {
const today = new Date(); /* Gets today */
const todayIndex = today.getDay(); /* Gets index of today. 0 = sunday */
const rotated = weekDays.slice(todayIndex).concat(weekDays.slice(0, todayIndex));
return rotated;
};
const rotatedWeekdays = rotateWeekdays();
weatherForecast = {
firstDay: data.timeSeries[0].data.air_temperature,
secondDay: data.timeSeries[25].data.air_temperature,
thirdDay: data.timeSeries[49].data.air_temperature,
fourthDay: data.timeSeries[55].data.air_temperature,
fifthDay: data.timeSeries[59].data.air_temperature,
sixthDay: data.timeSeries[63].data.air_temperature,
seventhDay: data.timeSeries[67].data.air_temperature
};
const labels = rotatedWeekdays.map((day, i) => {
if (i === 0)
return "Today";
return day;
});
weeklyTempContainer.innerHTML = `
<div id="mondayTemp">
<p>${labels[0]}</p>
<p>${weatherForecast.firstDay}°</p>
</div>

<div id="tuesdayTemp">
<p>${labels[1]}</p>
<p>${weatherForecast.secondDay}°</p>
</div>

<div id="wednesdayTemp">
<p>${labels[2]}</p>
<p>${weatherForecast.thirdDay}°</p>
</div>

<div id="thursdayTemp">
<p>${labels[3]}</p>
<p>${weatherForecast.fourthDay}°</p>
</div>

<div id="fridayTemp">
<p>${labels[4]}</p>
<p>${weatherForecast.fifthDay}°</p>
</div>

<div id="saturdayTemp">
<p>${labels[5]}</p>
<p>${weatherForecast.sixthDay}°</p>
</div>

<div id="sundayTemp">
<p>${labels[6]}</p>
<p>${weatherForecast.seventhDay}°</p>
</div>
`;
};
Loading