diff --git a/package.json b/package.json index 4946556688..7e91ddd465 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "@gsap/react": "2.1.1", "@headlessui/react": "2.1.0", "@hookform/error-message": "2.0.1", - "@hookform/resolvers": "3.3.4", + "@hookform/resolvers": "3.9.0", "@paypal/react-paypal-js": "8.3.0", "@radix-ui/react-slider": "1.1.2", "@radix-ui/react-tooltip": "1.1.2", @@ -62,7 +62,7 @@ "react-dropzone": "14.2.3", "react-fast-marquee": "1.6.4", "react-helmet": "6.1.0", - "react-hook-form": "7.51.5", + "react-hook-form": "7.53.0", "react-player": "2.16.0", "react-redux": "9.1.2", "react-router-dom": "6.23.0", diff --git a/src/pages/Registration/Steps/ContactDetails/Form/ReferralMethodSelector.tsx b/src/pages/Registration/Steps/ContactDetails/Form/ReferralMethodSelector.tsx new file mode 100644 index 0000000000..cd49dd1491 --- /dev/null +++ b/src/pages/Registration/Steps/ContactDetails/Form/ReferralMethodSelector.tsx @@ -0,0 +1,73 @@ +import { + Field, + Label, + Listbox, + ListboxButton, + ListboxOption, + ListboxOptions, +} from "@headlessui/react"; +import Icon from "components/Icon"; +import { forwardRef } from "react"; +import { referralOptions } from "../constants"; +import type { ReferralOption } from "./schema"; + +interface Props { + disabled?: boolean; + value: ReferralOption; + onChange: (value: ReferralOption) => void; + error?: string; + classes?: string; +} + +function Star() { + return *; +} + +export const ReferralMethodSelector = forwardRef( + function List({ classes = "", ...props }, ref) { + return ( + + + + + {props.value.label} + + + + {referralOptions.map((o) => ( + + {o.label} + + ))} + +

+ {props.error} +

+
+
+ ); + } +); diff --git a/src/pages/Registration/Steps/ContactDetails/Form/RoleSelector.tsx b/src/pages/Registration/Steps/ContactDetails/Form/RoleSelector.tsx new file mode 100644 index 0000000000..83a79620e4 --- /dev/null +++ b/src/pages/Registration/Steps/ContactDetails/Form/RoleSelector.tsx @@ -0,0 +1,74 @@ +import { + Field, + Label, + Listbox, + ListboxButton, + ListboxOption, + ListboxOptions, +} from "@headlessui/react"; +import Icon from "components/Icon"; +import { forwardRef } from "react"; +import { roleOptions } from "../constants"; +import type { RoleOption } from "./schema"; + +interface Props { + disabled?: boolean; + value: RoleOption; + onChange: (value: RoleOption) => void; + error?: string; + classes?: string; +} + +function Star() { + return *; +} + +export const RoleSelector = forwardRef(function List( + { classes = "", ...props }, + ref +) { + return ( + + + + + {props.value.label} + + + + {roleOptions.map((o) => ( + + {o.label} + + ))} + +

+ {props.error} +

+
+
+ ); +}); diff --git a/src/pages/Registration/Steps/ContactDetails/Form/index.tsx b/src/pages/Registration/Steps/ContactDetails/Form/index.tsx index 1d1e6dda89..08588b9a00 100644 --- a/src/pages/Registration/Steps/ContactDetails/Form/index.tsx +++ b/src/pages/Registration/Steps/ContactDetails/Form/index.tsx @@ -1,18 +1,72 @@ -import type { ReferralMethod, Role } from "@better-giving/registration/models"; +import { Field, Input, Label } from "@headlessui/react"; import LoadText from "components/LoadText"; -import { Selector } from "components/Selector"; -import { Field, Label } from "components/form"; import { APP_NAME } from "constants/env"; -import { referralOptions, roleOptions } from "../constants"; -import type { FormValues as FV } from "../types"; -import useSubmit from "./useSubmit"; +import { useAuthenticatedUser } from "contexts/Auth"; +import { useErrorContext } from "contexts/ErrorContext"; +import type { SubmitHandler } from "react-hook-form"; +import { useNavigate } from "react-router-dom"; +import { useUpdateRegMutation } from "services/aws/registration"; +import { steps } from "../../../routes"; +import { useRegState } from "../../StepGuard"; +import { ReferralMethodSelector } from "./ReferralMethodSelector"; +import { RoleSelector } from "./RoleSelector"; +import type { FV } from "./schema"; +import { useRhf } from "./useRhf"; + +function Star() { + return *; +} export default function Form({ classes = "" }: { classes?: string }) { - const { submit, isSubmitting } = useSubmit(); + const state = useRegState<1>(); + const user = useAuthenticatedUser(); + const { + register, + errors, + orgRole, + onOrgRoleChange, + orgRoleRef, + referralMethod, + onReferralMethodChange, + referralMethodRef, + isDirty, + handleSubmit, + isSubmitting, + } = useRhf(state.data, user); + const navigate = useNavigate(); + + const [updateReg] = useUpdateRegMutation(); + const { handleError } = useErrorContext(); + + const submit: SubmitHandler = async (fv) => { + try { + if (!isDirty && state.data.contact) { + return navigate(`../${steps.orgDetails}`, { state: state.data.init }); // go to latest step + } + + const { org_role, referral_method, registrant_id, ...rest } = fv; + + await updateReg({ + type: "contact", + ...rest, + org_role: org_role.value, + referral_method: referral_method.value, + id: state.data.init.id, + }).unwrap(); + + navigate(`../${steps.orgDetails}`, { state: state.data.init }); + } catch (err) { + handleError(err, { context: "updating registration" }); + } + }; + + console.log({ errors }); + return (

Let's start with your contact details @@ -22,98 +76,150 @@ export default function Form({ classes = "" }: { classes?: string }) { let us know more about you and your organization

Personal information

- - name="first_name" - label="First name" - placeholder="e.g. John" - required - classes={{ container: "mb-4" }} - /> - - name="last_name" - label="Last name" - placeholder="e.g. Doe" - required - classes={{ container: "mb-4" }} - /> - - name="contact_number" - label="Phone number" - placeholder="000000000" - required={false} - classes={{ container: "mb-4" }} - /> - - name="registrant_id" - label="E-mail address" - required - disabled - /> + + + + +

+ {errors.first_name?.message} +

+
+ + + +

+ {errors.last_name?.message} +

+
+ + + +

+ {errors.contact_number?.message} +

+
+ + + + + +

Organization information

- - name="org_name" - label="Name of your organization" - placeholder="Organization name" - classes={{ container: "mb-4" }} - required + + + + +

+ {errors.org_name?.message} +

+
+ + - - - name="org_role" - options={roleOptions} - classes={{ options: "text-sm" }} - > - {({ value }) => - value === "other" && ( - - name="other_role" - label="Specify your role" - required - classes={{ container: "mt-4" }} - /> - ) - } - + {orgRole.value === "other" && ( + + + +

+ {errors.other_role?.message} +

+
+ )}

Other information

- - - name="referral_method" - options={referralOptions} - classes={{ options: "text-sm" }} - > - {({ value }) => ( - <> - {value === "other" && ( - - name="other_referral_method" - label="Please provide additional information" - required - classes={{ container: "mt-4" }} - /> - )} - {value === "referral" && ( - - name="referral_code" - label="Referral Code" - required - classes={{ container: "mt-4" }} - /> - )} - - )} - - - name="goals" - label="Goals" - placeholder={`What is your goal working with ${APP_NAME}?`} - classes={{ container: "mt-4" }} - required + + {referralMethod.value === "other" && ( + + + +

+ {errors.other_referral_method?.message} +

+
+ )} + + {referralMethod.value === "referral" && ( + + + +

+ {errors.referral_code?.message} +

+
+ )} + + + + +

+ {errors.goals?.message} +

+
+