diff --git a/src/App.tsx b/src/App.tsx index c787f4a..85bbfd3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -12,7 +12,7 @@ import { Segmented } from 'antd'; import { ChoroplethMap } from './Components/Graphs/Maps/ChoroplethMap'; import Header from './Components/Header'; import FilterCountryGroup from './Components/Filter'; -import { PROGRAMMES } from './Components/Constants'; +import { GROUPS, PROGRAMMES } from './Components/Constants'; import { ProgrammeProvider, useProgramme } from './Components/ProgrammeContext'; import CheckboxGroup from './Components/CheckboxGroup'; import { ChoroplethMapDataType } from './Types'; @@ -154,35 +154,78 @@ function AppContent() { if (countryGroup === 'allCountries') return true; if (countryGroup === 'sids') return sidsCountries.includes(item.iso); if (countryGroup === 'ldc') return ldcCountries.includes(item.iso); - if (countryGroup === 'fragile') return item.fragile > 0; - return item[countryGroup] > 0; + if (countryGroup === 'fragile') return item.fragile === 1; + return item[countryGroup] === 1; }); - console.log('Filtered by country:', filteredByCountry); - if (selectedCheckboxes.length === 0) return filteredByCountry; - const filteredByCheckboxes = filteredByCountry.filter(item => + return filteredByCountry.filter(item => selectedCheckboxes.some( - sub => typeof sub === 'string' && item[sub] > 0, + sub => typeof sub === 'string' && item[sub] === 1, ), ); - - console.log('Filtered by checkboxes:', filteredByCheckboxes); - return filteredByCheckboxes; }, [sidsCountries, ldcCountries, selectedCheckboxes], ); + const calculateProgrammeCounts = ( + filteredData: any[], + programmes: any[], + ): any => { + const result: any = {}; + programmes.forEach(programme => { + let sum = 0; + if (programme.subprogrammes) { + sum = calculateProgrammeCounts( + filteredData, + programme.subprogrammes, + ).total; + } else { + sum = filteredData.reduce( + (acc, item) => acc + (item[programme.value] || 0), + 0, + ); + } + result[programme.value] = sum; + result.total = (result.total || 0) + sum; + }); + return result; + }; + + const calculateCountryGroupCounts = ( + datum: any[], + countryGroups: any[], + ): any[] => { + return countryGroups.map(group => { + const filteredData = filterData(datum, group.value); + const countryCount = filteredData.length; + return { + label: group.label, + value: group.value, + count: countryCount, + }; + }); + }; + + const filteredData = filterData(data, selectedRadio); + + const sums = calculateProgrammeCounts( + filteredData, + currentProgramme.subprogrammes || PROGRAMMES, + ); + + const countryGroupCounts = calculateCountryGroupCounts(data, GROUPS); + const transformData = useCallback( ( rawData: any[], programme: string, countryGroup: string, ): ChoroplethMapDataType[] => { - const filteredData = filterData(rawData, countryGroup); + const filteredDatum = filterData(rawData, countryGroup); - return filteredData.map(item => { + return filteredDatum.map(item => { let value = 0; if (programme === 'all_programmes') { @@ -199,12 +242,12 @@ function AppContent() { ]; value = relevantSubprogrammes.reduce( - (sum, sub) => sum + (item[sub] || 0), + (sum, subProg) => sum + (item[subProg] || 0), 0, ); } else if (currentProgramme.subprogrammes) { value = currentProgramme.subprogrammes.reduce( - (sum, sub) => sum + (item[sub.value] || 0), + (sum, subProg) => sum + (item[subProg.value] || 0), 0, ); } else { @@ -221,20 +264,12 @@ function AppContent() { [filterData, selectedCheckboxes, currentProgramme], ); - useEffect(() => { - console.log('Current Programme:', currentProgramme); - }, [currentProgramme]); - const filteredAndTransformedData = transformData( data, currentProgramme.value, selectedRadio, ); - useEffect(() => { - console.log('Filtered and Transformed Data:', filteredAndTransformedData); - }, [filteredAndTransformedData]); - const filteredDataForCards = filterData(data, selectedRadio); const subcategoriesToShow = currentProgramme.subprogrammes || []; @@ -243,11 +278,7 @@ function AppContent() { const subcategories = subcategoriesToShow.map(sub => sub.value); setSelectedCheckboxes(subcategories); }, [currentProgramme, subcategoriesToShow]); - - useEffect(() => { - console.log('Filtered Data for Cards:', filteredDataForCards); - }, [filteredDataForCards]); - + console.log(filteredData, countryGroupCounts); return (
@@ -317,7 +349,7 @@ function AppContent() { letterSpacing: '.03em', }} > - Filter By Programmes + Filter By SubProgrammes
({ label: sub.short, value: sub.value, + count: sums[sub.value] || 0, }))} onChange={handleCheckboxChange} value={selectedCheckboxes} diff --git a/src/Components/Calculations.tsx b/src/Components/Calculations.tsx new file mode 100644 index 0000000..75a3ac0 --- /dev/null +++ b/src/Components/Calculations.tsx @@ -0,0 +1,69 @@ +import { PROGRAMMES } from './Constants'; + +export interface ProgrammeCount { + value: string; + label: string; + count: number; + subprogrammes?: ProgrammeCount[]; +} + +const calculateCount = (data: any[], value: string): number => { + return data.reduce((sum, item) => sum + (item[value] || 0), 0); +}; + +const calculateSubprogrammeCounts = ( + data: any[], + subprogrammes: any[] = [], +): ProgrammeCount[] => { + return subprogrammes.map(subProg => { + const subprogrammeCounts = subProg.subprogrammes + ? calculateSubprogrammeCounts(data, subProg.subprogrammes) + : undefined; + + const subProgrammeCount = subprogrammeCounts + ? subprogrammeCounts.reduce((acc, sub) => acc + sub.count, 0) + : calculateCount(data, subProg.value); + + return { + value: subProg.value, + label: subProg.short, + count: subProgrammeCount, + subprogrammes: subprogrammeCounts, + }; + }); +}; + +export const calculateProgrammeCounts = (data: any[]): ProgrammeCount[] => { + const mainProgrammes = PROGRAMMES[0].subprogrammes || []; + + const programmeCounts: ProgrammeCount[] = mainProgrammes.map(prog => { + const subprogrammeCounts = calculateSubprogrammeCounts( + data, + prog.subprogrammes, + ); + const mainProgrammeCount = + subprogrammeCounts.reduce((acc, sub) => acc + sub.count, 0) + + calculateCount(data, prog.value); + + return { + value: prog.value, + label: prog.short, + count: mainProgrammeCount, + subprogrammes: subprogrammeCounts, + }; + }); + + const allProgrammesCount = programmeCounts.reduce( + (acc, programme) => acc + programme.count, + 0, + ); + + return [ + { + value: 'all_programmes', + label: 'All Programmes', + count: allProgrammesCount, + subprogrammes: programmeCounts, + }, + ]; +}; diff --git a/src/Components/CheckboxGroup.tsx b/src/Components/CheckboxGroup.tsx index 9e6a53e..87d95c5 100644 --- a/src/Components/CheckboxGroup.tsx +++ b/src/Components/CheckboxGroup.tsx @@ -4,24 +4,55 @@ import styled from 'styled-components'; const StyledCheckboxGroup = styled(Checkbox.Group)` display: inline-grid; + width: 100%; .ant-checkbox-wrapper { + border-bottom: 0.07rem solid var(--gray-300); + padding: 4px 0; + &:last-child { + border-bottom: none; + } + span:first-child { + width: 18px; + } span:last-child { font-size: 14px !important; line-height: 1.8; + width: 100%; } } `; interface CheckboxGroupProps { - options: { label: string; value: string }[]; + options: { label: string; value: string; count: number }[]; onChange: (checkedValues: CheckboxValueType[]) => void; value: CheckboxValueType[]; } function CheckboxGroup({ options, onChange, value }: CheckboxGroupProps) { + const optionsWithCounts = options.map(option => ({ + label: ( +
+
{option.label}
+

+ {option.count} +

+
+ ), + value: option.value, + })); + return ( void; // Callback function prop for Radio Group - selectedRadio: string; // Selected radio value + onRadioChange: (value: string) => void; + selectedRadio: string; + groups: { label: string; value: string; count?: number }[]; } function FilterCountryGroup(props: CountryGroupProps): JSX.Element { - const { onRadioChange, selectedRadio } = props; + const { onRadioChange, selectedRadio, groups } = props; return ( onRadioChange(e.target.value)} className='undp-radio margin-top-04' - /> + > + {groups.map(group => ( + +
+
{group.label}
+ {group.count !== undefined ? ( +

+ {group.count} +

+ ) : ( + '' + )} +
+
+ ))} +
); }