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 f294dbce75..18c08be8e7 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") window.sessionStorage.removeItem("bloom-app-doorway") diff --git a/sites/public/src/pages/_app.tsx b/sites/public/src/pages/_app.tsx index 071d3c3bba..e53d39d637 100644 --- a/sites/public/src/pages/_app.tsx +++ b/sites/public/src/pages/_app.tsx @@ -26,7 +26,7 @@ function BloomApp({ Component, router, pageProps }: AppProps) { const { locale } = router const [initialized, setInitialized] = useState(false) 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 432a398a1f..846ae6bd2e 100644 --- a/sites/public/src/pages/applications/contact/address.tsx +++ b/sites/public/src/pages/applications/contact/address.tsx @@ -53,21 +53,25 @@ const ApplicationAddress = () => { /* Form Handler */ // 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 fa34e0264b..a937555ee1 100644 --- a/sites/public/src/pages/applications/contact/alternate-contact-contact.tsx +++ b/sites/public/src/pages/applications/contact/alternate-contact-contact.tsx @@ -37,10 +37,13 @@ export default () => { /* Form Handler */ // 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 6eb8978aa1..45ebde6b04 100644 --- a/sites/public/src/pages/applications/contact/alternate-contact-name.tsx +++ b/sites/public/src/pages/applications/contact/alternate-contact-name.tsx @@ -28,10 +28,13 @@ export default () => { /* Form Handler */ // 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 ac4bcfbe55..548b7d717a 100644 --- a/sites/public/src/pages/applications/contact/alternate-contact-type.tsx +++ b/sites/public/src/pages/applications/contact/alternate-contact-type.tsx @@ -35,10 +35,13 @@ const ApplicationAlternateContactType = () => { /* Form Handler */ // 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 992823d596..ff9185f72b 100644 --- a/sites/public/src/pages/applications/contact/name.tsx +++ b/sites/public/src/pages/applications/contact/name.tsx @@ -34,14 +34,17 @@ const ApplicationName = () => { /* Form Handler */ // 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 679fa1720c..b058a9b38d 100644 --- a/sites/public/src/pages/applications/financial/income.tsx +++ b/sites/public/src/pages/applications/financial/income.tsx @@ -70,7 +70,7 @@ const ApplicationIncome = () => { /* Form Handler */ // 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, @@ -78,7 +78,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(",", "") // Commenting out validation to not have income be a blocker https://github.com/bloom-housing/bloom/issues/3675 @@ -181,12 +184,11 @@ const ApplicationIncome = () => { { error={errors.incomePeriod} errorMessage={t("errors.selectOption")} register={register} - // TODO: Commenting out temporarily due to application issues - // validation={{ required: true, min: 0.01 }} + validation={{ required: true }} fields={incomePeriodValues} dataTestId={"app-income-period"} fieldGroupClassName="grid grid-cols-1" diff --git a/sites/public/src/pages/applications/financial/vouchers.tsx b/sites/public/src/pages/applications/financial/vouchers.tsx index cd8b6c15e3..136293feed 100644 --- a/sites/public/src/pages/applications/financial/vouchers.tsx +++ b/sites/public/src/pages/applications/financial/vouchers.tsx @@ -36,12 +36,15 @@ const ApplicationVouchers = () => { : 3 /* Form Handler */ // 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 4917263e4f..103474ca46 100644 --- a/sites/public/src/pages/applications/household/ada.tsx +++ b/sites/public/src/pages/applications/household/ada.tsx @@ -37,7 +37,7 @@ const ApplicationAda = () => { /* Form Handler */ // 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: { @@ -49,7 +49,10 @@ 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 8550c90271..b2f61b26cf 100644 --- a/sites/public/src/pages/applications/household/add-members.tsx +++ b/sites/public/src/pages/applications/household/add-members.tsx @@ -27,14 +27,18 @@ 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 /* Form Handler */ // eslint-disable-next-line @typescript-eslint/unbound-method - const { errors, handleSubmit, register, clearErrors } = useForm() - const onSubmit = () => { + const { errors, handleSubmit, register, clearErrors, trigger } = useForm() + + const onSubmit = async () => { + const validation = await trigger() + if (!validation) return + 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 43d038412c..58baa3a822 100644 --- a/sites/public/src/pages/applications/household/changes.tsx +++ b/sites/public/src/pages/applications/household/changes.tsx @@ -27,11 +27,15 @@ const ApplicationHouseholdChanges = () => { /* Form Handler */ // 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 7ae1cc2f15..ccba8c1dbd 100644 --- a/sites/public/src/pages/applications/household/live-alone.tsx +++ b/sites/public/src/pages/applications/household/live-alone.tsx @@ -29,6 +29,7 @@ const ApplicationLiveAlone = () => { /* Form Handler */ // eslint-disable-next-line @typescript-eslint/unbound-method const { handleSubmit, register, errors, clearErrors } = useForm() + const onSubmit = () => { 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 ae37586457..a7c964fabe 100644 --- a/sites/public/src/pages/applications/household/member.tsx +++ b/sites/public/src/pages/applications/household/member.tsx @@ -55,10 +55,14 @@ const ApplicationMember = () => { /* Form Handler */ // 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 ecbdf55b0a..c7c9dd5c8e 100644 --- a/sites/public/src/pages/applications/household/preferred-units.tsx +++ b/sites/public/src/pages/applications/household/preferred-units.tsx @@ -35,9 +35,12 @@ const ApplicationPreferredUnits = () => { /* Form Handler */ // eslint-disable-next-line @typescript-eslint/unbound-method - const { register, handleSubmit, errors } = useForm() + const { register, handleSubmit, errors, trigger } = useForm() + + const onSubmit = async (data) => { + const validation = await trigger() + if (!validation) return - const onSubmit = (data) => { 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 71a67a39df..32d69095a4 100644 --- a/sites/public/src/pages/applications/household/student.tsx +++ b/sites/public/src/pages/applications/household/student.tsx @@ -27,11 +27,15 @@ const ApplicationHouseholdStudent = () => { /* Form Handler */ // 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 282432a772..af90571703 100644 --- a/sites/public/src/pages/applications/start/autofill.tsx +++ b/sites/public/src/pages/applications/start/autofill.tsx @@ -45,17 +45,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)