diff --git a/src/api/requests/submitUpdateFinancialProfile.ts b/src/api/requests/submitUpdateFinancialProfile.ts index 85f129838..18b6fc8ef 100644 --- a/src/api/requests/submitUpdateFinancialProfile.ts +++ b/src/api/requests/submitUpdateFinancialProfile.ts @@ -2,37 +2,57 @@ import { request } from 'api/axiosService'; import type { CaseType } from 'api/common'; import { caseTypes } from 'api/common'; import type { SblAuthProperties } from 'api/useSblAuth'; -import type { UFPSchema } from 'pages/Filing/UpdateFinancialProfile/types'; - -// Used to remove 'checkboxes' property -function omit(key: string, object: UFPSchema): Record { - // @ts-expect-error intentional key omission - const { [key]: omitted, ...rest } = object; - return rest; -} - -// Pulls 'checkboxes' property out to keep the object flat, and then reinserts every checkbox property at first depth -const formatFinancialProfileObject = ( - object: UFPSchema, -): Record => { - const solution = omit('checkboxes', object); - for (const key of Object.keys(object.checkboxes)) { - solution[key] = String(object.checkboxes[key]); +import { checkboxOptions } from 'pages/Filing/UpdateFinancialProfile/types'; +import type { InstitutionDetailsApiType } from 'types/formTypes'; +import { One } from 'utils/constants'; + +export const collectChangedData = ( + formData: InstitutionDetailsApiType, + changedFields: Record, +): InstitutionDetailsApiType => { + const result: InstitutionDetailsApiType = {}; + + // Include only fields which have been identified as "changed" + for (const key of Object.keys(changedFields)) { + result[key] = formData[key] as string; + } + + // Institution types are not registered as "changed" by react-hook-form (because they're in an array?), so we have to manually process them. + if ( + formData.sbl_institution_types && + typeof formData.sbl_institution_types === 'object' + ) { + const sblInstitutionTypes = []; + for (const key of formData.sbl_institution_types.keys()) { + if (formData.sbl_institution_types[key]) { + const indexToTypeArray = Number(key) - One; + sblInstitutionTypes.push(checkboxOptions[indexToTypeArray].label); + } + } + + result.sbl_institution_types = sblInstitutionTypes.join(', '); + + // TODO: Okay to merge 'Other' into this listing? + if (sblInstitutionTypes.includes('Other')) + result.sbl_institution_types += ` (${formData.sbl_institution_types_other})`; } - return solution; + + // TODO: additional_details is not registering as "changed" (due to ref forwarding issue?), need to manually process them. + if ((formData.additional_details ?? '').length > 0) + result.additional_details = formData.additional_details; + + return result; }; const submitUpdateFinancialProfile = async ( auth: SblAuthProperties, - financialProfileObject: UFPSchema, + financialProfileObject: Record, ): Promise => { return request({ url: `/send`, method: 'post', // ex: 'userName=test%40gmail.com&password=Password%21&grant_type=password' - body: new URLSearchParams( - formatFinancialProfileObject(financialProfileObject), - ), + body: new URLSearchParams(financialProfileObject), headers: { Authorization: `Bearer ${auth.user?.access_token}`, 'Content-Type': 'application/x-www-form-urlencoded', diff --git a/src/pages/Filing/UpdateFinancialProfile/UfpForm.tsx b/src/pages/Filing/UpdateFinancialProfile/UfpForm.tsx index c440ac429..aa6cbe897 100644 --- a/src/pages/Filing/UpdateFinancialProfile/UfpForm.tsx +++ b/src/pages/Filing/UpdateFinancialProfile/UfpForm.tsx @@ -1,4 +1,8 @@ import { zodResolver } from '@hookform/resolvers/zod'; +import submitUpdateFinancialProfile, { + collectChangedData, +} from 'api/requests/submitUpdateFinancialProfile'; +import useSblAuth from 'api/useSblAuth'; import CrumbTrail from 'components/CrumbTrail'; import FormButtonGroup from 'components/FormButtonGroup'; import FormErrorHeader from 'components/FormErrorHeader'; @@ -6,83 +10,76 @@ import FormHeaderWrapper from 'components/FormHeaderWrapper'; import FormWrapper from 'components/FormWrapper'; import { Button, Link, TextIntroduction } from 'design-system-react'; import type { JSXElement } from 'design-system-react/dist/types/jsxElement'; -import type { UFPSchema } from 'pages/Filing/UpdateFinancialProfile/types'; -import { ufpSchema } from 'pages/Filing/UpdateFinancialProfile/types'; import { scenarios } from 'pages/Summary/Summary.data'; -import { useState } from 'react'; +import { useMemo } from 'react'; import { useForm } from 'react-hook-form'; -import { Navigate, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom'; import type { InstitutionDetailsApiType } from 'types/formTypes'; +import { institutionDetailsApiTypeSchema } from 'types/formTypes'; import { Five } from 'utils/constants'; import getIsRoutingEnabled from 'utils/getIsRoutingEnabled'; import AdditionalDetails from './AdditionalDetails'; import FinancialInstitutionDetailsForm from './FinancialInstitutionDetailsForm'; import UpdateAffiliateInformation from './UpdateAffiliateInformation'; import UpdateIdentifyingInformation from './UpdateIdentifyingInformation'; -import buildUfpDefaults from './buildUfpDefaults'; +import buildProfileFormDefaults from './buildProfileFormDefaults'; export default function UFPForm({ data, }: { data: InstitutionDetailsApiType; }): JSXElement { - const [submitted, setSubmitted] = useState(false); const { lei } = useParams(); - - const defaultValues = buildUfpDefaults(data); + const auth = useSblAuth(); const isRoutingEnabled = getIsRoutingEnabled(); + const navigate = useNavigate(); + + const defaultValues = useMemo(() => buildProfileFormDefaults(data), [data]); const { - register, + // trigger, control, - setValue, - trigger, getValues, + register, reset, + setValue, formState: { errors: formErrors, dirtyFields }, - } = useForm({ - resolver: zodResolver(ufpSchema), + } = useForm({ + resolver: zodResolver(institutionDetailsApiTypeSchema), defaultValues, }); - // TODO: Render this based on the actual API call result - // TODO: No need to track "submitted" state once we implement validations - // https://github.com/cfpb/sbl-frontend/pull/276/files#r1509023108 - if (isRoutingEnabled && submitted) { - return ( - - ); - } - // Used for error scrolling const formErrorHeaderId = 'UFPFormErrorHeader'; // NOTE: This function is used for submitting the multipart/formData const onSubmitButtonAction = async (): Promise => { - const passesValidation = await trigger(); + // const passesValidation = await trigger(); // TODO: Will be used for debugging after clicking 'Submit' // eslint-disable-next-line no-console - console.log('passes validation?', passesValidation); + // console.log('passes validation?', passesValidation); // if (passesValidation) { - const preFormattedData = getValues(); - // TODO: Will be used for debugging after clicking 'Submit' - // eslint-disable-next-line no-console - console.log( - 'data to be submitted (before format):', - JSON.stringify(preFormattedData, null, Five), - ); - // TODO: Send data in human readable format - // POST formData - // const response = await submitUpdateFinancialProfile( - // auth, - // preFormattedData, - // ) + try { + const formData = getValues(); + const postableData = collectChangedData(formData, dirtyFields); + postableData.Note = + 'This data reflects the institution data that has been changed'; + // eslint-disable-next-line no-console + console.log( + 'data being submitted:', + JSON.stringify(postableData, null, Five), + ); + await submitUpdateFinancialProfile(auth, postableData); + if (isRoutingEnabled) + navigate('/summary', { + state: { scenario: scenarios.SuccessInstitutionProfileUpdate }, + }); + } catch (error) { + // eslint-disable-next-line no-console + console.log('Error submitting UFP', error); + } // } - setSubmitted(true); }; // Reset form data to the defaultValues @@ -90,18 +87,14 @@ export default function UFPForm({ // TODO: Will be used for debugging errors after clicking 'Submit' // eslint-disable-next-line no-console - console.log('formErrors:', formErrors); - - // TODO: Use dirtyFields to determine which data to send to SBL Help - // TODO: Nested fields (sbl_institution_types) do not register as dirty when content changes, will need to always check those values - console.log('dirtyFields:', dirtyFields); + // console.log('formErrors:', formErrors); return (
- + Platform home {lei ? ( @@ -144,6 +137,8 @@ export default function UFPForm({ aria-label='Submit User Profile' size='default' type='submit' + // TODO: Allow form submission without changed data? + // disabled={!(hasChanges || Object.keys(dirtyFields).length > 0)} />