Files
aviation/ui/src/components/AirportMarker.tsx
2025-04-20 13:14:40 -04:00

100 lines
2.6 KiB
TypeScript

import { Airport, AirportCategory } from '@lib/airport.types.ts';
import { Marker, Popup } from 'react-leaflet';
import L from 'leaflet';
import { useRef } from 'react';
import { getMarkerColor } from '@lib/metar.types.ts';
import { LayerInfo } from '@/App.tsx';
export default function AirportMarker({
index,
airport,
setAirport,
selectedLayer
}: {
index: number;
airport: Airport;
setAirport: (airport: Airport) => void;
selectedLayer: LayerInfo;
}) {
const icon = createCustomIcon(airport, selectedLayer);
const markerRef = useRef<L.Marker>(null);
return (
<Marker
key={index}
ref={markerRef}
position={[airport.latitude, airport.longitude]}
icon={icon}
eventHandlers={{
click: () => setAirport(airport),
mouseover: () => markerRef.current?.openPopup(),
mouseout: () => markerRef.current?.closePopup()
}}
>
<Popup closeButton={false} autoPan={false} interactive={false}>
{airport.icao} - {airport.name}
</Popup>
</Marker>
);
}
function createCustomIcon(airport: Airport, selectedLayer: LayerInfo): L.DivIcon {
if (airport.category === AirportCategory.HELIPORT) {
return L.divIcon({
html: `
<div style="
width: 14px;
height: 14px;
border-radius: 50%;
border: 2px solid black;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
z-index: {info[1]}">
<span style="color: black; font-size: 8px; font-weight: bold;">H</span>
</div>
`,
className: '',
iconSize: [20, 20],
iconAnchor: [10, 10]
});
} else {
// Default to a filled circle.
const flightCategory = airport.latest_metar?.flight_category || 'UNKN';
const color = getMarkerColor(flightCategory);
if (flightCategory == 'UNKN') {
return L.divIcon({
html: `
<div style="
background-color: ${color};
width: 10px;
height: 10px;
border-radius: 50%;
z-index: {info[1]}">
</div>
`,
className: '',
iconSize: [20, 20],
iconAnchor: [10, 10]
});
} else {
return L.divIcon({
html: `
<div style="
background-color: ${color};
width: 18px;
height: 18px;
border-radius: 50%;
border: 2px solid ${selectedLayer.markerOutline};
z-index: {info[1]}">
</div>
`,
className: '',
iconSize: [20, 20],
iconAnchor: [10, 10]
});
}
}
}