Skip to content

Commit

Permalink
get last data station added
Browse files Browse the repository at this point in the history
  • Loading branch information
Minotriz02 authored and Minotriz02 committed Oct 15, 2024
1 parent df9ef31 commit 080c865
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 99 deletions.
66 changes: 66 additions & 0 deletions src/src/components/stationPopup/StationPopup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React, { useMemo } from "react";
import { Marker, Popup, Tooltip } from "react-leaflet";
import { IconChartDonut } from "@tabler/icons-react";
import { Link } from "react-router-dom";
import L from "leaflet";

function StationPopup({ station, lastData }) {
const iconMarker = useMemo(
() =>
new L.Icon({
iconUrl: require("../../assets/img/marker.png"),
iconSize: [48, 48],
}),
[]
);

const renderClimaticData = (label, measure, unit) => (
<tr>
<td className="d-flex align-items-center me-2">{label}:</td>
<td>
{lastData?.climaticData
.find((item) => item.measure === measure)
?.value.toFixed(1) ?? "N/A"}{" "}
{unit}
</td>
</tr>
);

return (
<Marker position={[station.latitude, station.longitude]} icon={iconMarker}>
<Popup closeButton={false} className="popup">
<div className="text-dark">
<div className="d-flex align-items-center justify-content-between">
<h6 className="fw-medium mb-0 text-nowrap">
Estación {station.name}
</h6>
</div>
<p className="mt-0 mb-2">Fecha: {lastData?.date ?? "N/A"}</p>
</div>
<table className="fs-6 text-nowrap w-100 text-dark">
<tbody>
{renderClimaticData("Temperatura máxima", "t_max", "°C")}
{renderClimaticData("Temperatura mínima", "t_min", "°C")}
{renderClimaticData("Precipitación", "prec", "mm")}
{renderClimaticData("Radiación solar", "sol_rad", "MJ")}
</tbody>
</table>
<div className="d-flex justify-content-between flex-column align-items-end mt-3">
<Link
to={`/dashboard/${station.id}`}
className="btn btn-primary btn-sm text-light rounded-3 fw-medium d-flex align-items-center justify-content-between px-2 py-2 mx-2"
aria-label="Data"
>
<IconChartDonut stroke={2} className="me-2" />
Data
</Link>
</div>
</Popup>
<Tooltip direction="right" offset={[0, -5]} opacity={1} permanent>
{station.name}
</Tooltip>
</Marker>
);
}

export default StationPopup;
160 changes: 61 additions & 99 deletions src/src/pages/station/Station.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,73 @@
import React, { useState, useEffect, useRef } from "react";
import "./Station.css";
import { Modal, Spinner } from "react-bootstrap";
import {
MapContainer,
Marker,
Popup,
TileLayer,
Tooltip,
ZoomControl,
useMap,
} from "react-leaflet";
import { MapContainer, TileLayer, ZoomControl, useMap } from "react-leaflet";
import Services from "../../services/Services";
import L from "leaflet";
import { IconChartDonut } from "@tabler/icons-react";
import SearchBar from "../../components/searchBar/SearchBar";
import { Link } from "react-router-dom";
import StationPopup from "../../components/stationPopup/StationPopup";

const MapCenter = ({ stations }) => {
const map = useMap();

useEffect(() => {
if (stations.length > 0) {
const bounds = L.latLngBounds(
stations.map((station) => [station.latitude, station.longitude])
);
map.fitBounds(bounds);
}
}, [stations, map]);

return null;
};

function Station() {
const [stations, setStations] = useState([]);
const [loading, setLoading] = useState(true); // Manejo de estado de carga
const [error, setError] = useState(null); // Manejo de errores
const [lastDataStations, setLastDataStations] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const mapRef = useRef(null);

const iconMarker = new L.Icon({
iconUrl: require("../../assets/img/marker.png"),
iconSize: [48, 48],
});

useEffect(() => {
// Llamada a la API para obtener las estaciones
Services.getAllWeatherStations()
.then((response) => {
const fetchStations = async () => {
try {
const response = await Services.getAllWeatherStations();
const filteredStations = response.filter(
(item) => item.origin === "CHIRPS y ERA-5"
);
setStations(filteredStations);
setLoading(false); // Marcar como cargado
})
.catch((error) => {
} catch (error) {
console.error("Error al cargar las estaciones:", error);
setError("Error al cargar las estaciones");
setLoading(false); // Marcar como cargado aunque haya error
});
} finally {
setLoading(false);
}
};
fetchStations();
}, []);

const MapCenter = ({ stations }) => {
const map = useMap();
useEffect(() => {
if (stations.length === 0) return;

useEffect(() => {
if (stations.length > 0) {
const bounds = L.latLngBounds(
stations.map((station) => [station.latitude, station.longitude])
const fetchLastDailyWeather = async () => {
try {
setLoading(true);
const idsStations = stations.map((station) => station.id).join(",");
const response = await Services.getLastDailyWeather(idsStations);
setLastDataStations(response);
} catch (error) {
console.error(
"Error al cargar la última información de las estaciones:",
error
);
map.fitBounds(bounds); // Ajustar el mapa a los límites de las estaciones
setError("Error al cargar la última información de las estaciones");
} finally {
setLoading(false);
}
}, [stations, map]);

return null; // No es necesario renderizar nada
};
};
fetchLastDailyWeather();
}, [stations]);

const handleStationClick = (station) => {
const map = mapRef.current;
Expand All @@ -66,79 +76,20 @@ function Station() {
}
};

const renderPopupData = (station) => (
<Marker
position={[station.latitude, station.longitude]}
key={station.id}
icon={iconMarker}
>
<Popup closeButton={false} className="popup ">
<div className="text-dark">
<div className="d-flex align-items-center justify-content-between">
<h6 className="fw-medium mb-0 text-nowrap">
Estación {station.name}
</h6>
</div>
<p className="mt-0 mb-2">Fecha: 32</p>
</div>
<table className="fs-6 text-nowrap w-100 text-dark">
<tbody>
<tr>
<td className="d-flex align-items-center me-2">
Temperatura máxima:
</td>
<td>432</td>
</tr>
<tr>
<td className="d-flex align-items-center me-2">
Temperatura mínima:
</td>
<td>432</td>
</tr>
<tr>
<td className="d-flex align-items-center me-2">Precipitación:</td>
<td>432</td>
</tr>
<tr>
<td className="d-flex align-items-center me-2">
Radiación solar:
</td>
<td>432</td>
</tr>
</tbody>
</table>
<div className="d-flex justify-content-between flex-column align-items-end mt-3">
<Link
to={`/dashboard/${station.id}`}
className="btn btn-primary btn-sm text-light rounded-3 fw-medium d-flex align-items-center justify-content-between px-2 py-2 mx-2"
aria-label="Data"
>
<IconChartDonut stroke={2} className="me-2" />
Data
</Link>
</div>
</Popup>
<Tooltip direction="right" offset={[0, -5]} opacity={1} permanent>
{station.name}
</Tooltip>
</Marker>
);

if (error) {
return <p>{error}</p>; // Mostrar mensaje de error
return <p>{error}</p>;
}

return (
<>
{/* Modal de loading */}
<Modal
show={loading}
backdrop="static"
keyboard={false}
centered
size="sm"
>
<Modal.Body className="d-flex align-items-center ">
<Modal.Body className="d-flex align-items-center">
<Spinner animation="border" role="status" className="me-2" />
Obteniendo estaciones...
</Modal.Body>
Expand All @@ -154,7 +105,18 @@ function Station() {
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<ZoomControl position="topright" />
{stations.map((station) => renderPopupData(station))}
{stations.map((station) => {
const lastData = lastDataStations.find(
(item) => item.weather_station === station.id
);
return (
<StationPopup
key={station.id}
station={station}
lastData={lastData}
/>
);
})}
<MapCenter stations={stations} />
</MapContainer>
<SearchBar
Expand Down
22 changes: 22 additions & 0 deletions src/src/services/Services.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,28 @@ class Services {
);
}
}

/**
* Fetches last daily weather data for a specific station.
* @param {Array} stationId - The IDs of the weather stations.
* @returns {Promise<Object>} A promise that resolves to the daily weather data.
* @throws Will throw an error if the request fails.
*/
async getLastDailyWeather(stationsIds) {
const url = `/DailyWeatherData/LastDailyData/${stationsIds}/json`;
try {
const response = await apiClient.get(url);
return response.data;
} catch (error) {
console.error(
`Error fetching last daily weather for station ${stationsIds}:`,
error
);
throw new Error(
`Failed to fetch last daily weather for station ${stationsIds}. Please try again later.`
);
}
}
}

export default new Services();

0 comments on commit 080c865

Please sign in to comment.