@@ -12,12 +12,16 @@ import {
1212import {
1313 Button ,
1414 Container ,
15- LegendItem ,
15+ Legend ,
1616 List ,
1717 TextOutput ,
1818} from '@ifrc-go/ui' ;
1919import { useTranslation } from '@ifrc-go/ui/hooks' ;
20- import { sumSafe } from '@ifrc-go/ui/utils' ;
20+ import {
21+ numericIdSelector ,
22+ stringNameSelector ,
23+ sumSafe ,
24+ } from '@ifrc-go/ui/utils' ;
2125import {
2226 isDefined ,
2327 isNotDefined ,
@@ -30,10 +34,7 @@ import {
3034 MapSource ,
3135} from '@togglecorp/re-map' ;
3236import getBbox from '@turf/bbox' ;
33- import type {
34- CircleLayer ,
35- SymbolLayer ,
36- } from 'mapbox-gl' ;
37+ import { type SymbolLayer } from 'mapbox-gl' ;
3738
3839import ActiveCountryBaseMapLayer from '#components/domain/ActiveCountryBaseMapLayer' ;
3940import BaseMap from '#components/domain/BaseMap' ;
@@ -44,8 +45,7 @@ import useAuth from '#hooks/domain/useAuth';
4445import useFilterState from '#hooks/useFilterState' ;
4546import { getFirstTruthyString } from '#utils/common' ;
4647import {
47- COLOR_DARK_GREY ,
48- COLOR_PRIMARY_BLUE ,
48+ COLOR_PRIMARY_RED ,
4949 COLOR_WHITE ,
5050 DEFAULT_MAP_PADDING ,
5151 DURATION_MAP_ZOOM ,
@@ -63,13 +63,22 @@ import {
6363 VALIDATED ,
6464} from '../common' ;
6565import Filters , { FilterValue } from '../Filters' ;
66+ import { TYPE_HEALTH_CARE } from '../LocalUnitsFormModal/LocalUnitsForm/schema' ;
6667
6768import i18n from './i18n.json' ;
6869import styles from './styles.module.css' ;
6970
7071const LOCAL_UNIT_ICON_KEY = 'local-units' ;
7172const HEALTHCARE_ICON_KEY = 'healthcare' ;
7273
74+ function iconSourceSelector ( { image_url } : { image_url ?: string | undefined } ) {
75+ return image_url ;
76+ }
77+
78+ function primaryRedColorSelector ( ) {
79+ return COLOR_PRIMARY_RED ;
80+ }
81+
7382const localUnitIconLayerOptions : Omit < SymbolLayer , 'id' > = {
7483 layout : {
7584 visibility : 'visible' ,
@@ -211,35 +220,6 @@ function LocalUnitsMap(props: Props) {
211220 [ loadedIcons , localUnitsOptions ] ,
212221 ) ;
213222
214- const localUnitPointLayerOptions : Omit < CircleLayer , 'id' > = useMemo ( ( ) => ( {
215- layout : {
216- visibility : 'visible' ,
217- } ,
218- type : 'circle' ,
219- paint : {
220- 'circle-radius' : 12 ,
221- 'circle-color' : isDefined ( localUnitsOptions ) ? [
222- 'match' ,
223- [ 'get' , 'type' ] ,
224- ...localUnitsOptions . type . flatMap (
225- ( { code, colour } ) => [ code , colour ] ,
226- ) ,
227- COLOR_DARK_GREY ,
228- ] : COLOR_DARK_GREY ,
229- 'circle-opacity' : 0.6 ,
230- 'circle-stroke-color' : isDefined ( localUnitsOptions ) ? [
231- 'match' ,
232- [ 'get' , 'type' ] ,
233- ...localUnitsOptions . type . flatMap (
234- ( { code, colour } ) => [ code , colour ] ,
235- ) ,
236- COLOR_DARK_GREY ,
237- ] : COLOR_DARK_GREY ,
238- 'circle-stroke-width' : 1 ,
239- 'circle-stroke-opacity' : 1 ,
240- } ,
241- } ) , [ localUnitsOptions ] ) ;
242-
243223 const countryBounds = useMemo ( ( ) => (
244224 ( countryResponse && countryResponse . bbox )
245225 ? getBbox ( countryResponse . bbox )
@@ -295,8 +275,9 @@ function LocalUnitsMap(props: Props) {
295275 properties : {
296276 id : localUnit . id ,
297277 localUnitId : localUnit . id ,
278+ radius : 12 ,
298279 type : localUnit . type ,
299- subType : isDefined ( localUnit . health_details )
280+ subType : localUnit . type === TYPE_HEALTH_CARE
300281 ? localUnit . health_details . health_facility_type
301282 : undefined ,
302283 iconKey : isDefined ( localUnit . health_details )
@@ -378,8 +359,8 @@ function LocalUnitsMap(props: Props) {
378359 >
379360 < div className = { styles . mapContainerWithContactDetails } >
380361 < BaseMap
381- mapStyle = { localUnitMapStyle }
382362 withoutLabel
363+ mapStyle = { localUnitMapStyle }
383364 baseLayers = { (
384365 < ActiveCountryBaseMapLayer
385366 activeCountryIso3 = { countryResponse ?. iso3 }
@@ -390,6 +371,13 @@ function LocalUnitsMap(props: Props) {
390371 < MapContainerWithDisclaimer
391372 className = { styles . mapContainer }
392373 />
374+ { countryBounds && (
375+ < MapBounds
376+ duration = { DURATION_MAP_ZOOM }
377+ padding = { DEFAULT_MAP_PADDING }
378+ bounds = { countryBounds }
379+ />
380+ ) }
393381 { localUnitsOptions ?. type . map (
394382 ( typeOption ) => (
395383 < MapImage
@@ -419,7 +407,13 @@ function LocalUnitsMap(props: Props) {
419407 >
420408 < MapLayer
421409 layerKey = "point"
422- layerOptions = { localUnitPointLayerOptions }
410+ layerOptions = { {
411+ type : 'circle' ,
412+ paint : {
413+ 'circle-radius' : [ 'get' , 'radius' ] ,
414+ 'circle-color' : COLOR_PRIMARY_RED ,
415+ } ,
416+ } }
423417 onClick = { handlePointClick }
424418 />
425419 { allIconsLoaded && (
@@ -429,11 +423,6 @@ function LocalUnitsMap(props: Props) {
429423 />
430424 ) }
431425 </ MapSource >
432- < MapBounds
433- duration = { DURATION_MAP_ZOOM }
434- padding = { DEFAULT_MAP_PADDING }
435- bounds = { countryBounds }
436- />
437426 { isDefined ( clickedPointProperties ) && clickedPointProperties . lngLat && (
438427 < MapPopup
439428 popupClassName = { styles . mapPopup }
@@ -544,50 +533,28 @@ function LocalUnitsMap(props: Props) {
544533 </ Container >
545534 ) }
546535 </ div >
547- {
548- isDefined ( localUnitsOptions ) && (
549- < Container
550- contentViewType = "vertical"
551- spacing = "comfortable"
552- >
553- < Container
554- heading = { strings . localUnitLegendLocalUnitTitle }
555- headingLevel = { 4 }
556- contentViewType = "grid"
557- numPreferredGridContentColumns = { 5 }
558- spacing = "compact"
559- >
560- { localUnitsOptions ?. type . map ( ( legendItem ) => (
561- < LegendItem
562- key = { legendItem . id }
563- iconSrc = { legendItem . image_url }
564- iconClassName = { styles . legendIcon }
565- color = { legendItem . colour ?? COLOR_DARK_GREY }
566- label = { legendItem . name }
567- />
568- ) ) }
569- </ Container >
570- < Container
571- heading = { strings . localUnitLegendHealthCareTitle }
572- headingLevel = { 5 }
573- contentViewType = "grid"
574- numPreferredGridContentColumns = { 5 }
575- spacing = "compact"
576- >
577- { localUnitsOptions ?. health_facility_type . map ( ( legendItem ) => (
578- < LegendItem
579- key = { legendItem . id }
580- // FIXME: use color from server
581- color = { COLOR_PRIMARY_BLUE }
582- iconSrc = { legendItem . image_url }
583- iconClassName = { styles . legendIcon }
584- label = { legendItem . name }
585- />
586- ) ) }
587- </ Container >
588- </ Container >
589- )
590- }
536+ { filter . type === TYPE_HEALTH_CARE && (
537+ < Legend
538+ label = { strings . localUnitHealthFacilityType }
539+ items = { localUnitsOptions ?. health_facility_type }
540+ keySelector = { numericIdSelector }
541+ labelSelector = { stringNameSelector }
542+ iconSrcSelector = { iconSourceSelector }
543+ colorSelector = { primaryRedColorSelector }
544+ iconElementClassName = { styles . legendIcon }
545+ />
546+ ) }
547+ { filter . type !== TYPE_HEALTH_CARE && (
548+ < Legend
549+ label = { strings . localUnitLocalUnitType }
550+ items = { localUnitsOptions ?. type }
551+ keySelector = { numericIdSelector }
552+ labelSelector = { stringNameSelector }
553+ iconSrcSelector = { iconSourceSelector }
554+ colorSelector = { primaryRedColorSelector }
555+ iconElementClassName = { styles . legendIcon }
556+ />
557+ ) }
591558 </ Container >
592559 ) ;
593560}
0 commit comments