Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement fcs legend and overlay #31

Merged
merged 2 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AlertsMenuWrapper } from '@/components/AlertsMenu/AlertsMenuWrapper';
import Chatbot from '@/components/Chatbot/Chatbot';
import HungerAlertLoader from '@/components/HungerAlert/HungerAlertLoader';
import MapLegend from '@/components/Legend/MapLegend';
import MapLoader from '@/components/Map/MapLoader';
import { Sidebar } from '@/components/Sidebar/Sidebar';
import container from '@/container';
Expand All @@ -18,6 +19,7 @@ export default async function Home() {
<Chatbot />
<MapLoader countries={countryMapData} disputedAreas={disputedAreas} />
<HungerAlertLoader countryMapData={countryMapData} />
<MapLegend />
</>
);
}
14 changes: 14 additions & 0 deletions src/components/Legend/MapLegend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

import LegendContainer from '@/components/Legend/LegendContainer';
import { mapLegendData } from '@/domain/constant/legend/mapLegendData.ts';
import { useSidebar } from '@/domain/contexts/SidebarContext';

export default function MapLegend() {
const { selectedMapType } = useSidebar();
return (
<div className="absolute bottom-5 right-0 z-50 pr-10">
<LegendContainer items={mapLegendData(selectedMapType)} />
</div>
);
}
7 changes: 6 additions & 1 deletion src/components/Map/VectorTileLayer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import mapboxgl from 'mapbox-gl'; // eslint-disable-line import/no-webpack-loade
import { useTheme } from 'next-themes';
import React, { RefObject, useEffect, useRef } from 'react';

import { useSidebar } from '@/domain/contexts/SidebarContext';
import { MapProps } from '@/domain/props/MapProps';
import { MapOperations } from '@/operations/map/MapOperations.ts';

export default function VectorTileLayer({ countries, disputedAreas }: MapProps) {
const { theme } = useTheme();
const context: LeafletContextInterface = useLeafletContext();
const mapContainer: RefObject<HTMLDivElement> = useRef<HTMLDivElement>(null);
const { selectedMapType } = useSidebar();

mapboxgl.accessToken = process.env.NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN as string;

Expand All @@ -23,12 +25,15 @@ export default function VectorTileLayer({ countries, disputedAreas }: MapProps)
);
MapOperations.setMapInteractionFunctionality(baseMap);
MapOperations.synchronizeLeafletMapbox(baseMap, mapContainer, context);
/* To add when CORS issue is solved
MapOperations.addFCSFunctionality(baseMap, selectedMapType);
*/

return () => {
baseMap.remove();
context.map.off('move');
};
}, [context, theme]);
}, [context, theme, selectedMapType]);

return <div ref={mapContainer} style={{ width: '100%', height: '100%', zIndex: 2 }} />;
}
35 changes: 35 additions & 0 deletions src/domain/constant/legend/mapLegendData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { GlobalInsight } from '@/domain/enums/GlobalInsight.ts';
import { GradientLegendContainerItem } from '@/domain/props/GradientLegendContainerItem.ts';
import PointLegendContainerItem from '@/domain/props/PointLegendContainerItem.ts';

export function mapLegendData(
selectedMapType: GlobalInsight
): (PointLegendContainerItem | GradientLegendContainerItem)[] {
switch (selectedMapType) {
case GlobalInsight.FOOD:
return [
{
title: 'Prevalence of insufficient food consumption',
startColor: 'fcsGreen',
endColor: 'fcsRed',
startLabel: '0%',
endLabel: 'above 40%',
middleColor: 'fcsOrange',
tooltipInfo:
'People with insufficient food consumption refers to those with poor or borderline food consumption, according to the Food Consumption Score (FCS).' +
'\n' +
'\n' +
"The Food Consumption Score (FCS) is a proxy of household's food access and a core WFP indicator used to classify households into different groups based on the adequacy of the foods consumed in the week prior to being surveyed. " +
"FCS is the most commonly used food security indicator by WFP and partners. This indicator is a composite score based on household's dietary diversity, food frequency, and relative nutritional importance of different food groups. " +
'The FCS is calculated using the frequency of consumption of eight food groups by a household during the 7 days before the survey using standardized weights for each of the food groups reflecting its respective nutrient density,and then classifies households as having ‘poor’, ‘borderline’ or ‘acceptable’ food consumption. ' +
'Poor food consumption: Typically refers to households that are not consuming staples and vegetables every day and never or very seldom consume protein-rich food such as meat and dairy (FCS of less than 28). ' +
'Borderline food consumption: Typically refers to households that are consuming staples and vegetables every day, accompanied by oil and pulses a few times a week (FCS of less than 42). ' +
'Acceptable food consumption: Typically refers to households that are consuming staples and vegetables every day, frequently accompanied by oil and pulses, and occasionally meat, fish and dairy (FCS greater than 42).\n' +
'Data source: World Food Programme - (i) near real-time food security monitoring systems (where available), based on mobile Vulnerability Analysis and Mapping (mVAM) surveys; (ii) HungerMapLIVE predictive model; or Proteus index.\n' +
'Updated: Daily (low and lower-middle income countries), Annually (upper-middle and high income countries).',
},
];
default:
return [];
}
}
20 changes: 20 additions & 0 deletions src/operations/map/MapOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { CountryMapData } from '@/domain/entities/country/CountryMapData.ts';
import { MapColorsType } from '@/domain/entities/map/MapColorsType.ts';
import { GlobalInsight } from '@/domain/enums/GlobalInsight.ts';
import { MapProps } from '@/domain/props/MapProps';
import { getColors } from '@/styles/MapColors.ts';

Expand Down Expand Up @@ -118,7 +119,7 @@

baseMap.on('mouseup', 'country-fills', (e) => {
if (!isDragging && e.features && (e.features[0] as unknown as CountryMapData).properties.interactive) {
alert(`You clicked on ${(e.features[0] as unknown as CountryMapData).properties.adm0_name}`);

Check warning on line 122 in src/operations/map/MapOperations.ts

View workflow job for this annotation

GitHub Actions / lint-and-format

Unexpected alert
}
});
}
Expand Down Expand Up @@ -184,4 +185,23 @@
syncZoom();
});
}

static addFCSFunctionality(baseMap: mapboxgl.Map, selectedMapType: GlobalInsight) {
baseMap.on('load', () => {
baseMap.addSource('fcsRaster', {
type: 'raster',
tiles: ['https://static.hungermapdata.org/proteus_tiles/{z}/{x}/{y}.png'],
tileSize: 256,
scheme: 'tms',
});

baseMap.addLayer({
id: 'fcsLayer',
type: 'raster',
source: 'fcsRaster',
layout: { visibility: selectedMapType === GlobalInsight.FOOD ? 'visible' : 'none' },
paint: {},
});
});
}
}
13 changes: 3 additions & 10 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,6 @@ module.exports = {
},
darkMode: 'class',
plugins: [
function ({ addBase, theme }) {
addBase({
':root': {
'--color-hover': theme('colors.hover'),
'--color-background': theme('colors.background'),
'--color-active-countries': theme('colors.activeCountries'),
'--color-inactive-countries': theme('colors.inactiveCountries'),
},
});
},
nextui({
themes: {
light: {
Expand Down Expand Up @@ -125,6 +115,9 @@ module.exports = {
conflictCivil: '#96badc',
conflictExplosion: '#eaaf75',
conflictStrategic: '#bec0c1',
fcsGreen: '#345d34',
fcsOrange: '#ea6a2c',
fcsRed: '#fa190e'
},
},
dark: {
Expand Down