andrewammann commited on
Commit
747692d
·
verified ·
1 Parent(s): f47732d

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +240 -18
index.html CHANGED
@@ -1,19 +1,241 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Weather Dashboard</title>
7
+ <!-- Bootstrap CSS for styling -->
8
+ <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
+ <!-- Leaflet CSS for map -->
10
+ <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
11
+ <style>
12
+ body {
13
+ background-color: #f4f6fa;
14
+ font-family: Arial, sans-serif;
15
+ }
16
+ .header {
17
+ text-align: center;
18
+ padding: 20px;
19
+ background-color: #007bff;
20
+ color: white;
21
+ border-radius: 8px;
22
+ margin-bottom: 20px;
23
+ }
24
+ .metric-card {
25
+ background-color: #ffffff;
26
+ padding: 15px;
27
+ border-radius: 8px;
28
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
29
+ text-align: center;
30
+ margin-bottom: 15px;
31
+ }
32
+ #map {
33
+ height: 400px;
34
+ border-radius: 8px;
35
+ margin-bottom: 20px;
36
+ }
37
+ .footer {
38
+ font-size: 12px;
39
+ text-align: center;
40
+ margin-top: 30px;
41
+ padding: 15px;
42
+ background-color: #e9ecef;
43
+ border-radius: 8px;
44
+ }
45
+ .city-section {
46
+ margin-bottom: 20px;
47
+ }
48
+ .weather-table {
49
+ width: 100%;
50
+ border-collapse: collapse;
51
+ }
52
+ .weather-table th, .weather-table td {
53
+ border: 1px solid #dee2e6;
54
+ padding: 8px;
55
+ text-align: center;
56
+ }
57
+ .weather-table th {
58
+ background-color: #f8f9fa;
59
+ }
60
+ </style>
61
+ </head>
62
+ <body>
63
+ <!-- Header -->
64
+ <div class="header">
65
+ <h1>🌍 Global Weather Dashboard</h1>
66
+ <p>Powered by Open-Meteo API</p>
67
+ <img src="https://via.placeholder.com/100x50.png?text=Logo" alt="Logo" style="margin-top: 10px;">
68
+ </div>
69
+
70
+ <!-- Main Content -->
71
+ <div class="container">
72
+ <!-- Input Form -->
73
+ <div class="row mb-4">
74
+ <div class="col-md-6">
75
+ <label for="cityInput" class="form-label">Enter city names (comma-separated):</label>
76
+ <input type="text" class="form-control" id="cityInput" placeholder="e.g., New York, London, Tokyo" value="New York, London, Tokyo">
77
+ </div>
78
+ <div class="col-md-3">
79
+ <label for="citySelect" class="form-label">Or select a city:</label>
80
+ <select class="form-select" id="citySelect">
81
+ <option value="">Select a city</option>
82
+ <option value="New York">New York</option>
83
+ <option value="London">London</option>
84
+ <option value="Tokyo">Tokyo</option>
85
+ <option value="Sydney">Sydney</option>
86
+ <option value="Paris">Paris</option>
87
+ <option value="Dubai">Dubai</option>
88
+ <option value="Singapore">Singapore</option>
89
+ </select>
90
+ </div>
91
+ <div class="col-md-3 align-self-end">
92
+ <button class="btn btn-primary w-100" onclick="fetchWeather()">Fetch Weather</button>
93
+ </div>
94
+ </div>
95
+
96
+ <!-- Map -->
97
+ <h3>City Locations</h3>
98
+ <div id="map"></div>
99
+
100
+ <!-- Weather Data -->
101
+ <div id="weatherData"></div>
102
+ </div>
103
+
104
+ <!-- Footer -->
105
+ <div class="footer">
106
+ <p>Weather data by <a href="https://open-meteo.com" target="_blank">Open-Meteo.com</a> under <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank">CC BY 4.0</a> |
107
+ For non-commercial use only |
108
+ <a href="https://github.com/open-meteo/open-meteo" target="_blank">Source Code</a> |
109
+ Contact: <a href="mailto:[email protected]">[email protected]</a></p>
110
+ </div>
111
+
112
+ <!-- Scripts -->
113
+ <!-- Leaflet JS for map -->
114
+ <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
115
+ <script>
116
+ // Weather code to icon mapping
117
+ const weatherIcons = {
118
+ 0: "☀️", 1: "🌤️", 2: "⛅", 3: "☁️", 61: "🌧️", 71: "❄️"
119
+ };
120
+
121
+ // Initialize Leaflet map
122
+ const map = L.map('map').setView([0, 0], 2);
123
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
124
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
125
+ }).addTo(map);
126
+
127
+ // Fetch weather data
128
+ async function fetchWeather() {
129
+ const cityInput = document.getElementById('cityInput').value;
130
+ const citySelect = document.getElementById('citySelect').value;
131
+ let cities = citySelect ? [citySelect] : cityInput.split(',').map(city => city.trim()).filter(city => city);
132
+ cities = [...new Set(cities)]; // Remove duplicates
133
+
134
+ if (cities.length === 0) {
135
+ alert("Please enter or select at least one city.");
136
+ return;
137
+ }
138
+
139
+ const weatherDataDiv = document.getElementById('weatherData');
140
+ weatherDataDiv.innerHTML = '<p>Loading weather data...</p>';
141
+ const coordinates = [];
142
+
143
+ // Clear existing markers
144
+ map.eachLayer(layer => {
145
+ if (layer instanceof L.Marker) map.removeLayer(layer);
146
+ });
147
+
148
+ for (const city of cities) {
149
+ try {
150
+ // Fetch coordinates
151
+ const geoUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(city)}&count=1&language=en&format=json`;
152
+ const geoResponse = await fetch(geoUrl);
153
+ const geoData = await geoResponse.json();
154
+
155
+ if (geoData.results && geoData.results.length > 0) {
156
+ const { latitude, longitude, country, timezone } = geoData.results[0];
157
+ coordinates.push({ city, lat: latitude, lon: longitude, country, timezone });
158
+
159
+ // Fetch weather data
160
+ const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=temperature_2m_max,temperature_2m_min,precipitation_probability_mean,weathercode&current_weather=true&temperature_unit=fahrenheit&timezone=auto`;
161
+ const weatherResponse = await fetch(weatherUrl);
162
+ const weatherData = await weatherResponse.json();
163
+
164
+ // Add marker to map
165
+ L.marker([latitude, longitude])
166
+ .addTo(map)
167
+ .bindPopup(`<b>${city}</b><br>Temp: ${weatherData.current_weather.temperature}°F<br>Country: ${country}`);
168
+
169
+ // Render weather data
170
+ const current = weatherData.current_weather;
171
+ const daily = weatherData.daily;
172
+ const localTime = new Date().toLocaleString('en-US', { timeZone: timezone });
173
+
174
+ let html = `
175
+ <div class="city-section">
176
+ <h4>🌆 Weather for ${city}</h4>
177
+ <p>📍 ${city}, ${country} (Lat: ${latitude.toFixed(2)}, Lon: ${longitude.toFixed(2)})</p>
178
+ <p>🕒 Local Time: ${localTime}</p>
179
+ <h5>Current Weather</h5>
180
+ <div class="row">
181
+ <div class="col-md-4">
182
+ <div class="metric-card">
183
+ <p><strong>Temperature</strong></p>
184
+ <p>${current.temperature} °F</p>
185
+ </div>
186
+ </div>
187
+ <div class="col-md-4">
188
+ <div class="metric-card">
189
+ <p><strong>Wind Speed</strong></p>
190
+ <p>${current.windspeed} km/h</p>
191
+ </div>
192
+ </div>
193
+ <div class="col-md-4">
194
+ <div class="metric-card">
195
+ <p><strong>Condition</strong></p>
196
+ <p>${weatherIcons[current.weathercode] || '🌫️'} ${current.weathercode}</p>
197
+ </div>
198
+ </div>
199
+ </div>
200
+ <h5>7-Day Forecast</h5>
201
+ <table class="weather-table">
202
+ <tr>
203
+ <th>Date</th>
204
+ <th>Max Temp (°F)</th>
205
+ <th>Min Temp (°F)</th>
206
+ <th>Precipitation Prob (%)</th>
207
+ <th>Condition</th>
208
+ </tr>
209
+ `;
210
+
211
+ for (let i = 0; i < daily.time.length; i++) {
212
+ html += `
213
+ <tr>
214
+ <td>${new Date(daily.time[i]).toLocaleDateString()}</td>
215
+ <td>${daily.temperature_2m_max[i].toFixed(1)}</td>
216
+ <td>${daily.temperature_2m_min[i].toFixed(1)}</td>
217
+ <td>${(daily.precipitation_probability_mean[i] * 100).toFixed(0)}</td>
218
+ <td>${weatherIcons[daily.weathercode[i]] || '🌫️'}</td>
219
+ </tr>
220
+ `;
221
+ }
222
+
223
+ html += `</table></div>`;
224
+ weatherDataDiv.innerHTML += html;
225
+ } else {
226
+ weatherDataDiv.innerHTML += `<div class="alert alert-danger">Could not find coordinates for ${city}.</div>`;
227
+ }
228
+ } catch (error) {
229
+ weatherDataDiv.innerHTML += `<div class="alert alert-danger">Error fetching data for ${city}: ${error.message}</div>`;
230
+ }
231
+ }
232
+
233
+ // Adjust map to fit all markers
234
+ if (coordinates.length > 0) {
235
+ const bounds = L.latLngBounds(coordinates.map(c => [c.lat, c.lon]));
236
+ map.fitBounds(bounds, { padding: [50, 50] });
237
+ }
238
+ }
239
+ </script>
240
+ </body>
241
  </html>