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
136 changes: 0 additions & 136 deletions .gitignore

This file was deleted.

Binary file added cloudy.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 fog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 88 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,13 +1,98 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple HTML Page</title>
<link rel="stylesheet" href="./style/style.css">
<script src="./src/main.js" defer></script>
<link rel="stylesheet" href="style.css">
<title>Weather Forecast App</title>
</head>

<body>
<div class="box">
<div class="search-row">
<input type="text" id="cityInput" placeholder="Enter city name" />
<button class="search-btn">Search</button>
</div>

<div class="weather-main">
<div class="left-panel">
<div class="location">
<h2 class="city">Kyiv</h2>
<p class="country">Ukraine</p>
</div>

<div class="temp">
<h1>23°C</h1>
<p class="condition">Clear</p>
</div>
</div>

<div class="current-weather-icon">
<img src="sunny.png" alt="sunny">
</div>

<div class="right-panel">
<div class="extra-info">
<p>Wind: 13 km/h</p>
<p>Humidity: 56%</p>
</div>
</div>
</div>

<div class="forecast-carousel">
<div class="forecast-day">
<p>Today</p>
<div class="icon"><img src="sunny.png" alt="sunny"></div>
<p>23°C</p>
<p class="low-temp">14°C</p>
</div>
<div class="forecast-day">
<p>Tue</p>
<div class="icon"><img src="sunny.png" alt="sunny"></div>
<p>23°C</p>
<p class="low-temp">14°C</p>
</div>
<div class="forecast-day">
<p>Wed</p>
<div class="icon"><img src="rainy.png" alt="rainy"></div>
<p>20°C</p>
<p class="low-temp">13°C</p>
</div>
<div class="forecast-day">
<p>Thu</p>
<div class="icon"><img src="sunny.png" alt="sunny"></div>
<p>22°C</p>
<p class="low-temp">13°C</p>
</div>
<!-- додаткові 3 дні -->
<div class="forecast-day">
<p>Fri</p>
<div class="icon"><img src="rainy.png" alt="rainy"></div>
<p>18°C</p>
<p class="low-temp">13°C</p>
</div>
<div class="forecast-day">
<p>Sat</p>
<div class="icon"><img src="cloudy.png" alt="sunny"></div>
<p>20°C</p>
<p class="low-temp">15°C</p>
</div>
<div class="forecast-day">
<p>Sun</p>
<div class="icon"><img src="sunny.png" alt="sunny"></div>
<p>22°C</p>
<p class="low-temp">21°C</p>
</div>
</div>

<div class="report">
<a href="report.html" class="report-backward">View Weather Report</a>
</div>
</div>

<script src="main.js"></script>

</body>

</html>
119 changes: 119 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
const API_KEY = 'FF7ZYNQQ68ZK9BB677FAW6CTX';
const BASE_URL = 'https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/';

const searchBtn = document.querySelector('.search-btn');
const cityInput = document.getElementById('cityInput');
const cityElem = document.querySelector('.city');
const countryElem = document.querySelector('.country');
const tempElem = document.querySelector('.temp h1');
const conditionElem = document.querySelector('.condition');
const windElem = document.querySelector('.extra-info p:nth-child(1)');
const humidityElem = document.querySelector('.extra-info p:nth-child(2)');
const forecastCarousel = document.querySelector('.forecast-carousel');
const weatherIcon = document.querySelector('.current-weather-icon img');

// Створення та приховування попапу
const popup = document.createElement('div');
popup.classList.add('popup');
document.body.appendChild(popup);
popup.style.display = 'none';

async function fetchWeather(city) {
const url = `${BASE_URL}${city}?unitGroup=metric&key=${API_KEY}&contentType=json&include=days`;

// Відправляється асинхронний запит на сервер, отримується відповідь і перетворюється в об'єкт JSON.
const res = await fetch(url);
const data = await res.json();
forecastData = data.days.slice(0, 10); // Зберігається тільки перших 10 днів прогнозу

// Збереження прогнозу і назви міста
localStorage.setItem('weatherForecast', JSON.stringify(forecastData));
localStorage.setItem('forecastCity', data.resolvedAddress);

updateMainWeather(data);
updateForecast();
}

function updateMainWeather(data, dayIndex = 0) {
const day = forecastData[dayIndex]; // Вибирається день (за замовчуванням -- сьогодні)
cityElem.textContent = data.resolvedAddress.split(',')[0];
countryElem.textContent = data.resolvedAddress.split(',')[1]?.trim() || '';
tempElem.textContent = `${Math.round(day.temp)}°C`;
conditionElem.textContent = day.conditions;
windElem.textContent = `Wind: ${day.windspeed} km/h`;
humidityElem.textContent = `Humidity: ${day.humidity}%`;
weatherIcon.src = getIcon(day.icon);
}

function updateForecast() {
forecastCarousel.innerHTML = '';
forecastData.forEach((day, index) => {
const forecastDay = document.createElement('div');
forecastDay.classList.add('forecast-day');
forecastDay.innerHTML = `
<p>${index === 0 ? 'Today' : new Date(day.datetime).toLocaleDateString('en-US', { weekday: 'short' })}</p>
<div class="icon"><img src="${getIcon(day.icon)}" alt="${day.icon}"></div>
<p class="temp-click" data-index="${index}">${Math.round(day.temp)}°C</p>
<p class="low-temp">${Math.round(day.tempmin)}°C</p>
`;

// Оновлює головну панель з погодою на вибраний день
forecastDay.addEventListener('click', () => {
updateMainWeather({ resolvedAddress: `${cityElem.textContent}, ${countryElem.textContent}` }, index);
});

// Клік по температурі відкриває попап з деталями дня
forecastDay.querySelector('.temp-click').addEventListener('click', (e) => {
e.stopPropagation();
const idx = e.target.dataset.index;
showPopup(forecastData[idx]);
});

forecastCarousel.appendChild(forecastDay);
});
}

function getIcon(condition) {
const icons = {
'clear-day': 'sunny.png',
'rain': 'rainy.png',
'cloudy': 'cloudy.png',
'partly-cloudy-day': 'cloudy.png',
'snow': 'snow.png',
'fog': 'fog.png',
'wind': 'windy.png'
};
return icons[condition] || 'sunny.png';
}

// Відображення попапу з деталями про день
function showPopup(day) {
popup.innerHTML = `
<div class="popup-content">
<h3>Details for ${day.datetime}</h3>
<p>Conditions: ${day.conditions}</p>
<p>Max Temp: ${day.tempmax}°C</p>
<p>Min Temp: ${day.tempmin}°C</p>
<p>Humidity: ${day.humidity}%</p>
<p>Wind: ${day.windspeed} km/h</p>
<p>UV Index: ${day.uvindex}</p>
<button class="popup-content-btn" onclick="document.querySelector('.popup').style.display='none'">Close</button>
</div>
`;
popup.style.display = 'block';
}

searchBtn.addEventListener('click', () => {
const city = cityInput.value.trim();
if (city) fetchWeather(city);
});

cityInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter'){
const city = cityInput.value.trim();
if (city) fetchWeather(city);
}
});

// Load default city
fetchWeather('Kyiv');
Binary file added rainy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading