|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>Tashkent 30-Day Weather Dashboard</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
<style> |
|
|
.weather-card:hover { |
|
|
transform: translateY(-5px); |
|
|
box-shadow: 0 10px 20px rgba(0,0,0,0.1); |
|
|
} |
|
|
.scroll-container { |
|
|
scrollbar-width: thin; |
|
|
scrollbar-color: #3b82f6 #f1f1f1; |
|
|
} |
|
|
.scroll-container::-webkit-scrollbar { |
|
|
height: 8px; |
|
|
} |
|
|
.scroll-container::-webkit-scrollbar-track { |
|
|
background: #f1f1f1; |
|
|
border-radius: 10px; |
|
|
} |
|
|
.scroll-container::-webkit-scrollbar-thumb { |
|
|
background-color: #3b82f6; |
|
|
border-radius: 10px; |
|
|
} |
|
|
.animate-pulse { |
|
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; |
|
|
} |
|
|
@keyframes pulse { |
|
|
0%, 100% { |
|
|
opacity: 1; |
|
|
} |
|
|
50% { |
|
|
opacity: 0.5; |
|
|
} |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-gradient-to-br from-blue-50 to-indigo-100 min-h-screen"> |
|
|
<div class="container mx-auto px-4 py-8"> |
|
|
|
|
|
<header class="mb-8 text-center"> |
|
|
<h1 class="text-3xl md:text-4xl font-bold text-gray-800 mb-2">Tashkent Weather Dashboard</h1> |
|
|
<p class="text-lg text-gray-600">30-Day Weather Forecast</p> |
|
|
<div class="flex justify-center items-center mt-4"> |
|
|
<div class="relative w-full max-w-md"> |
|
|
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none"> |
|
|
<i class="fas fa-map-marker-alt text-gray-400"></i> |
|
|
</div> |
|
|
<input type="text" id="location" class="bg-white border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full pl-10 p-2.5" value="Tashkent, Uzbekistan" readonly> |
|
|
</div> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl shadow-lg p-6 mb-8"> |
|
|
<div class="flex flex-col md:flex-row justify-between items-center"> |
|
|
<div class="flex items-center mb-4 md:mb-0"> |
|
|
<div class="text-5xl mr-4"> |
|
|
<i class="fas fa-sun text-yellow-400"></i> |
|
|
</div> |
|
|
<div> |
|
|
<h2 class="text-2xl font-semibold text-gray-800">Today</h2> |
|
|
<p class="text-gray-600" id="current-date">Loading date...</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="text-center md:text-right"> |
|
|
<div class="text-4xl font-bold text-gray-800 mb-1" id="current-temp">--°C</div> |
|
|
<div class="text-gray-600" id="current-condition">Loading...</div> |
|
|
<div class="flex justify-center md:justify-end space-x-4 mt-2"> |
|
|
<div class="flex items-center"> |
|
|
<i class="fas fa-temperature-high text-red-400 mr-1"></i> |
|
|
<span id="current-high">--°</span> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<i class="fas fa-temperature-low text-blue-400 mr-1"></i> |
|
|
<span id="current-low">--°</span> |
|
|
</div> |
|
|
<div class="flex items-center"> |
|
|
<i class="fas fa-wind text-gray-400 mr-1"></i> |
|
|
<span id="current-wind">-- km/h</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-8"> |
|
|
<div class="bg-white rounded-xl shadow p-4 flex items-center"> |
|
|
<div class="bg-blue-100 p-3 rounded-full mr-4"> |
|
|
<i class="fas fa-umbrella text-blue-500 text-xl"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="text-gray-500 text-sm">Precipitation</p> |
|
|
<p class="font-semibold text-gray-800" id="precipitation">--%</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-white rounded-xl shadow p-4 flex items-center"> |
|
|
<div class="bg-green-100 p-3 rounded-full mr-4"> |
|
|
<i class="fas fa-water text-green-500 text-xl"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="text-gray-500 text-sm">Humidity</p> |
|
|
<p class="font-semibold text-gray-800" id="humidity">--%</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-white rounded-xl shadow p-4 flex items-center"> |
|
|
<div class="bg-purple-100 p-3 rounded-full mr-4"> |
|
|
<i class="fas fa-wind text-purple-500 text-xl"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="text-gray-500 text-sm">Wind Speed</p> |
|
|
<p class="font-semibold text-gray-800" id="wind-speed">-- km/h</p> |
|
|
</div> |
|
|
</div> |
|
|
<div class="bg-white rounded-xl shadow p-4 flex items-center"> |
|
|
<div class="bg-yellow-100 p-3 rounded-full mr-4"> |
|
|
<i class="fas fa-sun text-yellow-500 text-xl"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="text-gray-500 text-sm">UV Index</p> |
|
|
<p class="font-semibold text-gray-800" id="uv-index">--</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl shadow-lg p-6"> |
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-4">30-Day Forecast</h2> |
|
|
|
|
|
<div class="relative"> |
|
|
<div class="absolute right-0 top-0 flex space-x-2"> |
|
|
<button id="scroll-left" class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700"> |
|
|
<i class="fas fa-chevron-left"></i> |
|
|
</button> |
|
|
<button id="scroll-right" class="p-2 rounded-full bg-gray-100 hover:bg-gray-200 text-gray-700"> |
|
|
<i class="fas fa-chevron-right"></i> |
|
|
</button> |
|
|
</div> |
|
|
|
|
|
<div class="scroll-container overflow-x-auto pb-4" id="forecast-container"> |
|
|
<div class="flex space-x-4" id="forecast-days"> |
|
|
|
|
|
<div class="animate-pulse flex space-x-4"> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
<div class="w-24 h-40 bg-gray-200 rounded-xl"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="bg-white rounded-xl shadow-lg p-6 mt-8"> |
|
|
<h2 class="text-xl font-semibold text-gray-800 mb-4">Temperature Trends</h2> |
|
|
<div class="h-64" id="weather-chart"> |
|
|
<div class="animate-pulse h-full bg-gray-200 rounded"></div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<footer class="mt-12 text-center text-gray-500 text-sm"> |
|
|
<p>Data provided by simulated weather API | Last updated: <span id="last-updated">--</span></p> |
|
|
<p class="mt-2">© 2023 Tashkent Weather Dashboard</p> |
|
|
</footer> |
|
|
</div> |
|
|
|
|
|
<script> |
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
|
|
const now = new Date(); |
|
|
document.getElementById('current-date').textContent = now.toLocaleDateString('en-US', { |
|
|
weekday: 'long', |
|
|
month: 'long', |
|
|
day: 'numeric' |
|
|
}); |
|
|
document.getElementById('last-updated').textContent = now.toLocaleString(); |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
|
|
document.getElementById('current-temp').textContent = '28°C'; |
|
|
document.getElementById('current-condition').textContent = 'Sunny'; |
|
|
document.getElementById('current-high').textContent = '32°'; |
|
|
document.getElementById('current-low').textContent = '20°'; |
|
|
document.getElementById('current-wind').textContent = '12 km/h'; |
|
|
|
|
|
|
|
|
document.getElementById('precipitation').textContent = '5%'; |
|
|
document.getElementById('humidity').textContent = '45%'; |
|
|
document.getElementById('wind-speed').textContent = '12 km/h'; |
|
|
document.getElementById('uv-index').textContent = '7 (High)'; |
|
|
|
|
|
|
|
|
const forecastContainer = document.getElementById('forecast-days'); |
|
|
forecastContainer.innerHTML = ''; |
|
|
|
|
|
const weatherIcons = [ |
|
|
'fa-sun', 'fa-cloud-sun', 'fa-cloud', 'fa-cloud-showers-heavy', |
|
|
'fa-cloud-rain', 'fa-bolt', 'fa-smog', 'fa-wind' |
|
|
]; |
|
|
const weatherColors = [ |
|
|
'text-yellow-400', 'text-yellow-300', 'text-gray-400', 'text-blue-400', |
|
|
'text-blue-300', 'text-purple-400', 'text-gray-500', 'text-gray-300' |
|
|
]; |
|
|
|
|
|
for (let i = 0; i < 30; i++) { |
|
|
const date = new Date(); |
|
|
date.setDate(now.getDate() + i); |
|
|
|
|
|
const dayName = date.toLocaleDateString('en-US', { weekday: 'short' }); |
|
|
const dayNum = date.getDate(); |
|
|
|
|
|
const randomTempHigh = Math.floor(Math.random() * 10) + 25; |
|
|
const randomTempLow = Math.floor(Math.random() * 5) + 15; |
|
|
const randomIconIndex = Math.floor(Math.random() * weatherIcons.length); |
|
|
|
|
|
const dayElement = document.createElement('div'); |
|
|
dayElement.className = 'weather-card flex-shrink-0 w-24 bg-white rounded-xl shadow p-4 transition-all duration-300 cursor-pointer'; |
|
|
dayElement.innerHTML = ` |
|
|
<div class="text-center"> |
|
|
<p class="font-semibold text-gray-800">${dayName}</p> |
|
|
<p class="text-sm text-gray-500 mb-2">${dayNum}</p> |
|
|
<div class="text-3xl mb-2 ${weatherColors[randomIconIndex]}"> |
|
|
<i class="fas ${weatherIcons[randomIconIndex]}"></i> |
|
|
</div> |
|
|
<div class="flex justify-center space-x-2"> |
|
|
<span class="font-medium text-red-400">${randomTempHigh}°</span> |
|
|
<span class="text-gray-400">${randomTempLow}°</span> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
forecastContainer.appendChild(dayElement); |
|
|
} |
|
|
|
|
|
|
|
|
const chartContainer = document.getElementById('weather-chart'); |
|
|
chartContainer.innerHTML = ` |
|
|
<div class="h-full flex items-end space-x-1"> |
|
|
${Array.from({length: 30}, (_, i) => { |
|
|
const height = Math.floor(Math.random() * 40) + 30; |
|
|
const color = i === 0 ? 'bg-blue-500' : 'bg-blue-300'; |
|
|
return `<div class="${color} w-full rounded-t" style="height: ${height}%"></div>`; |
|
|
}).join('')} |
|
|
</div> |
|
|
<div class="flex justify-between text-xs text-gray-500 mt-2"> |
|
|
<span>Today</span> |
|
|
<span>+30 days</span> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
}, 1500); |
|
|
|
|
|
|
|
|
const container = document.getElementById('forecast-container'); |
|
|
const scrollLeftBtn = document.getElementById('scroll-left'); |
|
|
const scrollRightBtn = document.getElementById('scroll-right'); |
|
|
|
|
|
scrollLeftBtn.addEventListener('click', () => { |
|
|
container.scrollBy({ left: -200, behavior: 'smooth' }); |
|
|
}); |
|
|
|
|
|
scrollRightBtn.addEventListener('click', () => { |
|
|
container.scrollBy({ left: 200, behavior: 'smooth' }); |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=rustamsamandarov/weather-in-tashkent" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |