Skip to content

Commit

Permalink
Intake Form Validation - Phone Numbers (#243)
Browse files Browse the repository at this point in the history
Description: 

Added validation for phone numbers and dates in the forms where applicable.
  • Loading branch information
malvikapatel authored Apr 4, 2024
1 parent b8155da commit cd0f4f1
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 7 deletions.
3 changes: 3 additions & 0 deletions frontend/src/components/intake/IntakeFormFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export type IntakeFooterProps = {
childrens?: Children;
caregivers?: Caregivers;
permittedIndividuals?: PermittedIndividuals;
isButtonDisabled?: boolean;
};

const IntakeFooter = ({
Expand All @@ -50,6 +51,7 @@ const IntakeFooter = ({
childrens,
caregivers,
permittedIndividuals,
isButtonDisabled,
}: IntakeFooterProps): React.ReactElement => {
const toast = useToast();
// TODO: remove useHistory once dashboard is implemented
Expand Down Expand Up @@ -233,6 +235,7 @@ const IntakeFooter = ({
onNextStep();
}
}}
disabled={isButtonDisabled}
>
<Box pr="5px">{nextButtonText}</Box>
<ArrowRight />
Expand Down
58 changes: 57 additions & 1 deletion frontend/src/components/intake/NewCaregiverModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ const NewCaregiverModal = ({
const [relationshipChanged, setRelationshipChanged] = useState(false);
const [indivConsiderationsChanged, setIndivConsiderationsChanged] =
useState(false);
const [dateOfBirthError, setDateOfBirthError] = useState<string | null>(null);
const [primaryPhoneNoError, setPrimaryPhoneNoError] = useState<string | null>(
null,
);
const [secondaryPhoneNoError, setSecondaryPhoneNoError] = useState<
string | null
>(null);
const [isButtonDisabled, setButtonDisabled] = useState(false);

const handleClose = () => {
setCaregiverName(caregiver ? caregiver.caregiverName : "");
Expand Down Expand Up @@ -105,6 +113,41 @@ const NewCaregiverModal = ({
return newDate;
};

function validateDate(value: string) {
if (!value) {
setDateOfBirthError("Required");
} else if (!/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2]\d|3[01])$/.test(value)) {
setDateOfBirthError("Invalid Date");
} else {
setDateOfBirthError(null);
}
}

function validatePhoneNo(value: string, isSecondaryPhoneNo: boolean) {
if (
/^(\+\d{1,3}\s?)?((\(\d{3}\)\s?)|(\d{3})(\s|-?))(\d{3}(\s|-?))(\d{4}[,]?)(\s?([E|e]xt[.]?)(\s?\d+))?/.test(
value,
) ||
(value === "" && isSecondaryPhoneNo)
) {
if (isSecondaryPhoneNo) {
setSecondaryPhoneNoError(null);
} else {
setPrimaryPhoneNoError(null);
}
setButtonDisabled(false);
} else {
if (isSecondaryPhoneNo) {
setSecondaryPhoneNoError("Invalid phone number");
} else {
const primaryErrorMessageTemp =
value === "" ? "Required" : "Invalid phone number";
setPrimaryPhoneNoError(primaryErrorMessageTemp);
}
setButtonDisabled(true);
}
}

return (
<Box>
<ModalComponent
Expand Down Expand Up @@ -144,8 +187,12 @@ const NewCaregiverModal = ({
onChange={(event) => {
setDateOfBirth(event.target.value);
setDateOfBirthChanged(true);
validateDate(event.target.value);
}}
/>
{dateOfBirthError && (
<div style={{ color: "red" }}>{dateOfBirthError}</div>
)}
</Box>
<Box>
<FormLabel htmlFor="primaryPhoneNumber">
Expand All @@ -161,8 +208,12 @@ const NewCaregiverModal = ({
onChange={(event) => {
setPrimaryPhoneNo(event.target.value);
setPrimaryPhoneNoChanged(true);
validatePhoneNo(event.target.value, false);
}}
/>
{primaryPhoneNoError && (
<div style={{ color: "red" }}>{primaryPhoneNoError}</div>
)}
</Box>
<Box>
<FormLabel htmlFor="secondaryPhoneNumber">
Expand All @@ -178,8 +229,12 @@ const NewCaregiverModal = ({
onChange={(event) => {
setSecondaryPhoneNo(event.target.value);
setSecondaryPhoneNoChanged(true);
validatePhoneNo(event.target.value, true);
}}
/>
{secondaryPhoneNoError && (
<div style={{ color: "red" }}>{secondaryPhoneNoError}</div>
)}
</Box>
</SimpleGrid>
<Box marginTop="0.75rem">
Expand Down Expand Up @@ -367,7 +422,8 @@ const NewCaregiverModal = ({
? primaryPhoneNo
: caregiver?.primaryPhoneNo) &&
(addressChanged ? address : caregiver?.address) &&
(relationshipChanged ? relationship : caregiver?.relationship)
(relationshipChanged ? relationship : caregiver?.relationship) &&
isButtonDisabled
)
}
secondaryTitle="Individual Details"
Expand Down
43 changes: 42 additions & 1 deletion frontend/src/components/intake/NewProviderModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ const NewProviderModal = ({
const [contactNotesChanged, setContactNotesChanged] = useState(false);
const [addressChanged, setAddressChanged] = useState(false);
const [relationshipChanged, setRelationshipChanged] = useState(false);
const [primaryPhoneNoError, setPrimaryPhoneNoError] = useState<string | null>(
null,
);
const [secondaryPhoneNoError, setSecondaryPhoneNoError] = useState<
string | null
>(null);
const [isButtonDisabled, setButtonDisabled] = useState(false);

const handleClose = () => {
setProviderName("");
Expand All @@ -70,6 +77,31 @@ const NewProviderModal = ({
onClose();
};

function validatePhoneNo(value: string, isSecondaryPhoneNo: boolean) {
if (
/^(\+\d{1,3}\s?)?((\(\d{3}\)\s?)|(\d{3})(\s|-?))(\d{3}(\s|-?))(\d{4}[,]?)(\s?([E|e]xt[.]?)(\s?\d+))?/.test(
value,
) ||
(value === "" && isSecondaryPhoneNo)
) {
if (isSecondaryPhoneNo) {
setSecondaryPhoneNoError(null);
} else {
setPrimaryPhoneNoError(null);
}
setButtonDisabled(false);
} else {
if (isSecondaryPhoneNo) {
setSecondaryPhoneNoError("Invalid phone number");
} else {
const primaryErrorMessageTemp =
value === "" ? "Required" : "Invalid phone number";
setPrimaryPhoneNoError(primaryErrorMessageTemp);
}
setButtonDisabled(true);
}
}

return (
<Box>
<ModalComponent
Expand Down Expand Up @@ -123,8 +155,12 @@ const NewProviderModal = ({
onChange={(event) => {
setPrimaryPhoneNo(event.target.value);
setPrimaryPhoneNoChanged(true);
validatePhoneNo(event.target.value, false);
}}
/>
{primaryPhoneNoError && (
<div style={{ color: "red" }}>{primaryPhoneNoError}</div>
)}
</Box>
<Box>
<FormLabel htmlFor="secondaryPhoneNumber">
Expand All @@ -140,8 +176,12 @@ const NewProviderModal = ({
onChange={(event) => {
setSecondaryPhoneNo(event.target.value);
setSecondaryPhoneNoChanged(true);
validatePhoneNo(event.target.value, true);
}}
/>
{secondaryPhoneNoError && (
<div style={{ color: "red" }}>{secondaryPhoneNoError}</div>
)}
</Box>
<Box>
<FormLabel htmlFor="email">
Expand Down Expand Up @@ -252,7 +292,8 @@ const NewProviderModal = ({
? primaryPhoneNo
: provider?.primaryPhoneNo) &&
(addressChanged ? address : provider?.address) &&
(relationshipChanged ? relationship : provider?.relationship)
(relationshipChanged ? relationship : provider?.relationship) &&
!isButtonDisabled
)
}
secondaryTitle="Individual Details"
Expand Down
21 changes: 20 additions & 1 deletion frontend/src/components/intake/ProgramForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import {
FormControl,
Text,
Expand Down Expand Up @@ -100,6 +100,20 @@ const ProgramForm = ({
});
};

const [dateOfBirthError, setDateOfBirthError] = useState<string | null>(null);

function validateDate(value: string) {
if (!value) {
setDateOfBirthError("Required");
} else if (
!/^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/.test(value)
) {
setDateOfBirthError("Invalid Date");
} else {
setDateOfBirthError(null);
}
}

return (
<>
{!hideStepper && (
Expand Down Expand Up @@ -172,7 +186,11 @@ const ProgramForm = ({
type="string"
placeholder="DD/MM/YYYY"
icon={<Icon as={Calendar} />}
validate={(value: string) => validateDate(value)}
/>
{dateOfBirthError && (
<div style={{ color: "red" }}>{dateOfBirthError}</div>
)}
</Box>
</SimpleGrid>
<Text textAlign="left" paddingTop="35px" textStyle="title-medium">
Expand Down Expand Up @@ -254,6 +272,7 @@ const ProgramForm = ({
registrationLoading={false}
nextStepCallBack={onNextStep}
clearFields={onClear}
isButtonDisabled={dateOfBirthError != null}
/>
)}
</>
Expand Down
47 changes: 46 additions & 1 deletion frontend/src/components/intake/ReferralForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import {
Box,
FormControl,
Expand Down Expand Up @@ -73,6 +73,38 @@ const ReferralForm = ({
});
};

const [referringWorkerContactError, setreferringWorkerContactError] =
useState<string | null>(null);
const [refferalDateError, setRefferalDateError] = useState<string | null>(
null,
);

function validatePhone(value: string) {
if (!value) {
setreferringWorkerContactError("Required");
} else if (
!/^(\+\d{1,3}\s?)?((\(\d{3}\)\s?)|(\d{3})(\s|-?))(\d{3}(\s|-?))(\d{4}[,]?)(\s?([E|e]xt[.]?)(\s?\d+))?/.test(
value,
)
) {
setreferringWorkerContactError("Invalid phone number");
} else {
setreferringWorkerContactError(null);
}
}

function validateDate(value: string) {
if (!value) {
setRefferalDateError("Required");
} else if (
!/^(0[1-9]|[12][0-9]|3[01])\/(0[1-9]|1[0-2])\/\d{4}$/.test(value)
) {
setRefferalDateError("Invalid Date");
} else {
setRefferalDateError(null);
}
}

return (
<>
{!hideStepper && (
Expand Down Expand Up @@ -120,7 +152,13 @@ const ReferralForm = ({
type="string"
placeholder="(e.g. 555-555-5555, ext. 123)"
icon={<Icon as={Phone} />}
validate={(value: string) => validatePhone(value)}
/>
{referringWorkerContactError && (
<div style={{ color: "red" }}>
{referringWorkerContactError}
</div>
)}
</Box>
<Box>
<FormLabel htmlFor="cpinFileNumber">CPIN FILE NUMBER</FormLabel>
Expand Down Expand Up @@ -168,7 +206,11 @@ const ReferralForm = ({
type="string"
placeholder="DD/MM/YYYY"
icon={<Icon as={Calendar} />}
validate={(value: string) => validateDate(value)}
/>
{refferalDateError && (
<div style={{ color: "red" }}>{refferalDateError}</div>
)}
</Box>
</FormControl>
</Form>
Expand All @@ -181,6 +223,9 @@ const ReferralForm = ({
registrationLoading={false}
nextStepCallBack={onNextStep}
clearFields={onClear}
isButtonDisabled={
referringWorkerContactError != null || refferalDateError != null
}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,17 @@ const AddChild = ({
dismissalTime: "",
});
const [providers, setProviders] = useState<Providers>([]);
const [childInfoDateError, setChildInfoDateError] = useState<boolean>(false);
const [childInfoSchoolPhoneNoError, setChildInfoSchoolPhoneNoError] =
useState<boolean>(false);

const requiredInfomationMissing: boolean =
!childDetails.childName ||
!childDetails.cpinFileNumber ||
!childDetails.dateOfBirth;
!childDetails.dateOfBirth ||
!schoolDetails.schoolPhoneNo ||
childInfoDateError ||
childInfoSchoolPhoneNoError;

// TODO: Check other required fields

Expand Down Expand Up @@ -96,13 +102,15 @@ const AddChild = ({
<ChildInformationForm
childDetails={childDetails}
setChildDetails={setChildDetails}
setChildInfoDateError={setChildInfoDateError}
/>
);
case AddChildSteps.SCHOOL_DAYCARE_FORM:
return (
<SchoolDaycareForm
schoolDetails={schoolDetails}
setSchoolDetails={setSchoolDetails}
setChildInfoSchoolPhoneNoError={setChildInfoSchoolPhoneNoError}
/>
);
case AddChildSteps.CHILD_PROVIDER_FORM:
Expand Down
Loading

0 comments on commit cd0f4f1

Please sign in to comment.