diff --git a/app/src/views/OperationalLearning/i18n.json b/app/src/views/OperationalLearning/i18n.json
index 89de54521..202513e19 100644
--- a/app/src/views/OperationalLearning/i18n.json
+++ b/app/src/views/OperationalLearning/i18n.json
@@ -20,6 +20,9 @@
"failedToCreateExport": "Failed to generate export.",
"disclaimerMessage": "This is an updated implementation of the Operational Learning project started by the DREF and PER teams at IFRC. The previous dashboard can be found {link}.",
"here": "here",
- "beta": "beta"
+ "beta": "beta",
+ "learningBySector": "learnings by sectors",
+ "learningByRegions": "learnings by regions",
+ "sourceOvertime": "Sources Overtime"
}
}
diff --git a/app/src/views/OperationalLearning/index.tsx b/app/src/views/OperationalLearning/index.tsx
index e60659bc0..5bba2b299 100644
--- a/app/src/views/OperationalLearning/index.tsx
+++ b/app/src/views/OperationalLearning/index.tsx
@@ -5,6 +5,7 @@ import {
} from 'react';
import { InfoIcon } from '@ifrc-go/icons';
import {
+ BarChart,
Button,
Chip,
Container,
@@ -18,9 +19,12 @@ import {
TabPanel,
Tabs,
TextOutput,
+ TimeSeriesChart,
} from '@ifrc-go/ui';
import { useTranslation } from '@ifrc-go/ui/hooks';
import {
+ getDatesSeparatedByMonths,
+ getFormattedDateKey,
hasSomeDefinedValue,
numericIdSelector,
resolveToComponent,
@@ -98,6 +102,88 @@ const disasterTypeKeySelector = (type: DisasterType) => type.id;
const disasterTypeLabelSelector = (type: DisasterType) => type.name ?? '?';
/** @knipignore */
+
+const data = {
+ operations_included: 9,
+ learning_extracts: 6,
+ sectors_covered: 6,
+ sources_used: 8,
+ learning_by_region: [
+ { region_name: 'Americas', region_id: 1, count: 2 },
+ { region_name: 'Asia Pacific', region_id: 2, count: 5 },
+ { region_name: 'Europe', region_id: 3, count: 2 },
+ ],
+ 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 },
+ ],
+ learning_by_sector: [
+ { id: 17, count: 1, title: 'health' },
+ { id: 18, count: 1, title: 'education' },
+ { id: 19, count: 3, title: 'Livelihoods and basic needs' },
+ { id: 20, count: 4, title: 'Migration' },
+ { id: 21, count: 1, title: 'WASH' },
+ { id: 22, count: 1, title: 'Shelter' },
+ ],
+ sources_overtime: {
+ DREF: [
+ { year: 2023, count: 1 },
+ { year: 2024, count: 3 },
+ ],
+ 'Emergency Appeal': [
+ { year: 2023, count: 1 },
+ { year: 2024, count: 1 },
+ ],
+ 'International Appeal': [
+ { year: 2023, count: 1 },
+ { year: 2024, count: 1 },
+ ],
+ 'Forecast Based Action': [
+ { year: 2022, count: 1 },
+ ],
+ },
+};
+
+const mockSectorData = data.learning_by_sector.map((sector) => ({
+ key: sector.id,
+ value: sector.count,
+ label: sector.title,
+}));
+
+const mockRegionData = data.learning_by_region.map((region) => ({
+ key: region.region_id,
+ value: region.count,
+ label: region.region_name,
+}));
+
+const timeSeriesDataKeys = Object.entries(
+ data.sources_overtime,
+).flatMap(([source, entries]) => entries.map((entry) => ({
+ date: `${entry.year}-01-01`,
+ value: entry.count,
+ source,
+})));
+
+const oneYearAgo = new Date();
+oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
+oneYearAgo.setDate(1);
+oneYearAgo.setMonth(oneYearAgo.getMonth() + 1);
+oneYearAgo.setHours(0, 0, 0, 0);
+const timeseriesChartClassNameSelector = () => styles.sourceChart;
+const xAxisFormatter = (date: Date) => date.toLocaleString(
+ navigator.language,
+ { month: 'short' },
+);
+const keySelector = (datum: { key: number; value: number; label: string }) => datum.key;
+
+const valueSelector = (d: { value: number }) => d.value;
+const labelSelector = (d: { label: string }) => d.label;
+const dateSelector = (d: { date: string }) => d.date;
+
// eslint-disable-next-line import/prefer-default-export
export function Component() {
const strings = useTranslation(i18n);
@@ -225,8 +311,8 @@ export function Component() {
{ variant: 'danger' },
);
},
- onSuccess: (data) => {
- const unparseData = Papa.unparse(data);
+ onSuccess: (responseData) => {
+ const unparseData = Papa.unparse(responseData);
const blob = new Blob(
[unparseData],
{ type: 'text/csv' },
@@ -281,7 +367,22 @@ export function Component() {
setFilterPristine(true);
setQuery(undefined);
}, [resetFilter]);
-
+ const dateList = useMemo(
+ () => {
+ const startDate = oneYearAgo;
+ const endDate = new Date();
+ return getDatesSeparatedByMonths(startDate, endDate);
+ },
+ [],
+ );
+ const timeSeriesValueSelector = useCallback(
+ (_: string, date: Date) => timeSeriesDataKeys?.find(
+ (source) => (
+ getFormattedDateKey(source.date) === getFormattedDateKey(date)
+ ),
+ ) ?? null,
+ [],
+ );
return (