diff --git a/src/components/contact-info-section/ContactInfoEmail.tsx b/src/components/contact-info-section/ContactInfoEmail.tsx new file mode 100644 index 0000000000..fb47b4269f --- /dev/null +++ b/src/components/contact-info-section/ContactInfoEmail.tsx @@ -0,0 +1,52 @@ +import * as React from "react"; +import { FC } from "react"; +import TextInput from "../atoms/input/TextInput"; +import { PatronSettingsV3, PatronV5 } from "../../core/fbs/model"; +import { useText } from "../../core/utils/text"; +import CheckBox from "../checkbox/Checkbox"; +import { ChangePatronProps } from "./types"; + +export interface ContactInfoEmailProps { + className?: string; + patron: PatronV5 | PatronSettingsV3 | null; + changePatron: ChangePatronProps; + showCheckboxes: boolean; + isRequired?: boolean; +} + +const ContactInfoEmail: FC = ({ + className = "", + patron, + changePatron, + showCheckboxes, + isRequired = false +}) => { + const t = useText(); + return ( + <> + changePatron(newEmail, "emailAddress")} + value={patron?.emailAddress} + label={t("patronContactEmailLabelText")} + /> + {showCheckboxes && ( + + changePatron(newReceiveEmail, "receiveEmail") + } + id="email-messages" + selected={patron?.receiveEmail} + disabled={false} + label={t("patronContactEmailCheckboxText")} + /> + )} + + ); +}; + +export default ContactInfoEmail; diff --git a/src/components/contact-info-section/ContactInfoInputs.tsx b/src/components/contact-info-section/ContactInfoInputs.tsx new file mode 100644 index 0000000000..acaeba3816 --- /dev/null +++ b/src/components/contact-info-section/ContactInfoInputs.tsx @@ -0,0 +1,48 @@ +// eslint-disable-next-line import/no-extraneous-dependencies +import { configure, render } from "@testing-library/react"; +import clsx from "clsx"; +import * as React from "react"; +import { FC } from "react"; + +export interface ContactInfoInputsProps { + isInline: boolean; + children: React.ReactNode; + dataCy?: string; + className?: string; +} + +// This component wraps the input fields for the contact info section +// depending on the isInline prop. +const ContactInfoInputs: FC = ({ + isInline, + children, + dataCy = "contact-info-input", + className = undefined +}) => { + if (!isInline) { + return ( +
+ {children} +
+ ); + } + + const renderableChildren = React.Children.toArray(children); + return ( +
+ {renderableChildren.map((child, i) => { + const childClassName = clsx("patron__input--desktop", { + "mr-16": i < renderableChildren.length - 1 + }); + return
{child}
; + })} +
+ ); +}; + +export default ContactInfoInputs; diff --git a/src/components/contact-info-section/ContactInfoPhone.tsx b/src/components/contact-info-section/ContactInfoPhone.tsx new file mode 100644 index 0000000000..6237e83138 --- /dev/null +++ b/src/components/contact-info-section/ContactInfoPhone.tsx @@ -0,0 +1,52 @@ +import * as React from "react"; +import { FC } from "react"; +import TextInput from "../atoms/input/TextInput"; +import { PatronSettingsV3, PatronV5 } from "../../core/fbs/model"; +import CheckBox from "../checkbox/Checkbox"; +import { useText } from "../../core/utils/text"; +import { ChangePatronProps } from "./types"; + +export interface ContactInfoPhoneProps { + patron: PatronV5 | PatronSettingsV3 | null; + changePatron: ChangePatronProps; + showCheckboxes: boolean; + className?: string; +} + +const ContactInfoPhone: FC = ({ + patron, + changePatron, + showCheckboxes, + className = "" +}) => { + const t = useText(); + return ( + <> + + changePatron(newPhoneNumber, "phoneNumber") + } + value={patron?.phoneNumber} + label={t("patronContactPhoneLabelText")} + /> + {showCheckboxes && ( + + changePatron(newReceiveSms, "receiveSms") + } + id="phone-messages" + selected={patron?.receiveSms} + disabled={false} + label={t("patronContactPhoneCheckboxText")} + /> + )} + + ); +}; + +export default ContactInfoPhone; diff --git a/src/components/contact-info-section/ContactInfoSection.tsx b/src/components/contact-info-section/ContactInfoSection.tsx index 7565d697a8..335a0db24f 100644 --- a/src/components/contact-info-section/ContactInfoSection.tsx +++ b/src/components/contact-info-section/ContactInfoSection.tsx @@ -1,14 +1,12 @@ import React, { FC } from "react"; import clsx from "clsx"; import { PatronV5, PatronSettingsV3 } from "../../core/fbs/model"; -import TextInput from "../atoms/input/TextInput"; -import CheckBox from "../checkbox/Checkbox"; import { useText } from "../../core/utils/text"; import { useConfig } from "../../core/utils/config"; - -export interface ChangePatronProps { - (newValue: string | boolean, key: string): void; -} +import ContactInfoInputs from "./ContactInfoInputs"; +import ContactInfoPhone from "./ContactInfoPhone"; +import ContactInfoEmail from "./ContactInfoEmail"; +import { ChangePatronProps } from "./types"; interface ContactInfoSectionProps { patron: PatronV5 | PatronSettingsV3 | null; @@ -26,64 +24,9 @@ const ContactInfoSection: FC = ({ const t = useText(); const inputsClass = clsx("dpl-input", { input__desktop: inLine }); const config = useConfig(); - const textNotificationsEnabled = + const textNotificationsEnabledConfig = config("textNotificationsEnabledConfig") === "1"; - const phoneNode = ( - <> - - changePatron(newPhoneNumber, "phoneNumber") - } - value={patron?.phoneNumber} - label={t("patronContactPhoneLabelText")} - /> - {showCheckboxes && textNotificationsEnabled && ( - - changePatron(newReceiveSms, "receiveSms") - } - id="phone-messages" - selected={patron?.receiveSms} - disabled={false} - label={t("patronContactPhoneCheckboxText")} - /> - )} - - ); - const emailNode = ( - <> - changePatron(newEmail, "emailAddress")} - value={patron?.emailAddress} - label={t("patronContactEmailLabelText")} - /> - {showCheckboxes && ( - - changePatron(newReceiveEmail, "receiveEmail") - } - id="email-messages" - selected={patron?.receiveEmail} - disabled={false} - label={t("patronContactEmailCheckboxText")} - /> - )} - - ); - return (

@@ -94,17 +37,22 @@ const ContactInfoSection: FC = ({ {t("patronContactInfoBodyText")}

)} - {inLine && ( -
-
{phoneNode}
-
{emailNode}
-
- )} - {!inLine && ( - <> - {phoneNode} {emailNode} - - )} + + + +

); }; diff --git a/src/components/contact-info-section/__snapshots__/ContactInfoInputs.tsx.snap b/src/components/contact-info-section/__snapshots__/ContactInfoInputs.tsx.snap new file mode 100644 index 0000000000..c2591cf8f7 --- /dev/null +++ b/src/components/contact-info-section/__snapshots__/ContactInfoInputs.tsx.snap @@ -0,0 +1,36 @@ +// Vitest Snapshot v1 + +exports[`ContactInfoInputs > Should NOT wrap the input fields if it is NOT inline 1`] = ` +
+

+ One input component +

+

+ Another input component +

+
+`; + +exports[`ContactInfoInputs > Should wrap the input fields if it is inline 1`] = ` +
+
+

+ One input component +

+
+
+

+ Another input component +

+
+
+`; diff --git a/src/components/contact-info-section/types.ts b/src/components/contact-info-section/types.ts new file mode 100644 index 0000000000..ec855d2c17 --- /dev/null +++ b/src/components/contact-info-section/types.ts @@ -0,0 +1,3 @@ +export interface ChangePatronProps { + (newValue: string | boolean, key: string): void; +} diff --git a/src/tests/unit/__snapshots__/contact-info.test.tsx.snap b/src/tests/unit/__snapshots__/contact-info.test.tsx.snap new file mode 100644 index 0000000000..c2591cf8f7 --- /dev/null +++ b/src/tests/unit/__snapshots__/contact-info.test.tsx.snap @@ -0,0 +1,36 @@ +// Vitest Snapshot v1 + +exports[`ContactInfoInputs > Should NOT wrap the input fields if it is NOT inline 1`] = ` +
+

+ One input component +

+

+ Another input component +

+
+`; + +exports[`ContactInfoInputs > Should wrap the input fields if it is inline 1`] = ` +
+
+

+ One input component +

+
+
+

+ Another input component +

+
+
+`; diff --git a/src/tests/unit/contact-info.test.tsx b/src/tests/unit/contact-info.test.tsx new file mode 100644 index 0000000000..f72b3cf513 --- /dev/null +++ b/src/tests/unit/contact-info.test.tsx @@ -0,0 +1,36 @@ +import { describe, expect, it } from "vitest"; +import React from "react"; +import { render } from "@testing-library/react"; +import { configure } from "@testing-library/dom"; +import ContactInfoInputs from "../../components/contact-info-section/ContactInfoInputs"; + +configure({ + testIdAttribute: "data-cy" +}); + +describe("ContactInfoInputs", () => { + it("Should wrap the input fields if it is inline", async () => { + const { getByTestId } = render( + +

One input component

+

Another input component

+
+ ); + + const contactInfoInputs = getByTestId("contact-info-input"); + + expect(contactInfoInputs).toMatchSnapshot(); + }); + it("Should NOT wrap the input fields if it is NOT inline", async () => { + const { getByTestId } = render( + +

One input component

+

Another input component

+
+ ); + + const contactInfoInputs = getByTestId("contact-info-input-inline"); + + expect(contactInfoInputs).toMatchSnapshot(); + }); +});