2025-07-14 03:31:57 +02:00

117 lines
3.3 KiB
TypeScript

import { MapContainer, GeoJSON, TileLayer } from "react-leaflet";
import Parser from "./parser/parser";
import { createRef, useEffect, useState } from "react";
import hash from "object-hash";
import Leaflet from "leaflet";
import L from "leaflet";
const parser = await Parser.instance();
const terminals = [10394, 10395, 10475, 10480, 10482, 10485, 10653];
function App() {
const [selectedTerminal, setSelectedTerminal] = useState(terminals[0]);
const [procedure, setProcedure] = useState<string>();
const mapRef = createRef<Leaflet.Map>();
const layerRef = createRef<Leaflet.GeoJSON>();
useEffect(() => {
(async () => {
setProcedure(await parser.parse(selectedTerminal));
})();
}, [selectedTerminal]);
useEffect(() => {
if (layerRef.current && mapRef.current) {
mapRef.current.flyToBounds(layerRef.current.getBounds(), {
animate: false,
padding: [50, 50],
});
}
});
return (
<div style={{ display: "flex", height: "100vh", width: "100vw" }}>
<MapContainer
center={[51.505, -0.09]}
zoom={13}
zoomSnap={0}
zoomDelta={0.1}
wheelPxPerZoomLevel={1000}
style={{ height: "100%", width: "100%" }}
ref={mapRef}
>
<TileLayer
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<GeoJSON
key={hash(procedure ?? "") + "lines"}
data={procedure}
style={{
color: "#00ffff",
stroke: true,
weight: 5,
opacity: 1,
}}
filter={(feature) => feature.geometry.type !== "Point"}
ref={layerRef}
/>
<GeoJSON
key={hash(procedure ?? "") + "points"}
data={procedure}
style={(feature) => ({
color: feature.properties["marker-color"],
stroke: false,
fill: true,
fillOpacity: 1,
})}
pointToLayer={(_, latlng) => {
return L.circleMarker(latlng, { radius: 5 });
}}
onEachFeature={({ geometry, properties }, layer) => {
if (geometry.type === "Point") {
layer.bindPopup(
`${properties.name}<br>
${properties.altitude} ft<br>
${properties.speed} kts<br>
CNSTR:
${properties.altitudeConstraint ?? ""}
${properties.speedConstraint ?? ""}<br>`
);
}
}}
filter={(feature) => feature.geometry.type === "Point"}
/>
</MapContainer>
<div
style={{
padding: "5px",
display: "flex",
flexDirection: "column",
gap: "10px",
}}
>
{terminals.map((terminal) => (
<div
key={terminal}
style={{
display: "flex",
gap: "10px",
background: selectedTerminal === terminal ? "#eeeeee" : undefined,
}}
>
<pre>ID {terminal}</pre>
<button onClick={() => setSelectedTerminal(terminal)}>
Select
</button>
</div>
))}
</div>
</div>
);
}
export default App;