1
- import { AmdbLayerName , getAmdbAPI } from "@navigraph/amdb"
2
- import { useQueries } from "@tanstack/react-query"
1
+ import { AmdbLayerName } from "@navigraph/amdb"
3
2
import { circleMarker , geoJson , GeoJSON } from "leaflet"
4
3
import { memo , useEffect , useRef } from "react"
5
4
import { renderToString } from "react-dom/server"
6
5
import { useMap } from "react-leaflet"
7
6
import { useRecoilValue } from "recoil"
7
+ import useAmdbLayers from "../../hooks/useAmdbLayers"
8
8
import { amdbLayersState } from "../../state/amdb"
9
9
import JsonView from "../JsonView"
10
10
import amdbStyle , { layerOrder } from "./amdbStyle"
11
11
12
- const AmdbManager = memo ( ( ) => {
13
- const amdb = getAmdbAPI ( )
14
-
12
+ /**
13
+ * Handles the rendering of AMDB layers to the map for a specific airport
14
+ */
15
+ function AmdbLayer ( { idarpt, layerNames } : { idarpt : string ; layerNames : AmdbLayerName [ ] } ) {
15
16
const map = useMap ( )
16
17
17
- const amdbLayers = useRecoilValue ( amdbLayersState )
18
-
19
- const data = useQueries ( {
20
- queries : amdbLayers . flatMap ( ( [ idarpt , layers ] ) =>
21
- layers . map ( layer => ( {
22
- queryKey : [ "amdb-data" , idarpt , layer ] ,
23
- queryFn : async ( ) => ( { idarpt, layer, data : await amdb . getAmdbLayer ( { icao : idarpt , layer } ) } ) ,
24
- } ) ) ,
25
- ) ,
26
- } )
18
+ const data = useAmdbLayers ( idarpt , layerNames )
27
19
28
- const layers = useRef < { idarpt : string ; layerName : AmdbLayerName ; layer : GeoJSON } [ ] > ( [ ] )
20
+ // Store references to the layer instances
21
+ const layers = useRef < { layerName : AmdbLayerName ; layer : GeoJSON } [ ] > ( [ ] )
29
22
23
+ // This use effect will run each time the layer data or layers to render has (probably) updated
30
24
useEffect ( ( ) => {
31
- const toRemove = layers . current . filter (
32
- ( { idarpt, layerName } ) => ! data . some ( ( { data } ) => data ?. idarpt === idarpt && data ?. layer === layerName ) ,
33
- )
25
+ // Find layers which are no longer present in the queried data
26
+ const toRemove = layers . current . filter ( ( { layerName } ) => ! data . some ( ( [ _layerName ] ) => _layerName === layerName ) )
34
27
28
+ // Remove these layers from the map and from the stored references
35
29
toRemove . forEach ( ( { layer } ) => {
36
30
map . removeLayer ( layer )
37
31
layers . current . splice (
@@ -40,20 +34,17 @@ const AmdbManager = memo(() => {
40
34
)
41
35
} )
42
36
43
- const newLayers = data . flatMap ( ( { data } ) => {
44
- if (
45
- data ?. data &&
46
- ! layers . current . some ( ( { idarpt, layerName } ) => idarpt === data . idarpt && layerName === data . layer )
47
- ) {
37
+ // Create layers which there is now queried data for, but no stored layer for it
38
+ const newLayers = data . flatMap ( ( [ layerName , data ] ) => {
39
+ if ( data && ! layers . current . some ( x => x . layerName === layerName ) ) {
48
40
return [
49
41
{
50
- idarpt : data . idarpt ,
51
- layerName : data . layer ,
52
- layer : geoJson ( data . data , {
53
- style : amdbStyle ( data . layer ) ,
42
+ layerName,
43
+ layer : geoJson ( data , {
44
+ style : amdbStyle ,
54
45
55
46
pointToLayer : ( feature , latlng ) => {
56
- const marker = circleMarker ( latlng , amdbStyle ( data . layer ) ( feature ) )
47
+ const marker = circleMarker ( latlng , amdbStyle ( feature ) )
57
48
58
49
marker . feature = feature
59
50
@@ -67,7 +58,7 @@ const AmdbManager = memo(() => {
67
58
const feature = target . feature
68
59
69
60
if ( feature ?. type === "Feature" ) {
70
- const style = amdbStyle ( data . layer ) ( feature )
61
+ const style = amdbStyle ( feature )
71
62
72
63
style . stroke = true
73
64
style . color = "blue"
@@ -84,8 +75,8 @@ const AmdbManager = memo(() => {
84
75
_layer . bindPopup (
85
76
renderToString (
86
77
< div className = "flex flex-col items-center gap-2" >
87
- < span className = "text-ng-background-200" > { data . layer } </ span >
88
- < JsonView content = { feature . properties } />
78
+ < span className = "text-ng-background-200" > { layerName } </ span >
79
+ < JsonView content = { feature . properties as unknown } />
89
80
</ div > ,
90
81
) ,
91
82
)
@@ -99,17 +90,28 @@ const AmdbManager = memo(() => {
99
90
return [ ]
100
91
} )
101
92
102
- newLayers . forEach ( ( { idarpt, layerName, layer } ) => {
93
+ // Add the new layers to the map and store the references
94
+ newLayers . forEach ( ( { layerName, layer } ) => {
103
95
map . addLayer ( layer )
104
- layers . current . push ( { idarpt , layerName, layer } )
96
+ layers . current . push ( { layerName, layer } )
105
97
} )
106
98
99
+ // Sort the layers and bring them to front in that correct order to ensure they appear in the correct order on the map
107
100
layers . current
108
101
. sort ( ( a , b ) => layerOrder [ b . layerName ] - layerOrder [ a . layerName ] )
109
102
. forEach ( ( { layer } ) => layer . bringToFront ( ) )
110
103
} , [ data , map ] )
111
104
112
105
return null
106
+ }
107
+
108
+ /**
109
+ * Handles the rendering of selected AMDB layers from selected airports to the leaflet map
110
+ */
111
+ const AmdbManager = memo ( ( ) => {
112
+ const amdbLayers = useRecoilValue ( amdbLayersState )
113
+
114
+ return amdbLayers . map ( ( [ idarpt , layerNames ] ) => < AmdbLayer idarpt = { idarpt } layerNames = { layerNames } /> )
113
115
} )
114
116
115
117
export default AmdbManager
0 commit comments