Spaces:
Running
Running
can you create a weather widget that mimic the one from perplexity fully interactive
aadabc6 verified | // Weather API configuration | |
| const WEATHER_API_KEY = 'demo_key'; // Replace with actual API key | |
| const WEATHER_API_URL = 'https://api.openweathermap.org/data/2.5'; | |
| // Mock weather data for demonstration | |
| const mockWeatherData = { | |
| current: { | |
| temp: 22, | |
| feels_like: 24, | |
| humidity: 65, | |
| pressure: 1013, | |
| wind_speed: 3.5, | |
| weather: [{ main: 'Clear', description: 'clear sky', icon: '01d' }] | |
| }, | |
| daily: [ | |
| { dt: Date.now()/1000 + 86400, temp: { day: 23 }, weather: [{ main: 'Clouds', icon: '02d' }] }, | |
| { dt: Date.now()/1000 + 172800, temp: { day: 21 }, weather: [{ main: 'Rain', icon: '10d' }] }, | |
| { dt: Date.now()/1000 + 259200, temp: { day: 25 }, weather: [{ main: 'Clear', icon: '01d' }] }, | |
| { dt: Date.now()/1000 + 345600, temp: { day: 20 }, weather: [{ main: 'Clouds', icon: '03d' }] }, | |
| { dt: Date.now()/1000 + 432000, temp: { day: 19 }, weather: [{ main: 'Rain', icon: '09d' }] } | |
| ] | |
| }; | |
| // Utility functions | |
| class WeatherUtils { | |
| static kelvinToCelsius(kelvin) { | |
| return Math.round(kelvin - 273.15); | |
| } | |
| static getWeatherIcon(iconCode) { | |
| const iconMap = { | |
| '01d': 'sun', | |
| '01n': 'moon', | |
| '02d': 'cloud', | |
| '02n': 'cloud', | |
| '03d': 'cloud', | |
| '03n': 'cloud', | |
| '04d': 'cloud', | |
| '04n': 'cloud', | |
| '09d': 'cloud-rain', | |
| '09n': 'cloud-rain', | |
| '10d': 'cloud-drizzle', | |
| '10n': 'cloud-drizzle', | |
| '11d': 'cloud-lightning', | |
| '11n': 'cloud-lightning', | |
| '13d': 'cloud-snow', | |
| '13n': 'cloud-snow', | |
| '50d': 'wind', | |
| '50n': 'wind' | |
| }; | |
| return iconMap[iconCode] || 'cloud'; | |
| } | |
| static formatDate(timestamp) { | |
| const date = new Date(timestamp * 1000); | |
| return date.toLocaleDateString('en-US', { weekday: 'short' }); | |
| } | |
| static getWindDirection(degrees) { | |
| const directions = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; | |
| return directions[Math.round(degrees / 45) % 8]; | |
| } | |
| } | |
| // Weather API service | |
| class WeatherService { | |
| static async getWeatherData(lat, lon) { | |
| try { | |
| // For demo purposes, return mock data | |
| // In production, uncomment the API call below | |
| /* | |
| const response = await fetch( | |
| `${WEATHER_API_URL}/onecall?lat=${lat}&lon=${lon}&exclude=minutely,hourly,alerts&appid=${WEATHER_API_KEY}` | |
| ); | |
| if (!response.ok) throw new Error('Weather data fetch failed'); | |
| return await response.json(); | |
| */ | |
| // Simulate API delay | |
| await new Promise(resolve => setTimeout(resolve, 1000)); | |
| return mockWeatherData; | |
| } catch (error) { | |
| console.error('Error fetching weather data:', error); | |
| throw error; | |
| } | |
| } | |
| static async getLocationWeather(city) { | |
| try { | |
| // For demo, return mock data with city name | |
| const data = { ...mockWeatherData, city: city || 'Current Location' }; | |
| await new Promise(resolve => setTimeout(resolve, 800)); | |
| return data; | |
| } catch (error) { | |
| console.error('Error fetching location weather:', error); | |
| throw error; | |
| } | |
| } | |
| } | |
| // Global state management | |
| class WeatherState { | |
| constructor() { | |
| this.currentLocation = 'Current Location'; | |
| this.weatherData = null; | |
| this.loading = false; | |
| this.error = null; | |
| } | |
| setLoading(loading) { | |
| this.loading = loading; | |
| this.notifyListeners(); | |
| } | |
| setWeatherData(data, location) { | |
| this.weatherData = data; | |
| this.currentLocation = location; | |
| this.error = null; | |
| this.notifyListeners(); | |
| } | |
| setError(error) { | |
| this.error = error; | |
| this.weatherData = null; | |
| this.notifyListeners(); | |
| } | |
| addListener(listener) { | |
| this.listeners = this.listeners || []; | |
| this.listeners.push(listener); | |
| } | |
| notifyListeners() { | |
| if (this.listeners) { | |
| this.listeners.forEach(listener => listener(this)); | |
| } | |
| } | |
| } | |
| // Initialize global state | |
| const weatherState = new WeatherState(); | |
| // Event handlers | |
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize with current location weather | |
| loadCurrentLocationWeather(); | |
| }); | |
| async function loadCurrentLocationWeather() { | |
| weatherState.setLoading(true); | |
| try { | |
| if (navigator.geolocation) { | |
| navigator.geolocation.getCurrentPosition( | |
| async (position) => { | |
| const { latitude, longitude } = position.coords; | |
| const data = await WeatherService.getWeatherData(latitude, longitude); | |
| weatherState.setWeatherData(data, 'Current Location'); | |
| }, | |
| async (error) => { | |
| // Fallback to default location | |
| const data = await WeatherService.getLocationWeather('New York'); | |
| weatherState.setWeatherData(data, 'New York'); | |
| } | |
| ); | |
| } else { | |
| // Fallback to default location | |
| const data = await WeatherService.getLocationWeather('New York'); | |
| weatherState.setWeatherData(data, 'New York'); | |
| } | |
| } catch (error) { | |
| weatherState.setError('Failed to load weather data'); | |
| } | |
| } | |
| async function searchLocation(city) { | |
| if (!city.trim()) return; | |
| weatherState.setLoading(true); | |
| try { | |
| const data = await WeatherService.getLocationWeather(city); | |
| weatherState.setWeatherData(data, city); | |
| } catch (error) { | |
| weatherState.setError('Location not found'); | |
| } | |
| } | |
| // Export for use in components | |
| window.WeatherState = weatherState; | |
| window.WeatherUtils = WeatherUtils; | |
| window.searchLocation = searchLocation; | |
| window.loadCurrentLocationWeather = loadCurrentLocationWeather; |