Skip to content

Commit

Permalink
weather card started and features updated
Browse files Browse the repository at this point in the history
  • Loading branch information
Minotriz02 committed Nov 12, 2024
1 parent d8f7e8d commit 2d5e43f
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 12 deletions.
16 changes: 16 additions & 0 deletions src/src/components/stationCard/StationCard.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.wave1 {
position: absolute;
top: 0px;
right: -16px;
rotate: 0grad;
width: 100%;
height: 100px; /* Ajusta el tamaño del área de la onda */
z-index: 0;
overflow: hidden;
}

.wave1 > svg {
position: absolute;
top: -20px; /* Ajusta la posición vertical de la onda */
right: 0;
}
141 changes: 141 additions & 0 deletions src/src/components/stationCard/StationCard.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React, { useEffect, useState } from "react";
import "./StationCard.css";
import { Card, Col, Spinner } from "react-bootstrap";
import { IconDroplet, IconMapPin, IconSun } from "@tabler/icons-react";
import Services from "../../services/Services";

function StationCard({ loading, msgError, station }) {
const [lastDataStation, setLastDataStation] = useState();

console.log(station);

useEffect(() => {
if (!station) return;

const fetchLastDailyWeather = async () => {
try {
const idStations = station.id;
const response = await Services.getLastDailyWeather(idStations);
setLastDataStation(response);
console.log(response);
} catch (error) {
console.error(
"Error al cargar la última información de las estaciones:",
error
);
} finally {
}
};
fetchLastDailyWeather();
}, [station]);

const getDayOfWeek = (dateString) => {
const date = new Date(dateString);
return date.toLocaleDateString("es-ES", { weekday: "long" });
};

return (
<Col className="col-12 col-md-6 col-xl-4">
<Card className="position-relative overflow-hidden border-0">
{/* Onda SVG */}
<div className="wave1">
<svg
width="177"
height="95"
viewBox="0 0 355 190"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M385.398 12.4147L0 4.31812C14.6818 32.8181 56.8561 96.2594 104.446 99.3181C141.061 103.276 257.166 119.359 282.031 136.832C311.989 157.883 368.035 187.301 385.398 190V12.4147Z"
fill="#411010"
/>
<path
d="M434.517 9.71582L444.503 158.963C357.599 136.832 302.812 121.449 256.932 89.3323C211.051 57.2158 149.787 82.0454 103.097 71.2499C65.7443 62.6135 54.0672 29.6874 52.8977 14.3039L434.517 9.71582Z"
fill="#8D5D33"
/>
<path
d="M398.082 0H32.926C47.6078 28.5 146.458 41.7424 194.048 44.8011C230.663 48.7595 308.102 62.1818 324.943 84.2046C341.784 106.227 380.72 117.131 398.082 119.83V0Z"
fill="#D2A859"
/>
</svg>
</div>
{loading ? (
<div className="text-center my-5">
<Spinner animation="border" />
<p>Cargando datos...</p>
</div>
) : msgError ? (
<div className="text-center my-5">
<p>{msgError}</p>
</div>
) : station ? (
<Card.Body className="position-relative">
<div className="d-flex justify-content-between">
<div className="">
<div className="mb-4">
<h4 className="mb-0">{station.name}</h4>
<span>
{lastDataStation?.climaticData
? lastDataStation.climaticData
.find((item) => item.measure === "t_min")
?.value.toFixed(1) ?? "N/A"
: "N/A"}{" "}
-{" "}
{lastDataStation?.climaticData
? lastDataStation.climaticData
.find((item) => item.measure === "t_max")
?.value.toFixed(1) ?? "N/A"
: "N/A"}
</span>
</div>
<div className="d-flex flex-column gap-1">
<span className="d-flex ">
<IconDroplet size={24} className="me-2" />
{lastDataStation?.climaticData
? lastDataStation.climaticData
.find((item) => item.measure === "prec")
?.value.toFixed(1) ?? "N/A"
: "N/A"}{" "}
mm
</span>
<span className="d-flex">
<IconSun size={24} className="me-2" />
{lastDataStation?.climaticData
? lastDataStation.climaticData
.find((item) => item.measure === "sol_rad")
?.value.toFixed(1) ?? "N/A"
: "N/A"}{" "}
M/J
</span>
</div>
</div>
<div className="d-flex flex-column justify-content-between align-items-end">
<div className="d-flex flex-column align-items-end">
<span>
{lastDataStation?.date
? getDayOfWeek(lastDataStation.date)
: "N/A"}
</span>
<span>{lastDataStation?.date ?? "N/A"}</span>
</div>
<div>
<span>
<IconMapPin size={24} className="me-2" />
{station.municipality}, {station.state}
</span>
</div>
</div>
</div>
</Card.Body>
) : (
<div className="text-center my-5">
<p>No se ha seleccionado ninguna estación</p>
</div>
)}
</Card>
</Col>
);
}

export default StationCard;
2 changes: 1 addition & 1 deletion src/src/pages/dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const Dashboard = () => {
try {
const response = await Services.getAllWeatherStations();
const filteredStations = response.filter(
(item) => item.origin === "CHIRPS y ERA-5"
(item) => item.origin === "WEATHERLINK"
);
const station = filteredStations.find((item) => item.id === idWS);
setStations(filteredStations);
Expand Down
6 changes: 3 additions & 3 deletions src/src/pages/home/Home.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
url("../../assets/img/bg-home.jpg");
background-size: cover;
background-position: center;
min-height: 80vh;
min-height: 90vh;
}

.container-header {
/* .container-header {
position: relative;
top: 150px;
}
} */
103 changes: 98 additions & 5 deletions src/src/pages/home/Home.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useEffect, useState } from "react";
import "./Home.css";
import { Col, Container, Row } from "react-bootstrap";
import Feature from "../../components/feature/Feature";
Expand All @@ -8,17 +8,107 @@ import {
IconMapSearch,
IconCloudRain,
} from "@tabler/icons-react";
import StationCard from "../../components/stationCard/StationCard";
import Services from "../../services/Services";

function Home() {
// Definir colores en una variable para facilitar ajustes globales
const green = "green";
const white = "white";

const [stations, setStations] = useState([]);
const [nearestStation, setNearestStation] = useState([]);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);

useEffect(() => {
const fetchStations = async () => {
try {
const response = await Services.getAllWeatherStations();
const filteredStations = response.filter(
(item) => item.origin === "WEATHERLINK"
);
setStations(filteredStations);
} catch (error) {
console.error("Error al cargar las estaciones:", error);
setError("Error al cargar las estaciones");
} finally {
setLoading(false);
}
};

fetchStations();
}, []);

useEffect(() => {
const getUserLocation = () => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position) => {
const userLat = position.coords.latitude;
const userLon = position.coords.longitude;
findNearestStation(userLat, userLon);
},
(error) => {
console.error("Error al obtener la ubicación del usuario:", error);
setError("Error al obtener la ubicación del usuario");
setLoading(false);
}
);
} else {
console.error("Geolocalización no es soportada por este navegador.");
setError("Geolocalización no es soportada por este navegador.");
setLoading(false);
}
};

const findNearestStation = (userLat, userLon) => {
let minDistance = Infinity;
let nearest = null;

stations.forEach((station) => {
const distance = getDistanceFromLatLonInKm(
userLat,
userLon,
station.latitude,
station.longitude
);
if (distance < minDistance) {
minDistance = distance;
nearest = station;
}
});

setNearestStation(nearest);
setLoading(false);
};

const getDistanceFromLatLonInKm = (lat1, lon1, lat2, lon2) => {
const R = 6371; // Radio de la Tierra en km
const dLat = deg2rad(lat2 - lat1);
const dLon = deg2rad(lon2 - lon1);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2rad(lat1)) *
Math.cos(deg2rad(lat2)) *
Math.sin(dLon / 2) *
Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c; // Distancia en km
return distance;
};

const deg2rad = (deg) => {
return deg * (Math.PI / 180);
};
getUserLocation();
}, [stations]);

return (
<div>
{/* Sección de bienvenida */}
<div className="header-bg">
<Container className="container-header">
<div className="header-bg align-content-center">
<Container className="container-header pt-3">
<Row className="justify-content-between flex-column flex-md-row">
<Col className="col-12 col-md-7 col-lg-5 d-flex flex-column gap-2 mb-5 mb-md-0">
<h1 className="text-light">Bienvenido a AClimate monitoring</h1>
Expand All @@ -37,14 +127,17 @@ function Home() {
</Link>
</Col>
</Row>
<Row className="mt-4 justify-content-around gy-4">
<StationCard loading={loading} msgError={error} station={nearestStation} />
</Row>
</Container>
</div>

{/* Sección de características */}
<Row className="g-0">
<Feature
title="Mapa interactivo de estaciones climáticas"
description="Consulta en un mapa interactivo la ubicación y datos en tiempo real de las estaciones climáticas, incluyendo temperaturas, precipitaciones y más."
description="Consulta en un mapa interactivo la ubicación y datos históricos climáticos de las estaciones climatológicas, incluyendo temperaturas, precipitaciones y más."
image={IconMapSearch}
color={green}
/>
Expand All @@ -56,7 +149,7 @@ function Home() {
/>
<Feature
title="Comparación de datos climáticos con otras fuentes"
description="Compara los datos del dashboard con otras bases de datos climáticas, detectando patrones y obteniendo insights más precisos para tus análisis."
description="Compara los datos de las estaciones climatológicas con otras bases de datos satelitales como CHIRPS y AgERA5."
image={IconCloudRain}
color={green}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/src/pages/station/Station.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function Station() {
try {
const response = await Services.getAllWeatherStations();
const filteredStations = response.filter(
(item) => item.origin === "CHIRPS y ERA-5"
(item) => item.origin === "WEATHERLINK"
);
setStations(filteredStations);
} catch (error) {
Expand Down
26 changes: 24 additions & 2 deletions src/src/services/Services.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,32 @@ class Services {
* @throws Will throw an error if the request fails.
*/
async getAllWeatherStations() {
const url = `/geographic/${COUNTRY_ID}/WeatherStations/json`;
const url = `/geographic/${COUNTRY_ID}/json`;
try {
const response = await apiClient.get(url);
return response.data;
const data = response.data;

// Flatten the response to extract the weather stations
const weatherStations = [];

data.forEach((state) => {
const stateName = state.name;

state.municipalities.forEach((municipality) => {
const municipalityName = municipality.name;

municipality.weather_stations.forEach((station) => {
// Add municipality and state to each weather station
weatherStations.push({
...station,
municipality: municipalityName,
state: stateName,
});
});
});
});

return weatherStations;
} catch (error) {
console.error("Error fetching weather stations:", error);
throw new Error(
Expand Down

0 comments on commit 2d5e43f

Please sign in to comment.