conectado nearby

This commit is contained in:
Pablo Ferreiro 2024-10-17 20:14:05 +02:00
parent 51fdd88378
commit 266d1605d4
5 changed files with 141 additions and 7 deletions

View File

@ -11,6 +11,10 @@ export default class Api {
return Api._makeReq(`/embalses/${id}`); return Api._makeReq(`/embalses/${id}`);
} }
static async embalsesNearby(lat: string, lon: string): Promise<Embalse[]> {
return Api._makeReq(`/embalsesCercanos/${lat}/${lon}`);
}
static async _makeReq<T>(endpoint: string): Promise<T[]> { static async _makeReq<T>(endpoint: string): Promise<T[]> {
let hasMore = true; let hasMore = true;

View File

@ -0,0 +1,36 @@
import OWMResponse from "../interfaces/OWMResponse";
/**
* Wrapper para recibir los datos del clima de OpenWeatherMap
*/
export default class OpenWeather {
static async week(lat: string, lon: string): Promise<string> {
const res = await fetch('https://api.openweathermap.org/data/2.5/forecast?lat=' + lat + '&lon=' + lon + '&appid=' + import.meta.env.VITE_OWM_KEY);
if (!res.ok) {
throw new Error("API Error");
}
const json = await res.json() as OWMResponse;
let rains = 0;
json.list.forEach((el) => {
if (el.weather[0].id === 500) {
rains++;
}
});
let probability = '';
if (rains > json.list.length / 2) {
// Bien
probability = 'Sabiendo que ha llovido un total de ' + rains + ' días, podemos predecir que el caudal será alto';
} else {
// Mal
probability = 'Sabiendo que ha llovido un total de ' + rains + ' días, podemos predecir que el caudal será bajo';
}
return probability;
}
}

View File

@ -0,0 +1,68 @@
export default interface OWMResponse {
cod: string
message: number
cnt: number
list: Weather[]
city: City
}
export interface Weather {
dt: number
main: Main
weather: Weather[]
clouds: Clouds
wind: Wind
visibility: number
pop: number
sys: Sys
dt_txt: string
}
export interface Main {
temp: number
feels_like: number
temp_min: number
temp_max: number
pressure: number
sea_level: number
grnd_level: number
humidity: number
temp_kf: number
}
export interface Weather {
id: number
main: string
description: string
icon: string
}
export interface Clouds {
all: number
}
export interface Wind {
speed: number
deg: number
gust: number
}
export interface Sys {
pod: string
}
export interface City {
id: number
name: string
coord: Coord
country: string
population: number
timezone: number
sunrise: number
sunset: number
}
export interface Coord {
lat: number
lon: number
}

View File

@ -5,19 +5,22 @@ import Navbar from "../partials/Navbar";
import Loader from "../partials/Loader"; import Loader from "../partials/Loader";
import Api from "../helpers/Api"; import Api from "../helpers/Api";
import Card from "../partials/Card"; import Card from "../partials/Card";
import { FaSolidLocationDot, FaSolidLocationPin, FaSolidMapLocationDot, FaSolidWater } from "solid-icons/fa"; import { FaSolidCircleInfo, FaSolidLocationDot, FaSolidMapLocationDot, FaSolidWater } from "solid-icons/fa";
import OpenWeather from "../helpers/OpenWeather";
interface CustomParams extends Params { interface CustomParams extends Params {
id: string; id: string;
} }
function Embalse() { function Embalse() {
const params = useParams<CustomParams>(); const params = useParams<CustomParams>();
const [embalse, setEmbalse] = createSignal<EmbalseType>(); const [embalse, setEmbalse] = createSignal<EmbalseType>();
const [prediction, setPrediction] = createSignal('');
onMount(() => { onMount(() => {
getEmbalse(); getEmbalse().then(async () => {
setPrediction(await OpenWeather.week(embalse()!.x, embalse()!.y));
});
}); });
const getEmbalse = async () => { const getEmbalse = async () => {
@ -26,6 +29,17 @@ function Embalse() {
setEmbalse(res[0]); setEmbalse(res[0]);
} }
const getPercentage = () => {
const perc = Math.round(embalse()!.agua_actual / embalse()!.agua_total * 100);
return (
<span classList={{
'has-text-danger': perc <= 50,
'has-text-warning': perc > 50 && perc < 70,
'has-text-success': perc >= 70
}}>{perc}%</span>
)
}
return ( return (
<> <>
<Navbar /> <Navbar />
@ -59,10 +73,15 @@ function Embalse() {
<> <>
<p><b>Actual</b>: {embalse()!.agua_actual} l/m2</p> <p><b>Actual</b>: {embalse()!.agua_actual} l/m2</p>
<p><b>Total</b>: {embalse()!.agua_total} l/m2</p> <p><b>Total</b>: {embalse()!.agua_total} l/m2</p>
<p><b>Porcentaje</b>: {embalse()!.agua_actual / embalse()!.agua_total * 100}%</p> <p><b>Porcentaje</b>: {getPercentage()}</p>
</> </>
</Card> </Card>
</div> </div>
<div class="column is-narrow">
<Card title="Predicción" icon={<FaSolidCircleInfo />}>
<p>{prediction()}</p>
</Card>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,9 +1,12 @@
import { createSignal, onCleanup, onMount } from "solid-js"; import { createSignal, onCleanup, onMount } from "solid-js";
import L from 'leaflet'; import { useNavigate } from "@solidjs/router";
import L, { Icon } from 'leaflet';
import { FaSolidLocationPin } from "solid-icons/fa"; import { FaSolidLocationPin } from "solid-icons/fa";
import Navbar from "../partials/Navbar"; import Navbar from "../partials/Navbar";
import Api from "../helpers/Api";
function Finder() { function Finder() {
const navigate = useNavigate();
const [pos, setPos] = createSignal<[number, number]>([0, 0]); const [pos, setPos] = createSignal<[number, number]>([0, 0]);
const [geo, setGeo] = createSignal(true); const [geo, setGeo] = createSignal(true);
@ -73,7 +76,7 @@ function Finder() {
* Escribe los puntos relevantes * Escribe los puntos relevantes
* (Mi ubicación y los embalses cercanos) * (Mi ubicación y los embalses cercanos)
*/ */
const handleLocation = () => { const handleLocation = async () => {
me.setLatLng(pos()); me.setLatLng(pos());
if (first) { if (first) {
map.setView(pos(), 9); map.setView(pos(), 9);
@ -90,7 +93,11 @@ function Finder() {
markers = []; markers = [];
} }
// TODO: Hacer petición y sacar markers const res = await Api.embalsesNearby(pos()[0].toString(), pos()[1].toString());
res.forEach((c) => {
L.marker([parseFloat(c.x), parseFloat(c.y)]).on("click", () => navigate('/embalses/' + c.id)).addTo(map);
})
} }
/** /**