Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import requests | |
| from datetime import datetime, timedelta | |
| import json | |
| def get_weather(city_name): | |
| """Fetch weather data for a given city using the provided API key""" | |
| if not city_name.strip(): | |
| city_name = "Dubai" # Default city | |
| try: | |
| # Use the provided API key and URL structure | |
| api_key = "openweather" | |
| url = f"https://api.openweathermap.org/data/2.5/weather?q={city_name}&appid=79007029562c2ab46617d801d8018750&units=metric" | |
| response = requests.get(url) | |
| data = response.json() | |
| if data["cod"] == 200: | |
| # Extract weather information | |
| city = data["name"] | |
| country = data["sys"]["country"] | |
| temperature = int(data["main"]["temp"]) | |
| feels_like = int(data["main"]["feels_like"]) | |
| humidity = data["main"]["humidity"] | |
| pressure = data["main"]["pressure"] | |
| description = data["weather"][0]["description"].title() | |
| wind_speed = data["wind"]["speed"] | |
| visibility = data.get("visibility", 10000) // 1000 # Convert to km | |
| # Mock some additional data for the UI | |
| rain_chance = f"{humidity//3}%" # Mock rain chance based on humidity | |
| return { | |
| "city": city, | |
| "country": country, | |
| "temperature": temperature, | |
| "feels_like": feels_like, | |
| "description": description, | |
| "humidity": humidity, | |
| "pressure": pressure, | |
| "wind_speed": wind_speed, | |
| "visibility": visibility, | |
| "rain_chance": rain_chance | |
| } | |
| else: | |
| return None | |
| except Exception as e: | |
| return None | |
| def format_weather_display(weather_data): | |
| """Format weather data for display""" | |
| if not weather_data: | |
| return "Sorry, I couldn't find weather information for that city." | |
| # Create the main weather display | |
| main_display = f""" | |
| <div style="text-align: center; margin-bottom: 30px;"> | |
| <h1 style="font-size: 48px; margin: 0; color: #333; font-weight: 300;">{weather_data['city']}</h1> | |
| <div style="display: flex; align-items: center; justify-content: center; margin: 20px 0;"> | |
| <span style="font-size: 72px; font-weight: 200; color: #333;">{weather_data['temperature']}Β°C</span> | |
| </div> | |
| <p style="color: #666; font-size: 18px; margin: 0;">{weather_data['description']}</p> | |
| </div> | |
| """ | |
| # Create weather details grid | |
| details_grid = f""" | |
| <div> | |
| <h3 style="color: #666; font-size: 14px; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 20px;">WEATHER DETAILS</h3> | |
| <div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px;"> | |
| <div style="text-align: center; padding: 15px; background: rgba(255,255,255,0.5); border-radius: 12px;"> | |
| <div style="color: #666; font-size: 12px; margin-bottom: 5px;">Chance of rain</div> | |
| <div style="font-size: 18px; font-weight: 500; color: #333;">{weather_data['rain_chance']}</div> | |
| <div style="font-size: 16px; margin-top: 5px;">π§</div> | |
| </div> | |
| <div style="text-align: center; padding: 15px; background: rgba(255,255,255,0.5); border-radius: 12px;"> | |
| <div style="color: #666; font-size: 12px; margin-bottom: 5px;">Pressure</div> | |
| <div style="font-size: 18px; font-weight: 500; color: #333;">{weather_data['pressure']} mb</div> | |
| <div style="font-size: 16px; margin-top: 5px;">π</div> | |
| </div> | |
| <div style="text-align: center; padding: 15px; background: rgba(255,255,255,0.5); border-radius: 12px;"> | |
| <div style="color: #666; font-size: 12px; margin-bottom: 5px;">Wind</div> | |
| <div style="font-size: 18px; font-weight: 500; color: #333;">{weather_data['wind_speed']} km/h</div> | |
| <div style="font-size: 16px; margin-top: 5px;">π¨</div> | |
| </div> | |
| <div style="text-align: center; padding: 15px; background: rgba(255,255,255,0.5); border-radius: 12px;"> | |
| <div style="color: #666; font-size: 12px; margin-bottom: 5px;">Feels like</div> | |
| <div style="font-size: 18px; font-weight: 500; color: #333;">{weather_data['feels_like']}Β°C</div> | |
| <div style="font-size: 16px; margin-top: 5px;">π‘οΈ</div> | |
| </div> | |
| <div style="text-align: center; padding: 15px; background: rgba(255,255,255,0.5); border-radius: 12px;"> | |
| <div style="color: #666; font-size: 12px; margin-bottom: 5px;">Visibility</div> | |
| <div style="font-size: 18px; font-weight: 500; color: #333;">{weather_data['visibility']} km</div> | |
| <div style="font-size: 16px; margin-top: 5px;">ποΈ</div> | |
| </div> | |
| <div style="text-align: center; padding: 15px; background: rgba(255,255,255,0.5); border-radius: 12px;"> | |
| <div style="color: #666; font-size: 12px; margin-bottom: 5px;">Humidity</div> | |
| <div style="font-size: 18px; font-weight: 500; color: #333;">{weather_data['humidity']}%</div> | |
| <div style="font-size: 16px; margin-top: 5px;">π§</div> | |
| </div> | |
| </div> | |
| </div> | |
| """ | |
| return main_display + details_grid | |
| def search_weather(city_name): | |
| """Search for weather and format the display""" | |
| weather_data = get_weather(city_name) | |
| return format_weather_display(weather_data) | |
| # Custom CSS for the purple gradient background and card styling | |
| custom_css = """ | |
| body, .gradio-container { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important; | |
| min-height: 100vh; | |
| } | |
| .main-container { | |
| background: white !important; | |
| border-radius: 24px !important; | |
| padding: 40px !important; | |
| margin: 40px auto !important; | |
| max-width: 900px !important; | |
| box-shadow: 0 20px 40px rgba(0,0,0,0.1) !important; | |
| } | |
| .search-container { | |
| display: flex !important; | |
| align-items: center !important; | |
| justify-content: space-between !important; | |
| margin-bottom: 30px !important; | |
| } | |
| .app-title { | |
| font-size: 20px !important; | |
| font-weight: 600 !important; | |
| color: #333 !important; | |
| display: flex !important; | |
| align-items: center !important; | |
| } | |
| .search-input { | |
| flex: 1 !important; | |
| margin: 0 20px !important; | |
| border-radius: 12px !important; | |
| border: 1px solid #e0e0e0 !important; | |
| padding: 12px 16px !important; | |
| font-size: 16px !important; | |
| } | |
| #weather_display { | |
| border: none !important; | |
| background: transparent !important; | |
| } | |
| """ | |
| # Create the Gradio interface | |
| with gr.Blocks(css=custom_css, title="Shafaq's Weather App") as app: | |
| with gr.Column(elem_classes=["main-container"]): | |
| # Header | |
| with gr.Row(elem_classes=["search-container"]): | |
| gr.HTML('<div class="app-title">π€οΈ Shafaq\'s Weather App</div>') | |
| city_input = gr.Textbox( | |
| placeholder="Search for cities", | |
| show_label=False, | |
| elem_classes=["search-input"], | |
| value="Dubai" | |
| ) | |
| # Weather display | |
| weather_display = gr.HTML( | |
| value="", | |
| elem_id="weather_display" | |
| ) | |
| # Load Dubai weather on startup | |
| app.load( | |
| fn=search_weather, | |
| inputs=gr.Textbox(value="Dubai", visible=False), | |
| outputs=weather_display | |
| ) | |
| # Search functionality | |
| city_input.submit( | |
| fn=search_weather, | |
| inputs=city_input, | |
| outputs=weather_display | |
| ) | |
| # Launch the app | |
| if __name__ == "__main__": | |
| print("π€οΈ Starting Shafaq's Weather App...") | |
| print("ποΈ Default city: Dubai") | |
| app.launch() | |