From 48cb352c00df6847161213e6e4915b1eae38559e Mon Sep 17 00:00:00 2001 From: Emily Jablonski <65367387+emilyjablonski@users.noreply.github.com> Date: Mon, 11 Dec 2023 12:09:52 -0700 Subject: [PATCH] fix: verify application errors (#3736) --- .../lib/applications/AppSubmissionContext.ts | 2 +- .../lib/applications/ApplicationConductor.ts | 10 +++--- sites/public/src/pages/_app.tsx | 2 +- .../pages/applications/contact/address.tsx | 33 ++++++++++--------- .../contact/alternate-contact-contact.tsx | 7 ++-- .../contact/alternate-contact-name.tsx | 7 ++-- .../contact/alternate-contact-type.tsx | 7 ++-- .../src/pages/applications/contact/name.tsx | 7 ++-- .../pages/applications/financial/income.tsx | 7 ++-- .../pages/applications/financial/vouchers.tsx | 7 ++-- .../src/pages/applications/household/ada.tsx | 6 ++-- .../applications/household/add-members.tsx | 4 +-- .../pages/applications/household/changes.tsx | 6 ++-- .../applications/household/live-alone.tsx | 7 ++-- .../pages/applications/household/member.tsx | 7 ++-- .../household/preferred-units.tsx | 6 ++-- .../pages/applications/household/student.tsx | 7 ++-- .../src/pages/applications/start/autofill.tsx | 7 ++-- 18 files changed, 87 insertions(+), 52 deletions(-) diff --git a/sites/public/src/lib/applications/AppSubmissionContext.ts b/sites/public/src/lib/applications/AppSubmissionContext.ts index a4e58ba7ab..0398af9fa4 100644 --- a/sites/public/src/lib/applications/AppSubmissionContext.ts +++ b/sites/public/src/lib/applications/AppSubmissionContext.ts @@ -109,7 +109,7 @@ export const retrieveApplicationConfig = (listing: Listing) => { export const AppSubmissionContext = createContext({ conductor: {} as ApplicationConductor, - application: { ...blankApplication }, + application: JSON.parse(JSON.stringify(blankApplication)), listing: null as Listing, /* eslint-disable */ syncApplication: (data) => {}, diff --git a/sites/public/src/lib/applications/ApplicationConductor.ts b/sites/public/src/lib/applications/ApplicationConductor.ts index 5860e4d727..df1d1d412c 100644 --- a/sites/public/src/lib/applications/ApplicationConductor.ts +++ b/sites/public/src/lib/applications/ApplicationConductor.ts @@ -15,7 +15,7 @@ import PreferencesAllStep from "./PreferencesAllStep" import ProgramsStep from "./ProgramsStep" export const loadApplicationFromAutosave = () => { - if (typeof window != "undefined") { + if (typeof window !== "undefined") { const autosavedApplication = window.sessionStorage.getItem("bloom-app-autosave") if (autosavedApplication) { const application = JSON.parse(autosavedApplication) @@ -28,7 +28,7 @@ export const loadApplicationFromAutosave = () => { } export const loadSavedListing = () => { - if (typeof window != "undefined") { + if (typeof window !== "undefined") { const savedListing = window.sessionStorage.getItem("bloom-app-listing") if (savedListing) { return JSON.parse(savedListing) @@ -193,7 +193,7 @@ export default class ApplicationConductor { sync() { // NOTE: had to remove timeout because of Next doing full-page reloads in // some cases. Need to revisit after upgrading to v10 - if (typeof window != "undefined") { + if (typeof window !== "undefined") { window.sessionStorage.setItem("bloom-app-autosave", JSON.stringify(this.application)) if (this.listing) { window.sessionStorage.setItem("bloom-app-listing", JSON.stringify(this.listing)) @@ -202,10 +202,10 @@ export default class ApplicationConductor { } reset() { - this.application = { ...blankApplication } + this.application = JSON.parse(JSON.stringify(blankApplication)) this.listing = {} as Listing this.currentStepIndex = 0 - if (typeof window != "undefined") { + if (typeof window !== "undefined") { window.sessionStorage.removeItem("bloom-app-autosave") window.sessionStorage.removeItem("bloom-app-listing") } diff --git a/sites/public/src/pages/_app.tsx b/sites/public/src/pages/_app.tsx index 38c62f9b6c..c293c8ce9e 100644 --- a/sites/public/src/pages/_app.tsx +++ b/sites/public/src/pages/_app.tsx @@ -30,7 +30,7 @@ function BloomApp({ Component, router, pageProps }: AppProps) { const { locale } = router // const initialized = useState(true) const [application, setApplication] = useState(() => { - return loadApplicationFromAutosave() || { ...blankApplication } + return loadApplicationFromAutosave() || JSON.parse(JSON.stringify(blankApplication)) }) const [savedListing, setSavedListing] = useState(() => { return loadSavedListing() diff --git a/sites/public/src/pages/applications/contact/address.tsx b/sites/public/src/pages/applications/contact/address.tsx index 8911f7978d..53982fa46d 100644 --- a/sites/public/src/pages/applications/contact/address.tsx +++ b/sites/public/src/pages/applications/contact/address.tsx @@ -43,21 +43,24 @@ const ApplicationAddress = () => { const currentPageSection = 1 // eslint-disable-next-line @typescript-eslint/unbound-method - const { control, register, handleSubmit, setValue, watch, errors } = useForm>( - { - defaultValues: { - "applicant.phoneNumber": application.applicant.phoneNumber, - "applicant.noPhone": application.applicant.noPhone, - additionalPhone: application.additionalPhone, - "applicant.phoneNumberType": application.applicant.phoneNumberType, - sendMailToMailingAddress: application.sendMailToMailingAddress, - "applicant.workInRegion": application.applicant.workInRegion, - "applicant.address.state": application.applicant.address.state, - }, - shouldFocusError: false, - } - ) - const onSubmit = (data) => { + const { control, register, handleSubmit, setValue, watch, errors, trigger } = useForm< + Record + >({ + defaultValues: { + "applicant.phoneNumber": application.applicant.phoneNumber, + "applicant.noPhone": application.applicant.noPhone, + additionalPhone: application.additionalPhone, + "applicant.phoneNumberType": application.applicant.phoneNumberType, + sendMailToMailingAddress: application.sendMailToMailingAddress, + "applicant.workInRegion": application.applicant.workInRegion, + "applicant.address.state": application.applicant.address.state, + }, + shouldFocusError: false, + }) + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + if (!verifyAddress) { setFoundAddress({}) setVerifyAddress(true) diff --git a/sites/public/src/pages/applications/contact/alternate-contact-contact.tsx b/sites/public/src/pages/applications/contact/alternate-contact-contact.tsx index d68724550e..d7881b6df9 100644 --- a/sites/public/src/pages/applications/contact/alternate-contact-contact.tsx +++ b/sites/public/src/pages/applications/contact/alternate-contact-contact.tsx @@ -22,10 +22,13 @@ export default () => { const currentPageSection = 1 // eslint-disable-next-line @typescript-eslint/unbound-method - const { control, register, handleSubmit, errors } = useForm>({ + const { control, register, handleSubmit, errors, trigger } = useForm>({ shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + application.alternateContact.phoneNumber = data.phoneNumber application.alternateContact.emailAddress = data.emailAddress || null application.alternateContact.mailingAddress.street = data.mailingAddress.street diff --git a/sites/public/src/pages/applications/contact/alternate-contact-name.tsx b/sites/public/src/pages/applications/contact/alternate-contact-name.tsx index 5695f6cb0c..7d9da43195 100644 --- a/sites/public/src/pages/applications/contact/alternate-contact-name.tsx +++ b/sites/public/src/pages/applications/contact/alternate-contact-name.tsx @@ -16,10 +16,13 @@ export default () => { const currentPageSection = 1 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors } = useForm>({ + const { register, handleSubmit, errors, trigger } = useForm>({ shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + application.alternateContact.firstName = data.firstName application.alternateContact.lastName = data.lastName application.alternateContact.agency = data.agency diff --git a/sites/public/src/pages/applications/contact/alternate-contact-type.tsx b/sites/public/src/pages/applications/contact/alternate-contact-type.tsx index c4e252859c..74b01c70bd 100644 --- a/sites/public/src/pages/applications/contact/alternate-contact-type.tsx +++ b/sites/public/src/pages/applications/contact/alternate-contact-type.tsx @@ -22,10 +22,13 @@ const ApplicationAlternateContactType = () => { const currentPageSection = 1 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors, watch } = useForm>({ + const { register, handleSubmit, errors, watch, trigger } = useForm>({ shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + application.alternateContact.type = data.type application.alternateContact.otherType = data.otherType diff --git a/sites/public/src/pages/applications/contact/name.tsx b/sites/public/src/pages/applications/contact/name.tsx index fd09d7ae69..f05c3b181a 100644 --- a/sites/public/src/pages/applications/contact/name.tsx +++ b/sites/public/src/pages/applications/contact/name.tsx @@ -26,14 +26,17 @@ const ApplicationName = () => { const currentPageSection = 1 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, watch, errors } = useForm>({ + const { register, handleSubmit, watch, errors, trigger } = useForm>({ shouldFocusError: false, defaultValues: { "applicant.emailAddress": application.applicant.emailAddress, "applicant.noEmail": application.applicant.noEmail, }, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + if (!autofilled) { conductor.currentStep.save({ applicant: { ...application.applicant, ...data.applicant } }) } diff --git a/sites/public/src/pages/applications/financial/income.tsx b/sites/public/src/pages/applications/financial/income.tsx index 17dcffdac3..097b8de2f5 100644 --- a/sites/public/src/pages/applications/financial/income.tsx +++ b/sites/public/src/pages/applications/financial/income.tsx @@ -55,7 +55,7 @@ const ApplicationIncome = () => { : 3 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors, getValues, setValue } = useForm({ + const { register, handleSubmit, errors, getValues, setValue, trigger } = useForm({ defaultValues: { income: application.income, incomePeriod: application.incomePeriod, @@ -63,7 +63,10 @@ const ApplicationIncome = () => { shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + const { income, incomePeriod } = data const incomeValue = income.replaceAll(",", "") // Skip validation of total income if the applicant has income vouchers. diff --git a/sites/public/src/pages/applications/financial/vouchers.tsx b/sites/public/src/pages/applications/financial/vouchers.tsx index a5a917e239..44ddc2163f 100644 --- a/sites/public/src/pages/applications/financial/vouchers.tsx +++ b/sites/public/src/pages/applications/financial/vouchers.tsx @@ -25,12 +25,15 @@ const ApplicationVouchers = () => { : 3 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors, getValues } = useForm({ + const { register, handleSubmit, errors, getValues, trigger } = useForm({ defaultValues: { incomeVouchers: application.incomeVouchers?.toString() }, shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + const { incomeVouchers } = data const toSave = { incomeVouchers: JSON.parse(incomeVouchers) } diff --git a/sites/public/src/pages/applications/household/ada.tsx b/sites/public/src/pages/applications/household/ada.tsx index b28eeec572..c32e0179d4 100644 --- a/sites/public/src/pages/applications/household/ada.tsx +++ b/sites/public/src/pages/applications/household/ada.tsx @@ -22,7 +22,7 @@ const ApplicationAda = () => { const currentPageSection = 2 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, setValue, errors, getValues, clearErrors } = useForm< + const { register, handleSubmit, setValue, errors, getValues, clearErrors, trigger } = useForm< Record >({ defaultValues: { @@ -34,7 +34,9 @@ const ApplicationAda = () => { shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return conductor.currentStep.save({ accessibility: { mobility: !!data["app-accessibility-mobility"], diff --git a/sites/public/src/pages/applications/household/add-members.tsx b/sites/public/src/pages/applications/household/add-members.tsx index 72156c1559..115ec3ac9b 100644 --- a/sites/public/src/pages/applications/household/add-members.tsx +++ b/sites/public/src/pages/applications/household/add-members.tsx @@ -17,13 +17,13 @@ const ApplicationAddMembers = () => { const { conductor, application, listing } = useFormConductor("addMembers") const router = useRouter() const currentPageSection = 2 - const householdSize = application.householdMembers.length + 1 + const householdSize = parseInt(application.householdMembers.length) + 1 // eslint-disable-next-line @typescript-eslint/unbound-method const { errors, handleSubmit, register, clearErrors } = useForm() const onSubmit = () => { conductor.currentStep.save({ - householdSize: application.householdMembers.length + 1, + householdSize: parseInt(application.householdMembers.length) + 1, }) conductor.routeToNextOrReturnUrl() } diff --git a/sites/public/src/pages/applications/household/changes.tsx b/sites/public/src/pages/applications/household/changes.tsx index 166cfab6aa..3b50c9eb33 100644 --- a/sites/public/src/pages/applications/household/changes.tsx +++ b/sites/public/src/pages/applications/household/changes.tsx @@ -16,11 +16,13 @@ const ApplicationHouseholdChanges = () => { const currentPageSection = 2 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors, getValues } = useForm>({ + const { register, handleSubmit, errors, getValues, trigger } = useForm>({ defaultValues: { householdExpectingChanges: application.householdExpectingChanges?.toString() }, shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return const { householdExpectingChanges } = data conductor.currentStep.save({ householdExpectingChanges: householdExpectingChanges === "true", diff --git a/sites/public/src/pages/applications/household/live-alone.tsx b/sites/public/src/pages/applications/household/live-alone.tsx index c07ca27869..dcc0d9a5b0 100644 --- a/sites/public/src/pages/applications/household/live-alone.tsx +++ b/sites/public/src/pages/applications/household/live-alone.tsx @@ -18,8 +18,11 @@ const ApplicationLiveAlone = () => { const currentPageSection = 2 // eslint-disable-next-line @typescript-eslint/unbound-method - const { handleSubmit, register, errors, clearErrors } = useForm() - const onSubmit = () => { + const { handleSubmit, register, errors, clearErrors, trigger } = useForm() + + const onSubmit = async () => { + const validation = await trigger() + if (!validation) return conductor.sync() conductor.routeToNextOrReturnUrl() } diff --git a/sites/public/src/pages/applications/household/member.tsx b/sites/public/src/pages/applications/household/member.tsx index 33927209cb..1dff92f52e 100644 --- a/sites/public/src/pages/applications/household/member.tsx +++ b/sites/public/src/pages/applications/household/member.tsx @@ -47,10 +47,13 @@ const ApplicationMember = () => { } // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors, watch } = useForm({ + const { register, handleSubmit, errors, watch, trigger } = useForm({ shouldFocusError: false, }) - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return + application.householdMembers[memberId] = { ...member, ...data } as HouseholdMember conductor.sync() void router.push("/applications/household/add-members") diff --git a/sites/public/src/pages/applications/household/preferred-units.tsx b/sites/public/src/pages/applications/household/preferred-units.tsx index ccd2abab89..5c846b90ec 100644 --- a/sites/public/src/pages/applications/household/preferred-units.tsx +++ b/sites/public/src/pages/applications/household/preferred-units.tsx @@ -23,9 +23,11 @@ const ApplicationPreferredUnits = () => { const currentPageSection = 2 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors } = useForm() + const { register, handleSubmit, errors, trigger } = useForm() - const onSubmit = (data) => { + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return const { preferredUnit } = data // save units always as an array (when is only one option, react-hook-form stores an option as string) diff --git a/sites/public/src/pages/applications/household/student.tsx b/sites/public/src/pages/applications/household/student.tsx index a005686b15..9cc1c647d3 100644 --- a/sites/public/src/pages/applications/household/student.tsx +++ b/sites/public/src/pages/applications/household/student.tsx @@ -16,11 +16,14 @@ const ApplicationHouseholdStudent = () => { const currentPageSection = 2 // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors, getValues } = useForm>({ + const { register, handleSubmit, errors, getValues, trigger } = useForm>({ defaultValues: { householdStudent: application.householdStudent?.toString() }, shouldFocusError: false, }) - const onSubmit = (data) => { + + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return const { householdStudent } = data conductor.currentStep.save({ householdStudent: householdStudent === "true", diff --git a/sites/public/src/pages/applications/start/autofill.tsx b/sites/public/src/pages/applications/start/autofill.tsx index 169b485405..ceebaa4d7d 100644 --- a/sites/public/src/pages/applications/start/autofill.tsx +++ b/sites/public/src/pages/applications/start/autofill.tsx @@ -39,17 +39,16 @@ export default () => { setSubmitted(true) if (previousApplication && useDetails) { const withUpdatedLang = { - ...previousApplication, + ...JSON.parse(JSON.stringify(previousApplication)), language: router.locale, } conductor.application = withUpdatedLang } else { - const newApplication = { - ...blankApplication, + conductor.application = { + ...JSON.parse(JSON.stringify(blankApplication)), language: router.locale, } - conductor.application = newApplication } context.syncApplication(conductor.application)