Building a Weather Dashboard using OpenWeatherMap with Real-Time Location

0
39

In today’s digital world, staying updated with the latest weather conditions is essential. While there are many weather apps and websites, creating a personalized weather dashboard for your website can provide a more engaging and customized experience. In this tutorial, we’ll explore how to build a weather dashboard that pulls real-time data from OpenWeatherMap API, including fetching weather based on your current location.

The Basics of the Weather Dashboard

At the core of the weather dashboard, we are using OpenWeatherMap API to retrieve weather information. The API provides data like temperature, humidity, wind speed, and even sunrise and sunset times. These details are shown on a visually appealing, responsive dashboard.

The design itself is built using Bootstrap 5 for a clean, mobile-first layout. We’ve included cards for each weather detail—temperature, humidity, pressure, and more—making it easy to digest and interact with.

Follow this video for complete guidance :

Weather Dashboard – Full Source Code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Weather Dashboard</title>
    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <style>
        .weather-header {
            background: linear-gradient(to right, #0d6efd, #0a58ca);
            color: white;
        }
        .loading-spinner {
            width: 3rem;
            height: 3rem;
        }
    </style>
</head>
<body class="bg-light py-4">
    <div class="container">
        <!-- Loading State -->
        <div id="loading" class="text-center py-5">
            <div class="spinner-border text-primary loading-spinner" role="status">
                <span class="visually-hidden">Loading...</span>
            </div>
            <p class="mt-3 text-secondary">Loading weather data...</p>
        </div>

        <!-- Error State -->
        <div id="error" class="alert alert-danger d-none" role="alert">
            <strong>Error!</strong>
            <span id="error-message"></span>
        </div>

        <!-- Weather Card -->
        <div id="weather-card" class="card shadow d-none">
            <!-- Header -->
            <div class="card-header weather-header py-4">
                <h1 id="city-name" class="display-6 mb-2">Loading...</h1>
                <div class="d-flex align-items-center">
                    <img id="weather-icon" src="" alt="Weather icon" class="me-2" style="width: 50px; height: 50px;">
                    <span id="weather-description" class="fs-4 text-capitalize">Loading...</span>
                </div>
            </div>

            <!-- Temperature Section -->
            <div class="card-body border-bottom">
                <div class="row align-items-center">
                    <div class="col">
                        <div id="current-temp" class="display-4 fw-bold">--°C</div>
                        <div id="feels-like" class="text-secondary">Feels like --°C</div>
                    </div>
                    <div class="col text-end">
                        <div class="mb-2">
                            <i class="bi bi-arrow-up me-1"></i>
                            <span id="temp-max">--°C</span>
                        </div>
                        <div>
                            <i class="bi bi-arrow-down me-1"></i>
                            <span id="temp-min">--°C</span>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Weather Details Grid -->
            <div class="card-body">
                <div class="row g-4">
                    <div class="col-6 col-md-3">
                        <div class="card h-100">
                            <div class="card-body text-center">
                                <i class="bi bi-droplet-fill text-primary mb-2 fs-4"></i>
                                <div class="text-secondary">Humidity</div>
                                <div id="humidity" class="fs-5 fw-semibold">--%</div>
                            </div>
                        </div>
                    </div>

                    <div class="col-6 col-md-3">
                        <div class="card h-100">
                            <div class="card-body text-center">
                                <i class="bi bi-wind text-primary mb-2 fs-4"></i>
                                <div class="text-secondary">Wind Speed</div>
                                <div id="wind-speed" class="fs-5 fw-semibold">-- m/s</div>
                            </div>
                        </div>
                    </div>

                    <div class="col-6 col-md-3">
                        <div class="card h-100">
                            <div class="card-body text-center">
                                <i class="bi bi-eye-fill text-primary mb-2 fs-4"></i>
                                <div class="text-secondary">Visibility</div>
                                <div id="visibility" class="fs-5 fw-semibold">-- km</div>
                            </div>
                        </div>
                    </div>

                    <div class="col-6 col-md-3">
                        <div class="card h-100">
                            <div class="card-body text-center">
                                <i class="bi bi-graph-up text-primary mb-2 fs-4"></i>
                                <div class="text-secondary">Pressure</div>
                                <div id="pressure" class="fs-5 fw-semibold">-- hPa</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <!-- Sun Times -->
            <div class="card-footer bg-light">
                <div class="row justify-content-between align-items-center">
                    <div class="col-auto d-flex align-items-center">
                        <i class="bi bi-sunrise text-warning me-2 fs-4"></i>
                        <div>
                            <div class="text-secondary">Sunrise</div>
                            <div id="sunrise" class="fw-semibold">--:-- AM</div>
                        </div>
                    </div>
                    <div class="col-auto d-flex align-items-center">
                        <i class="bi bi-sunset text-warning me-2 fs-4"></i>
                        <div>
                            <div class="text-secondary">Sunset</div>
                            <div id="sunset" class="fw-semibold">--:-- PM</div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Last Updated -->
        <div id="last-updated" class="text-center mt-3 text-secondary">
            Last updated: --:--
        </div>
    </div>

    <!-- Bootstrap Icons -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">
    <!-- Bootstrap JS -->
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>

    <script>
    	var latitude,longitude;

        function select(id){
            return document.getElementById(id);
        }

        // Utility function to convert Kelvin to Celsius
        function kelvinToCelsius(kelvin) {
            return (kelvin - 273.15).toFixed(1);
        }

        // Utility function to format timestamp
        function formatTime(timestamp) {
            return new Date(timestamp * 1000).toLocaleTimeString('en-US', {
                hour: 'numeric',
                minute: '2-digit',
                hour12: true
            });
        }

        // Function to update the UI with weather data
        function updateUI(data) {
            // Hide loading, show weather card
            select('loading').classList.add('d-none');
            select('weather-card').classList.remove('d-none');

            // Update weather icon
            const iconCode = data.weather[0].icon;
            const iconUrl = `https://openweathermap.org/img/wn/${iconCode}@2x.png`;
            select('weather-icon').src = iconUrl;

            // Update all weather information
            select('city-name').textContent = `${data.name}, ${data.sys.country}`;
            select('weather-description').textContent = data.weather[0].description;
            select('current-temp').textContent = `${kelvinToCelsius(data.main.temp)}°C`;
            select('feels-like').textContent = `Feels like ${kelvinToCelsius(data.main.feels_like)}°C`;
            select('temp-max').textContent = `${kelvinToCelsius(data.main.temp_max)}°C`;
            select('temp-min').textContent = `${kelvinToCelsius(data.main.temp_min)}°C`;
            select('humidity').textContent = `${data.main.humidity}%`;
            select('wind-speed').textContent = `${data.wind.speed} m/s`;
            select('visibility').textContent = `${(data.visibility / 1000).toFixed(1)} km`;
            select('pressure').textContent = `${data.main.pressure} hPa`;
            select('sunrise').textContent = formatTime(data.sys.sunrise);
            select('sunset').textContent = formatTime(data.sys.sunset);
            
            // Update last updated time
            select('last-updated').textContent = 
                `Last updated: ${new Date().toLocaleString()}`;
        }

        // Function to show error message
        function showError(message) {
            select('loading').classList.add('d-none');
            const errorDiv = select('error');
            errorDiv.classList.remove('d-none');
            select('error-message').textContent = message;
        }

        // Fetch weather data
        function fetchWeatherData() {
            try {
            	if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(async function(position) {
                    latitude = position.coords.latitude;
                    longitude = position.coords.longitude;
                    const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=API_KEY`);
                    if (!response.ok) {
                        throw new Error('Weather data not available');
                    }
                    const data = await response.json();
                    updateUI(data);
                });
            }
            } catch (error) {
                showError(error.message);
                console.error('Error fetching weather data:', error);
            }
        }

        // Initial fetch
        fetchWeatherData();

        // Refresh data every 5 minutes
        setInterval(fetchWeatherData, 100 * 60 * 1000);
    </script>
</body>
</html>

 

ALSO READ  Cryptocurrency : Get Current Bitcoin Price using PHP API

Fetching Weather Data Using OpenWeatherMap API

The OpenWeatherMap API allows you to retrieve detailed weather information, either by specifying a city name or geographical coordinates (latitude and longitude). Initially, the weather app fetches data for a fixed location (in this case, the coordinates of a specific city). The app then presents key weather metrics in a user-friendly interface.

But we’ve taken it a step further by adding a feature that fetches the weather data based on the user’s current location. This is achieved using the navigator.geolocation API, which allows the web browser to access the user’s geographical position in real-time.

Fetching Weather Data Based on Current Location

Here’s the core logic behind fetching the weather for the user’s current location:

  • Geolocation API: We use the navigator.geolocation.getCurrentPosition() method to fetch the user’s latitude and longitude. This method accesses the device’s location services and retrieves real-time coordinates.
  • API Request: With the obtained coordinates, we dynamically build the OpenWeatherMap API URL, appending the lat and lon parameters to the URL.
  • Displaying Data: Once the weather data is fetched successfully, the app updates the UI with the current weather details—temperature, wind speed, humidity, and more—based on the user’s location.

Benefits of Real-Time Location Weather

By integrating the current location feature, you can provide a more personalized weather experience. Users no longer need to manually input their city or region. Instead, the app automatically detects their location and shows the most relevant and accurate weather conditions. This is especially useful for mobile applications and services where location-based information is essential.

Additionally, by using the setInterval() function, the weather data refreshes every 5 minutes, ensuring that the user gets updated information without needing to refresh the page manually.

ALSO READ  PHP API : Get Weather Report and Forecast

Error Handling

Handling errors is crucial to ensure a smooth user experience. In case the location cannot be determined (e.g., if the user denies location access), the app gracefully displays an error message and notifies the user that the data cannot be fetched. This ensures that users are always informed about the state of the application.

Building a weather dashboard with OpenWeatherMap and real-time location data is an excellent way to combine practical functionality with user-centric features. This app not only provides users with essential weather data but also does so in a way that is personalized and easy to use. Whether you’re building a simple weather app for fun or using this as a foundation for more complex projects, this approach demonstrates how APIs and modern browser features can be used to create a highly interactive user experience.

 

Comments are closed.