qu-ropa-llevar / index.html
RedSparkie's picture
Add 2 files
2e9f7fe verified
raw
history blame contribute delete
29.5 kB
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WeatherWardrobe - Asesor de Vestimenta Meteorol贸gico</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 {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.18);
}
.sunny-gradient {
background: linear-gradient(135deg, #f6d365 0%, #fda085 100%);
}
.rainy-gradient {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
}
.cloudy-gradient {
background: linear-gradient(135deg, #bdc3c7 0%, #2c3e50 100%);
}
.night-gradient {
background: linear-gradient(135deg, #0f2027 0%, #203a43 50%, #2c5364 100%);
}
.transition-all {
transition: all 0.3s ease;
}
.clothing-icon {
font-size: 2rem;
margin-bottom: 0.5rem;
}
.hourly-forecast {
scrollbar-width: thin;
scrollbar-color: rgba(255,255,255,0.5) transparent;
}
.hourly-forecast::-webkit-scrollbar {
height: 6px;
}
.hourly-forecast::-webkit-scrollbar-track {
background: transparent;
}
.hourly-forecast::-webkit-scrollbar-thumb {
background-color: rgba(255,255,255,0.5);
border-radius: 20px;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fadeIn {
animation: fadeIn 0.5s ease-out forwards;
}
.delay-100 { animation-delay: 0.1s; }
.delay-200 { animation-delay: 0.2s; }
.delay-300 { animation-delay: 0.3s; }
.delay-400 { animation-delay: 0.4s; }
</style>
</head>
<body class="min-h-screen font-sans bg-gray-100">
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="bg-blue-600 text-white shadow-lg">
<div class="container mx-auto px-4 py-6">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="flex items-center mb-4 md:mb-0">
<i class="fas fa-cloud-sun text-3xl mr-3"></i>
<h1 class="text-2xl font-bold">WeatherWardrobe</h1>
</div>
<div class="relative w-full md:w-1/3">
<input
type="text"
id="cityInput"
placeholder="Ingresa una ciudad..."
class="w-full px-4 py-2 rounded-full text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-300"
>
<button
id="searchBtn"
class="absolute right-0 top-0 h-full px-4 text-blue-600 hover:text-blue-800 focus:outline-none"
>
<i class="fas fa-search"></i>
</button>
</div>
</div>
</div>
</header>
<!-- Main Content -->
<main class="flex-grow container mx-auto px-4 py-8">
<!-- Loading State -->
<div id="loading" class="hidden text-center py-12">
<div class="inline-block animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-blue-500 mb-4"></div>
<p class="text-gray-600">Buscando informaci贸n meteorol贸gica...</p>
</div>
<!-- Error State -->
<div id="error" class="hidden text-center py-12">
<i class="fas fa-exclamation-triangle text-4xl text-red-500 mb-4"></i>
<p class="text-gray-600">No se pudo obtener la informaci贸n. Intenta con otra ciudad.</p>
</div>
<!-- Weather Display -->
<div id="weatherDisplay" class="hidden">
<!-- Current Weather -->
<div class="weather-card p-6 mb-8 text-white sunny-gradient rounded-xl animate-fadeIn">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<h2 class="text-2xl font-bold" id="currentCity">Ciudad</h2>
<p class="text-lg" id="currentDate">Fecha</p>
<p class="text-5xl font-bold my-2" id="currentTemp">0掳C</p>
<p class="text-xl" id="currentCondition">Condici贸n</p>
</div>
<div class="text-center">
<i class="fas fa-sun text-6xl mb-2"></i>
<div class="grid grid-cols-3 gap-4 mt-4">
<div>
<p class="text-sm">HUMEDAD</p>
<p class="text-xl font-semibold" id="currentHumidity">0%</p>
</div>
<div>
<p class="text-sm">VIENTO</p>
<p class="text-xl font-semibold" id="currentWind">0 km/h</p>
</div>
<div>
<p class="text-sm">UV</p>
<p class="text-xl font-semibold" id="currentUV">0</p>
</div>
</div>
</div>
</div>
</div>
<!-- Hourly Forecast -->
<div class="mb-8 animate-fadeIn delay-100">
<h3 class="text-xl font-semibold mb-4 text-gray-700">Pron贸stico por horas</h3>
<div class="hourly-forecast flex overflow-x-auto pb-4 gap-4">
<!-- Hourly items will be inserted here by JS -->
</div>
</div>
<!-- Clothing Recommendations -->
<div class="animate-fadeIn delay-200">
<h3 class="text-xl font-semibold mb-4 text-gray-700">Recomendaciones de vestimenta</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<!-- Morning -->
<div class="weather-card bg-white p-6 rounded-lg shadow-md">
<div class="flex items-center mb-4">
<i class="fas fa-sun text-yellow-500 text-2xl mr-3"></i>
<h4 class="text-lg font-semibold text-gray-800">Ma帽ana</h4>
</div>
<div class="flex flex-wrap gap-4 justify-center" id="morningClothing">
<!-- Clothing items will be inserted here by JS -->
</div>
<p class="mt-4 text-gray-600 text-sm italic" id="morningAdvice">Cargando recomendaci贸n...</p>
</div>
<!-- Afternoon -->
<div class="weather-card bg-white p-6 rounded-lg shadow-md">
<div class="flex items-center mb-4">
<i class="fas fa-sun text-orange-500 text-2xl mr-3"></i>
<h4 class="text-lg font-semibold text-gray-800">Tarde</h4>
</div>
<div class="flex flex-wrap gap-4 justify-center" id="afternoonClothing">
<!-- Clothing items will be inserted here by JS -->
</div>
<p class="mt-4 text-gray-600 text-sm italic" id="afternoonAdvice">Cargando recomendaci贸n...</p>
</div>
<!-- Night -->
<div class="weather-card bg-white p-6 rounded-lg shadow-md">
<div class="flex items-center mb-4">
<i class="fas fa-moon text-indigo-500 text-2xl mr-3"></i>
<h4 class="text-lg font-semibold text-gray-800">Noche</h4>
</div>
<div class="flex flex-wrap gap-4 justify-center" id="nightClothing">
<!-- Clothing items will be inserted here by JS -->
</div>
<p class="mt-4 text-gray-600 text-sm italic" id="nightAdvice">Cargando recomendaci贸n...</p>
</div>
</div>
</div>
<!-- Additional Tips -->
<div class="mt-8 grid grid-cols-1 md:grid-cols-2 gap-6 animate-fadeIn delay-300">
<div class="weather-card bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-umbrella text-blue-500 mr-3"></i> Consejos para la lluvia
</h4>
<ul class="list-disc pl-5 text-gray-600 space-y-2" id="rainTips">
<!-- Tips will be inserted here by JS -->
</ul>
</div>
<div class="weather-card bg-white p-6 rounded-lg shadow-md">
<h4 class="text-lg font-semibold text-gray-800 mb-4 flex items-center">
<i class="fas fa-temperature-high text-red-500 mr-3"></i> Consejos para el calor
</h4>
<ul class="list-disc pl-5 text-gray-600 space-y-2" id="heatTips">
<!-- Tips will be inserted here by JS -->
</ul>
</div>
</div>
</div>
<!-- Initial State -->
<div id="initialState" class="text-center py-12">
<i class="fas fa-cloud-sun text-5xl text-blue-400 mb-6"></i>
<h2 class="text-2xl font-semibold text-gray-700 mb-2">Consulta el clima y recibe recomendaciones de vestimenta</h2>
<p class="text-gray-500 mb-6">Ingresa una ciudad en el buscador para conocer el pron贸stico y qu茅 ropa usar seg煤n las condiciones clim谩ticas.</p>
<div class="max-w-md mx-auto">
<div class="relative">
<input
type="text"
placeholder="Ej: Madrid, Buenos Aires, Nueva York"
class="w-full px-4 py-3 rounded-full border border-gray-300 focus:outline-none focus:ring-2 focus:ring-blue-300"
id="initialCityInput"
>
<button
class="absolute right-0 top-0 h-full px-6 bg-blue-500 text-white rounded-r-full hover:bg-blue-600 transition-all"
id="initialSearchBtn"
>
Buscar
</button>
</div>
</div>
</div>
</main>
<!-- Footer -->
<footer class="bg-gray-800 text-white py-6">
<div class="container mx-auto px-4 text-center">
<p>漏 2023 WeatherWardrobe - Asesor de vestimenta seg煤n el clima</p>
<p class="text-gray-400 text-sm mt-2">Datos meteorol贸gicos simulados para prop贸sitos demostrativos</p>
</div>
</footer>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Elements
const cityInput = document.getElementById('cityInput');
const searchBtn = document.getElementById('searchBtn');
const initialCityInput = document.getElementById('initialCityInput');
const initialSearchBtn = document.getElementById('initialSearchBtn');
const loading = document.getElementById('loading');
const error = document.getElementById('error');
const weatherDisplay = document.getElementById('weatherDisplay');
const initialState = document.getElementById('initialState');
// Event Listeners
searchBtn.addEventListener('click', fetchWeather);
initialSearchBtn.addEventListener('click', () => {
if(initialCityInput.value) {
cityInput.value = initialCityInput.value;
fetchWeather();
}
});
cityInput.addEventListener('keypress', (e) => {
if(e.key === 'Enter') fetchWeather();
});
initialCityInput.addEventListener('keypress', (e) => {
if(e.key === 'Enter' && initialCityInput.value) {
cityInput.value = initialCityInput.value;
fetchWeather();
}
});
// Mock weather data (since we're not using a real API)
function getMockWeatherData(city) {
// Base data
const baseTemp = Math.floor(Math.random() * 30) + 10; // 10-40掳C
const isRaining = Math.random() > 0.7;
const isSunny = !isRaining && Math.random() > 0.5;
const isCloudy = !isRaining && !isSunny;
// Current weather
const currentWeather = {
city: city,
date: new Date().toLocaleDateString('es-ES', { weekday: 'long', day: 'numeric', month: 'long' }),
temp: baseTemp,
condition: isRaining ? 'Lluvioso' : (isSunny ? 'Soleado' : 'Nublado'),
humidity: Math.floor(Math.random() * 50) + 30, // 30-80%
wind: Math.floor(Math.random() * 20) + 5, // 5-25 km/h
uv: Math.floor(Math.random() * 8) + 1, // 1-8
icon: isRaining ? 'cloud-rain' : (isSunny ? 'sun' : 'cloud')
};
// Hourly forecast (next 12 hours)
const hourlyForecast = [];
const now = new Date();
for(let i = 0; i < 12; i++) {
const hour = new Date(now.getTime() + i * 3600000);
const hourTemp = baseTemp + (Math.random() * 6 - 3); // 卤3掳 variation
const hourRain = isRaining ? Math.random() * 30 : Math.random() * 10;
const hourIcon = hourRain > 20 ? 'cloud-rain' : (isSunny ? 'sun' : 'cloud');
hourlyForecast.push({
time: hour.getHours() + ':00',
temp: Math.round(hourTemp),
rain: Math.round(hourRain),
icon: hourIcon
});
}
// Clothing recommendations
const recommendations = {
morning: generateClothingRecommendation(baseTemp - 5, isRaining, Math.min(currentWeather.uv, 5)),
afternoon: generateClothingRecommendation(baseTemp + 2, isRaining, currentWeather.uv),
night: generateClothingRecommendation(baseTemp - 8, isRaining, 1)
};
return {
current: currentWeather,
hourly: hourlyForecast,
recommendations: recommendations
};
}
// Generate clothing recommendations based on weather
function generateClothingRecommendation(temp, isRaining, uvIndex) {
const clothing = [];
const advice = [];
// Base clothing
if(temp < 10) {
clothing.push('coat', 'sweater', 'gloves', 'scarf');
advice.push("Hace mucho fr铆o, abr铆gate bien.");
} else if(temp < 18) {
clothing.push('jacket', 'long-sleeve');
advice.push("Temperaturas frescas, lleva algo de abrigo.");
} else if(temp < 25) {
clothing.push('t-shirt', 'light-jacket');
advice.push("Temperaturas agradables, ropa ligera.");
} else {
clothing.push('tank-top', 'shorts', 'hat');
advice.push("Hace calor, usa ropa fresca y ligera.");
}
// Rain considerations
if(isRaining) {
clothing.push('umbrella', 'waterproof-shoes');
advice.push("Lleva paraguas o impermeable, hay probabilidad de lluvia.");
}
// UV considerations
if(uvIndex > 6) {
clothing.push('sunglasses', 'hat', 'sunscreen');
advice.push("Alto 铆ndice UV, protege tu piel y ojos.");
} else if(uvIndex > 3) {
clothing.push('sunglasses', 'sunscreen');
advice.push("Moderado 铆ndice UV, protecci贸n solar recomendada.");
}
// Footwear
if(isRaining) {
clothing.push('boots');
} else if(temp > 22) {
clothing.push('sandals');
} else {
clothing.push('sneakers');
}
return {
clothing: clothing,
advice: advice.join(' ')
};
}
// Get icon for clothing item
function getClothingIcon(item) {
const icons = {
'coat': 'fa-coat',
'sweater': 'fa-shirt',
'gloves': 'fa-mitten',
'scarf': 'fa-scarf',
'jacket': 'fa-jacket',
'long-sleeve': 'fa-tshirt',
't-shirt': 'fa-tshirt',
'light-jacket': 'fa-vest',
'tank-top': 'fa-vest',
'shorts': 'fa-shorts',
'hat': 'fa-hat-cowboy',
'umbrella': 'fa-umbrella',
'waterproof-shoes': 'fa-shoe-prints',
'sunglasses': 'fa-sunglasses',
'sunscreen': 'fa-spray-can',
'boots': 'fa-boot',
'sandals': 'fa-shoe-prints',
'sneakers': 'fa-sneaker'
};
return icons[item] || 'fa-tshirt';
}
// Get weather icon
function getWeatherIcon(iconName) {
const icons = {
'sun': 'fa-sun',
'cloud': 'fa-cloud',
'cloud-rain': 'fa-cloud-rain'
};
return icons[iconName] || 'fa-cloud';
}
// Get gradient class based on weather
function getWeatherGradient(condition, hour) {
const isNight = hour < 6 || hour > 20;
if(isNight) return 'night-gradient';
if(condition.includes('Lluvia')) return 'rainy-gradient';
if(condition.includes('Nublado')) return 'cloudy-gradient';
return 'sunny-gradient';
}
// Fetch weather data (mock in this case)
function fetchWeather() {
const city = cityInput.value.trim();
if(!city) return;
// Show loading state
loading.classList.remove('hidden');
error.classList.add('hidden');
weatherDisplay.classList.add('hidden');
initialState.classList.add('hidden');
// Simulate API delay
setTimeout(() => {
try {
const weatherData = getMockWeatherData(city);
displayWeather(weatherData);
loading.classList.add('hidden');
weatherDisplay.classList.remove('hidden');
} catch(e) {
console.error(e);
loading.classList.add('hidden');
error.classList.remove('hidden');
}
}, 1000);
}
// Display weather data
function displayWeather(data) {
// Current weather
const current = data.current;
const currentHour = new Date().getHours();
document.getElementById('currentCity').textContent = current.city;
document.getElementById('currentDate').textContent = current.date;
document.getElementById('currentTemp').textContent = `${current.temp}掳C`;
document.getElementById('currentCondition').textContent = current.condition;
document.getElementById('currentHumidity').textContent = `${current.humidity}%`;
document.getElementById('currentWind').textContent = `${current.wind} km/h`;
document.getElementById('currentUV').textContent = current.uv;
// Update background based on current weather
const weatherCard = document.querySelector('#weatherDisplay .weather-card');
weatherCard.className = weatherCard.className.split(' ').filter(c => !c.includes('gradient')).join(' ');
weatherCard.classList.add(getWeatherGradient(current.condition, currentHour));
// Weather icon
const weatherIcon = document.querySelector('#weatherDisplay .weather-card i.fas');
weatherIcon.className = `fas ${getWeatherIcon(current.icon)} text-6xl mb-2`;
// Hourly forecast
const hourlyContainer = document.querySelector('.hourly-forecast');
hourlyContainer.innerHTML = '';
data.hourly.forEach(hour => {
const hourEl = document.createElement('div');
hourEl.className = 'flex-shrink-0 weather-card bg-white bg-opacity-20 p-4 rounded-lg text-center text-white';
const hourTime = document.createElement('p');
hourTime.className = 'font-semibold';
hourTime.textContent = hour.time;
const hourIcon = document.createElement('i');
hourIcon.className = `fas ${getWeatherIcon(hour.icon)} text-3xl my-2`;
const hourTemp = document.createElement('p');
hourTemp.className = 'text-xl font-bold';
hourTemp.textContent = `${hour.temp}掳`;
const hourRain = document.createElement('p');
hourRain.className = 'text-sm opacity-80';
hourRain.textContent = `${hour.rain}%`;
hourEl.appendChild(hourTime);
hourEl.appendChild(hourIcon);
hourEl.appendChild(hourTemp);
hourEl.appendChild(hourRain);
hourlyContainer.appendChild(hourEl);
});
// Clothing recommendations
const rec = data.recommendations;
// Morning
const morningContainer = document.getElementById('morningClothing');
morningContainer.innerHTML = '';
rec.morning.clothing.forEach(item => {
const itemEl = document.createElement('div');
itemEl.className = 'text-center';
const icon = document.createElement('i');
icon.className = `clothing-icon fas ${getClothingIcon(item)}`;
const label = document.createElement('p');
label.className = 'text-xs capitalize';
label.textContent = item.replace('-', ' ');
itemEl.appendChild(icon);
itemEl.appendChild(label);
morningContainer.appendChild(itemEl);
});
document.getElementById('morningAdvice').textContent = rec.morning.advice;
// Afternoon
const afternoonContainer = document.getElementById('afternoonClothing');
afternoonContainer.innerHTML = '';
rec.afternoon.clothing.forEach(item => {
const itemEl = document.createElement('div');
itemEl.className = 'text-center';
const icon = document.createElement('i');
icon.className = `clothing-icon fas ${getClothingIcon(item)}`;
const label = document.createElement('p');
label.className = 'text-xs capitalize';
label.textContent = item.replace('-', ' ');
itemEl.appendChild(icon);
itemEl.appendChild(label);
afternoonContainer.appendChild(itemEl);
});
document.getElementById('afternoonAdvice').textContent = rec.afternoon.advice;
// Night
const nightContainer = document.getElementById('nightClothing');
nightContainer.innerHTML = '';
rec.night.clothing.forEach(item => {
const itemEl = document.createElement('div');
itemEl.className = 'text-center';
const icon = document.createElement('i');
icon.className = `clothing-icon fas ${getClothingIcon(item)}`;
const label = document.createElement('p');
label.className = 'text-xs capitalize';
label.textContent = item.replace('-', ' ');
itemEl.appendChild(icon);
itemEl.appendChild(label);
nightContainer.appendChild(itemEl);
});
document.getElementById('nightAdvice').textContent = rec.night.advice;
// Additional tips
const rainTips = document.getElementById('rainTips');
rainTips.innerHTML = `
<li>Usa calzado impermeable para mantener tus pies secos</li>
<li>Lleva siempre un paraguas plegable en tu bolso/mochila</li>
<li>Considera un impermeable ligero si llover谩 todo el d铆a</li>
<li>Protege tus dispositivos electr贸nicos con fundas resistentes al agua</li>
`;
const heatTips = document.getElementById('heatTips');
heatTips.innerHTML = `
<li>Mantente hidratado, lleva siempre una botella de agua</li>
<li>Usa ropa clara y de tejidos transpirables como el lino o algod贸n</li>
<li>No olvides aplicar protector solar cada 2 horas</li>
<li>Busca la sombra durante las horas de mayor calor (12-16h)</li>
`;
}
});
</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=RedSparkie/qu-ropa-llevar" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>