1
+ import { RefObject , useEffect } from 'react' ;
1
2
import { get } from 'lodash' ;
2
- import { Layer , Source } from 'react-map-gl/maplibre' ;
3
+ import { Layer , MapRef , Source } from 'react-map-gl/maplibre' ;
3
4
import { useSelector } from 'react-redux' ;
4
5
import { addPopupData } from 'context/tooltipStateSlice' ;
5
6
import {
@@ -33,6 +34,7 @@ import {
33
34
import { opacitySelector } from 'context/opacityStateSlice' ;
34
35
import { getFormattedDate } from 'utils/date-utils' ;
35
36
import { invertLegendColors } from 'components/MapView/Legends/utils' ;
37
+ import { layersSelector } from 'context/mapStateSlice/selectors' ;
36
38
37
39
const layerId = getLayerMapId ( 'analysis' ) ;
38
40
@@ -166,14 +168,99 @@ function fillPaintData(
166
168
} ;
167
169
}
168
170
169
- function AnalysisLayer ( { before } : { before ?: string } ) {
171
+ function AnalysisLayer ( {
172
+ before,
173
+ mapRef,
174
+ } : {
175
+ before ?: string ;
176
+ mapRef : RefObject < MapRef > ;
177
+ } ) {
170
178
// TODO maybe in the future we can try add this to LayerType so we don't need exclusive code in Legends and MapView to make this display correctly
171
179
// Currently it is quite difficult due to how JSON focused the typing is. We would have to refactor it to also accept layers generated on-the-spot
172
180
const analysisData = useSelector ( analysisResultSelector ) ;
173
181
const isAnalysisLayerActive = useSelector ( isAnalysisLayerActiveSelector ) ;
174
182
const opacityState = useSelector ( opacitySelector ( 'analysis' ) ) ;
175
183
const invertedColorsForAnalysis = useSelector ( invertedColorsSelector ) ;
176
184
useMapCallback ( 'click' , layerId , undefined , onClick ( analysisData ) ) ;
185
+ const layers = useSelector ( layersSelector ) ;
186
+ const boundaryLayer = layers . find (
187
+ layer => layer . id === analysisData ?. baselineLayerId ,
188
+ ) ?. id ;
189
+ const boundary =
190
+ analysisData && 'boundaryId' in analysisData && analysisData . boundaryId
191
+ ? getLayerMapId ( analysisData . boundaryId )
192
+ : before ;
193
+
194
+ const legend =
195
+ analysisData && invertedColorsForAnalysis
196
+ ? invertLegendColors ( analysisData . legend )
197
+ : analysisData ?. legend ;
198
+
199
+ useEffect ( ( ) => {
200
+ if (
201
+ analysisData instanceof BaselineLayerResult &&
202
+ analysisData . adminBoundariesFormat === 'pmtiles'
203
+ ) {
204
+ // Step 1: Get a reference to your map
205
+ const map = mapRef . current ?. getMap ( ) ;
206
+
207
+ if ( ! map ) {
208
+ return ;
209
+ }
210
+
211
+ // Step 2: Define the source and layer IDs for your admin boundary layer
212
+ const boundarySourceId = `source-${ boundaryLayer } ` ;
213
+
214
+ // Step 3: Get all features from the admin boundary layer
215
+ // Option 1: Query rendered features (visible in current view)
216
+ const features = map . queryRenderedFeatures ( { layers : [ boundary ] } ) ;
217
+ const { statistic } = analysisData ;
218
+ // Step 4: Match features with analysisData and set feature state
219
+ // Assuming analysisData.featureCollection.features contains your feature data
220
+ features . forEach ( feature => {
221
+ try {
222
+ const adminId = feature . properties . dv_adm0_id ;
223
+
224
+ // Find matching data in analysisData feature collection
225
+ const matchingFeature = analysisData . featureCollection . features . find (
226
+ f => f . dv_adm0_id === adminId ,
227
+ ) ;
228
+
229
+ if ( matchingFeature ) {
230
+ // Set feature state based on properties in matchingFeature
231
+ map . setFeatureState (
232
+ {
233
+ source : boundarySourceId ,
234
+ sourceLayer : boundary ,
235
+ id : matchingFeature . dv_adm0_id ,
236
+ } ,
237
+ {
238
+ data : matchingFeature [ statistic ] ,
239
+ selected : true ,
240
+ } ,
241
+ ) ;
242
+ }
243
+ } catch ( error ) {
244
+ console . error ( 'Error setting feature state' , error ) ;
245
+ }
246
+ } ) ;
247
+
248
+ // Step 5: Apply styling based on fillPaintData
249
+ // Create a legend from your analysisData
250
+
251
+ const property = statistic ; // The property name you set in feature state
252
+
253
+ // Apply the fill paint style to your layer
254
+ map . setPaintProperty ( boundary , 'fill-color' , {
255
+ property,
256
+ stops : legendToStops ( legend ) ,
257
+ type : 'interval' ,
258
+ } ) ;
259
+
260
+ // Set the opacity
261
+ map . setPaintProperty ( boundary , 'fill-opacity' , 0.7 ) ;
262
+ }
263
+ } , [ analysisData , mapRef ] ) ;
177
264
178
265
if ( ! analysisData || ! isAnalysisLayerActive ) {
179
266
return null ;
@@ -196,15 +283,6 @@ function AnalysisLayer({ before }: { before?: string }) {
196
283
}
197
284
} ) ( ) ;
198
285
199
- const boundary =
200
- 'boundaryId' in analysisData && analysisData . boundaryId
201
- ? getLayerMapId ( analysisData . boundaryId )
202
- : before ;
203
-
204
- const legend = invertedColorsForAnalysis
205
- ? invertLegendColors ( analysisData . legend )
206
- : analysisData . legend ;
207
-
208
286
return (
209
287
< Source data = { analysisData . featureCollection } type = "geojson" >
210
288
< Layer
0 commit comments