diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 3beaf5a..a71635c 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -8,9 +8,11 @@ import markerShadow from 'leaflet/dist/images/marker-shadow.png'; import L from 'leaflet'; import { Header } from '@components/Header'; import AirportLayer from '@components/AirportLayer.tsx'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { Airport } from '@lib/airport.types.ts'; import AirportDrawer from '@components/AirportDrawer.tsx'; +import { getWeatherMapUrl } from '@lib/rainViewer.ts'; +import { Switch } from '@mantine/core'; // Fix Leaflet's default icon path issues with Webpack // eslint-disable-next-line @typescript-eslint/ban-ts-comment @@ -24,13 +26,22 @@ L.Icon.Default.mergeOptions({ }); const openStreetMapUrl = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'; -// const rainViewerUrl = 'https://tilecache.rainviewer.com/v2/radar/{time}/256/10/290/391/2/1_1.png' -// https://api.rainviewer.com/public/weather-maps.json const defaultZoom = 6; const defaultCenter: L.LatLngExpression = [38.944444, -77.455833]; function App() { const [airport, setAirport] = useState(null); + const [rainViewerUrl, setRainViewerUrl] = useState(null); + const [showRadar, setShowRadar] = useState(false); + + useEffect(() => { + if (showRadar) { + getWeatherMapUrl().then(url => { + setRainViewerUrl(url); + }); + } + }, [showRadar]) + return (
@@ -52,8 +63,21 @@ function App() { > + { rainViewerUrl && showRadar && ( + + )} +
+ setShowRadar(event.currentTarget.checked)} + /> +
); diff --git a/ui/src/lib/rainViewer.ts b/ui/src/lib/rainViewer.ts new file mode 100644 index 0000000..eeeb32c --- /dev/null +++ b/ui/src/lib/rainViewer.ts @@ -0,0 +1,36 @@ +import { WeatherMaps } from '@lib/rainViewer.types.ts'; + +const weatherMapsUrl = 'https://api.rainviewer.com/public/weather-maps.json'; + +async function getWeatherMaps(): Promise { + const response = await fetch(`${weatherMapsUrl}`, { + method: 'GET', + }); + if (response?.status === 200) { + return response.json(); + } else { + return undefined; + } +} + +// const rainViewerUrl = 'https://tilecache.rainviewer.com/v2/radar/1744386000/256/{z}/{x}/{y}/2/1_1.png'; +// const rainViewerUrl = 'https://tilecache.rainviewer.com/v2/radar/1744386000/256/10/290/391/2/1_1.png' +// https://api.rainviewer.com/public/weather-maps.json +export async function getWeatherMapUrl(): Promise { + const weatherMaps = await getWeatherMaps(); + if (weatherMaps != undefined) { + let url = weatherMaps.host; + let latest = ""; + if (weatherMaps.radar.nowcast.length > 0) { + latest = weatherMaps.radar.nowcast[weatherMaps.radar.nowcast.length - 1].path; + } else if (weatherMaps.radar.past.length > 0) { + latest = weatherMaps.radar.past[weatherMaps.radar.past.length - 1].path; + } else { + return null; + } + url += latest + "/256/{z}/{x}/{y}/2/1_1.png"; + return url; + } else { + return null; + } +} \ No newline at end of file diff --git a/ui/src/lib/rainViewer.types.ts b/ui/src/lib/rainViewer.types.ts new file mode 100644 index 0000000..141dce7 --- /dev/null +++ b/ui/src/lib/rainViewer.types.ts @@ -0,0 +1,21 @@ +export interface WeatherMaps { + version: string; + generated: number; + host: string; + radar: RadarObject; + satellite: SatelliteObject; +} + +export interface RadarObject { + past: FrameObject[]; + nowcast: FrameObject[]; +} + +export interface SatelliteObject { + infrared: FrameObject[]; +} + +export interface FrameObject { + time: number; + path: string; +} \ No newline at end of file