diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..6b665aa
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "liveServer.settings.port": 5501
+}
diff --git a/img/close.png b/img/close.png
new file mode 100644
index 0000000..8ed3142
Binary files /dev/null and b/img/close.png differ
diff --git a/img/close1.png b/img/close1.png
new file mode 100644
index 0000000..fd23bce
Binary files /dev/null and b/img/close1.png differ
diff --git a/img/cloudy.png b/img/cloudy.png
new file mode 100644
index 0000000..c6d9d7c
Binary files /dev/null and b/img/cloudy.png differ
diff --git a/img/cloudyBigger.png b/img/cloudyBigger.png
new file mode 100644
index 0000000..4222575
Binary files /dev/null and b/img/cloudyBigger.png differ
diff --git a/img/cloudyBiggest.png b/img/cloudyBiggest.png
new file mode 100644
index 0000000..4ce9402
Binary files /dev/null and b/img/cloudyBiggest.png differ
diff --git a/img/rain.png b/img/rain.png
new file mode 100644
index 0000000..e3e60f3
Binary files /dev/null and b/img/rain.png differ
diff --git a/img/rainBigger.png b/img/rainBigger.png
new file mode 100644
index 0000000..b074b14
Binary files /dev/null and b/img/rainBigger.png differ
diff --git a/img/rainBiggest.png b/img/rainBiggest.png
new file mode 100644
index 0000000..1ddb440
Binary files /dev/null and b/img/rainBiggest.png differ
diff --git a/img/sun.png b/img/sun.png
new file mode 100644
index 0000000..dce795b
Binary files /dev/null and b/img/sun.png differ
diff --git a/img/sunBigger.png b/img/sunBigger.png
new file mode 100644
index 0000000..e33a838
Binary files /dev/null and b/img/sunBigger.png differ
diff --git a/img/sunBiggest.png b/img/sunBiggest.png
new file mode 100644
index 0000000..597a5e1
Binary files /dev/null and b/img/sunBiggest.png differ
diff --git a/index.html b/index.html
index 09c6dc0..b69e00c 100644
--- a/index.html
+++ b/index.html
@@ -1,13 +1,92 @@
-
-
+
+
+
- Simple HTML Page
-
+ Weather app
+
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index e69de29..c7784db 100644
--- a/src/main.js
+++ b/src/main.js
@@ -0,0 +1,208 @@
+let daysData = []
+let currentCity
+let currentAddress
+let isFirstLoad = true
+
+async function loadWeather(city) {
+ const apiKey = '42X3PN2U3BCYZV8FFRWCV3UVA'
+ const resp = await fetch(`https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/${encodeURIComponent(city)}?unitGroup=metric&key=${apiKey}&contentType=json`)
+ if (!resp.ok) {
+ alert('City not found')
+ return
+ }
+ const data = await resp.json()
+ daysData = data.days.slice(0, 10)
+
+ currentCity = data.address
+ currentAddress = data.resolvedAddress
+
+ isFirstLoad = true
+ updateDetailedInfo(0)
+ renderCarousel()
+ console.log(data)
+}
+
+function updateDetailedInfo(index) {
+ const detailedCity = document.querySelector('.detailed-city')
+ const detailedCountry = document.querySelector('.detailed-country')
+ const detailedTemp = document.querySelector('.detailed-temp')
+ const detailedDesc = document.querySelector('.detailed-desc')
+ const windElem = document.querySelector('.wind')
+ const humidityElem = document.querySelector('.humidity')
+ const detailedIcon = document.querySelector('.detailed-icon')
+
+ const day = daysData[index]
+ detailedCity.textContent = currentCity
+ detailedCountry.textContent = currentAddress
+ detailedTemp.textContent = Math.round(day.temp) + '°C'
+ detailedDesc.textContent = day.conditions
+ windElem.textContent = Math.round(day.windspeed) + 'km/h'
+ humidityElem.textContent = day.humidity + '%'
+ createDetailedIconByConditions(day.icon, detailedIcon)
+ setUpPopupListener(index)
+}
+
+function renderCarousel() {
+ const carousel = document.querySelector('.carousel')
+ carousel.innerHTML = ''
+ daysData.forEach((day, index) => {
+ const li = document.createElement('li')
+ li.className = 'carousel-item'
+
+ const title = document.createElement('h5')
+ title.className = 'carousel-title'
+ title.textContent = `${index === 0 ? 'Today' : new Date(day.datetime).toLocaleDateString('en-EN', { weekday: 'short' })}`
+
+ const dateStr = day.datetime
+ const date = new Date(dateStr)
+
+ const formatted = date.toLocaleDateString('en-GB', { day: 'numeric', month: 'short'})
+
+ const subTitle = document.createElement('span')
+ subTitle.className = 'carousel-subtitle'
+ subTitle.textContent = formatted
+
+
+ const icon = document.createElement('picture')
+ icon.className = 'carousel-icon'
+
+ let currentPicture = ''
+ if (day.icon.includes('rain')) currentPicture = 'rain'
+ if (day.icon.includes('cloud')) currentPicture = 'cloudy'
+ if (day.icon.includes('clear')) currentPicture = 'sun'
+
+ const source = document.createElement('source')
+ source.setAttribute('srcset', `./img/${currentPicture}Bigger.png`)
+ source.setAttribute('media', '(min-width: 600px)')
+
+ const img = document.createElement('img')
+ img.setAttribute('src', `./img/${currentPicture}.png`)
+
+ icon.append(source, img)
+
+ const maxTemperature = document.createElement('span')
+ maxTemperature.className = 'max-temp'
+ maxTemperature.textContent = Math.round(day.tempmax) + '°C'
+
+ const minTemperature = document.createElement('span')
+ minTemperature.className = 'min-temp'
+ minTemperature.textContent = Math.round(day.tempmin) + '°C'
+
+ li.append(title, subTitle, icon, maxTemperature, minTemperature)
+
+ li.addEventListener('click', () => {
+ updateDetailedInfo(index)
+ document.querySelectorAll('.carousel-item').forEach(item => { item.classList.remove('current')})
+ li.classList.add('current')
+ })
+
+ carousel.appendChild(li)
+ })
+
+ if (isFirstLoad) {
+ const firstItem = carousel.querySelector('.carousel-item')
+ if (firstItem) {
+ firstItem.classList.add('current')
+ }
+ isFirstLoad = false
+ }
+}
+
+function createDetailedIconByConditions(icon, detailedIcon) {
+ let currentPicture = ''
+ if (icon.includes('rain')) currentPicture = 'rain'
+ if (icon.includes('cloud')) currentPicture = 'cloudy'
+ if (icon.includes('clear')) currentPicture = 'sun'
+
+ detailedIcon.innerHTML =''
+
+ const sourceOne = document.createElement('source')
+ sourceOne.setAttribute('srcset', `./img/${currentPicture}Biggest.png`)
+ sourceOne.setAttribute('media', '(min-width: 600px)')
+
+ const sourceTwo = document.createElement('source')
+ sourceTwo.setAttribute('srcset', `./img/${currentPicture}Bigger.png`)
+
+ const img = document.createElement('img')
+ img.setAttribute('src', `./img/${currentPicture}.png`)
+
+ detailedIcon.append(sourceOne, sourceTwo, img)
+}
+
+const searchInput = document.querySelector('.search-input')
+const searchButton = document.querySelector('.search-button')
+searchButton.addEventListener('click', () => {
+ const value = searchInput.value.trim();
+ if (value !== '') {
+ loadWeather(value)
+ searchInput.value = '';
+ } else {
+ searchInput.focus();
+ }
+})
+searchInput.addEventListener('keydown', (e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ searchButton.click();
+ }
+})
+
+function setUpPopupListener(index) {
+ const detailedTemp = document.querySelector('.detailed-temp')
+ let popup = document.querySelector(".popup")
+ let closePopupButton = document.querySelector(".popup-close")
+ let popupContent = document.querySelector(".popup-content")
+
+ detailedTemp.addEventListener('click', () => {
+ popup.classList.add('popup-active')
+ popupContent.classList.add('popup-content-active')
+ setUpPopupContent(index)
+ })
+
+ closePopupButton.addEventListener('click', () => {
+ popup.classList.remove('popup-active')
+ popupContent.classList.remove('popup-content-active')
+ })
+}
+
+function setUpPopupContent(index) {
+ const popupCity = document.querySelector('.popup-city')
+ const popupDate = document.querySelector('.popup-date')
+ const popupDescription = document.querySelector('.popup-description')
+ const popupMaxTemp = document.querySelector('.max-real')
+ const popupMinTemp = document.querySelector('.min-real')
+ const popupMaxFeel = document.querySelector('.max-feels')
+ const popupMinFeel = document.querySelector('.min-feels')
+ const popupSunrise = document.querySelector('.sunrise')
+ const popupSunset = document.querySelector('.sunset')
+ const popupVisibility = document.querySelector('.visibility')
+ const popupPressure = document.querySelector('.pressure')
+
+ const day = daysData[index]
+
+ popupCity.textContent = currentAddress
+ const dateStr = day.datetime
+ const date = new Date(dateStr)
+
+ const formatted = date.toLocaleDateString('en-GB', { day: 'numeric', month: 'long' })
+ popupDate.textContent = formatted
+ popupDescription.textContent = day.description
+ popupMaxTemp.textContent = Math.round(day.tempmax) + '°C'
+ popupMinTemp.textContent = Math.round(day.tempmin) + '°C'
+ popupMaxFeel.textContent = Math.round(day.feelslikemax) + '°C'
+ popupMinFeel.textContent = Math.round(day.feelslikemin) + '°C'
+ const time = day.sunrise
+ const [hours, minutes] = time.split(":")
+ const shortTime = `${hours}:${minutes}`
+ popupSunrise.textContent = shortTime
+
+ const timeTwo = day.sunset
+ const [hoursTwo, minutesTwo] = timeTwo.split(":")
+ const shortTimeTwo = `${hoursTwo}:${minutesTwo}`
+ popupSunset.textContent = shortTimeTwo
+
+ popupVisibility.textContent = day.visibility + 'km'
+ popupPressure.textContent = day.pressure + 'hPa'
+}
+
+loadWeather('Kyiv')
\ No newline at end of file
diff --git a/style/style.css b/style/style.css
index e69de29..9c96500 100644
--- a/style/style.css
+++ b/style/style.css
@@ -0,0 +1,486 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ font-family: "Montserrat", sans-serif;
+}
+
+a {
+ text-decoration: none;
+}
+
+li {
+ list-style-type: none;
+}
+
+.container {
+ width: 100%;
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ background-color: rgba(238, 239, 238, 255);
+ padding: 20px;
+}
+
+.weather-panel {
+ width: 100%;
+ height: fit-content;
+ display: flex;
+ flex-direction: column;
+ background-color: white;
+ border-radius: 5px;
+}
+
+.search {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 30px;
+}
+
+.search-input {
+ width: 80%;
+ height: 50px;
+ border-radius: 7px;
+ padding: 0 10px;
+ border: 2px solid rgba(245, 245, 246, 255);
+ color: rgba(173, 173, 173, 255);
+ font-size: 18px;
+}
+
+.search-input::placeholder {
+ color: rgba(173, 173, 173, 255);
+}
+
+.search-input:focus {
+ outline: none;
+ border-color: rgba(66, 131, 202, 255);
+}
+
+.search-button {
+ width: 15%;
+ height: 50px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ border-radius: 8px;
+ background-color: rgba(47, 108, 220, 255);
+ color: white;
+ border: none;
+ cursor: pointer;
+ font-size: 20px;
+ padding: 20px 0;
+ position: relative;
+}
+
+.search-button::after {
+ content: attr(data-tooltip);
+ position: absolute;
+ top: -30px;
+ left: 9%;
+ transform: translateY(10px) scale(0.5);
+ background-color: rgba(78, 164, 250, 255);
+ color: white;
+ font-size: 14px;
+ font-weight: bold;
+ padding: 5px 15px;
+ border-radius: 8px;
+ white-space: nowrap;
+ opacity: 0;
+ transition: all 0.3s ease;
+}
+
+.search-button:hover::after {
+ opacity: 1;
+ transform: scale(1);
+}
+
+.search-button:hover {
+ background-color: rgba(30, 90, 170, 255);
+}
+
+.detailed-panel {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0px 30px;
+}
+
+.detailed-info {
+ display: flex;
+ flex-direction: column;
+ align-items: start;
+ gap: 10px;
+}
+
+.detailed-temp{
+ font-size: 40px;
+ font-weight: bold;
+ cursor: pointer;
+}
+
+.detailed-temp:hover {
+ color: rgba(78, 164, 250, 255);
+ transition: color 0.3s ease;
+}
+
+.detailed-city {
+ font-size: 32px;
+}
+
+.detailed-country {
+ font-size: 22px;
+ color: rgba(92, 103, 106, 255);
+}
+
+.detailed-desc{
+ font-size: 20px;
+}
+
+.detailed-extra {
+ font-size: 20px;
+}
+
+.extra{
+ display: flex;
+ flex-direction: column;
+ align-items: end;
+ min-width: 211px;
+}
+
+.carousel {
+ overflow-x: auto;
+ -webkit-overflow-scrolling: touch;
+ scroll-snap-type: x mandatory;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 30px;
+ >li {
+ scroll-snap-align: center;
+ }
+}
+.carousel::-webkit-scrollbar {
+ height: 8px;
+}
+
+.carousel::-webkit-scrollbar-track {
+ background: transparent;
+}
+
+.carousel::-webkit-scrollbar-thumb {
+ background-color: #dcdfe6;
+ border-radius: 8px;
+}
+
+.carousel::-webkit-scrollbar-thumb:hover {
+ background-color: #c0c4cc;
+}
+
+.carousel-item {
+ flex: 1, 1;
+ min-width: 150px;
+ border-radius: 10px;
+ margin-right: 20px;
+ padding: 20px 30px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 10px;
+ border: 1px solid rgba(221, 221, 223, 255);
+ cursor: pointer;
+}
+
+.carousel-item:hover {
+ background-color: rgba(245, 245, 246, 255);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(201, 201, 203, 255);
+}
+
+.current {
+ background-color: rgba(245, 245, 246, 255);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ border: 1px solid rgba(201, 201, 203, 255);
+}
+
+.carousel-item:last-child {
+ margin-right: 0;
+}
+
+.carousel-title {
+ font-size: 26px;
+ font-weight: bold;
+}
+
+.carousel-subtitle {
+ font-size: 22px;
+ color: rgba(92, 103, 106, 255);
+}
+
+.max-temp {
+ font-size: 20px;
+}
+
+.min-temp {
+ font-size: 18px;
+ color: rgba(92, 103, 106, 255);
+}
+
+.popup {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ position: fixed;
+ top: 0;
+ left: 0;
+ height: 100%;
+ width: 100%;
+ background-color: rgba(0, 0, 0, 0.6);
+ visibility: hidden;
+ opacity: 0;
+ transition: all 1s 0s;
+}
+
+.popup-active {
+ visibility: visible;
+ opacity: 1;
+}
+
+.popup-content {
+ background: #FFFFFF;
+ width: 50%;
+ height: 90%;
+ box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.12), 0px 1px 1px rgba(0, 0, 0, 0.14), 0px 2px 1px rgba(0, 0, 0, 0.2);
+ border-radius: 20px;
+ padding: 30px;
+ position: relative;
+ transition: all 1s 0s;
+ opacity: 0;
+ transform: translate(0px, -100%)
+}
+
+.popup-content-active {
+ opacity: 1;
+ transform: translate(0px, 0px)
+}
+
+.popup-close {
+ background-color: white;
+ border-radius: 50%;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ width: 30px;
+ height: 30px;
+ background-image: url('../img/close.png');
+ fill: black;
+ background-position: center;
+ background-repeat: no-repeat;
+ position: absolute;
+ top: 8px;
+ right: 8px;
+ cursor: pointer;
+}
+
+.popup-close:hover {
+ background-image: url('../img/close1.png');
+}
+
+.popup-close:active {
+ transform: scale(1.1);
+}
+
+.popup-information {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 30px;
+}
+
+.popup-city{
+ font-size: 26px;
+ font-weight: bold;
+}
+
+.popup-date {
+ font-size: 24px;
+ color: rgba(92, 103, 106, 255);
+}
+
+.popup-description {
+ font-size: 16px;
+ font-style: italic;
+}
+
+.popup-temp {
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 15px;
+}
+
+.popup-temp-item {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 5px;
+}
+
+.popup-real {
+ font-size: 18px;
+ font-weight: bold;
+}
+
+.popup-feels-like {
+ font-size: 16px;
+ font-weight: bold;
+ font-style: italic;
+ color: rgba(92, 103, 106, 255);
+}
+
+.popup-extra {
+ font-size: 20px;
+}
+
+@media (max-width: 1024px) {
+ .popup-city {
+ font-size: 22px;
+ }
+}
+
+@media (max-width: 900px) {
+ .popup-city {
+ font-size: 18px;
+ }
+
+ .popup-real {
+ font-size: 16px;
+ }
+
+ .popup-feels-like {
+ font-size: 14px;
+ }
+
+ .popup-extra {
+ font-size: 16px;
+ }
+
+ .popup-description {
+ font-size: 14px;
+ }
+
+ .popup-date {
+ font-size: 16px;
+ }
+}
+
+@media (max-width: 768px) {
+ .popup-city {
+ font-size: 16px;
+ }
+}
+
+@media (max-width: 600px) {
+ .search-button {
+ width: 20%;
+ }
+
+ .search-input {
+ width: 75%;
+ }
+
+ .carousel-item {
+ min-width: 100px;
+ }
+
+ .weather-panel .detailed-panel:first-child {
+ margin-bottom: 20px;
+ }
+
+ .popup-real {
+ font-size: 14px;
+ }
+
+ .popup-feels-like {
+ font-size: 12px;
+ }
+
+ .popup-description {
+ font-size: 12px;
+ }
+
+ .popup-date {
+ font-size: 16px;
+ }
+
+ .popup-extra {
+ font-size: 16px;
+ }
+
+ .popup-information {
+ gap: 20px;
+ }
+}
+
+@media (max-width: 500px) {
+ .search-button {
+ font-size: 18px;
+ }
+
+ .extra {
+ margin-top: 20px;
+ align-items: start;
+ }
+}
+
+@media (max-width: 425px) {
+ .search-button {
+ width: 25%;
+ }
+
+ .search-input {
+ width: 70%;
+ }
+
+ .popup-extra {
+ font-size: 14px;
+ }
+}
+
+@media (max-width: 400px) {
+ .detailed-info {
+ align-items: start;
+ }
+
+ .popup-extra {
+ font-size: 12px;
+ }
+}
+
+@media (max-width: 375px) {
+ .search-button {
+ width: 30%;
+ }
+
+ .search-input {
+ width: 65%;
+ }
+
+ .popup-city {
+ font-size: 14px;
+ }
+
+ .popup-date {
+ font-size: 14px;
+ }
+ .popup-real {
+ font-size: 12px;
+ }
+
+ .popup-feels-like {
+ font-size: 10px;
+ }
+}
\ No newline at end of file