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

Make register/create patron form show and make email field optional #579

6 changes: 1 addition & 5 deletions src/apps/create-patron-user-info/CreatePatron.dev.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,10 @@ export default {
'[\n {\n "branchId":"DK-775120",\n "title":"Højbjerg"\n },\n {\n "branchId":"DK-775122",\n "title":"Beder-Malling"\n },\n {\n "branchId":"DK-775144",\n "title":"Gellerup"\n },\n {\n "branchId":"DK-775167",\n "title":"Lystrup"\n },\n {\n "branchId":"DK-775146",\n "title":"Harlev"\n },\n {\n "branchId":"DK-775168",\n "title":"Skødstrup"\n },\n {\n "branchId":"FBS-751010",\n "title":"Arresten"\n },\n {\n "branchId":"DK-775147",\n "title":"Hasle"\n },\n {\n "branchId":"FBS-751032",\n "title":"Må ikke benyttes"\n },\n {\n "branchId":"FBS-751031",\n "title":"Fjernlager 1"\n },\n {\n "branchId":"DK-775126",\n "title":"Solbjerg"\n },\n {\n "branchId":"FBS-751030",\n "title":"ITK"\n },\n {\n "branchId":"DK-775149",\n "title":"Sabro"\n },\n {\n "branchId":"DK-775127",\n "title":"Tranbjerg"\n },\n {\n "branchId":"DK-775160",\n "title":"Risskov"\n },\n {\n "branchId":"DK-775162",\n "title":"Hjortshøj"\n },\n {\n "branchId":"DK-775140",\n "title":"Åby"\n },\n {\n "branchId":"FBS-751009",\n "title":"Fjernlager 2"\n },\n {\n "branchId":"FBS-751029",\n "title":"Stadsarkivet"\n },\n {\n "branchId":"FBS-751027",\n "title":"Intern"\n },\n {\n "branchId":"FBS-751026",\n "title":"Fælles undervejs"\n },\n {\n "branchId":"FBS-751025",\n "title":"Fællessekretariatet"\n },\n {\n "branchId":"DK-775133",\n "title":"Bavnehøj"\n },\n {\n "branchId":"FBS-751024",\n "title":"Fjernlånte materialer"\n },\n {\n "branchId":"DK-775100",\n "title":"Hovedbiblioteket"\n },\n {\n "branchId":"DK-775170",\n "title":"Trige"\n },\n {\n "branchId":"DK-775150",\n "title":"Tilst"\n },\n {\n "branchId":"DK-775130",\n "title":"Viby"\n },\n {\n "branchId":"DK-775164",\n "title":"Egå"\n }\n]',
control: { type: "text" }
},
loginUrl: {
userinfoUrl: {
defaultValue: "https://login.bib.dk/userinfo",
control: { type: "text" }
},
spaceo marked this conversation as resolved.
Show resolved Hide resolved
userToken: {
defaultValue: "",
control: { type: "text" }
},
spaceo marked this conversation as resolved.
Show resolved Hide resolved
textNotificationsEnabledConfig: {
defaultValue: "1",
control: { type: "text" }
Expand Down
15 changes: 11 additions & 4 deletions src/apps/create-patron-user-info/CreatePatron.entry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { withConfig } from "../../core/utils/config";
import { withText } from "../../core/utils/text";
import { withUrls } from "../../core/utils/url";
import CreatePatron from "./CreatePatron";
import { getToken, hasToken } from "../../core/token";

interface CreatePatronConfigProps {
pincodeLengthMinConfig: string;
Expand Down Expand Up @@ -46,11 +47,17 @@ interface CreatePatronTextProps {
export interface CreatePatronProps
extends CreatePatronConfigProps,
CreatePatronUrlProps,
CreatePatronTextProps {
userToken: string;
}
CreatePatronTextProps {}

const CreatePatronEntry: FC<CreatePatronProps> = () => {
const userToken = hasToken("user") ? getToken("user") : null;

// The application using this app should handle the case where the user is not logged in.
// Eg by returning 403 Forbidden or redirecting to the login page.
if (!userToken) {
return null;
}

const CreatePatronEntry: FC<CreatePatronProps> = ({ userToken }) => {
return <CreatePatron userToken={userToken} />;
};

Expand Down
30 changes: 18 additions & 12 deletions src/apps/create-patron-user-info/CreatePatron.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, FC } from "react";
import React, { useState, FC, useEffect } from "react";
import UserInfo from "./UserInfo";
import { useUrls } from "../../core/utils/url";

Expand All @@ -8,18 +8,24 @@ interface CreatePatronProps {

const CreatePatron: FC<CreatePatronProps> = ({ userToken }) => {
const [cpr, setCpr] = useState<string | null>(null);
const { loginUrl } = useUrls();
const { userinfoUrl } = useUrls();

fetch(String(loginUrl), {
method: "get",
headers: { Authorization: `Bearer ${userToken}` }
})
.then((response) => response.json())
.then((data) => {
if (data?.attributes?.cpr) {
setCpr(data.attributes.cpr);
}
});
if (!userinfoUrl) {
throw new Error("userinfoUrl is not defined");
}

useEffect(() => {
fetch(String(userinfoUrl), {
method: "get",
headers: { Authorization: `Bearer ${userToken}` }
})
.then((response) => response.json())
spaceo marked this conversation as resolved.
Show resolved Hide resolved
.then((data) => {
if (data?.attributes?.cpr) {
setCpr(data.attributes.cpr);
}
});
}, [userToken, userinfoUrl]);

if (cpr === null) return null;

Expand Down
6 changes: 3 additions & 3 deletions src/apps/create-patron-user-info/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,17 @@ const UserInfo: FC<UserInfoProps> = ({ cpr }) => {
changePatron={changePatron}
patron={patron}
/>
<PincodeSection required changePincode={setPin} />
{t("createPatronChangePickupHeaderText") && (
<h2 className="text-body-small-regular mt-32 mb-16">
<h2 className="text-subtitle mt-32 mb-16">
spaceo marked this conversation as resolved.
Show resolved Hide resolved
{t("createPatronChangePickupHeaderText")}
</h2>
)}
{t("createPatronChangePickupBodyText") && (
<p className="text-subtitle my-32">
<p className="text-body-small-regular my-32">
{t("createPatronChangePickupBodyText")}
</p>
)}
<PincodeSection required changePincode={setPin} />
<div className="mt-32">
<BranchesDropdown
classNames="dropdow dropdown__desktop"
Expand Down
52 changes: 52 additions & 0 deletions src/components/contact-info-section/ContactInfoEmail.tsx
Original file line number Diff line number Diff line change
@@ -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<ContactInfoEmailProps> = ({
className = "",
patron,
changePatron,
showCheckboxes,
isRequired = false
}) => {
const t = useText();
return (
<>
<TextInput
className={className}
id="email-address-input"
type="email"
required={isRequired}
onChange={(newEmail) => changePatron(newEmail, "emailAddress")}
value={patron?.emailAddress}
label={t("patronContactEmailLabelText")}
/>
{showCheckboxes && (
<CheckBox
className="mt-8 mb-16"
onChecked={(newReceiveEmail: boolean) =>
changePatron(newReceiveEmail, "receiveEmail")
}
id="email-messages"
selected={patron?.receiveEmail}
disabled={false}
label={t("patronContactEmailCheckboxText")}
/>
)}
</>
);
};

export default ContactInfoEmail;
46 changes: 46 additions & 0 deletions src/components/contact-info-section/ContactInfoInputs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
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<ContactInfoInputsProps> = ({
spaceo marked this conversation as resolved.
Show resolved Hide resolved
isInline,
children,
dataCy = "contact-info-input",
className = undefined
}) => {
if (!isInline) {
return (
<div className={className} data-cy={dataCy}>
{children}
</div>
);
}

const renderableChildren = React.Children.toArray(children);
return (
<div
className={clsx(className, {
"contact-info-flex": isInline
})}
data-cy={dataCy}
>
{renderableChildren.map((child, i) => {
const childClassName = clsx("patron__input--desktop", {
"mr-16": i < renderableChildren.length - 1
});
return <div className={childClassName}>{child}</div>;
})}
</div>
);
};

export default ContactInfoInputs;
54 changes: 54 additions & 0 deletions src/components/contact-info-section/ContactInfoPhone.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
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;
isRequired?: boolean;
}

const ContactInfoPhone: FC<ContactInfoPhoneProps> = ({
patron,
changePatron,
showCheckboxes,
className = "",
isRequired = false
}) => {
const t = useText();
return (
<>
<TextInput
className={className}
id="phone-input"
required={isRequired}
type="number"
onChange={(newPhoneNumber) =>
changePatron(newPhoneNumber, "phoneNumber")
}
value={patron?.phoneNumber}
label={t("patronContactPhoneLabelText")}
/>
{showCheckboxes && (
<CheckBox
className="mt-8 mb-16"
onChecked={(newReceiveSms: boolean) =>
changePatron(newReceiveSms, "receiveSms")
}
id="phone-messages"
selected={patron?.receiveSms}
disabled={false}
label={t("patronContactPhoneCheckboxText")}
/>
)}
</>
);
};

export default ContactInfoPhone;
95 changes: 22 additions & 73 deletions src/components/contact-info-section/ContactInfoSection.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -26,64 +24,9 @@ const ContactInfoSection: FC<ContactInfoSectionProps> = ({
const t = useText();
const inputsClass = clsx("dpl-input", { input__desktop: inLine });
const config = useConfig();
const textNotificationsEnabled =
const textNotificationsEnabledConfig =
config("textNotificationsEnabledConfig") === "1";

const phoneNode = (
<>
<TextInput
className={inputsClass}
id="phone-input"
required
type="number"
onChange={(newPhoneNumber) =>
changePatron(newPhoneNumber, "phoneNumber")
}
value={patron?.phoneNumber}
label={t("patronContactPhoneLabelText")}
/>
{showCheckboxes && textNotificationsEnabled && (
<CheckBox
className="mt-8 mb-16"
onChecked={(newReceiveSms: boolean) =>
changePatron(newReceiveSms, "receiveSms")
}
id="phone-messages"
selected={patron?.receiveSms}
disabled={false}
label={t("patronContactPhoneCheckboxText")}
/>
)}
</>
);
const emailNode = (
<>
<TextInput
className={clsx(inputsClass, {
"mt-32": !textNotificationsEnabled && !inLine
})}
id="email-address-input"
type="email"
required
onChange={(newEmail) => changePatron(newEmail, "emailAddress")}
value={patron?.emailAddress}
label={t("patronContactEmailLabelText")}
/>
{showCheckboxes && (
<CheckBox
className="mt-8 mb-16"
onChecked={(newReceiveEmail: boolean) =>
changePatron(newReceiveEmail, "receiveEmail")
}
id="email-messages"
selected={patron?.receiveEmail}
disabled={false}
label={t("patronContactEmailCheckboxText")}
/>
)}
</>
);

return (
<section data-cy="patron-page-contact-info">
<h2 className="text-header-h4 mt-32 mb-16">
Expand All @@ -94,17 +37,23 @@ const ContactInfoSection: FC<ContactInfoSectionProps> = ({
{t("patronContactInfoBodyText")}
</p>
)}
{inLine && (
<div className={`${inLine ? "contact-info-flex" : ""}`}>
<div className="patron__input--desktop mr-16">{phoneNode}</div>
<div className="patron__input--desktop">{emailNode}</div>
</div>
)}
{!inLine && (
<>
{phoneNode} {emailNode}
</>
)}
<ContactInfoInputs isInline={inLine}>
<ContactInfoPhone
spaceo marked this conversation as resolved.
Show resolved Hide resolved
className={inputsClass}
changePatron={changePatron}
patron={patron}
showCheckboxes={showCheckboxes && textNotificationsEnabledConfig}
/>
<ContactInfoEmail
className={clsx(inputsClass, {
"mt-32": !textNotificationsEnabledConfig && !inLine
})}
changePatron={changePatron}
patron={patron}
showCheckboxes={showCheckboxes}
isRequired
/>
</ContactInfoInputs>
</section>
);
};
Expand Down
Loading