Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elisa/5818 facility form #5983

Merged
merged 13 commits into from
Jun 22, 2023
20 changes: 10 additions & 10 deletions cypress/e2e/01-organization_sign_up.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,16 @@ describe("Organization sign up",() => {
cy.checkA11y();
});
it("fills out the form for a new facility", () => {
cy.get('input[name="name"]').type(facility.name);
cy.get('input[name="facility-phone"]').first().type("5308675309");
cy.get('input[name="facility-street"]').first().type("123 Beach Way");
cy.get('input[name="facility-zipCode"]').first().type("90210");
cy.get('select[name="facility-state"]').first().select("CA");
cy.get('input[name="cliaNumber"]').type("12D4567890");
cy.get('input[name="firstName"]').type("Phil");
cy.get('input[name="lastName"]').type("McTester");
cy.get('input[name="NPI"]').type("1234567890");
cy.get('input[name="op-phone"]').last().type("5308675309");
cy.get('input[name="facility.name"]').type(facility.name);
cy.get('input[name="facility.phone"]').first().type("5308675309");
cy.get('input[name="facility.street"]').first().type("123 Beach Way");
cy.get('input[name="facility.zipCode"]').first().type("90210");
cy.get('select[name="facility.state"]').first().select("CA");
cy.get('input[name="facility.cliaNumber"]').type("12D4567890");
cy.get('input[name="orderingProvider.firstName"]').type("Phil");
cy.get('input[name="orderingProvider.lastName"]').type("McTester");
cy.get('input[name="orderingProvider.NPI"]').type("1234567890");
cy.get('input[name="orderingProvider.phone"]').last().type("5308675309");
cy.contains("Save changes").last().click();
cy.get(
'.modal__container input[name="addressSelect-facility"][value="userAddress"]+label'
Expand Down
311 changes: 182 additions & 129 deletions frontend/src/app/Settings/Facility/Components/FacilityInformation.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
import React from "react";

import { stateCodes } from "../../../../config/constants";
import {
liveJurisdictions,
stateCodes,
urls,
} from "../../../../config/constants";
import TextInput from "../../../commonComponents/TextInput";
import { FacilityErrors } from "../facilitySchema";
import { ValidateField } from "../FacilityForm";
import { getSubStrAfterChar } from "../../../utils/text";
import Dropdown from "../../../commonComponents/Dropdown";
import {
isValidCLIANumber,
stateRequiresCLIANumberValidation,
} from "../../../utils/clia";
import { getStateNameFromCode } from "../../../utils/state";
import { emailRegex } from "../../../utils/email";
import { phoneNumberIsValid } from "../../../patients/personSchema";
import { FacilityFormData } from "../FacilityForm";
import { zipCodeRegex } from "../../../utils/address";
import { facilityInfoErrMsgs } from "../constants";

interface Props {
facility: Facility;
updateFacility: (facility: Facility) => void;
errors: FacilityErrors;
validateField: ValidateField;
setError: any;
newOrg?: boolean;
errors: any;
register: any;
formCurrentValues: FacilityFormData;
getFieldState: any;
}

const FacilityInformation: React.FC<Props> = ({
facility,
updateFacility,
errors,
validateField,
newOrg = false,
errors,
register,
formCurrentValues,
getFieldState,
}) => {
const onChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLSelectElement>
) => {
let fieldName = getSubStrAfterChar(e.target.name, "-");
updateFacility({ ...facility, [fieldName]: e.target.value });
const fieldState = getFieldState("facility.state");
const isLiveState = (state: string) => {
return liveJurisdictions.includes(state) && stateCodes.includes(state);
};

return (
Expand All @@ -44,119 +55,161 @@ const FacilityInformation: React.FC<Props> = ({
</p>
</>
)}
<h2 className="font-heading-lg" style={{ margin: 0 }}>
Testing facility information
</h2>
<TextInput
label="Testing facility name"
name="name"
value={facility.name}
required
onChange={onChange}
onBlur={() => {
validateField("name");
}}
validationStatus={errors.name ? "error" : undefined}
errorMessage={errors.name}
/>
<TextInput
label="Phone number"
name="facility-phone"
value={facility.phone}
required
onChange={onChange}
onBlur={() => {
validateField("phone");
}}
validationStatus={errors.phone ? "error" : undefined}
errorMessage={errors.phone}
/>
<TextInput
label="Email"
name="email"
data-testid="facility-email"
value={facility.email || ""}
onChange={onChange}
onBlur={() => {
validateField("email");
}}
validationStatus={errors.email ? "error" : undefined}
errorMessage={errors.email}
/>
<TextInput
label="Street address 1"
name="facility-street"
value={facility.street}
required
onChange={onChange}
onBlur={() => {
validateField("street");
}}
validationStatus={errors.street ? "error" : undefined}
errorMessage={errors.street}
/>
<TextInput
label="Street address 2"
name="facility-streetTwo"
value={facility.streetTwo || ""}
onChange={onChange}
/>
<TextInput
label="City"
name="facility-city"
value={facility.city || ""}
onChange={onChange}
/>
<TextInput
label="ZIP code"
name="facility-zipCode"
value={facility.zipCode}
required
onChange={onChange}
onBlur={() => {
validateField("zipCode");
}}
validationStatus={errors.zipCode ? "error" : undefined}
errorMessage={errors.zipCode}
className="usa-input--medium"
/>
<Dropdown
label="State"
name="facility-state"
selectedValue={facility.state}
options={stateCodes.map((c) => ({ label: c, value: c }))}
defaultSelect
required
onChange={onChange}
onBlur={() => {
validateField("state");
}}
validationStatus={errors.state ? "error" : undefined}
errorMessage={errors.state}
selectClassName="usa-input--medium"
data-testid="facility-state-dropdown"
/>
<TextInput
label="CLIA number"
hintText={
<a
href="https://www.cdc.gov/clia/LabSearch.html#"
target="_blank"
rel="noopener noreferrer"
>
Find my CLIA
</a>
}
name="cliaNumber"
value={facility.cliaNumber}
required
onChange={onChange}
onBlur={() => {
validateField("cliaNumber");
}}
validationStatus={errors.cliaNumber ? "error" : undefined}
errorMessage={errors.cliaNumber}
/>
<fieldset className="usa-fieldset">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just to double check given the large diff here: the only thing that's changing is the extra html <fieldset> and <legend> tags?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's what you pointed out as well as using the react-hook-form library so calling the register method on each input and doing some validation there! Let me know if you have any more questions/concerns!

<legend>
<h2 className="font-heading-lg" style={{ margin: 0 }}>
Testing facility information
</h2>
</legend>
<TextInput
label="Testing facility name"
name="name"
value={formCurrentValues.facility?.name}
required
registrationProps={register("facility.name", {
required: facilityInfoErrMsgs.name.required,
})}
validationStatus={errors?.facility?.name?.type ? "error" : undefined}
errorMessage={errors?.facility?.name?.message}
/>
<TextInput
label="Phone number"
name="facility-phone"
value={formCurrentValues.facility?.phone}
required
registrationProps={register("facility.phone", {
required: facilityInfoErrMsgs.phone.required,
validate: {
valid: (facPhone: string) =>
phoneNumberIsValid(facPhone) ||
facilityInfoErrMsgs.phone.invalid,
},
})}
validationStatus={errors?.facility?.phone?.type ? "error" : undefined}
errorMessage={errors?.facility?.phone?.message}
/>
<TextInput
label="Email"
name="email"
data-testid="facility-email"
value={formCurrentValues.facility?.email ?? undefined}
validationStatus={errors?.facility?.email?.type ? "error" : undefined}
errorMessage={errors?.facility?.email?.message}
registrationProps={register("facility.email", {
pattern: {
value: emailRegex,
message: facilityInfoErrMsgs.email.invalid,
},
})}
/>
<TextInput
label="Street address 1"
name="facility-street"
value={formCurrentValues.facility?.street}
required
validationStatus={
errors?.facility?.street?.type ? "error" : undefined
}
errorMessage={errors?.facility?.street?.message}
registrationProps={register("facility.street", {
required: facilityInfoErrMsgs.street.required,
})}
/>
<TextInput
label="Street address 2"
name="facility-streetTwo"
value={formCurrentValues.facility?.streetTwo ?? undefined}
registrationProps={register("facility.streetTwo")}
/>
<TextInput
label="City"
name="facility-city"
value={formCurrentValues.facility?.city ?? undefined}
registrationProps={register("facility.city")}
/>
<TextInput
label="ZIP code"
name="facility-zipCode"
value={formCurrentValues.facility?.zipCode}
required
validationStatus={
errors?.facility?.zipCode?.type ? "error" : undefined
}
errorMessage={errors?.facility?.zipCode?.message}
registrationProps={register("facility.zipCode", {
required: facilityInfoErrMsgs.zip.required,
pattern: {
value: zipCodeRegex,
message: facilityInfoErrMsgs.zip.invalid,
},
})}
className="usa-input--medium"
/>
<Dropdown
label="State"
name="facility-state"
selectedValue={formCurrentValues.facility?.state}
options={stateCodes.map((c) => ({ label: c, value: c }))}
defaultSelect
required
hintText={
fieldState?.error && (
<span className="display-block margin-top-05 usa-error-message">
See a{" "}
<a href={urls.FACILITY_INFO}>
{" "}
list of states where SimpleReport is supported
</a>
.
</span>
)
}
validationStatus={errors?.facility?.state?.type ? "error" : undefined}
errorMessage={errors?.facility?.state?.message}
selectClassName="usa-input--medium"
data-testid="facility-state-dropdown"
registrationProps={register("facility.state", {
required: facilityInfoErrMsgs.state.required,
validate: {
liveJurisdiction: (state: string) =>
isLiveState(state) ||
`${facilityInfoErrMsgs.state.invalid} ${getStateNameFromCode(
state
)}.`,
},
})}
/>
<TextInput
label="CLIA number"
hintText={
<a
href="https://www.cdc.gov/clia/LabSearch.html#"
target="_blank"
rel="noopener noreferrer"
>
Find my CLIA
</a>
}
name="cliaNumber"
value={formCurrentValues.facility?.cliaNumber}
required
validationStatus={
errors?.facility?.cliaNumber?.type ? "error" : undefined
}
errorMessage={errors?.facility?.cliaNumber?.message}
registrationProps={register("facility.cliaNumber", {
required: facilityInfoErrMsgs.clia.required,
validate: {
validCLIA: (clia: string) =>
(stateRequiresCLIANumberValidation(
formCurrentValues.facility.state
)
? isValidCLIANumber(clia, formCurrentValues.facility.state)
: true) || facilityInfoErrMsgs.clia.invalid,
},
})}
/>
</fieldset>
</div>
);
};
Expand Down
Loading