Create a Weather Monitoring Dashboard with Next.js
This project involves building a Weather Monitoring Dashboard using NextJS. The dashboard allows users to check the current weather and forecast for a specific city, as well as an hourly forecast for the next few hours and a daily forecast for the next four days.
Output Preview: Let us have a look at how the final output will look like.
Prerequisites:
Approach to Create Weather Monitoring Dashboard with NextJS:
- Fetch current weather data using the OpenWeatherMap API based on geolocation or city search.
- Display current weather information including temperature, city name, and cloud conditions.
- Fetch hourly and daily forecasts for the specified location.
- Render hourly forecast data dynamically.
- Render daily forecast data dynamically.
Steps to Create the NextJS App:
Step 1: Set up a NextJS project and navigate to that project folder
npx create-next-app weather-monitoring-dashboard
Step 2: Navigate to the root directory of your project.
cd weather-monitoring-dashboard
Step 3: Install necessary dependencies (axios for making HTTP requests).
npm install axios
Project Structure:
- Create or replace index.js and _app.js of pages folder using following code
- generate your own api from openweathermap and replace it with index.js apikey
- create globals.css with the code given below inside styles
Example: Below is an example of building a weather monitoring dashboard with NextJS.
/* styles/global.css */
body {
height: 100%;
background: rgb(72, 37, 37);
padding: 1rem 5rem;
font-family: 'Roboto', sans-serif;
text-transform: capitalize;
/* background: linear-gradient(45deg, rgba(183, 204, 248, 0.717), rgba(7, 43, 127, 0.679)), url(); */
background-repeat: no-repeat;
background-position: center;
background-size: cover;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.header h1 {
color: rgb(214, 147, 45);
text-decoration: underline;
font-family: 'Orbitron', sans-serif;
}
#input {
font-size: 18px;
padding: 5px 10px;
outline: none;
border: none;
border-radius: 15px;
background: aliceblue;
}
#search {
background: none;
padding: 5px 20px;
color: aliceblue;
outline: none;
background: cadetblue;
font-size: 17px;
border-radius: 15px;
cursor: pointer;
border: none;
}
.weather {
text-align: center;
color: aliceblue;
}
#city {
font-size: 30px;
}
/* .weather img {
width: 120px;
height: 120px;
border-radius: 50%;
background: rgba(240, 248, 255, 0.408);
} */
#temperature {
font-size: 50px;
margin: 0;
margin-left: 30px;
margin-bottom: 10px;
}
.temp-box {
display: flex;
align-items: center;
justify-content: center;
margin: 30px 0;
}
#clouds {
font-size: 20px;
background: rgba(153, 205, 50, 0.778);
padding: 2px 20px;
border-radius: 15px;
}
main {
display: grid;
grid-column-gap: 25px;
grid-template-columns: 1fr 5px 1fr;
align-items: center;
margin: 0 50px;
color: white;
}
.next {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
}
.next p,
.next h3 {
margin: 3px 0;
}
.forecstD {
margin: 20px 50px;
color: aliceblue;
}
.weekF {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.cast-header {
color: aliceblue;
background: rgba(254, 189, 132, 0.539);
width: max-content;
padding: 5px 15px;
border-radius: 20px;
font-size: 18px;
margin-bottom: 5px;
}
.divider1,
.divider2 {
background: rgba(254, 189, 132, 0.539);
height: 200px;
border-radius: 5px;
}
.divider2 {
height: 5px;
width: 30%;
margin: 0 auto;
}
.time,
.date {
color: rgb(254, 189, 132);
}
.desc {
color: rgb(196, 255, 77);
}
//pages/index.js
import { useState, useEffect } from 'react';
import axios from 'axios';
import { useRouter } from 'next/router';
const apikey = "feff206daa60b539abe8fae8f2ab7f29";
const Weather = () => {
const router = useRouter();
const [city, setCity] = useState('');
const [weatherData, setWeatherData] = useState(null);
useEffect(() => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) => {
const { latitude, longitude } = position.coords;
const url = `
http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${apikey}`;
fetchWeatherData(url);
});
}
}, []);
const fetchWeatherData = async (url) => {
try {
const response = await axios.get(url);
const data = response.data;
console.log(data);
weatherReport(data);
} catch (error) {
console.error('Error fetching weather data:', error);
}
};
const searchByCity = async () => {
try {
const urlsearch = `http://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apikey}`;
const response = await axios.get(urlsearch);
const data = response.data;
console.log(data);
weatherReport(data);
} catch (error) {
console.error('Error fetching weather data:', error);
}
setCity('');
};
const weatherReport = async (data) => {
const urlcast = `http://api.openweathermap.org/data/2.5/forecast?q=${data.name}&appid=${apikey}`;
try {
const response = await axios.get(urlcast);
const forecast = response.data;
console.log(forecast.city);
hourForecast(forecast);
dayForecast(forecast);
console.log(data);
document.getElementById('city').innerText = data.name + ', ' + data.sys.country;
console.log(data.name, data.sys.country);
console.log(Math.floor(data.main.temp - 273));
document.getElementById('temperature').innerText = Math.floor(data.main.temp - 273) + ' °C';
document.getElementById('clouds').innerText = data.weather[0].description;
console.log(data.weather[0].description);
let icon1 = data.weather[0].icon;
let iconurl = "http://api.openweathermap.org/img/w/" + icon1 + ".png";
document.getElementById('img').src = iconurl;
} catch (error) {
console.error('Error fetching forecast data:', error);
}
};
const hourForecast = (forecast) => {
document.querySelector('.templist').innerHTML = '';
for (let i = 0; i < 5; i++) {
var date = new Date(forecast.list[i].dt * 1000);
console.log((date.toLocaleTimeString(
undefined, 'Asia/Kolkata')).replace(':00', ''));
let hourR = document.createElement('div');
hourR.setAttribute('class', 'next');
let div = document.createElement('div');
let time = document.createElement('p');
time.setAttribute('class', 'time');
time.innerText = (date.toLocaleTimeString(
undefined, 'Asia/Kolkata')).replace(':00', '');
let temp = document.createElement('p');
temp.innerText = Math.floor(
(forecast.list[i].main.temp_max - 273)) + ' °C' + ' / ' +
Math.floor((forecast.list[i].main.temp_min - 273)) + ' °C';
div.appendChild(time);
div.appendChild(temp);
let desc = document.createElement('p');
desc.setAttribute('class', 'desc');
desc.innerText = forecast.list[i].weather[0].description;
hourR.appendChild(div);
hourR.appendChild(desc);
document.querySelector('.templist').appendChild(hourR);
}
};
const dayForecast = (forecast) => {
document.querySelector('.weekF').innerHTML = '';
for (let i = 8; i < forecast.list.length; i += 8) {
console.log(forecast.list[i]);
let div = document.createElement('div');
div.setAttribute('class', 'dayF');
let day = document.createElement('p');
day.setAttribute('class', 'date');
day.innerText = new Date(
forecast.list[i].dt * 1000).toDateString(
undefined, 'Asia/Kolkata');
div.appendChild(day);
let temp = document.createElement('p');
temp.innerText = Math.floor(
(forecast.list[i].main.temp_max - 273)) + ' °C' + ' / ' +
Math.floor((forecast.list[i].main.temp_min - 273)) + ' °C';
div.appendChild(temp);
let description = document.createElement('p');
description.setAttribute('class', 'desc');
description.innerText = forecast.list[i].weather[0].description;
div.appendChild(description);
document.querySelector('.weekF').appendChild(div);
}
};
return (
<div>
<div className="header">
<h1>WEATHER Monitoring Dashboard</h1>
<div>
<input
type="text"
name=""
id="input"
placeholder="Enter city name"
value={city}
onChange={(e) => setCity(e.target.value)}
/>
<button id="search" onClick={searchByCity}>
Search
</button>
</div>
</div>
<main>
<div className="weather">
<h2 id="city">Delhi,IN</h2>
<div className="temp-box">
<p id="temperature">26 °C</p>
</div>
<span id="clouds">Broken Clouds</span>
</div>
<div className="divider"></div>
<div className="forecast">
<p className="cast-header">Upcoming forecast</p>
<div className="forecast-list templist">
{/* Hourly forecast will be rendered here */}
</div>
</div>
</main>
<div className="divider-2"></div>
<div className="forecast-2">
<p className="cast-header"> Next 4 days forecast</p>
<div className="forecast-list-2 weekF">
{/* Daily forecast will be rendered here */}
</div>
</div>
</div>
);
};
export default Weather;
//pages/_app.js
import '../styles/globals.css'; // Adjust the path as needed
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}
Start your application using the following command.
npm run dev
Output: Open your web browser and navigate to http://localhost:3000 to see your Weather Monitoring Dashboard in action.