Skip to content

Commit

Permalink
AC-234 dashboard chart finished
Browse files Browse the repository at this point in the history
  • Loading branch information
Minotriz02 authored and Minotriz02 committed Sep 20, 2024
1 parent ba7ee84 commit 20bbca0
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 117 deletions.
76 changes: 76 additions & 0 deletions src/src/components/weatherChart/WeatherChart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from "react";
import { Col } from "react-bootstrap";
import { Line } from "react-chartjs-2";
import {
Chart,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from "chart.js";

Chart.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);

const WeatherChart = ({
title,
data,
unit,
chartOptions,
chartConfig,
days,
color,
}) => {
const filteredData = data.slice(-days);

const maxItem = filteredData.reduce(
(max, item) => (item.value > max.value ? item : max),
filteredData[0] || { label: "N/A", value: 0 }
);
const minItem = filteredData.reduce(
(min, item) => (item.value < min.value ? item : min),
filteredData[0] || { label: "N/A", value: 0 }
);

return (
<Col lg={6} className="mb-4">
<div className="bg-white rounded p-4 text-dark">
<h5>{title}</h5>
<hr />
<p>
La gráfica muestra la evolución de {title.toLowerCase()} registrada en
la estación meteorológica durante los <b>{days} últimos</b> días. En
ella se destaca que el día con la {title.toLowerCase()} más alta fue
el <b>{maxItem.label}</b>, alcanzando un máximo de{" "}
<b>
{maxItem.value.toFixed(2)} {unit}
</b>
, mientras que el día con la {title.toLowerCase()} más baja fue el{" "}
<b>{minItem.label}</b>, con una {title.toLowerCase()} de{" "}
<b>
{minItem.value.toFixed(2)} {unit}
</b>
. Esta visualización permite analizar las variaciones diarias de{" "}
{title.toLowerCase()} y ofrece una referencia clara para identificar
patrones climáticos recientes en la región.
</p>
<Line
data={chartConfig(title, filteredData, `${color}`)}
options={chartOptions}
/>
</div>
</Col>
);
};

export default WeatherChart;
17 changes: 12 additions & 5 deletions src/src/conf/Configuration.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
const ACLIMATE_API = "https://webapi.aclimate.org/api";
/**
* Configuration class for application settings.
*/
class Configuration {
static #ACLIMATE_API = "https://webapi.aclimate.org/api";

const Configuration = {
getAclimateApiUrl() {
return ACLIMATE_API;
/**
* Gets the Aclimate API URL.
* @returns {string} The Aclimate API URL.
*/
static get aclimateApiUrl() {
return this.#ACLIMATE_API;
}
};
}

export default Configuration;
157 changes: 56 additions & 101 deletions src/src/pages/dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,10 @@ import { Button, Col, Container, Form, Row, Spinner } from "react-bootstrap";
import { useParams, useNavigate } from "react-router-dom";
import SearchBar from "../../components/searchBar/SearchBar";
import Services from "../../services/Services";
import { Line } from "react-chartjs-2";
import {
Chart,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from "chart.js";
import { MapContainer, Marker, TileLayer, ZoomControl } from "react-leaflet";
import L from "leaflet";
import "./Dashboard.css";

Chart.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
import WeatherChart from "../../components/weatherChart/WeatherChart";

const Dashboard = () => {
const [data, setData] = useState({
Expand All @@ -38,6 +18,7 @@ const Dashboard = () => {
const [stations, setStations] = useState([]);
const [currentStation, setCurrentStation] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [selectedDays, setSelectedDays] = useState(7);
const { idWS } = useParams();
const navigate = useNavigate();

Expand All @@ -58,7 +39,9 @@ const Dashboard = () => {
setStations(filteredStations);
setCurrentStation(station);
} catch (error) {
console.error(error);
console.error("Error fetching weather stations:", error);
} finally {
setIsLoading(false);
}
};
fetchStations();
Expand All @@ -77,7 +60,7 @@ const Dashboard = () => {
);
setData(parsedData);
} catch (error) {
console.error(error);
console.error("Error fetching daily weather data:", error);
} finally {
setIsLoading(false);
}
Expand Down Expand Up @@ -128,6 +111,11 @@ const Dashboard = () => {
setCurrentStation(station);
};

const handleDaysChange = (event) => {
const value = event.target.value;
setSelectedDays(value === "" ? 7 : parseInt(value, 10));
};

const chartConfig = (label, data, color) => ({
labels: data.map((item) => item.label),
datasets: [
Expand Down Expand Up @@ -168,10 +156,14 @@ const Dashboard = () => {
<>
<Col className="bg-white rounded p-4 my-2 text-dark">
<div className="d-flex justify-content-between mb-2">
<Form.Select aria-label="Periodo de tiempo" className="w-auto">
<option>Últimos 7 días</option>
<option value="1">Últimos 15 días</option>
<option value="2">Últimos 30 días</option>
<Form.Select
aria-label="Periodo de tiempo"
className="w-auto"
onChange={handleDaysChange}
>
<option value="7">Últimos 7 días</option>
<option value="15">Últimos 15 días</option>
<option value="30">Últimos 30 días</option>
</Form.Select>
<Button variant="primary text-light">
Comparar con datos satelitales
Expand All @@ -188,8 +180,7 @@ const Dashboard = () => {
</b>
Su principal objetivo es monitorear y registrar las condiciones
climáticas locales, proporcionando datos precisos y en tiempo
real sobre la temperatura, humedad, velocidad del viento,
presión atmosférica y precipitación.
real.
</p>
{currentStation?.latitude && currentStation?.longitude ? (
<MapContainer
Expand Down Expand Up @@ -219,80 +210,44 @@ const Dashboard = () => {
)}
</Col>
<Row>
<Col md={6} className="mb-4">
<div className="bg-white rounded p-4 text-dark">
<h5>Temperatura máxima</h5>
<hr />
{/* <p>
La gráfica muestra la evolución de la temperatura máxima
registrada en la estación meteorológica{" "}
<b>{currentStation?.name}</b> durante los últimos{" "}
<b>7 días</b> días. En ella se destaca que el día con la
temperatura más alta fue el <b>{}</b>,
alcanzando un máximo de{" "}
<b>{Math.max(...data.tempMax.map((item) => item.value))}</b>
°C, mientras que el día más frío fue el [Fecha del día más
frío], con una temperatura de [Temperatura mínima]°C. Esta
visualización permite analizar las variaciones diarias de
temperatura y ofrece una referencia clara para identificar
patrones climáticos recientes en la región.
</p> */}
<Line
data={chartConfig(
"Temperatura Máxima (°C)",
data.tempMax,
"rgba(75,192,192,1)"
)}
options={chartOptions}
/>
</div>
</Col>

<Col md={6} className="mb-4">
<div className="bg-white rounded p-4 text-dark">
<h5>Temperatura mínima</h5>
<hr />
<Line
data={chartConfig(
"Temperatura Mínima (°C)",
data.tempMin,
"rgba(192,75,75,1)"
)}
options={chartOptions}
/>
</div>
</Col>
<WeatherChart
title="Temperatura Máxima"
data={data.tempMax}
unit="°C"
chartOptions={chartOptions}
chartConfig={chartConfig}
days={selectedDays}
color="rgba(163, 36, 36, 1)"
/>
<WeatherChart
title="Temperatura Mínima"
data={data.tempMin}
unit="°C"
chartOptions={chartOptions}
chartConfig={chartConfig}
days={selectedDays}
color="rgba(54, 227, 224, 1)"
/>
</Row>
<Row>
<Col md={6} className="mb-4">
<div className="bg-white rounded p-4 text-dark">
<h5>Precipitación</h5>
<hr />
<Line
data={chartConfig(
"Precipitación (mm)",
data.precipitation,
"rgba(75,75,192,1)"
)}
options={chartOptions}
/>
</div>
</Col>

<Col md={6} className="mb-4">
<div className="bg-white rounded p-4 text-dark">
<h5>Radiación Solar</h5>
<hr />
<Line
data={chartConfig(
"Radiación Solar (MJ)",
data.solRad,
"rgba(192,192,75,1)"
)}
options={chartOptions}
/>
</div>
</Col>
<WeatherChart
title="Precipitación"
data={data.precipitation}
unit="mm"
chartOptions={chartOptions}
chartConfig={chartConfig}
days={selectedDays}
color="rgba(26, 51, 237, 1)"
/>
<WeatherChart
title="Radiación Solar"
data={data.solRad}
unit="MJ"
chartOptions={chartOptions}
chartConfig={chartConfig}
days={selectedDays}
color="rgba(237, 185, 12, 1)"
/>
</Row>
</>
)}
Expand Down
43 changes: 32 additions & 11 deletions src/src/services/Services.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,51 @@ import Configuration from "../conf/Configuration";

const NICARAGUA_ID = "651437a78a8437279ea6ca2c";

class Services {
constructor() {
this.apiBaseUrl = Configuration.getAclimateApiUrl();
}
// Create an Axios instance with the base URL
const apiClient = axios.create({
baseURL: Configuration.aclimateApiUrl,
});

class Services {
/**
* Fetches all weather stations for Nicaragua.
* @returns {Promise<Object[]>} A promise that resolves to an array of weather stations.
* @throws Will throw an error if the request fails.
*/
async getAllWeatherStations() {
const url = `${this.apiBaseUrl}/geographic/${NICARAGUA_ID}/WeatherStations/json`;
const url = `/geographic/${NICARAGUA_ID}/WeatherStations/json`;
try {
const response = await axios.get(url);
const response = await apiClient.get(url);
return response.data;
} catch (error) {
console.error("Error fetching weather stations:", error);
throw error; // Propagar el error para que pueda manejarse a nivel superior
throw new Error(
"Failed to fetch weather stations. Please try again later."
);
}
}

/**
* Fetches daily weather data for a specific station.
* @param {number} month - The month for which to fetch data.
* @param {number} year - The year for which to fetch data.
* @param {string} stationId - The ID of the weather station.
* @returns {Promise<Object>} A promise that resolves to the daily weather data.
* @throws Will throw an error if the request fails.
*/
async getDailyWeather(month, year, stationId) {
const url = `${this.apiBaseUrl}/DailyWeatherData/Climatology/${stationId}/json?year=${year}&month=${month}`;
const url = `/DailyWeatherData/Climatology/${stationId}/json?year=${year}&month=${month}`;
try {
const response = await axios.get(url);
const response = await apiClient.get(url);
return response.data;
} catch (error) {
console.error(`Error fetching daily weather for station ${stationId}:`, error);
throw error;
console.error(
`Error fetching daily weather for station ${stationId}:`,
error
);
throw new Error(
`Failed to fetch daily weather for station ${stationId}. Please try again later.`
);
}
}
}
Expand Down

0 comments on commit 20bbca0

Please sign in to comment.