diff --git a/src/operations/map/FcsCountryChoroplethOperations.tsx b/src/operations/map/FcsCountryChoroplethOperations.tsx
index fc0c22e0..dbb20ed3 100644
--- a/src/operations/map/FcsCountryChoroplethOperations.tsx
+++ b/src/operations/map/FcsCountryChoroplethOperations.tsx
@@ -3,7 +3,7 @@ import L from 'leaflet';
import React from 'react';
import { createRoot } from 'react-dom/client';
-import FcsRegionTooltip from '@/components/Map/FcsRegionTooltip';
+import FcsRegionTooltip from '@/components/Map/FcsMap/FcsRegionTooltip';
import { CountryMapData } from '@/domain/entities/country/CountryMapData.ts';
import { MapOperations } from '@/operations/map/MapOperations';
diff --git a/src/operations/map/FcsFoodSecurityOperations.tsx b/src/operations/map/FcsFoodSecurityOperations.tsx
new file mode 100644
index 00000000..020b9c8a
--- /dev/null
+++ b/src/operations/map/FcsFoodSecurityOperations.tsx
@@ -0,0 +1,150 @@
+import { Spacer } from '@nextui-org/react';
+
+import CustomCard from '@/components/Cards/Card';
+import { LineChart } from '@/components/Charts/LineChart';
+import CustomInfoCircle from '@/components/CustomInfoCircle/CustomInfoCircle';
+import { CountryData } from '@/domain/entities/country/CountryData';
+import { CountryIso3Data } from '@/domain/entities/country/CountryIso3Data';
+import { cardsWrapperClass } from '@/utils/primitives';
+
+import { ReactComponent as FoodConsumption } from '../../../public/Images/FoodConsumption.svg';
+import { ReactComponent as Nutrition } from '../../../public/Images/Nutrition.svg';
+import { ReactComponent as Population } from '../../../public/Images/Population.svg';
+import { FcsAccordionOperations } from './FcsAccordionOperations';
+import NutritionAccordionText from './NutritionAccordionText';
+
+export class FcsFoodSecurityOperations {
+ static getFcsFoodSecurityAccordionItems(
+ countryData: CountryData | undefined,
+ countryIso3Data: CountryIso3Data | undefined
+ ) {
+ const deltaOneMonth = countryData?.fcsMinus1 ? countryData.fcs - countryData.fcsMinus1 : null;
+ const deltaThreeMonth = countryData?.fcsMinus3 ? countryData.fcs - countryData.fcsMinus3 : null;
+ const fcsChartData = FcsAccordionOperations.getFcsChartData(countryData);
+ const rcsiChartData = FcsAccordionOperations.getRcsiChartData(countryData);
+ const nutritionData = FcsAccordionOperations.getNutritionData(countryIso3Data);
+ return [
+ {
+ title: 'Food Security',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getFoodSecutriyPopoverInfo(),
+ content: (
+
+ ,
+ text: countryData?.population ? `${countryData.population.toFixed(2)} M` : 'N/A',
+ altText: 'Population Icon',
+ textClass: 'text-base',
+ },
+ ]}
+ />
+ ,
+ text: 'Population with insufficient food consumption',
+ value: countryData?.fcs ? `${countryData.fcs.toFixed(2)} M` : 'N/A',
+ textClass: 'text-xs',
+ changeValues: [
+ {
+ imageSrc: deltaOneMonth && deltaOneMonth > 0 ? '/Images/ArrowUp.svg' : '/Images/ArrowDown.svg',
+ text: deltaOneMonth ? `${deltaOneMonth.toFixed(2)} M` : 'N/A',
+ timeText: '1 Month ago',
+ altText: 'Delta Icon',
+ },
+ {
+ imageSrc:
+ deltaThreeMonth && deltaThreeMonth > 0 ? '/Images/ArrowUp.svg' : '/Images/ArrowDown.svg',
+ text: deltaThreeMonth ? `${deltaThreeMonth.toFixed(2)} M` : 'N/A',
+ timeText: '3 Months ago',
+ altText: 'Delta Icon',
+ },
+ ],
+ },
+ ]}
+ />
+
+ ),
+ },
+ {
+ title: 'Nutrition',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getFoodSecutriyPopoverInfo(),
+ content:
+ nutritionData && (nutritionData.Acute != null || nutritionData.Chronic != null) ? (
+
+ {nutritionData.Acute != null && (
+ ,
+ text: (
+
+ ),
+ },
+ ]}
+ />
+ )}
+ {nutritionData.Chronic != null && (
+ ,
+ text: (
+
+ ),
+ },
+ ]}
+ />
+ )}
+
+ ) : (
+
No data about Nutrition is available
+ ),
+ },
+ {
+ title: 'Food Security Trends',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getFoodSecutriyTrendsPopoverInfo(),
+ content: (
+
+ {fcsChartData ? (
+
+ ) : (
+
No data about insufficient food consumption
+ )}
+
+ {rcsiChartData ? (
+
+ ) : (
+
No data about crisis or above crisis food-based coping
+ )}
+
+ ),
+ },
+ ];
+ }
+}
diff --git a/src/operations/map/FcsMacroEconomicOperations.tsx b/src/operations/map/FcsMacroEconomicOperations.tsx
new file mode 100644
index 00000000..bd4bc438
--- /dev/null
+++ b/src/operations/map/FcsMacroEconomicOperations.tsx
@@ -0,0 +1,88 @@
+import CustomCard from '@/components/Cards/Card';
+import { LineChart } from '@/components/Charts/LineChart';
+import CustomInfoCircle from '@/components/CustomInfoCircle/CustomInfoCircle';
+import { CountryData } from '@/domain/entities/country/CountryData';
+import { CountryIso3Data } from '@/domain/entities/country/CountryIso3Data';
+import { cardsWrapperClass } from '@/utils/primitives';
+
+import { ReactComponent as Import } from '../../../public/Images/Import.svg';
+import { FcsAccordionOperations } from './FcsAccordionOperations';
+
+export class FcsMacroEconomicOperations {
+ static getMacroEconomicAccordionItems(
+ countryData: CountryData | undefined,
+ countryIso3Data: CountryIso3Data | undefined
+ ) {
+ const currencyExchangeChartData = FcsAccordionOperations.getCurrencyExchangeChartData(countryIso3Data);
+ const balanceOfTradeChartData = FcsAccordionOperations.getBalanceOfTradeChartData(countryIso3Data);
+ const headlineAndFoodInflationChartData =
+ FcsAccordionOperations.getHeadlineAndFoodInflationChartData(countryIso3Data);
+
+ return [
+ {
+ title: 'Macroeconomic',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getMacroEconomicPopoverInfo(),
+ content: (
+
+ ,
+ text: countryData?.importDependency
+ ? `${countryData.importDependency.toFixed(1)}% of Cereals`
+ : 'N/A',
+ altText: 'Import Dependency Icon',
+ textClass: 'text-base',
+ },
+ ]}
+ />
+
+ ),
+ },
+ {
+ title: 'Currency Exchange',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getCurrencyExchangePopoverInfo(),
+ content: (
+
+ {currencyExchangeChartData ? (
+
+ ) : (
+
No data about currency exchange
+ )}
+
+ ),
+ },
+ {
+ title: 'Balance of Trade',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getBalanceOfTradePopoverInfo(),
+ content: (
+
+ {balanceOfTradeChartData ? (
+
+ ) : (
+
No data about balance of trade
+ )}
+
+ ),
+ },
+ {
+ title: 'Headline and food inflation',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getHeadlineAndFoodInflationPopoverInfo(),
+ content: (
+
+ {headlineAndFoodInflationChartData ? (
+
+ ) : (
+
No data about headline and food inflation
+ )}
+
+ ),
+ },
+ ];
+ }
+}
diff --git a/src/operations/map/IpcFoodSecurityOperations.tsx b/src/operations/map/IpcFoodSecurityOperations.tsx
new file mode 100644
index 00000000..066b5aa0
--- /dev/null
+++ b/src/operations/map/IpcFoodSecurityOperations.tsx
@@ -0,0 +1,128 @@
+import React from 'react';
+
+import CustomCard from '@/components/Cards/Card';
+import CustomInfoCircle from '@/components/CustomInfoCircle/CustomInfoCircle';
+import { CountryData } from '@/domain/entities/country/CountryData';
+import { CountryIso3Data } from '@/domain/entities/country/CountryIso3Data';
+import { cardsWrapperClass } from '@/utils/primitives';
+
+import { ReactComponent as FoodConsumption } from '../../../public/Images/FoodConsumption.svg';
+import { ReactComponent as Nutrition } from '../../../public/Images/Nutrition.svg';
+import { ReactComponent as Population } from '../../../public/Images/Population.svg';
+import { FcsAccordionOperations } from './FcsAccordionOperations';
+import NutritionAccordionText from './NutritionAccordionText';
+
+export class IpcFoodSecurityAccordionOperations {
+ static getFoodSecurityAccordionItems(
+ countryData: CountryData | undefined,
+ deltaOneMonth: number | null,
+ deltaThreeMonth: number | null
+ ) {
+ const hasNoData =
+ !countryData || !countryData.population || !countryData.fcs || deltaOneMonth === null || deltaThreeMonth === null;
+
+ if (hasNoData) {
+ return {
+ title: 'Food Security',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getFoodSecutriyPopoverInfo(),
+ content:
No data about food security
,
+ };
+ }
+
+ return {
+ title: 'Food Security',
+ infoIcon:
,
+ popoverInfo: FcsAccordionOperations.getFoodSecutriyPopoverInfo(),
+ content: (
+
+ ,
+ text: countryData.population ? `${countryData.population.toFixed(2)} M` : 'N/A',
+ altText: 'Population Icon',
+ textClass: 'text-base',
+ },
+ ]}
+ />
+ ,
+ text: 'Population with insufficient food consumption',
+ value: countryData.fcs ? `${countryData.fcs.toFixed(2)} M` : 'N/A',
+ textClass: 'text-xs',
+ changeValues: [
+ {
+ imageSrc: deltaOneMonth && deltaOneMonth > 0 ? '/Images/ArrowUp.svg' : '/Images/ArrowDown.svg',
+ text: deltaOneMonth ? `${deltaOneMonth.toFixed(2)} M` : 'N/A',
+ timeText: '1 Month ago',
+ altText: 'Delta Icon',
+ },
+ {
+ imageSrc: deltaThreeMonth && deltaThreeMonth > 0 ? '/Images/ArrowUp.svg' : '/Images/ArrowDown.svg',
+ text: deltaThreeMonth ? `${deltaThreeMonth.toFixed(2)} M` : 'N/A',
+ timeText: '3 Months ago',
+ altText: 'Delta Icon',
+ },
+ ],
+ },
+ ]}
+ />
+
+ ),
+ };
+ }
+
+ static getNutritionAccordionItems(countryIso3Data: CountryIso3Data | undefined) {
+ const nutritionData = FcsAccordionOperations.getNutritionData(countryIso3Data);
+
+ if (!nutritionData || (nutritionData.Acute == null && nutritionData.Chronic == null)) {
+ return {
+ title: 'Nutrition',
+ infoIcon:
,
+ content:
No data about Nutrition is available
,
+ };
+ }
+
+ return {
+ title: 'Nutrition',
+ infoIcon:
,
+ content: (
+
+ {nutritionData.Acute != null && (
+ ,
+ text: (
+
+ ),
+ },
+ ]}
+ />
+ )}
+ {nutritionData.Chronic != null && (
+ ,
+ text: (
+
+ ),
+ },
+ ]}
+ />
+ )}
+
+ ),
+ };
+ }
+}
diff --git a/src/operations/map/MapOperations.tsx b/src/operations/map/MapOperations.tsx
index 1aa77426..9df95f66 100644
--- a/src/operations/map/MapOperations.tsx
+++ b/src/operations/map/MapOperations.tsx
@@ -78,7 +78,7 @@ export class MapOperations {
setCountryData(newCountryData);
}
- if (selectedMapType === GlobalInsight.FOOD) {
+ if (selectedMapType === GlobalInsight.FOOD || selectedMapType === GlobalInsight.IPC) {
const newCountryIso3Data = await countryRepository.getCountryIso3Data(selectedCountryData.properties.iso3);
setCountryIso3Data(newCountryIso3Data);
}
diff --git a/src/operations/map/NutritionAccordionText.tsx b/src/operations/map/NutritionAccordionText.tsx
new file mode 100644
index 00000000..ad6a6396
--- /dev/null
+++ b/src/operations/map/NutritionAccordionText.tsx
@@ -0,0 +1,11 @@
+import NutritionAccordionTextProps from '@/domain/props/NutritionAccordionTextProps';
+
+function NutritionAccordionText({ nutritionValue, text }: NutritionAccordionTextProps) {
+ return (
+ <>
+
{nutritionValue}
+
{text}
+ >
+ );
+}
+export default NutritionAccordionText;
diff --git a/src/operations/map/NutritionStateChoroplethOperations.tsx b/src/operations/map/NutritionStateChoroplethOperations.tsx
index 7ee50e08..77e68635 100644
--- a/src/operations/map/NutritionStateChoroplethOperations.tsx
+++ b/src/operations/map/NutritionStateChoroplethOperations.tsx
@@ -2,7 +2,7 @@ import { Feature } from 'geojson';
import { PathOptions } from 'leaflet';
import { createRoot } from 'react-dom/client';
-import NutritionRegionTooltip from '@/components/Map/NutritionRegionTooltip';
+import NutritionRegionTooltip from '@/components/Map/NutritionMap/NutritionRegionTooltip';
import { NUTRIENT_LABELS } from '@/domain/constant/map/NutritionChoropleth.ts';
import { LayerWithFeature } from '@/domain/entities/map/LayerWithFeature.ts';
import { Nutrition } from '@/domain/entities/region/RegionNutritionProperties.ts';
diff --git a/src/utils/primitives.ts b/src/utils/primitives.ts
index 48ed96a9..95e98dcc 100644
--- a/src/utils/primitives.ts
+++ b/src/utils/primitives.ts
@@ -44,4 +44,4 @@ export const subtitle = tv({
},
});
-export const cardsWrapperClass = 'cards-wrapper flex flex-row gap-4 justify-center flex-wrap';
+export const cardsWrapperClass = 'cards-wrapper flex flex-row gap-1 justify-center flex-wrap';
diff --git a/yarn.lock b/yarn.lock
index 1a2c8f76..233f196a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1390,6 +1390,11 @@
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.7.tgz#5006f4460a7fa598a03e1c2aa4e59e45c71082d3"
integrity sha512-uVuRqoj28Ys/AI/5gVEgRAISd0KWI0HRjOO1CTpNgmX3ZsHb5mdn14Y59yk0IxizXdo7ZjsI2S7qbWnO+GNBcA==
+"@next/env@^13.4.3":
+ version "13.5.7"
+ resolved "https://registry.yarnpkg.com/@next/env/-/env-13.5.7.tgz#5006f4460a7fa598a03e1c2aa4e59e45c71082d3"
+ integrity sha512-uVuRqoj28Ys/AI/5gVEgRAISd0KWI0HRjOO1CTpNgmX3ZsHb5mdn14Y59yk0IxizXdo7ZjsI2S7qbWnO+GNBcA==
+
"@next/eslint-plugin-next@15.0.1":
version "15.0.1"
resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.1.tgz#76117d88aadc52f6e04b1892d44654d05468d53c"