Skip to content

Commit

Permalink
Add map for learning
Browse files Browse the repository at this point in the history
  • Loading branch information
roshni73 committed Dec 12, 2024
1 parent 6a70d50 commit 4e92b01
Show file tree
Hide file tree
Showing 6 changed files with 402 additions and 34 deletions.
8 changes: 8 additions & 0 deletions app/src/views/OperationalLearning/LearningMap/i18n.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"namespace": "learningMap",
"strings": {
"learningDownloadMapTitle": "Operational learning",
"presentationModeButton":"Presentation Mode"

}
}
228 changes: 228 additions & 0 deletions app/src/views/OperationalLearning/LearningMap/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
import {
useCallback,
useMemo,
useState,
} from 'react';
import { ArtboardLineIcon } from '@ifrc-go/icons';

Check warning on line 6 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'ArtboardLineIcon' is defined but never used

Check warning on line 6 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'ArtboardLineIcon' is defined but never used
import {
Button,

Check warning on line 8 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'Button' is defined but never used

Check warning on line 8 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'Button' is defined but never used
Container,
TextOutput,
} from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';
import {
_cs,
isDefined,
isNotDefined,
} from '@togglecorp/fujs';
import Map, {

Check warning on line 18 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'Map' is defined but never used

Check warning on line 18 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'Map' is defined but never used
MapBounds,

Check warning on line 19 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'MapBounds' is defined but never used

Check warning on line 19 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'MapBounds' is defined but never used
MapLayer,
MapSource,
} from '@togglecorp/re-map';
import { LngLatBoundsLike } from 'mapbox-gl';

Check warning on line 23 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'LngLatBoundsLike' is defined but never used

Check warning on line 23 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'LngLatBoundsLike' is defined but never used

import BaseMap from '#components/domain/BaseMap';
import Link from '#components/Link';
import MapContainerWithDisclaimer from '#components/MapContainerWithDisclaimer';
import MapPopup from '#components/MapPopup';
import useCountryRaw from '#hooks/domain/useCountryRaw';
import {
DEFAULT_MAP_PADDING,

Check warning on line 31 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'DEFAULT_MAP_PADDING' is defined but never used

Check warning on line 31 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'DEFAULT_MAP_PADDING' is defined but never used
DURATION_MAP_ZOOM,

Check warning on line 32 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

'DURATION_MAP_ZOOM' is defined but never used

Check warning on line 32 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

'DURATION_MAP_ZOOM' is defined but never used
} from '#utils/constants';

import {
adminFillLayerOptions,
basePointLayerOptions,
outerCircleLayerOptionsForPersonnel,
} from './utils';

import i18n from './i18n.json';
import styles from './styles.module.css';

const sourceOptions: mapboxgl.GeoJSONSourceRaw = {
type: 'geojson',
};

interface CountryProperties {
country_id: number;
name: string;
units: number;
}

interface ClickedPoint {
feature: GeoJSON.Feature<GeoJSON.Point, CountryProperties>;
lngLat: mapboxgl.LngLatLike;
}

interface Props {
className?: string;
}

function OperationalLearningMap(props: Props) {
const strings = useTranslation(i18n);
const {
className,
} = props;

const [
clickedPointProperties,
setClickedPointProperties] = useState<ClickedPoint | undefined>();

const learning_by_country = [
{
country_name: 'Afghanistan',
country_id: 14,
operation_count: 4,
},
{
country_name: 'Albania',
country_id: 15,
operation_count: 1,
},
{
country_name: 'Argentina',
country_id: 20,
operation_count: 1,
},
{
country_name: 'Australia',
country_id: 22,
operation_count: 1,
},
{
country_name: 'Belgium',
country_id: 30,
operation_count: 1,
},
{
country_name: 'Canada',
country_id: 42,
operation_count: 1,
},
];

const countryResponse = useCountryRaw();

const countryCentroidGeoJson = useMemo(
(): GeoJSON.FeatureCollection<GeoJSON.Geometry> => ({
type: 'FeatureCollection',
features: countryResponse
?.map((country) => {
if (
(!country.independent && isNotDefined(country.record_type))
|| isNotDefined(country.centroid)
|| isNotDefined(country.iso3)
) {
return undefined;
}

const learningList = learning_by_country.find(
(item) => item.country_id,
);
if (isNotDefined(learningList)) {
return undefined;
}

const units = learningList.operation_count ?? 0;

return {
type: 'Feature' as const,
geometry: country.centroid as {
type: 'Point',
coordinates: [number, number],
},
properties: {
id: country,
name: country.name,
units,
},
};
})
.filter(isDefined) ?? [],
}),
[],

Check warning on line 145 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Lint JS

React Hook useMemo has missing dependencies: 'countryResponse' and 'learning_by_country'. Either include them or remove the dependency array

Check warning on line 145 in app/src/views/OperationalLearning/LearningMap/index.tsx

View workflow job for this annotation

GitHub Actions / Build GO Web App

React Hook useMemo has missing dependencies: 'countryResponse' and 'learning_by_country'. Either include them or remove the dependency array
);

const handleCountryClick = useCallback(
(feature: mapboxgl.MapboxGeoJSONFeature, lngLat: mapboxgl.LngLatLike) => {
setClickedPointProperties({
feature: feature as unknown as ClickedPoint['feature'],
lngLat,
});
return false;
},
[],
);

const handlePointClose = useCallback(() => {
setClickedPointProperties(undefined);
}, []);

return (
<Container className={_cs(styles.learningMap, className)}>
<BaseMap
baseLayers={(
<MapLayer
layerKey="admin-0"
hoverable
layerOptions={adminFillLayerOptions}
onClick={handleCountryClick}
/>
)}
>
<MapContainerWithDisclaimer
className={styles.mapContainer}
title={strings.learningDownloadMapTitle}
/>
<MapSource
sourceKey="points"
sourceOptions={sourceOptions}
geoJson={countryCentroidGeoJson}
>
<MapLayer
layerKey="point-circle"
layerOptions={basePointLayerOptions}
/>
<MapLayer
layerKey="outer-circle"
layerOptions={outerCircleLayerOptionsForPersonnel}
/>
</MapSource>
{clickedPointProperties?.lngLat && (
<MapPopup
onCloseButtonClick={handlePointClose}
coordinates={clickedPointProperties.lngLat}
heading={(
<Link
to="countriesLayout"
urlParams={{
countryId: clickedPointProperties.feature.properties.country_id,
}}
>
{clickedPointProperties.feature.properties.name}
</Link>
)}
childrenContainerClassName={styles.popupContent}
>
<Container
className={styles.popupEvent}
childrenContainerClassName={styles.popupEventDetail}
heading=""
headingLevel={5}
>
<TextOutput
value={clickedPointProperties.feature.properties.units}
description=""
valueType="number"
/>
</Container>
</MapPopup>
)}
</BaseMap>
</Container>
);
}

export default OperationalLearningMap;
22 changes: 22 additions & 0 deletions app/src/views/OperationalLearning/LearningMap/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.learning-map {

.map-container {
height: 40rem;
}
}

.popup-content {
display: flex;
flex-direction: column;
gap: var(--go-ui-spacing-md);

.popup-appeal {
gap: var(--go-ui-spacing-xs);

.popup-appeal-detail {
display: flex;
flex-direction: column;
font-size: var(--go-ui-font-size-sm);
}
}
}
82 changes: 82 additions & 0 deletions app/src/views/OperationalLearning/LearningMap/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import type {
CircleLayer,
CirclePaint,
FillLayer,
} from 'mapbox-gl';

import {
COLOR_BLACK,
COLOR_BLUE,
COLOR_DARK_GREY,
COLOR_LIGHT_GREY,
COLOR_RED,
COLOR_YELLOW,
} from '#utils/constants';

const COLOR_LEARNING_AND_PERSONNEL = COLOR_BLUE;
const COLOR_LEARNING_ONLY = COLOR_RED;
const COLOR_PERSONNEL_ONLY = COLOR_YELLOW;
const COLOR_DEFAULT = COLOR_BLACK;

export const adminFillLayerOptions: Omit<FillLayer, 'id'> = {
type: 'fill',
paint: {
'fill-color': [
'case',
['boolean', ['feature-state', 'hovered'], false],
COLOR_DARK_GREY,
COLOR_LIGHT_GREY,
],
},
};

const circleColor: CirclePaint['circle-color'] = [
'case',
COLOR_LEARNING_AND_PERSONNEL,
COLOR_LEARNING_ONLY,
COLOR_PERSONNEL_ONLY,
COLOR_DEFAULT,
];

const basePointPaint: CirclePaint = {
'circle-radius': 5,
'circle-color': circleColor,
'circle-opacity': 0.8,
};

export const basePointLayerOptions: Omit<CircleLayer, 'id'> = {
type: 'circle',
paint: basePointPaint,
};

const baseOuterCirclePaint: CirclePaint = {
'circle-color': circleColor,
'circle-opacity': 0.4,
};

const outerCirclePaintForPersonnel: CirclePaint = {
...baseOuterCirclePaint,
'circle-radius': [
'interpolate',
['linear', 1],
['get', 'learning'],

2,
5,
4,
7,
6,
9,
8,
11,
10,
13,
12,
15,
],
};

export const outerCircleLayerOptionsForPersonnel: Omit<CircleLayer, 'id'> = {
type: 'circle',
paint: outerCirclePaintForPersonnel,
};
Loading

0 comments on commit 4e92b01

Please sign in to comment.