diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..f673a71b7
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "liveServer.settings.port": 5502
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index f8b15f4cb..1872594b3 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,15 @@
# 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.
+This week the project was to create a weather app by using APIs and using different methods to retrieve and convert the data, such as fetch and convert unix time.
## 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 started with adding the HTML and CSS code. Then I moved on to JS where I added the API and console.logged it. Then I moved on to adding the DOM selectors and created the first function to fetch the current weather data and sunset/sunrise time. After this was achived I moved on to converting the sunset/sunrise time. I needed help from chatGPT to achieve this and also how to get the forecast data which was not as straight forward as the current weather data.
+
+Then I also managed to change the background color, color (fonts) and images depending on weather description, for this I used if/if else statements.
+
+If I had more time I would also look into the geolocation API.
## 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://checkthe-weather.netlify.app/
diff --git a/assets/design-1/Group16.png b/assets/design-1/Group16.png
deleted file mode 100644
index c2d0e3f5a..000000000
Binary files a/assets/design-1/Group16.png and /dev/null differ
diff --git a/assets/design-1/Group34.png b/assets/design-1/Group34.png
deleted file mode 100644
index f7e90e552..000000000
Binary files a/assets/design-1/Group34.png and /dev/null differ
diff --git a/assets/design-1/Group36.png b/assets/design-1/Group36.png
deleted file mode 100644
index ce9c147cf..000000000
Binary files a/assets/design-1/Group36.png and /dev/null differ
diff --git a/assets/design-1/Group37.png b/assets/design-1/Group37.png
deleted file mode 100644
index ce9c147cf..000000000
Binary files a/assets/design-1/Group37.png and /dev/null differ
diff --git a/assets/design-1/Group38.png b/assets/design-1/Group38.png
deleted file mode 100644
index ce9c147cf..000000000
Binary files a/assets/design-1/Group38.png and /dev/null differ
diff --git a/assets/design-2/moonlight.png b/assets/design-2/moonlight.png
new file mode 100644
index 000000000..f2a534b40
Binary files /dev/null and b/assets/design-2/moonlight.png differ
diff --git a/assets/design-2/noun_Cloud_1188486.svg b/assets/design-2/noun_Cloud.svg
similarity index 100%
rename from assets/design-2/noun_Cloud_1188486.svg
rename to assets/design-2/noun_Cloud.svg
diff --git a/assets/design-2/noun_Sunglasses_2055147.svg b/assets/design-2/noun_Sunglasses.svg
similarity index 100%
rename from assets/design-2/noun_Sunglasses_2055147.svg
rename to assets/design-2/noun_Sunglasses.svg
diff --git a/assets/design-2/noun_Umbrella_2030530.svg b/assets/design-2/noun_Umbrella.svg
similarity index 100%
rename from assets/design-2/noun_Umbrella_2030530.svg
rename to assets/design-2/noun_Umbrella.svg
diff --git a/assets/design-2/sad-face-3.svg b/assets/design-2/sad-face-3.svg
new file mode 100644
index 000000000..d2580c2b6
--- /dev/null
+++ b/assets/design-2/sad-face-3.svg
@@ -0,0 +1,65 @@
+
\ No newline at end of file
diff --git a/assets/design-2/scattered.svg b/assets/design-2/scattered.svg
new file mode 100644
index 000000000..6adaa8f7d
--- /dev/null
+++ b/assets/design-2/scattered.svg
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/assets/design-2/snow.png b/assets/design-2/snow.png
new file mode 100644
index 000000000..0fe0e7fe8
Binary files /dev/null and b/assets/design-2/snow.png differ
diff --git a/assets/design-2/sunset.png b/assets/design-2/sunset.png
new file mode 100644
index 000000000..2b2f0dee4
Binary files /dev/null and b/assets/design-2/sunset.png differ
diff --git a/assets/design-2/sunset.svg b/assets/design-2/sunset.svg
new file mode 100644
index 000000000..b26b0e006
--- /dev/null
+++ b/assets/design-2/sunset.svg
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/assets/design-2/thunderstorm.png b/assets/design-2/thunderstorm.png
new file mode 100644
index 000000000..39f26f149
Binary files /dev/null and b/assets/design-2/thunderstorm.png differ
diff --git a/index.html b/index.html
new file mode 100644
index 000000000..3298e4135
--- /dev/null
+++ b/index.html
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+ Weather or Not
+
+
+
+
+ Check the Weather
+
+
+
+
+
+
+
+
|
+
+
+
+
+
sunrise
+
sunset
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/instructions.md b/instructions.md
index 42fc411ce..c8abf96ca 100644
--- a/instructions.md
+++ b/instructions.md
@@ -1,5 +1,5 @@
# Instructions
-Start out with signing up for a [free Open Weather Map](https://home.openweathermap.org/users/sign_up "free Open Weather Map") account, as it can take up to a few hours for the API key to be activated.
+Start out with signing up for a [free Open Weather Map]( "free Open Weather Map") account, as it can take up to a few hours for the API key to be activated.
## Step by step instructions
### Step 1 - Get started with the weather API
diff --git a/script.js b/script.js
new file mode 100644
index 000000000..4dd7cf27c
--- /dev/null
+++ b/script.js
@@ -0,0 +1,215 @@
+// True constants (SNAKECASE)
+const API_KEY = "ea9a90c62aeaaa3811505087d195520e"
+const BASE_URL = "https://api.openweathermap.org/data/2.5/weather?q="
+const FORECAST_BASE_URL = "https://api.openweathermap.org/data/2.5/forecast?q="
+
+let city = "Stockholm" // Dynamic city variable
+
+// DOM Selectors
+const temperatureDisplay = document.getElementById("temperature")
+const conditionDisplay = document.getElementById("condition")
+const sunriseDisplay = document.getElementById("sunriseTime")
+const sunsetDisplay = document.getElementById("sunsetTime")
+const weatherImg = document.getElementById("weatherImage")
+const weatherMsg = document.getElementById("weatherMessage")
+const forecastList = document.getElementById("forecastList")
+const searchButton = document.getElementById("searchButton")
+const cityInput = document.getElementById("cityInput")
+
+// Function to fetch weather data
+const fetchWeatherData = () => {
+ const URL = `${BASE_URL}${city}&units=metric&APPID=${API_KEY}`
+ const FORECAST_URL = `${FORECAST_BASE_URL}${city}&units=metric&APPID=${API_KEY}`
+
+ // Fetch current weather data
+ fetch(URL)
+ .then(response => response.json())
+ .then(data => {
+ if (!data || data.cod !== 200) {
+ throw new Error("City not found")
+ }
+ const stockholmTemp = data.main.temp
+ const weatherCondition = data.weather[0].description
+ const roundedTemp = Math.round(stockholmTemp)
+ const sunrise = data.sys.sunrise
+ const sunset = data.sys.sunset
+ const timezoneOffset = data.timezone // Timezone offset in seconds
+
+ temperatureDisplay.innerText = `${roundedTemp}°C`
+ conditionDisplay.innerText = `${weatherCondition}`
+
+ // Convert and display sunrise and sunset times with timezone offset
+ const sunriseTime = convertUnixToTime(sunrise, timezoneOffset)
+ const sunsetTime = convertUnixToTime(sunset, timezoneOffset)
+ sunriseDisplay.innerText = `${sunriseTime}`
+ sunsetDisplay.innerText = `${sunsetTime}`
+
+ updateUI(roundedTemp, weatherCondition, sunset)
+ })
+ .catch(error => {
+ console.error("Error fetching weather data:", error)
+ })
+
+ // Fetch 5-day forecast data
+ fetch(FORECAST_URL)
+ .then(response => response.json())
+ .then(forecastData => {
+ forecastList.innerHTML = ""
+ const today = new Date()
+
+ // Loop through the next 5 days
+ for (let i = 1; i <= 5; i++) {
+ const forecastDate = new Date(today)
+ forecastDate.setDate(today.getDate() + i)
+ const forecastDateString = forecastDate.toISOString().split("T")[0]
+
+ // Filter forecasts for this specific date
+ const dailyForecasts = forecastData.list.filter(item => {
+ const itemDate = new Date(item.dt * 1000).toISOString().split("T")[0]
+ return itemDate === forecastDateString
+ })
+
+ if (dailyForecasts.length > 0) {
+ // Initialize min and max temperature variables
+ let minTemp = Infinity
+ let maxTemp = -Infinity
+
+ // Calculate min and max temperatures for the day
+ dailyForecasts.forEach(item => {
+ const temp = Math.round(item.main.temp)
+ if (temp < minTemp) {
+ minTemp = temp
+ }
+ if (temp > maxTemp) {
+ maxTemp = temp
+ }
+ })
+
+ const weekDay = forecastDate.toLocaleDateString("en-US", {
+ weekday: "long",
+ })
+ const listItem = document.createElement("li")
+ listItem.innerHTML = `${weekDay} ${minTemp} / ${maxTemp}°C`
+ forecastList.appendChild(listItem)
+ }
+ }
+ })
+ .catch(error => {
+ console.error("Error fetching forecast data:", error)
+ })
+}
+
+// Function to convert UNIX timestamp to readable time format (24-hour clock)
+const convertUnixToTime = (unixTimestamp, timezoneOffset) => {
+ const date = new Date((unixTimestamp + timezoneOffset) * 1000)
+ const hours = date.getUTCHours()
+ const minutes = String(date.getUTCMinutes()).padStart(2, "0")
+ return `${hours}:${minutes}`
+}
+
+// Initial fetch for the default city
+fetchWeatherData()
+
+// Event listener for the search button
+searchButton.addEventListener("click", () => {
+ city = cityInput.value.trim() // Update city variable with input value
+ if (city) {
+ city = capitalizeCityName(city) // Capitalize the first letter of each word
+ fetchWeatherData() // Fetch new weather data for the entered city
+ }
+})
+
+// Event listener for the Enter key in the input field
+cityInput.addEventListener("keypress", (event) => {
+ if (event.key === "Enter") {
+ // Check if the pressed key is Enter
+ city = cityInput.value.trim()
+ if (city) {
+ city = capitalizeCityName(city) // Capitalize the first letter of each word
+ searchButton.click() // Trigger the click event of the search button
+ searchButton.click() // Trigger the click event of the search button
+ }
+ }
+})
+
+// Arrow function to capitalize the first letter of each word in the city name
+const capitalizeCityName = (city) => {
+ return city
+ .split(" ") // Split the city name into an array of words
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) // Capitalize the first letter of each word
+ .join(" ") // Join the words back into a single string
+}
+
+const updateUI = (temperature, weatherDescription, sunsetTime) => {
+ const weatherContainer = document.getElementById("weatherContainer")
+ const searchButton = document.getElementById("searchButton")
+ const currentTime = new Date() // Get the current time
+ const sunset = new Date(sunsetTime * 1000) // Convert sunset time to Date object
+ let weatherMessage // Variable to store the weather message
+
+ // Check if it's after sunset
+ if (currentTime > sunset) {
+ // Night styling
+ weatherContainer.style.backgroundColor = "#001f3f" // Dark blue for night
+ weatherContainer.style.color = "#ffffff" // White text
+ searchButton.style.backgroundColor = "#164A68" // Light blue button color
+ weatherImg.src = "assets/design-2/moonlight.png" // Moon image for night
+ weatherMessage = `It's ${weatherDescription} in ${city}. Enjoy the evening and have a good night!`
+
+ } else {
+ // Update background and text color based on weather condition
+ if (
+ weatherDescription.toLowerCase().includes("rain") ||
+ weatherDescription.toLowerCase().includes("drizzle") ||
+ weatherDescription.toLowerCase().includes("mist")
+ ) {
+ weatherContainer.style.backgroundColor = "#BDE8FA" // Blue for rain
+ weatherContainer.style.color = "#164A68" // Rainy font color
+ searchButton.style.backgroundColor = "#164A68"
+ weatherImg.src = "assets/design-2/noun_Umbrella.svg"
+ weatherMessage = `Don’t forget your umbrella. It’s wet in ${city} today.`
+
+ } else if (weatherDescription.toLowerCase().includes("few clouds")) {
+ weatherContainer.style.backgroundColor = "#F7E9B9" // Yellow for few clouds
+ weatherContainer.style.color = "#2A5510" // Green font color
+ searchButton.style.backgroundColor = "#2A5510"
+ weatherImg.src = "assets/design-2/noun_Sunglasses.svg"
+ weatherMessage = `Get your sunnies on. There are a few clouds, but it's still a lovely day in ${city}.`
+
+ } else if (weatherDescription.toLowerCase().includes("scattered clouds")) {
+ weatherContainer.style.backgroundColor = "#F7E9B9" // Yellow for scattered clouds
+ weatherContainer.style.color = "#2A5510" // Green font color
+ searchButton.style.backgroundColor = "#2A5510"
+ weatherImg.src = "assets/design-2/noun_cloud.svg"
+ weatherMessage = `There are some scattered clouds, but it's still a lovely day in ${city}.`
+
+ } else if (weatherDescription.toLowerCase().includes("clear")) {
+ weatherContainer.style.backgroundColor = "#F7E9B9" // Yellow for clear sky
+ weatherContainer.style.color = "#2A5510" // Green font color
+ searchButton.style.backgroundColor = "#2A5510"
+ weatherImg.src = "assets/design-2/noun_Sunglasses.svg"
+ weatherMessage = `Get your sunnies on. ${city} is looking rather great today.`
+
+ } else if (
+ weatherDescription.toLowerCase().includes("clouds") ||
+ weatherDescription.toLowerCase().includes("fog") ||
+ weatherDescription.toLowerCase().includes("haze")
+ ) {
+ weatherContainer.style.backgroundColor = "#FFFFFF" // White for cloudy
+ weatherContainer.style.color = "#F47775" // Orange font color
+ searchButton.style.backgroundColor = "#F47775"
+ weatherImg.src = "assets/design-2/noun_Cloud.svg"
+ weatherMessage = `Light a fire and get cosy. ${city} is looking grey today.`
+
+ } else if (weatherDescription.toLowerCase().includes("snow")) {
+ weatherContainer.style.backgroundColor = "#BDE8FA" // Blue for snow
+ weatherContainer.style.color = "#164A68" // Blue font color
+ searchButton.style.backgroundColor = "#164A68"
+ weatherImg.src = "assets/design-2/snow.png"
+ weatherMessage = `Wrap up warm! It's snowy in ${city}.`
+ }
+ }
+
+ // Update the DOM elements with weather message and image
+ weatherMsg.innerHTML = weatherMessage
+}
diff --git a/style.css b/style.css
new file mode 100644
index 000000000..c3ab6043d
--- /dev/null
+++ b/style.css
@@ -0,0 +1,196 @@
+body {
+ font-family: Montserrat;
+ height: 100%;
+}
+
+.weather-container {
+ display: flex;
+ flex-direction: column;
+ /* Stack items vertically */
+ justify-content: flex-start;
+ align-items: flex-start;
+ /* Align items to the left */
+ padding-top: 50px;
+ min-height: 100vh;
+ /* Ensure it takes up the full height of the viewport */
+ padding-left: 10px;
+ /* Optional: padding to the left for overall container */
+ overflow-x: hidden;
+
+}
+
+/* Container for condition and temperature */
+.temperature-info {
+ display: flex;
+ justify-content: flex-start;
+ /* Align temperature info to the left */
+ align-items: center;
+ font-size: 24px;
+ font-weight: 400;
+ line-height: 25.6px;
+ margin-bottom: 10px;
+ /* Optional spacing */
+}
+
+.temperature-info p {
+ margin: 0 5px;
+}
+
+/* Container for sunrise and sunset */
+.sun-times {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ /* Align sunrise/sunset to the left */
+ font-size: 24px;
+ font-weight: 400;
+ margin-bottom: 20px;
+ /* Space before other weather details */
+ line-height: 25.6px;
+}
+
+.sun-times p {
+ margin: 0 5px;
+ /* Adjust spacing between sunrise and sunset */
+}
+
+.weather-img {
+ margin-top: 30px;
+ max-width: 100%;
+ /* Ensure image doesn't exceed container width */
+ height: auto;
+ /* Maintain aspect ratio */
+
+}
+
+.weather-message {
+ font-family: Montserrat;
+ font-size: 37px;
+ font-weight: 700;
+ line-height: 45.1px;
+ text-align: left;
+ padding-right: 10px;
+}
+
+.forecast-wrapper {
+ display: flex;
+ flex-direction: column;
+ /* Stack items vertically */
+ justify-content: flex-start;
+ align-items: flex-start;
+ /* Align items to the left */
+ position: relative;
+ /* Optional: Positioning context for child elements */
+}
+
+#forecastList {
+ list-style-type: none;
+ /* Remove default list styling */
+ padding: 0;
+ /* Remove default padding */
+ margin: 0;
+ /* Remove default margin */
+ font-size: 21px;
+ line-height: 36px;
+ gap: 20px
+}
+
+li {
+ display: flex;
+ width: 290px;
+ justify-content: space-between;
+ font-size: 20px;
+ line-height: 1.6;
+}
+
+.weekday {
+ width: 100px;
+ /* Set a fixed width for all weekday names */
+}
+
+.min-max {
+ display: flex;
+}
+
+.min-temp {
+ margin-left: 10px;
+}
+
+.max-temp {
+ margin-right: 5px;
+}
+
+#searchContainer {
+ display: flex;
+ /* Align items horizontally */
+ justify-content: flex-start;
+ /* Align items to the left */
+ align-items: center;
+ /* Vertically center the items */
+ padding-top: 20px;
+ padding-bottom: 20px;
+}
+
+label {
+ font-size: 18px;
+ margin-right: 15px;
+ /* Space between the label and input */
+}
+
+#cityInput {
+ padding: 8px;
+ /* Padding for the input field */
+ border: 1px solid #ccc;
+ /* Border around the input field */
+ border-radius: 4px;
+ /* Rounded corners */
+ margin-right: 5px;
+ /* Space between the input and search button */
+ font-family: Montserrat;
+ font-weight: 500;
+ font-size: 16px;
+}
+
+#searchButton {
+ padding: 10px 12px;
+ /* Padding for the search button */
+ color: white;
+ border: none;
+ border-radius: 4px;
+ /* Rounded corners for the button */
+ cursor: pointer;
+ /* Pointer cursor on hover */
+ font-family: Montserrat;
+ flex-shrink: 0;
+}
+
+/* Media Queries */
+
+/* Apply centering only on desktop screens */
+@media (min-width: 768px) {
+ .weather-container {
+ align-items: center;
+ /* Center horizontally */
+ }
+
+ .temperature-info,
+ .sun-times,
+ .weather-message,
+ .forecast-wrapper {
+ text-align: left;
+ /* Keep content left-aligned */
+ width: 100%;
+ max-width: 600px;
+ /* Limit width on large screens */
+ }
+}
+
+@media (min-width: 768px) {
+ .weather-img {
+ max-width: 300px;
+ /* Limit max width for desktop */
+ height: auto;
+ /* Maintain aspect ratio */
+ margin-top: 30px;
+ }
+}
\ No newline at end of file