diff --git a/src/Assets/citizenshipFilterFormControlLabels.tsx b/src/Assets/citizenshipFilterFormControlLabels.tsx
index 844b1ac20..429cf3dec 100644
--- a/src/Assets/citizenshipFilterFormControlLabels.tsx
+++ b/src/Assets/citizenshipFilterFormControlLabels.tsx
@@ -1,7 +1,6 @@
import { FormattedMessage } from 'react-intl';
export type CitizenLabels =
- | 'citizen'
| 'non_citizen'
| 'green_card'
| 'refugee'
@@ -11,52 +10,36 @@ export type CitizenLabels =
| 'gc_under19_pregnant_no5';
const citizenshipFilterFormControlLabels = {
- citizen: (
-
- ),
non_citizen: (
- ),
- green_card: (
-
- ),
- refugee: (
-
- ),
- gc_5plus: (
-
),
+ green_card: ,
+ gc_5plus: ,
gc_18plus_no5: (
),
gc_under18_no5: (
),
gc_under19_pregnant_no5: (
+ ),
+ refugee: (
+
),
};
diff --git a/src/Components/FilterSection/CitizenshipPopover.css b/src/Components/FilterSection/CitizenshipPopover.css
new file mode 100644
index 000000000..abc06d425
--- /dev/null
+++ b/src/Components/FilterSection/CitizenshipPopover.css
@@ -0,0 +1,3 @@
+.MuiFormControlLabel-root.gc-subcitizen-indentation {
+ margin-left: 1.25rem;
+}
diff --git a/src/Components/FilterSection/CitizenshipPopover.tsx b/src/Components/FilterSection/CitizenshipPopover.tsx
index 4a444ad13..d08eca3c7 100644
--- a/src/Components/FilterSection/CitizenshipPopover.tsx
+++ b/src/Components/FilterSection/CitizenshipPopover.tsx
@@ -1,9 +1,11 @@
+import { FormattedMessage } from 'react-intl';
import FormControlLabel from '@mui/material/FormControlLabel';
import { Checkbox, Stack } from '@mui/material';
import { GridFilterItem, GridFilterOperator } from '@mui/x-data-grid';
import { UpdateFilterArg } from '../Results/Results';
import citizenshipFilterFormControlLabels from '../../Assets/citizenshipFilterFormControlLabels';
import type { CitizenLabels } from '../../Assets/citizenshipFilterFormControlLabels';
+import './CitizenshipPopover.css';
export const citizenshipFilterOperators: GridFilterOperator[] = [
{
@@ -39,49 +41,126 @@ const CitizenshipPopover = ({
citizenshipFilterIsChecked,
setCitizenshipFilterIsChecked,
}: CitizenshipPopoverProps) => {
+ const hasAtLeastOneCitizenshipFilter = (currentCitizenshipFilters: Record) => {
+ const citizenshipFilterValues = Object.values(currentCitizenshipFilters);
+
+ return citizenshipFilterValues.some((citizenshipFilterValue) => {
+ return citizenshipFilterValue === true;
+ });
+ };
+
const handleFilterSelect = (citizenshipType: CitizenLabels) => {
const isChecked = citizenshipFilterIsChecked[citizenshipType];
- const updatedCitizenshipFilterIsChecked: Record = {
+ let updatedCitizenshipFilterIsChecked: Record = {
...citizenshipFilterIsChecked,
[citizenshipType]: !isChecked,
};
+
+ if (citizenshipType === 'green_card') {
+ // if the citizenshipType is `green_card`, then set green_card and all the gc_options to true or false
+ // i.e. green_card and all the gc_options should be the same when citizenshipType is `green_card`
+ updatedCitizenshipFilterIsChecked = {
+ ...updatedCitizenshipFilterIsChecked,
+ gc_5plus: !isChecked,
+ gc_18plus_no5: !isChecked,
+ gc_under18_no5: !isChecked,
+ gc_under19_pregnant_no5: !isChecked,
+ };
+ }
const typedUpdatedCitizenshipFilterIsChecked = Object.keys(updatedCitizenshipFilterIsChecked) as CitizenLabels[];
const selectedCitizenshipFilters = typedUpdatedCitizenshipFilterIsChecked.filter((citizenshipType) => {
return updatedCitizenshipFilterIsChecked[citizenshipType];
});
- updateFilter({
- name: 'citizen',
- filter: {
- id: 1,
- columnField: 'citizenship',
- operatorValue: 'customCitizenshipOperator',
- value: selectedCitizenshipFilters,
- },
- });
+ //update the MUI filter that is being passed to the citizenship column
+ if (hasAtLeastOneCitizenshipFilter(updatedCitizenshipFilterIsChecked)) {
+ updateFilter({
+ name: 'citizen',
+ filter: {
+ id: 1,
+ columnField: 'citizenship',
+ operatorValue: 'customCitizenshipOperator',
+ value: selectedCitizenshipFilters,
+ },
+ });
+ } else {
+ // set the citizenship filter back to the default
+ updateFilter({
+ name: 'citizen',
+ filter: {
+ id: 1,
+ columnField: 'citizenship',
+ operatorValue: 'customCitizenshipOperator',
+ value: ['citizen'],
+ },
+ });
+ }
+ //update citizenshipFilterIsChecked state
setCitizenshipFilterIsChecked(updatedCitizenshipFilterIsChecked);
};
const typedCitizenshipFilterIsChecked = Object.keys(citizenshipFilterIsChecked) as CitizenLabels[];
- const citizenshipCheckboxFilters = typedCitizenshipFilterIsChecked.map((citizenshipType) => {
- return (
- handleFilterSelect(citizenshipType)}
- />
- }
- />
- );
- });
-
- return {citizenshipCheckboxFilters};
+
+ const renderMainAndSubFilters = (citizenshipFilters: Record) => {
+ return typedCitizenshipFilterIsChecked.map((citizenshipType) => {
+ //here we need to add an sx prop to indent them if they're the gc_filters
+ const isGreenCardSubCitizenshipType = [
+ 'gc_5plus',
+ 'gc_18plus_no5',
+ 'gc_under18_no5',
+ 'gc_under19_pregnant_no5',
+ ].includes(citizenshipType);
+
+ return (
+ handleFilterSelect(citizenshipType)}
+ />
+ }
+ />
+ );
+ });
+ };
+
+ const renderMainFilters = (citizenshipFilters: Record) => {
+ //green_card is false
+ const initialThreeFilters: CitizenLabels[] = ['non_citizen', 'green_card', 'refugee'];
+ return initialThreeFilters.map((initialFilter) => {
+ return (
+ handleFilterSelect(initialFilter)} />
+ }
+ />
+ );
+ });
+ };
+
+ const renderCitizenshipFilters = (citizenshipFilters: Record) => {
+ if (citizenshipFilters.green_card) {
+ return renderMainAndSubFilters(citizenshipFilters);
+ } else {
+ return renderMainFilters(citizenshipFilters);
+ }
+ };
+
+ return (
+
+
+
+
+ {renderCitizenshipFilters(citizenshipFilterIsChecked)}
+
+ );
};
export default CitizenshipPopover;
diff --git a/src/Components/FilterSection/FilterSection.tsx b/src/Components/FilterSection/FilterSection.tsx
index ca0c0d8ea..01ff1d161 100644
--- a/src/Components/FilterSection/FilterSection.tsx
+++ b/src/Components/FilterSection/FilterSection.tsx
@@ -78,13 +78,12 @@ const FilterSection = ({
//this resets the radio buttons
setCitizenshipFilterIsChecked({
non_citizen: false,
- citizen: true,
green_card: false,
- refugee: false,
gc_5plus: false,
gc_18plus_no5: false,
gc_under18_no5: false,
gc_under19_pregnant_no5: false,
+ refugee: false,
});
categoryState[1]('All Categories');
eligibilityState[1]('eligibleBenefits');
diff --git a/src/Components/Results/Results.tsx b/src/Components/Results/Results.tsx
index c41918f1d..ee47e3690 100644
--- a/src/Components/Results/Results.tsx
+++ b/src/Components/Results/Results.tsx
@@ -23,7 +23,6 @@ import {
GridValueFormatterParams,
GridFilterItem,
GridAlignment,
- gridVisibleRowCountSelector,
useGridApiRef,
gridVisibleSortedRowEntriesSelector,
} from '@mui/x-data-grid-pro';
@@ -64,13 +63,12 @@ const Results = () => {
const [filterResultsButton, setFilterResultsButton] = useState('benefits');
const [citizenshipFilterIsChecked, setCitizenshipFilterIsChecked] = useState>({
non_citizen: false,
- citizen: true,
green_card: false,
- refugee: false,
gc_5plus: false,
gc_18plus_no5: false,
gc_under18_no5: false,
gc_under19_pregnant_no5: false,
+ refugee: false,
});
const categoryState = useState('All Categories');
const eligibilityState = useState('eligibleBenefits');
@@ -121,22 +119,49 @@ const Results = () => {
category: false,
});
- const [visibleRowCount, setVisibleRowCount] = useState(1);
- const [totalEligibleDollarValue, setTotalEligibleDollarValue] = useState(0);
+ const [citizenshipRowCount, setCitizenshipRowCount] = useState(1);
+ const [totalCitizenshipDollarValue, setTotalCitizenshipDollarValue] = useState(0);
+ const [totalVisibleRowDollarValue, setTotalVisibleRowDollarValue] = useState(0);
const apiRef = useGridApiRef();
useEffect(() => {
- //use the visible row count so that we don't have to calculate the total eligible programs
- //because doing so would require rewriting all of DGPro's filtering logic
- //but the mui docs say that if you try to reference apiRef before the datagrid is rendered then it'll crash the app
- //hence the if statements prevent us from accessing the apiRef before it's ready
- if (apiRef && apiRef.current && Object.keys(apiRef.current).length) {
- setVisibleRowCount(gridVisibleRowCountSelector(apiRef));
+ let count = 0;
+ const eligiblePrograms = results.programs.filter((program) => program.eligible);
+
+ //this will calculate the number of eligible programs/rows
+ eligiblePrograms.forEach((program) => {
+ const hasOverlap = program.legal_status_required.some((legalStatusType) => {
+ return filt.citizen.value.includes(legalStatusType);
+ });
+
+ if (hasOverlap) {
+ count += 1;
+ }
+ });
+
+ //used this instead of the real total to take into account the preschool category value cap at 8640
+ const categoryValuesArray = Object.values(categoryValues(eligiblePrograms));
+ const cappedCatValuesTotalDollarAmount = categoryValuesArray.reduce((acc, categoryAmt) => {
+ return (acc += categoryAmt);
+ }, 0);
+ setCitizenshipRowCount(count);
+ setTotalCitizenshipDollarValue(cappedCatValuesTotalDollarAmount);
+
+ //this is for the category header
+ if (apiRef && apiRef.current && Object.keys(apiRef.current).length) {
const updatedTotalEligibleDollarValue = gridVisibleSortedRowEntriesSelector(apiRef).reduce((acc, row) => {
return (acc += row.model.value.value);
}, 0);
- setTotalEligibleDollarValue(updatedTotalEligibleDollarValue);
+
+ //this is only to cap the totalVisibleRowDollarValue for preschool
+ const typedFiltCategory = filt.category as GridFilterItem;
+ if (typedFiltCategory.value === preschoolProgramCategory && updatedTotalEligibleDollarValue > 8640) {
+ setTotalVisibleRowDollarValue(8640);
+ return;
+ }
+
+ setTotalVisibleRowDollarValue(updatedTotalEligibleDollarValue);
}
}, [results, filt]);
@@ -190,28 +215,29 @@ const Results = () => {
const preschoolProgramCategory = 'Child Care, Youth, and Education';
const categoryValues = (programs: Program[]) => {
- const preschoolPrograms = [0, 0];
+ const preschoolPrograms = { numOfPreSchoolPrograms: 0, totalEstVal: 0 }; //i=0 => num of preschool prog, i=1 => prog.est.value
const categoryValues: { [key: string]: number } = {};
for (let program of programs) {
+ //add this category to the categoryValues dictionary if the key doesn't already exist
if (categoryValues[program.category.default_message] === undefined) {
categoryValues[program.category.default_message] = 0;
}
- if (program.legal_status_required.includes(filt.citizen.value)) {
+ const hasOverlap = program.legal_status_required.some((status) => {
+ return filt.citizen.value.includes(status);
+ });
+
+ if (hasOverlap) {
categoryValues[program.category.default_message] += program.estimated_value;
- if (preschoolProgramCategory == program.category.default_message) {
- preschoolPrograms[0]++;
- preschoolPrograms[1] += program.estimated_value;
+ if (program.category.default_message === preschoolProgramCategory) {
+ preschoolPrograms.numOfPreSchoolPrograms++;
+ preschoolPrograms.totalEstVal += program.estimated_value;
}
}
}
- for (const category in preschoolPrograms) {
- if (Object.keys(preschoolPrograms).includes(category)) {
- if (preschoolPrograms[1] > 8640 && preschoolPrograms[0] > 1) {
- categoryValues[category] = 8640;
- }
- }
+ if (preschoolPrograms.totalEstVal > 8640 && preschoolPrograms.numOfPreSchoolPrograms > 1) {
+ categoryValues[preschoolProgramCategory] = 8640;
}
return categoryValues;
@@ -323,7 +349,7 @@ const Results = () => {
};
const displaySubheader = () => {
- if (visibleRowCount === 0) {
+ if (citizenshipRowCount === 0) {
return (
@@ -335,14 +361,14 @@ const Results = () => {
return (
- {visibleRowCount}
+ {citizenshipRowCount}
- ${totalEligibleDollarValue.toLocaleString()}
+ ${totalCitizenshipDollarValue.toLocaleString()}
$
- {Math.round(totalEligibleDollarValue / 12).toLocaleString()}
+ {Math.round(totalCitizenshipDollarValue / 12).toLocaleString()}
{
failed_tests: TestMessage[];
category: string;
navigators: ProgramNavigator[];
- citizenship: string;
+ citizenship: string[];
eligible: boolean;
};
const DataGridRows = (programs: Program[]): DataRow[] => {
@@ -402,7 +428,7 @@ const Results = () => {
application_time: programs[i].estimated_application_time,
delivery_time: programs[i].estimated_delivery_time,
description: programs[i].description,
- citizenship: '',
+ citizenship: [],
application_link: programs[i].apply_button_link,
passed_tests: programs[i].passed_tests,
failed_tests: programs[i].failed_tests,
@@ -651,7 +677,7 @@ const Results = () => {
- ${totalEligibleDollarValue.toLocaleString()}{' '}
+ ${totalVisibleRowDollarValue.toLocaleString()}{' '}
diff --git a/src/Types/Results.ts b/src/Types/Results.ts
index 2972606ad..e56d50532 100644
--- a/src/Types/Results.ts
+++ b/src/Types/Results.ts
@@ -28,7 +28,7 @@ export type Program = {
value_type: Translation;
learn_more_link: Translation;
apply_button_link: Translation;
- legal_status_required: string;
+ legal_status_required: string[];
category: Translation;
eligible: boolean;
failed_tests: TestMessage[];