Skip to content

Commit

Permalink
ORV2-2940 - FE: UPDATE: Application contact info field validation Add (
Browse files Browse the repository at this point in the history
…#1648)

Co-authored-by: GlenAOT <[email protected]>
  • Loading branch information
glen-aot and glen-aot authored Oct 23, 2024
1 parent e658f38 commit ddd3d7a
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 24 deletions.
16 changes: 15 additions & 1 deletion frontend/src/common/components/form/CustomFormComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ import { CustomOutlinedInput } from "./subFormComponents/CustomOutlinedInput";
import { CustomSelect } from "./subFormComponents/CustomSelect";
import { PhoneNumberInput } from "./subFormComponents/PhoneNumberInput";
import { CustomTextArea } from "./subFormComponents/CustomTextArea";
import { NumberInput } from "./subFormComponents/NumberInput";

/**
* Properties of onRouteBC custom form components
*/
export interface CustomFormComponentProps<T extends FieldValues> {
type: "input" | "select" | "phone" | "textarea";
type: "input" | "select" | "phone" | "textarea" | "number";
feature: string;
options: CustomFormOptionsProps<T>;
menuOptions?: JSX.Element[];
Expand Down Expand Up @@ -157,6 +158,19 @@ export const CustomFormComponent = <T extends ORBC_FormTypes>({
readOnly={readOnly}
/>
);
case "number":
return (
<NumberInput
feature={feature}
name={name}
rules={rules}
inputProps={inputProps}
invalid={invalid}
inputType={inputType}
disabled={disabled}
readOnly={readOnly}
/>
);
default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@use "../CustomFormComponents";

@include CustomFormComponents.custom-form-component(".custom-number-input");
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { OutlinedInput } from "@mui/material";
import { useFormContext } from "react-hook-form";
import { ORBC_FormTypes } from "../../../types/common";
import { CustomOutlinedInputProps } from "./CustomOutlinedInput";
import "./NumberInput.scss";

/**
* An onRouteBC customized MUI OutlineInput component
* that automatically filters out non-numeric values as the user types
*/
export const NumberInput = <T extends ORBC_FormTypes>(
props: CustomOutlinedInputProps<T>,
): JSX.Element => {
const { register, setValue } = useFormContext();
/**
* Function to prevent non-numeric input as the user types
*/
const filterNonNumericValue = (input?: string) => {
if (!input) return "";
// only allows 0-9 inputs
return input.replace(/[^\d]/g, "");
};

// Everytime the user types, update the format of the users input
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const formattedValue = filterNonNumericValue(e.target.value);
setValue<string>(props.name, formattedValue, { shouldValidate: true });
};

const className = `custom-phone-input ${props.disabled ? "custom-phone-input--disabled" : ""} ${props.invalid ? "custom-phone-input--invalid" : ""}`;

return (
<OutlinedInput
className={className}
aria-labelledby={`${props.feature}-${props.name}-label`}
inputProps={props.inputProps}
{...register(props.name, props.rules)}
onChange={handleChange}
autoComplete="tel"
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const ReusableUserInfoForm = ({
className="my-info-form__input my-info-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={FEATURE}
options={{
name: "phone1Extension",
Expand Down Expand Up @@ -137,7 +137,7 @@ export const ReusableUserInfoForm = ({
className="my-info-form__input my-info-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={FEATURE}
options={{
name: "phone2Extension",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export const CompanyContactDetailsForm = ({
className="company-contact-details-form__input company-contact-details-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={feature}
options={{
name: "extension",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const CompanyPrimaryContactForm = ({ feature }: { feature: string }) => (
className="company-primary-contact-form__input company-primary-contact-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={feature}
options={{
name: "primaryContact.phone1Extension",
Expand Down Expand Up @@ -127,7 +127,7 @@ export const CompanyPrimaryContactForm = ({ feature }: { feature: string }) => (
className="company-primary-contact-form__input company-primary-contact-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={feature}
options={{
name: "primaryContact.phone2Extension",
Expand Down
64 changes: 58 additions & 6 deletions frontend/src/features/permits/components/form/ContactDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import { Box, Typography } from "@mui/material";
import "./ContactDetails.scss";
import { InfoBcGovBanner } from "../../../../common/components/banners/InfoBcGovBanner";
import { CustomFormComponent } from "../../../../common/components/form/CustomFormComponents";
import { requiredMessage } from "../../../../common/helpers/validationMessages";
import {
invalidEmail,
invalidExtensionLength,
invalidPhoneLength,
requiredMessage,
} from "../../../../common/helpers/validationMessages";
import { PHONE_WIDTH, EXT_WIDTH } from "../../../../themes/orbcStyles";
import { BANNER_MESSAGES } from "../../../../common/constants/bannerMessages";
import isEmail from "validator/lib/isEmail";

export const ContactDetails = ({ feature }: { feature: string }) => {
return (
Expand Down Expand Up @@ -47,18 +53,33 @@ export const ContactDetails = ({ feature }: { feature: string }) => {
name: "permitData.contactDetails.phone1",
rules: {
required: { value: true, message: requiredMessage() },
validate: {
validatePhone: (phone: string) =>
(phone.length >= 10 && phone.length <= 20) ||
invalidPhoneLength(10, 20),
},
},

label: "Phone Number",
width: PHONE_WIDTH,
}}
/>

<CustomFormComponent
type="input"
type="number"
feature={feature}
options={{
name: "permitData.contactDetails.phone1Extension",
rules: { required: false },
rules: {
required: false,
validate: {
validateExt1: (ext?: string) =>
!ext ||
ext.length === 0 ||
ext.length <= 5 ||
invalidExtensionLength(5),
},
},
label: "Ext",
width: EXT_WIDTH,
}}
Expand All @@ -71,7 +92,16 @@ export const ContactDetails = ({ feature }: { feature: string }) => {
feature={feature}
options={{
name: "permitData.contactDetails.phone2",
rules: { required: false },
rules: {
required: false,
validate: {
validatePhone: (phone?: string) =>
!phone ||
phone.length === 0 ||
(phone.length >= 10 && phone.length <= 20) ||
invalidPhoneLength(10, 20),
},
},
label: "Alternate Number",
width: PHONE_WIDTH,
}}
Expand All @@ -82,7 +112,16 @@ export const ContactDetails = ({ feature }: { feature: string }) => {
feature={feature}
options={{
name: "permitData.contactDetails.phone2Extension",
rules: { required: false },
rules: {
required: false,
validate: {
validateExt2: (ext?: string) =>
!ext ||
ext.length === 0 ||
ext.length <= 5 ||
invalidExtensionLength(5),
},
},
label: "Ext",
width: EXT_WIDTH,
}}
Expand All @@ -98,6 +137,10 @@ export const ContactDetails = ({ feature }: { feature: string }) => {
name: "permitData.contactDetails.email",
rules: {
required: { value: true, message: requiredMessage() },
validate: {
validateEmail: (email: string) =>
isEmail(email) || invalidEmail(),
},
},
label: "Company Email",
}}
Expand All @@ -110,7 +153,16 @@ export const ContactDetails = ({ feature }: { feature: string }) => {
feature={feature}
options={{
name: "permitData.contactDetails.additionalEmail",
rules: { required: false },
rules: {
required: false,
validate: {
validateEmail: (email?: string) =>
!email ||
email.length === 0 ||
isEmail(email) ||
invalidEmail(),
},
},
label: "Additional Email",
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { useVoidPermit } from "../hooks/useVoidPermit";
import { mapToRevokeRequestData } from "../helpers/mapper";
import { Nullable } from "../../../../../common/types/common";
import { hasPermitsActionFailed } from "../../../helpers/permitState";
import { applyWhenNotNullable, getDefaultRequiredVal } from "../../../../../common/helpers/util";
import {
applyWhenNotNullable,
getDefaultRequiredVal,
} from "../../../../../common/helpers/util";
import { usePermitHistoryQuery } from "../../../hooks/hooks";
import {
CustomFormComponent,
Expand Down Expand Up @@ -53,7 +56,7 @@ export const VoidPermitForm = ({
const companyId: number = getDefaultRequiredVal(
0,
permit?.companyId,
applyWhenNotNullable(id => Number(id), companyIdParam),
applyWhenNotNullable((id) => Number(id), companyIdParam),
);

const originalPermitId = getDefaultRequiredVal("", permit?.originalPermitId);
Expand All @@ -63,13 +66,15 @@ export const VoidPermitForm = ({
originalPermitId,
);

const transactionHistory = getDefaultRequiredVal([], permitHistory)
.filter((history) =>
const transactionHistory = getDefaultRequiredVal([], permitHistory).filter(
(history) =>
isValidTransaction(history.paymentMethodTypeCode, history.pgApproved),
);

const amountToRefund = !permit || transactionHistory.length === 0
? 0 : -1 * calculateAmountForVoid(permit, transactionHistory);
);

const amountToRefund =
!permit || transactionHistory.length === 0
? 0
: -1 * calculateAmountForVoid(permit, transactionHistory);

useEffect(() => {
const revokeFailed = hasPermitsActionFailed(voidResults);
Expand Down Expand Up @@ -151,8 +156,11 @@ export const VoidPermitForm = ({
rules: {
required: false,
validate: {
validateEmail: (email: string) =>
email.length === 0 || isEmail(email) || invalidEmail(),
validateEmail: (email?: string) =>
!email ||
email.length === 0 ||
isEmail(email) ||
invalidEmail(),
},
},
label: "Additional Email",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const UserInformationWizardForm = memo(() => {
className="user-info-wizard-form__input user-info-wizard-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={FEATURE}
options={{
name: "adminUser.phone1Extension",
Expand Down Expand Up @@ -141,7 +141,7 @@ export const UserInformationWizardForm = memo(() => {
className="user-info-wizard-form__input user-info-wizard-form__input--left"
/>
<CustomFormComponent
type="input"
type="number"
feature={FEATURE}
options={{
name: "adminUser.phone2Extension",
Expand Down

0 comments on commit ddd3d7a

Please sign in to comment.