-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
151 lines (125 loc) · 5.51 KB
/
Copy pathapp.js
File metadata and controls
151 lines (125 loc) · 5.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// ─────────────────────────────────────────────
// STEP 1: Paste your OpenWeatherMap API key here
// Sign up free at: https://openweathermap.org/api
// ─────────────────────────────────────────────
const API_KEY = '72e9dfa3b2d8270a0e785395a4ad8d65';
// ── State ──
let useFahrenheit = true;
let lastCity = '';
// ── DOM Elements ──
const cityInput = document.getElementById('city-input');
const searchBtn = document.getElementById('search-btn');
const errorMsg = document.getElementById('error-msg');
const weatherContent = document.getElementById('weather-content');
const unitToggle = document.getElementById('unit-toggle');
// ── Helper: convert Kelvin to °F or °C ──
function kelvinTo(kelvin) {
if (useFahrenheit) return Math.round((kelvin - 273.15) * 9/5 + 32) + '°F';
return Math.round(kelvin - 273.15) + '°C';
}
// ── Helper: pick an emoji for the weather condition ──
function getWeatherEmoji(id) {
if (id >= 200 && id < 300) return '⛈️'; // Thunderstorm
if (id >= 300 && id < 400) return '🌦️'; // Drizzle
if (id >= 500 && id < 600) return '🌧️'; // Rain
if (id >= 600 && id < 700) return '❄️'; // Snow
if (id >= 700 && id < 800) return '🌫️'; // Fog/Mist
if (id === 800) return '☀️'; // Clear
if (id > 800) return '⛅'; // Clouds
return '🌡️';
}
// ── Helper: format a date from a Unix timestamp ──
function formatDay(unixTimestamp) {
const days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
const date = new Date(unixTimestamp * 1000);
return days[date.getDay()];
}
// ── Show an error message ──
function showError(msg) {
errorMsg.textContent = msg;
errorMsg.classList.remove('hidden');
weatherContent.classList.add('hidden');
}
// ── Hide error ──
function hideError() {
errorMsg.classList.add('hidden');
}
// ── Main: fetch weather for a city ──
async function fetchWeather(city) {
if (!city.trim()) return;
hideError();
// --- Current Weather ---
const currentUrl = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=${API_KEY}`;
try {
const res = await fetch(currentUrl);
const data = await res.json();
if (data.cod !== 200) {
showError(`City not found: "${city}". Please check the spelling and try again.`);
return;
}
// Display current weather
document.getElementById('city-name').textContent = `${data.name}, ${data.sys.country}`;
document.getElementById('date-desc').textContent = new Date().toLocaleDateString('en-US', { weekday:'long', month:'long', day:'numeric' });
document.getElementById('temperature').textContent = kelvinTo(data.main.temp);
document.getElementById('feels-like').textContent = `Feels like ${kelvinTo(data.main.feels_like)}`;
document.getElementById('humidity').textContent = `${data.main.humidity}%`;
document.getElementById('wind').textContent = `${Math.round(data.wind.speed * 2.237)} mph`;
document.getElementById('condition').textContent = data.weather[0].main;
document.getElementById('weather-icon').textContent = getWeatherEmoji(data.weather[0].id);
lastCity = city;
// Save last city to localStorage so it loads next visit
localStorage.setItem('lastCity', city);
// --- 5-Day Forecast ---
const forecastUrl = `https://api.openweathermap.org/data/2.5/forecast?q=${encodeURIComponent(city)}&appid=${API_KEY}`;
const fRes = await fetch(forecastUrl);
const fData = await fRes.json();
// The forecast returns data every 3 hours — pick one reading per day (noon-ish)
const dailyForecasts = [];
const seenDays = new Set();
for (const item of fData.list) {
const day = formatDay(item.dt);
if (!seenDays.has(day) && dailyForecasts.length < 5) {
seenDays.add(day);
dailyForecasts.push(item);
}
}
// Render forecast cards
const forecastEl = document.getElementById('forecast');
forecastEl.innerHTML = '';
for (const item of dailyForecasts) {
const card = document.createElement('div');
card.className = 'day-card';
card.innerHTML = `
<div class="day-name">${formatDay(item.dt)}</div>
<div class="day-icon">${getWeatherEmoji(item.weather[0].id)}</div>
<div class="day-hi">${kelvinTo(item.main.temp_max)}</div>
<div class="day-lo">${kelvinTo(item.main.temp_min)}</div>
`;
forecastEl.appendChild(card);
}
weatherContent.classList.remove('hidden');
} catch (err) {
showError('Something went wrong. Check your internet connection and try again.');
console.error(err);
}
}
// ── Event: Search button click ──
searchBtn.addEventListener('click', () => {
fetchWeather(cityInput.value);
});
// ── Event: Press Enter in the input ──
cityInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') fetchWeather(cityInput.value);
});
// ── Event: Toggle °F / °C ──
unitToggle.addEventListener('click', () => {
useFahrenheit = !useFahrenheit;
unitToggle.textContent = useFahrenheit ? 'Switch to °C' : 'Switch to °F';
if (lastCity) fetchWeather(lastCity); // Re-fetch to update all displayed temps
});
// ── On page load: restore last searched city ──
const savedCity = localStorage.getItem('lastCity');
if (savedCity) {
cityInput.value = savedCity;
fetchWeather(savedCity);
}