From 01bde4e81cd579d2ddb881e77fcffdad11045477 Mon Sep 17 00:00:00 2001 From: ericboucher Date: Sun, 22 Sep 2024 23:40:26 +0200 Subject: [PATCH] Add village --- apps/frontend/translations/en.json | 3 ++- apps/frontend/utils/aggregate/aggregate.ts | 6 +++++ .../utils/aggregate/generateFloodReport.ts | 3 +++ apps/frontend/utils/aggregate/setAgg.ts | 17 ++++++++++++ apps/frontend/utils/formatFormToRaw.ts | 2 ++ apps/frontend/utils/tableFormatting.tsx | 26 ++++++++++++++++++- packages/interfaces/src/kobo/DroughtDto.ts | 2 ++ packages/interfaces/src/kobo/FloodDto.ts | 1 + packages/interfaces/src/kobo/IncidentDto.ts | 1 + packages/interfaces/src/kobo/mapping/keys.ts | 6 ++++- packages/interfaces/src/kobo/utils.ts | 3 +++ 11 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 apps/frontend/utils/aggregate/setAgg.ts diff --git a/apps/frontend/translations/en.json b/apps/frontend/translations/en.json index 0a998c77..0a02b852 100644 --- a/apps/frontend/translations/en.json +++ b/apps/frontend/translations/en.json @@ -693,7 +693,8 @@ "COMMON": { "column": { "district": "District", - "commune": "Commune" + "commune": "Commune", + "village": "Villages" } } }, diff --git a/apps/frontend/utils/aggregate/aggregate.ts b/apps/frontend/utils/aggregate/aggregate.ts index 0629e12f..eeb5ab19 100644 --- a/apps/frontend/utils/aggregate/aggregate.ts +++ b/apps/frontend/utils/aggregate/aggregate.ts @@ -4,6 +4,7 @@ import { countAgg } from './countAgg'; import { countCategoriesAgg } from './countCategoriesAgg'; import { countMultipleChoicesAgg } from './countMultipleChoicesAgg'; import { firstAgg } from './firstAgg'; +import { getUniqueValuesSet } from './setAgg'; import { sumAgg } from './sumAgg'; interface IProps { @@ -14,6 +15,7 @@ interface IProps { countKeys?: string[]; countCategoriesKeys?: string[]; countMultipleChoicesKeys?: string[]; + setAggKeys?: string[]; } export const aggregate = ({ @@ -24,6 +26,7 @@ export const aggregate = ({ countKeys = [], countCategoriesKeys = [], countMultipleChoicesKeys = [], + setAggKeys = [], }: IProps) => { const groupedData = groupBy(data, groupKey); const aggregatedData = map(groupedData, (array, keyValue) => { @@ -37,6 +40,8 @@ export const aggregate = ({ countMultipleChoicesAgg(key, array), ); + const setAggValues = setAggKeys.map(key => getUniqueValuesSet(key, array)); + return assign( { [groupKey]: keyValue }, ...firstValues, @@ -44,6 +49,7 @@ export const aggregate = ({ ...countValues, ...countCategoriesValues, ...countMultipleChoicesValues, + ...setAggValues, ) as Record; }); diff --git a/apps/frontend/utils/aggregate/generateFloodReport.ts b/apps/frontend/utils/aggregate/generateFloodReport.ts index b969af83..91d6a7b2 100644 --- a/apps/frontend/utils/aggregate/generateFloodReport.ts +++ b/apps/frontend/utils/aggregate/generateFloodReport.ts @@ -19,6 +19,7 @@ const sumKeys = Object.values( const countCategoriesKeys = [FloodSpecific.RicePrice]; const countMultipleChoicesKeys = [FloodSpecific.threat]; +const setAggKeys = [KoboCommonKeys.village]; export const generateFloodCommuneLevelReport = ( data: Record[], @@ -37,6 +38,7 @@ export const generateFloodCommuneLevelReport = ( sumKeys, countCategoriesKeys, countMultipleChoicesKeys, + setAggKeys, }); }; @@ -57,5 +59,6 @@ export const generateFloodProvinceLevelReport = ( countKeys: provinceLevelReportCountKeys, countCategoriesKeys, countMultipleChoicesKeys, + setAggKeys, }); }; diff --git a/apps/frontend/utils/aggregate/setAgg.ts b/apps/frontend/utils/aggregate/setAgg.ts new file mode 100644 index 00000000..9407d93d --- /dev/null +++ b/apps/frontend/utils/aggregate/setAgg.ts @@ -0,0 +1,17 @@ +import { compact, flatten } from 'lodash'; + +/** + * Parses space-separated strings and returns an object with the key and a Set of unique values. + * @param key The key to look for in the group objects + * @param group An array of objects containing the key + * @returns An object with the key and an array of unique values parsed from the space-separated strings + */ +export const getUniqueValuesSet = ( + key: string, + group: Record[], +): { [key: string]: string[] | undefined } => { + const allValues = compact(flatten(group.map(x => x[key]?.split(' ')))); + const uniqueValues = Array.from(new Set(allValues)); + + return { [key]: uniqueValues.length === 0 ? undefined : uniqueValues }; +}; diff --git a/apps/frontend/utils/formatFormToRaw.ts b/apps/frontend/utils/formatFormToRaw.ts index bb6c609e..c504504b 100644 --- a/apps/frontend/utils/formatFormToRaw.ts +++ b/apps/frontend/utils/formatFormToRaw.ts @@ -17,6 +17,8 @@ export const formatFormToRaw = ( province: formValues.region.province[0], district: formValues.region.district[0], commune: formValues.region.commune[0], + // TODO - FIXME: This is just a placeholder for the village field + village: 'test', // TODO - FIXME: This is just a placeholder for the location field location: formValues.region.commune[0], entryName: formValues.interviewer, diff --git a/apps/frontend/utils/tableFormatting.tsx b/apps/frontend/utils/tableFormatting.tsx index 4ffd3f19..05974a7e 100644 --- a/apps/frontend/utils/tableFormatting.tsx +++ b/apps/frontend/utils/tableFormatting.tsx @@ -109,6 +109,16 @@ const getLocationCountColumnSetup = ( ), + // For villages, we need to count the number of villages in the list + ...(field === KoboCommonKeys.village + ? { + renderCell: (params: GridRenderCellParams) => { + const villageList = params.value as string[] | undefined; + + return villageList ? villageList.length : 0; + }, + } + : {}), }); export const getGroupSetup = (groupId: string, disaster: DisasterType) => ({ @@ -123,10 +133,20 @@ const addGroup = ( children: GridColumnNode[], groupParams?: ColumnSetupParams, ) => { + console.log({ children, addChill: groupParams?.additionalChildren }); const group: GridColumnGroup | undefined = groupParams ? { ...getGroupSetup(groupParams.groupId, groupParams.disaster), - children: [...children, ...groupParams.additionalChildren], + children: [ + ...children, + // Only add KoboCommonKeys.village if not already present + ...(children.some( + child => 'field' in child && child.field === KoboCommonKeys.village, + ) + ? [] + : [{ field: KoboCommonKeys.village as string } as GridColumnNode]), + ...groupParams.additionalChildren, + ], } : undefined; @@ -207,6 +227,8 @@ export const addCommuneLevelReportLocationColumns = ({ ); }, }, + // What to do in detailed commune level report? + getLocationCountColumnSetup(KoboCommonKeys.village as string, 'COMMON', 72), ...columns, ]; @@ -240,6 +262,7 @@ export const addProvinceLevelReportLocationColumns = ({ getLocationColumnSetup(KoboCommonKeys.province, 200), getLocationCountColumnSetup(KoboCommonKeys.district, 'COMMON', 72), getLocationCountColumnSetup(KoboCommonKeys.commune, 'COMMON', 84), + getLocationCountColumnSetup(KoboCommonKeys.village as string, 'COMMON', 72), ...columns, ]; @@ -249,6 +272,7 @@ export const addProvinceLevelReportLocationColumns = ({ { field: KoboCommonKeys.province }, { field: KoboCommonKeys.district }, { field: KoboCommonKeys.commune }, + { field: KoboCommonKeys.village as string }, ], groupParams, ); diff --git a/packages/interfaces/src/kobo/DroughtDto.ts b/packages/interfaces/src/kobo/DroughtDto.ts index 7db5aaf4..1bc0f134 100644 --- a/packages/interfaces/src/kobo/DroughtDto.ts +++ b/packages/interfaces/src/kobo/DroughtDto.ts @@ -24,6 +24,8 @@ export class DroughtDto { @IsString() @Length(2) readonly 'group_yu9nq00/Province'!: string; @IsString() @Length(4) readonly 'group_yu9nq00/District'!: string; @IsString() @Length(6) readonly 'group_yu9nq00/Commune'!: string; + // NOTE - This field does not exist in KOBO yet. + @IsString() readonly 'group_yu9nq00/Village'?: string; @IsDateString() readonly 'group_yu9nq00/Date_Dis': string; @IsNumberString() readonly 'group_yu9nq00/DisTyp'!: string; @IsOptional() @IsNumberString() readonly 'group_dg01m69/NumVillAff'?: string; diff --git a/packages/interfaces/src/kobo/FloodDto.ts b/packages/interfaces/src/kobo/FloodDto.ts index d4c78651..9fd54bc2 100644 --- a/packages/interfaces/src/kobo/FloodDto.ts +++ b/packages/interfaces/src/kobo/FloodDto.ts @@ -26,6 +26,7 @@ export class FloodDto { @IsString() @Length(2) readonly 'g2/Province'!: string; @IsString() @Length(4) readonly 'g2/District'!: string; @IsString() @Length(6) readonly 'g2/Commune'!: string; + @IsString() readonly 'g2/village'?: string; @IsDateString() readonly 'g2/Date_Dis'!: string; @IsNumberString() readonly 'g2/DisTyp'!: string; @IsOptional() @IsNumberString() readonly 'g2/flood_n'?: string; diff --git a/packages/interfaces/src/kobo/IncidentDto.ts b/packages/interfaces/src/kobo/IncidentDto.ts index 084f6138..6d262771 100644 --- a/packages/interfaces/src/kobo/IncidentDto.ts +++ b/packages/interfaces/src/kobo/IncidentDto.ts @@ -27,6 +27,7 @@ export class IncidentDto { @IsString() @Length(2) readonly 'G2/Province'!: string; @IsString() @Length(4) readonly 'G2/District'!: string; @IsString() @Length(6) readonly 'G2/Commune'!: string; + @IsString() readonly 'G2/Village'?: string; @IsOptional() @IsNumberString() readonly 'group_tc1fy38/group_pf1pd97/NumVillAff'?: string; @IsOptional() @IsNumberString() readonly 'group_tc1fy38/group_pf1pd97/NumFamAff'?: string; @IsOptional() @IsNumberString() readonly 'group_tc1fy38/group_pf1pd97/NumPeoAff'?: string; diff --git a/packages/interfaces/src/kobo/mapping/keys.ts b/packages/interfaces/src/kobo/mapping/keys.ts index c835fa0b..d8b37f1f 100644 --- a/packages/interfaces/src/kobo/mapping/keys.ts +++ b/packages/interfaces/src/kobo/mapping/keys.ts @@ -2,9 +2,10 @@ import { DROUGHT, FLOOD, INCIDENT } from '../constants'; import { floodSpecificKeys } from './flood'; export enum KoboCommonKeys { + province = 'province', district = 'district', commune = 'commune', - province = 'province', + village = 'village', disasterDate = 'disasterDate', entryName = 'entryName', phone = 'phone', @@ -21,6 +22,7 @@ export const koboKeys = { [KoboCommonKeys.district]: 'g2/District', [KoboCommonKeys.commune]: 'g2/Commune', [KoboCommonKeys.province]: 'g2/Province', + [KoboCommonKeys.village]: 'g2/village', [KoboCommonKeys.disasterDate]: 'g2/Date_Dis', [KoboCommonKeys.entryName]: 'g1/q_Enum', [KoboCommonKeys.phone]: 'g1/q_Phone', @@ -35,6 +37,7 @@ export const koboKeys = { [KoboCommonKeys.district]: 'group_yu9nq00/District', [KoboCommonKeys.commune]: 'group_yu9nq00/Commune', [KoboCommonKeys.province]: 'group_yu9nq00/Province', + [KoboCommonKeys.village]: 'group_yu9nq00/Village', [KoboCommonKeys.disasterDate]: 'group_yu9nq00/Date_Dis', [KoboCommonKeys.entryName]: 'group_ve4vz14/q_Enum', [KoboCommonKeys.phone]: 'group_ve4vz14/q_Phone', @@ -48,6 +51,7 @@ export const koboKeys = { [KoboCommonKeys.district]: 'G2/District', [KoboCommonKeys.commune]: 'G2/Commune', [KoboCommonKeys.province]: 'G2/Province', + [KoboCommonKeys.village]: 'G2/Village', [KoboCommonKeys.disasterDate]: 'G2/Date_Dis', [KoboCommonKeys.entryName]: 'G1/q_Enum', [KoboCommonKeys.phone]: 'G1/q_Phone', diff --git a/packages/interfaces/src/kobo/utils.ts b/packages/interfaces/src/kobo/utils.ts index 5515cd2c..711631c1 100644 --- a/packages/interfaces/src/kobo/utils.ts +++ b/packages/interfaces/src/kobo/utils.ts @@ -51,6 +51,7 @@ export const formatCommonFields = (form: DisasterDtoType) => { [KoboCommonKeys.province]: form[keys.province], [KoboCommonKeys.district]: form[keys.district], [KoboCommonKeys.commune]: form[keys.commune], + [KoboCommonKeys.village]: form[keys.village], [KoboCommonKeys.disasterDate]: form[keys.disasterDate], [KoboCommonKeys.disTyp]: form[keys.disTyp], [KoboCommonKeys.entryName]: form[keys.entryName], @@ -71,6 +72,7 @@ export const formatCommonFields = (form: DisasterDtoType) => { [KoboCommonKeys.province]: form[keys.province], [KoboCommonKeys.district]: form[keys.district], [KoboCommonKeys.commune]: form[keys.commune], + [KoboCommonKeys.village]: form[keys.village], [KoboCommonKeys.disasterDate]: form[keys.disasterDate], [KoboCommonKeys.disTyp]: form[keys.disTyp], [KoboCommonKeys.entryName]: form[keys.entryName], @@ -90,6 +92,7 @@ export const formatCommonFields = (form: DisasterDtoType) => { [KoboCommonKeys.province]: form[keys.province], [KoboCommonKeys.district]: form[keys.district], [KoboCommonKeys.commune]: form[keys.commune], + [KoboCommonKeys.village]: form[keys.village], [KoboCommonKeys.disasterDate]: form[keys.disasterDate], [KoboCommonKeys.disTyp]: form[keys.disTyp], [KoboCommonKeys.entryName]: form[keys.entryName],