Skip to content

Commit 0fba489

Browse files
authored
Merge pull request #3211 from bcgov/NDT-282-Refactor-how-we-handle-project-area-modal-opening
chore: refactor modal opening in project area page
2 parents b32cd5d + a11dac3 commit 0fba489

File tree

2 files changed

+191
-38
lines changed

2 files changed

+191
-38
lines changed

app/components/Form/ApplicationForm.tsx

+62-38
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,42 @@ const ApplicationForm: React.FC<Props> = ({
379379
const isOtherFundingSourcesPage = sectionName === 'otherFundingSources';
380380
const isReviewPage = sectionName === 'review';
381381

382+
const isAllZoneIntake =
383+
isProjectAreaPage &&
384+
acceptedProjectAreasArray.length ===
385+
(sectionSchema.properties?.geographicArea as any)?.items?.enum?.length;
386+
387+
const isZoneSelectionValid = (
388+
geographicAreaInput: number[],
389+
isFirstNationsLed: boolean,
390+
isNullAllowed: boolean = true
391+
) => {
392+
// null selection not allowed in submitted project area page
393+
if (!isNullAllowed && geographicAreaInput?.length === 0) return false;
394+
return (
395+
isAllZoneIntake ||
396+
isFirstNationsLed ||
397+
acceptedProjectAreasArray.includes(geographicAreaInput?.[0])
398+
);
399+
};
400+
401+
const getProjectAreaModalType = (
402+
geographicAreaInputChanged: boolean,
403+
firstNationsLedInputChanged: boolean
404+
) => {
405+
if (isSubmitted && geographicAreaInputChanged) {
406+
// display new modal saying
407+
// Invalid selection. You have indicated that this project is not led or supported by First Nations, therefore, you may only choose from zones 1,2,3 or 6.
408+
return 'invalid-geographic-area';
409+
}
410+
if (isSubmitted && firstNationsLedInputChanged) {
411+
// display modal saying
412+
// Invalid selection. Please first choose from zones 1,2,3 or 6 if this project is not supported or led by First Nations
413+
return 'first-nations-led';
414+
}
415+
return 'pre-submitted';
416+
};
417+
382418
const isSubmitEnabled = useMemo(() => {
383419
if (isUpdating) return false;
384420

@@ -455,17 +491,6 @@ const ApplicationForm: React.FC<Props> = ({
455491
}
456492
if (isProjectAreaPage) {
457493
const firstNationsLed = newFormSectionData?.firstNationsLed || false;
458-
const isGeographicAreaEmpty =
459-
newFormSectionData?.geographicArea?.[0] === 'undefined' ||
460-
newFormSectionData?.geographicArea?.length === 0;
461-
const projectAreaAccepted =
462-
firstNationsLed ||
463-
(!isGeographicAreaEmpty &&
464-
(firstNationsLed ||
465-
acceptedProjectAreasArray.includes(
466-
newFormSectionData?.geographicArea?.[0]
467-
)));
468-
const isZoneSpecificIntake = latestIntakeNumber !== 4;
469494
const geographicAreaInputChanged =
470495
typeof newFormSectionData?.geographicArea?.[0] !== 'undefined' &&
471496
newFormSectionData?.geographicArea[0] !==
@@ -474,30 +499,29 @@ const ApplicationForm: React.FC<Props> = ({
474499
typeof newFormSectionData?.firstNationsLed !== 'undefined' &&
475500
firstNationsLed !== jsonData.projectArea?.firstNationsLed;
476501

477-
if (isSubmitted && !projectAreaAccepted) {
478-
// revert form data
479-
newFormData = {
480-
...jsonData,
481-
};
482-
if (geographicAreaInputChanged && isZoneSpecificIntake) {
483-
// display new modal saying
484-
// Invalid selection. You have indicated that this project is not led or supported by First Nations, therefore, you may only choose from zones 1,2,3 or 6.
485-
setProjectAreaModalType('invalid-geographic-area');
502+
const isProjectAreaAccepted = isZoneSelectionValid(
503+
newFormSectionData?.geographicArea,
504+
firstNationsLed,
505+
!isSubmitted
506+
);
507+
508+
if (!isProjectAreaAccepted) {
509+
if (isSubmitted) {
510+
// revert form data
511+
newFormData = {
512+
...jsonData,
513+
};
486514
}
487-
if (firstNationsLedInputChanged && isZoneSpecificIntake) {
488-
// display modal saying
489-
// Invalid selection. Please first choose from zones 1,2,3 or 6 if this project is not supported or led by First Nations
490-
setProjectAreaModalType('first-nations-led');
515+
setProjectAreaModalType(
516+
getProjectAreaModalType(
517+
geographicAreaInputChanged,
518+
firstNationsLedInputChanged
519+
)
520+
);
521+
522+
if (geographicAreaInputChanged || firstNationsLedInputChanged) {
523+
projectAreaModal.open();
491524
}
492-
} else if (!isSubmitted && !projectAreaAccepted && isZoneSpecificIntake) {
493-
setProjectAreaModalType('pre-submitted');
494-
}
495-
if (
496-
!projectAreaAccepted &&
497-
(geographicAreaInputChanged ||
498-
(firstNationsLedInputChanged && isZoneSpecificIntake))
499-
) {
500-
projectAreaModal.open();
501525
}
502526

503527
// Setting below properties to handle validation errors separately in submission page
@@ -507,11 +531,11 @@ const ApplicationForm: React.FC<Props> = ({
507531
);
508532
// calculating project area selection validity to clearout temporary values
509533
// calculated for error handling/error modals
510-
const projectAreaValid =
511-
newFormData?.projectArea?.firstNationsLed ||
512-
acceptedProjectAreasArray.includes(
513-
newFormData?.projectArea?.geographicArea?.[0]
514-
);
534+
const projectAreaValid = isZoneSelectionValid(
535+
newFormData?.projectArea?.geographicArea,
536+
newFormData?.projectArea?.firstNationsLed
537+
);
538+
515539
setIsProjectAreaInvalid(!projectAreaValid);
516540
}
517541

app/tests/pages/applicantportal/form/[page].test.tsx

+129
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,18 @@ const mockAcceptedZones: moduleApi.FeatureResult<moduleApi.JSONValue> = {
5959
ruleId: 'intake_zones_json',
6060
};
6161

62+
const mockAllZones: moduleApi.FeatureResult<moduleApi.JSONValue> = {
63+
value: {
64+
'1': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
65+
'2': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
66+
'3': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14],
67+
},
68+
source: 'defaultValue',
69+
on: null,
70+
off: null,
71+
ruleId: 'intake_zones_json',
72+
};
73+
6274
const pageTestingHelper = new PageTestingHelper<PageQuery>({
6375
pageComponent: FormPage,
6476
compiledQuery: compiledPageQuery,
@@ -676,6 +688,102 @@ describe('The form page', () => {
676688
expect(geographicArea).toBeChecked();
677689
});
678690

691+
it('project area page should not allow null on geographic area after submission even when first nation led', async () => {
692+
const payload = {
693+
Application() {
694+
return {
695+
id: 'TestApplicationId',
696+
status: 'submitted',
697+
intakeByIntakeId: {
698+
ccbcIntakeNumber: 3,
699+
closeTimestamp: '2022-09-06T23:59:59-07:00',
700+
},
701+
formData: {
702+
formByFormSchemaId: {
703+
jsonSchema: schema,
704+
},
705+
jsonData: {
706+
review: {
707+
acknowledgeIncomplete: true,
708+
},
709+
submission: {
710+
submissionDate: '2023-12-28',
711+
submissionTitle: 'asdf',
712+
submissionCompletedBy: 'asdf',
713+
submissionCompletedFor: 'asdf',
714+
},
715+
projectArea: {
716+
geographicArea: [3],
717+
firstNationsLed: true,
718+
},
719+
techSolution: {
720+
systemDesign: 'asdfd',
721+
},
722+
projectFunding: {
723+
fundingRequestedCCBC2223: 111,
724+
totalFundingRequestedCCBC: 111,
725+
totalApplicantContribution: null,
726+
},
727+
acknowledgements: {
728+
acknowledgementsList: [
729+
'The Applicant acknowledges that it is under no obligation or prohibition, nor is it subject to, or threatened by any actions, suits or proceedings, which could or would affect its ability to implement this proposed Project.',
730+
'The Applicant acknowledges that the Program may collect and share Applicant information for purposes that include making enquiries of such persons, firms, corporations, federal and provincial government agencies/departments/ministries, and non-profit organizations as the Program deems necessary in order to reach a decision on this proposed project.',
731+
'The Applicant acknowledges that any person, who is required to be registered pursuant to the Lobbyists Transparency Act (British Columbia) or the Lobbying Act (Canada), including consultant and in-house lobbyists, must be registered pursuant to, and comply with, those Acts as applicable.',
732+
'The Applicant acknowledges that, where applicable, the Project may require an assessment under the Impact Assessment Act (Canada) or the Environmental Assessment Act (British Columbia).',
733+
'The Applicant recognizes that there is a duty to consult Indigenous groups if a funded Project may undertake infrastructure in, or affecting, an Indigenous community, and the Applicant understands that it must provide such information and assistance to the Province or Federal government in connection with such consultation as may reasonably be required, including, but not limited to, those obligations with respect to Indigenous consultation which may be set forth in any Funding Agreement.',
734+
'The Applicant acknowledges that any current or former public officer holder or public servant employed by the Applicant must comply with the provisions of the Standards of Conduct for BC Public Service employees, the Disclosing a Conflict of Interest: Employee Guideline & Disclosure Form (British Columbia), the Members’ Conflict of Interest Act (British Columbia), the Values and Ethics Code for the Public Service (Canada), the Policy on Conflict of Interest and Post-Employment (Canada), and the Conflict of Interest Act (Canada), as applicable.',
735+
'The Applicant understands that all costs incurred in the preparation and submission of the application shall be wholly absorbed by the Applicant.',
736+
'The Applicant understands that the Program reserves the right to make partial awards and to negotiate project scope changes with Applicants.',
737+
'The Applicant understands that the Program is a discretionary program subject to available funding, and that submission of a complete application, meeting any or all of the eligibility criteria, does not guarantee that funding will be granted. All Applicants whose Projects are approved for funding will be notified in writing.',
738+
'The Applicant acknowledges that it must ensure compliance with any applicable Canadian national security requirements as defined and/or administered by the Canadian security authorities, and any Provincial security requirements as defined and/or administered by the Province.',
739+
'The Applicant acknowledges that it must have the managerial and financial capacity to deliver this proposed project on time and within budget and to maintain the infrastructure and services on an ongoing basis for five years after project completion.',
740+
'The Applicant confirms that it is requesting the lowest possible Program contribution amount required to make this proposed Project financially viable.',
741+
'The Applicant acknowledges that information provided in this Application Form (including attachments) may be shared between the Province and the Government of Canada and other levels of government to promote the Program and maximize the benefits to Canadian citizens and permanent residents.',
742+
'The Applicant acknowledges that all activities required for this proposed Project must comply with all applicable federal, provincial, and territorial laws, regulations, municipal and other local by-laws.',
743+
'The Applicant acknowledges that knowingly making any false statements or misrepresentations, including by omission, in an application may affect its eligibility and may result in the revocation of funding approval.',
744+
'The Applicant acknowledges that information submitted in an application is subject to the Access to Information Act (Canada) or the Freedom of Information and Protection of Privacy Act (BC), as applicable.',
745+
'The Applicant confirms that, to the best of its knowledge, the information submitted in this application is true and correct as of the date of submission.',
746+
],
747+
},
748+
projectInformation: {
749+
projectTitle: 'asdf',
750+
projectDescription: 'asdfdsa',
751+
geographicAreaDescription: 'asdf',
752+
},
753+
organizationProfile: {
754+
organizationName: 'asdf',
755+
},
756+
existingNetworkCoverage: {
757+
hasProvidedExitingNetworkCoverage:
758+
'I have provided existing Network information and/or Coverage to ISED or the CRTC in the past 12 months',
759+
},
760+
},
761+
},
762+
};
763+
},
764+
Query() {
765+
return {
766+
openIntake: {
767+
closeTimestamp: '2022-08-27T12:52:00.00000-04:00',
768+
},
769+
};
770+
},
771+
};
772+
pageTestingHelper.setMockRouterValues({
773+
query: { id: '1', page: '2' },
774+
});
775+
pageTestingHelper.loadQuery(payload);
776+
pageTestingHelper.renderPage();
777+
778+
const geographicArea = screen.getAllByRole('checkbox')[3];
779+
780+
expect(geographicArea).toBeChecked();
781+
782+
await userEvent.click(geographicArea);
783+
784+
expect(geographicArea).toBeChecked();
785+
});
786+
679787
it('handles modal correctly when first nation based and not an available zone', async () => {
680788
pageTestingHelper.setMockRouterValues({
681789
query: { id: '1', page: '2' },
@@ -733,4 +841,25 @@ describe('The form page', () => {
733841

734842
await userEvent.click(modalOkButton);
735843
});
844+
845+
it('should not show modal if first nations led no if intake is all zone permitted', async () => {
846+
pageTestingHelper.setMockRouterValues({
847+
query: { id: '1', page: '2' },
848+
});
849+
850+
jest.spyOn(moduleApi, 'useFeature').mockReturnValue(mockAllZones);
851+
852+
pageTestingHelper.loadQuery();
853+
pageTestingHelper.renderPage();
854+
855+
const fnQuestionNo = screen.getAllByLabelText('No')[0];
856+
857+
await userEvent.click(fnQuestionNo);
858+
859+
expect(
860+
screen.queryByText(
861+
'For this intake, CCBC is considering projects that are in Zones 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, or 14 if the project is not First Nations-led or First Nations-supported.'
862+
)
863+
).not.toBeInTheDocument();
864+
});
736865
});

0 commit comments

Comments
 (0)