diff --git a/src/src/components/stationPopup/StationPopup.js b/src/src/components/stationPopup/StationPopup.js new file mode 100644 index 0000000..f0250a8 --- /dev/null +++ b/src/src/components/stationPopup/StationPopup.js @@ -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) => ( + + {label}: + + {lastData?.climaticData + .find((item) => item.measure === measure) + ?.value.toFixed(1) ?? "N/A"}{" "} + {unit} + + + ); + + return ( + + +
+
+
+ Estación {station.name} +
+
+

Fecha: {lastData?.date ?? "N/A"}

+
+ + + {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")} + +
+
+ + + Data + +
+
+ + {station.name} + +
+ ); +} + +export default StationPopup; diff --git a/src/src/pages/station/Station.js b/src/src/pages/station/Station.js index ca4c181..d006b12 100644 --- a/src/src/pages/station/Station.js +++ b/src/src/pages/station/Station.js @@ -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; @@ -66,71 +76,12 @@ function Station() { } }; - const renderPopupData = (station) => ( - - -
-
-
- Estación {station.name} -
-
-

Fecha: 32

-
- - - - - - - - - - - - - - - - - - - -
- Temperatura máxima: - 432
- Temperatura mínima: - 432
Precipitación:432
- Radiación solar: - 432
-
- - - Data - -
-
- - {station.name} - -
- ); - if (error) { - return

{error}

; // Mostrar mensaje de error + return

{error}

; } return ( <> - {/* Modal de loading */} - + Obteniendo estaciones... @@ -154,7 +105,18 @@ function Station() { url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" /> - {stations.map((station) => renderPopupData(station))} + {stations.map((station) => { + const lastData = lastDataStations.find( + (item) => item.weather_station === station.id + ); + return ( + + ); + })} } 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();