From 39875abaa2d9282cdaa3d09ee4e9a038bfce0323 Mon Sep 17 00:00:00 2001 From: emilyjablonski Date: Mon, 5 Feb 2024 18:27:32 -0700 Subject: [PATCH 1/4] fix: foreign language in export --- shared-helpers/src/views/multiselectQuestions.tsx | 11 ++++++----- sites/public/src/lib/helpers.tsx | 11 +++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/shared-helpers/src/views/multiselectQuestions.tsx b/shared-helpers/src/views/multiselectQuestions.tsx index 43234ba2aa..883637d589 100644 --- a/shared-helpers/src/views/multiselectQuestions.tsx +++ b/shared-helpers/src/views/multiselectQuestions.tsx @@ -433,26 +433,27 @@ export const mapApiToMultiselectForm = ( if (appQuestion.inputType === "checkbox") { options = question.options.reduce((acc, curr) => { const claimed = curr.checked + const cleanKey = curr.key.replace(/\.|,|'/g, "") if (appQuestion.inputType === "checkbox") { - acc[curr.key] = claimed + acc[cleanKey] = claimed if (curr.extraData?.length) { - acc[`${curr.key}-address`] = curr.extraData[0].value + acc[`${cleanKey}-address`] = curr.extraData[0].value const addressHolderName = curr.extraData?.find( (field) => field.key === AddressHolder.Name ) if (addressHolderName) { - acc[`${curr.key}-${AddressHolder.Name}`] = addressHolderName.value + acc[`${cleanKey}-${AddressHolder.Name}`] = addressHolderName.value } const addressHolderRelationship = curr.extraData?.find( (field) => field.key === AddressHolder.Relationship ) if (addressHolderRelationship) { - acc[`${curr.key}-${AddressHolder.Relationship}`] = addressHolderRelationship.value + acc[`${cleanKey}-${AddressHolder.Relationship}`] = addressHolderRelationship.value } if (curr?.mapPinPosition) { - acc[`${curr.key}-mapPinPosition`] = curr.mapPinPosition + acc[`${cleanKey}-mapPinPosition`] = curr.mapPinPosition } } } diff --git a/sites/public/src/lib/helpers.tsx b/sites/public/src/lib/helpers.tsx index 1aa6b9c4cb..40fddc6a45 100644 --- a/sites/public/src/lib/helpers.tsx +++ b/sites/public/src/lib/helpers.tsx @@ -184,7 +184,9 @@ export const untranslateMultiselectQuestion = ( data.forEach((datum) => { const question = multiselectQuestions.find( - (elem) => elem.multiselectQuestion.text === datum.key + (elem) => + elem.multiselectQuestion.text === datum.key || + elem.multiselectQuestion.untranslatedText === datum.key )?.multiselectQuestion if (question) { @@ -192,11 +194,12 @@ export const untranslateMultiselectQuestion = ( if (datum.options) { datum.options.forEach((option) => { - const selectedOption = question.options.find((elem) => elem.text === option.key) - + const selectedOption = question.options.find((elem) => { + return elem.text.replace(/\.|,|'/g, "") === option.key + }) if (selectedOption) { option.key = selectedOption.untranslatedText ?? selectedOption.text - } else if (question.optOutText === option.key) { + } else if (question?.optOutText?.replace(/\.|,|'/g, "") === option.key) { option.key = question.untranslatedOptOutText ?? question.optOutText } From 0589570828e6c0147f39ddb3ce73f037c9dceb66 Mon Sep 17 00:00:00 2001 From: emilyjablonski Date: Tue, 6 Feb 2024 11:42:03 -0700 Subject: [PATCH 2/4] fix: additional extra chars --- .../src/views/multiselectQuestions.tsx | 17 ++++++++++---- .../sections/FormMultiselectQuestions.tsx | 12 ++++++++-- .../components/shared/FormSummaryDetails.tsx | 23 ++++++++++++++++++- sites/public/src/lib/helpers.tsx | 6 +++-- 4 files changed, 49 insertions(+), 9 deletions(-) diff --git a/shared-helpers/src/views/multiselectQuestions.tsx b/shared-helpers/src/views/multiselectQuestions.tsx index 883637d589..23e1ee5531 100644 --- a/shared-helpers/src/views/multiselectQuestions.tsx +++ b/shared-helpers/src/views/multiselectQuestions.tsx @@ -37,8 +37,8 @@ export const fieldName = ( applicationSection: ApplicationSection, optionName?: string ) => { - return `application.${applicationSection}.${questionName?.replace(/'/g, "")}${ - optionName ? `.${optionName?.replace(/'/g, "")}` : "" + return `application.${applicationSection}.${questionName?.replace(/\.|,|'/g, "")}${ + optionName ? `.${optionName?.replace(/\.|,|'/g, "")}` : "" }` } @@ -343,7 +343,7 @@ export const mapCheckboxesToApi = ( question: MultiselectQuestion, applicationSection: ApplicationSection ): ApplicationMultiselectQuestion => { - const data = formData["application"][applicationSection][question.text.replace(/'/g, "")] + const data = formData["application"][applicationSection][question.text.replace(/\.|,|'/g, "")] const claimed = !!Object.keys(data).filter((key) => data[key] === true).length const addressFields = Object.keys(data).filter((option) => Object.keys(data[option])) @@ -378,8 +378,17 @@ export const mapCheckboxesToApi = ( } } + const getFinalKey = () => { + const optionKey = question?.options?.find( + (elem) => elem.text.replace(/\.|,|'/g, "") === key + )?.text + const cleanOptOutKey = question?.optOutText?.replace(/\.|,|'/g, "") + if (cleanOptOutKey === key) return question?.optOutText || key + return optionKey || key + } + return { - key, + key: getFinalKey(), mapPinPosition: data?.[`${key}-mapPinPosition`], checked: data[key] === true, extraData: extraData, diff --git a/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx b/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx index cac836d64c..fa78c3768e 100644 --- a/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx +++ b/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx @@ -41,7 +41,11 @@ const FormMultiselectQuestions = ({ questions?.forEach((listingQuestion) => listingQuestion?.multiselectQuestion.options.forEach((option) => keys.push( - fieldName(listingQuestion?.multiselectQuestion.text, applicationSection, option.text) + fieldName( + listingQuestion?.multiselectQuestion.text, + applicationSection, + option.text.replace(/\.|,|'/g, "") + ) ) ) ) @@ -68,7 +72,11 @@ const FormMultiselectQuestions = ({ const watchQuestions = watch(allOptionFieldNames) const getCheckboxOption = (option: MultiselectOption, question: MultiselectQuestion) => { - const optionFieldName = fieldName(question.text, applicationSection, option.text) + const optionFieldName = fieldName( + question.text, + applicationSection, + option.text.replace(/\.|,|'/g, "") + ) return ( { + const initialMultiselectQuestion = listing.listingMultiselectQuestions.find( + (elem) => + elem.multiselectQuestion.text.replace(/\.|,|'/g, "") === question.key.replace(/\.|,|'/g, "") + ) + + const initialOption = initialMultiselectQuestion?.multiselectQuestion.options.find( + (elem) => elem.text.replace(/\.|,|'/g, "") === option.key + ) + + const initialOptOut = initialMultiselectQuestion?.multiselectQuestion.optOutText + + const optOutOption = + option.key === initialOptOut?.replace(/\.|,|'/g, "") ? initialOptOut : undefined + + return initialOption?.text || optOutOption || option.key + } + const multiselectQuestionSection = ( applicationSection: ApplicationSection, appLink: string, @@ -141,7 +162,7 @@ const FormSummaryDetails = ({ testId={"app-summary-preference"} className={"pb-6 whitespace-pre-wrap"} > - {option.key} + {getOptionText(question, option)} )) )} diff --git a/sites/public/src/lib/helpers.tsx b/sites/public/src/lib/helpers.tsx index 40fddc6a45..496446aa6e 100644 --- a/sites/public/src/lib/helpers.tsx +++ b/sites/public/src/lib/helpers.tsx @@ -195,11 +195,13 @@ export const untranslateMultiselectQuestion = ( if (datum.options) { datum.options.forEach((option) => { const selectedOption = question.options.find((elem) => { - return elem.text.replace(/\.|,|'/g, "") === option.key + return elem.text.replace(/\.|,|'/g, "") === option.key.replace(/\.|,|'/g, "") }) if (selectedOption) { option.key = selectedOption.untranslatedText ?? selectedOption.text - } else if (question?.optOutText?.replace(/\.|,|'/g, "") === option.key) { + } else if ( + question?.optOutText?.replace(/\.|,|'/g, "") === option.key.replace(/\.|,|'/g, "") + ) { option.key = question.untranslatedOptOutText ?? question.optOutText } From 17f978dc6666e20896c91cb5c0ecc022a4a3832e Mon Sep 17 00:00:00 2001 From: emilyjablonski Date: Tue, 6 Feb 2024 11:55:57 -0700 Subject: [PATCH 3/4] refactor: cleanup --- .../src/views/multiselectQuestions.tsx | 17 +++++++++++------ .../sections/FormMultiselectQuestions.tsx | 12 +++++++++--- .../components/shared/FormSummaryDetails.tsx | 13 +++++++++---- sites/public/src/lib/helpers.tsx | 5 +++-- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/shared-helpers/src/views/multiselectQuestions.tsx b/shared-helpers/src/views/multiselectQuestions.tsx index 23e1ee5531..1adbc1261c 100644 --- a/shared-helpers/src/views/multiselectQuestions.tsx +++ b/shared-helpers/src/views/multiselectQuestions.tsx @@ -21,6 +21,10 @@ import { stateKeys } from "../utilities/formKeys" import { AddressHolder } from "../utilities/constants" import { FormAddressAlternate } from "./address/FormAddressAlternate" +export const cleanMultiselectString = (name: string | undefined) => { + return name?.replace(/\.|,|'/g, "") +} + export const listingSectionQuestions = ( listing: Listing, applicationSection: ApplicationSection @@ -37,8 +41,8 @@ export const fieldName = ( applicationSection: ApplicationSection, optionName?: string ) => { - return `application.${applicationSection}.${questionName?.replace(/\.|,|'/g, "")}${ - optionName ? `.${optionName?.replace(/\.|,|'/g, "")}` : "" + return `application.${applicationSection}.${cleanMultiselectString(questionName)}${ + optionName ? `.${cleanMultiselectString(optionName)}` : "" }` } @@ -343,7 +347,8 @@ export const mapCheckboxesToApi = ( question: MultiselectQuestion, applicationSection: ApplicationSection ): ApplicationMultiselectQuestion => { - const data = formData["application"][applicationSection][question.text.replace(/\.|,|'/g, "")] + const data = + formData["application"][applicationSection][cleanMultiselectString(question.text) || ""] const claimed = !!Object.keys(data).filter((key) => data[key] === true).length const addressFields = Object.keys(data).filter((option) => Object.keys(data[option])) @@ -380,9 +385,9 @@ export const mapCheckboxesToApi = ( const getFinalKey = () => { const optionKey = question?.options?.find( - (elem) => elem.text.replace(/\.|,|'/g, "") === key + (elem) => cleanMultiselectString(elem.text) === key )?.text - const cleanOptOutKey = question?.optOutText?.replace(/\.|,|'/g, "") + const cleanOptOutKey = cleanMultiselectString(question?.optOutText) if (cleanOptOutKey === key) return question?.optOutText || key return optionKey || key } @@ -442,7 +447,7 @@ export const mapApiToMultiselectForm = ( if (appQuestion.inputType === "checkbox") { options = question.options.reduce((acc, curr) => { const claimed = curr.checked - const cleanKey = curr.key.replace(/\.|,|'/g, "") + const cleanKey = cleanMultiselectString(curr.key) || "" if (appQuestion.inputType === "checkbox") { acc[cleanKey] = claimed if (curr.extraData?.length) { diff --git a/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx b/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx index fa78c3768e..9a574a9458 100644 --- a/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx +++ b/sites/partners/src/components/applications/PaperApplicationForm/sections/FormMultiselectQuestions.tsx @@ -2,7 +2,13 @@ import React, { useEffect, useMemo, useState } from "react" import { Field, t, FieldGroup, resolveObject } from "@bloom-housing/ui-components" import { FieldValue, Grid } from "@bloom-housing/ui-seeds" import { useFormContext } from "react-hook-form" -import { stateKeys, getInputType, fieldName, AddressHolder } from "@bloom-housing/shared-helpers" +import { + stateKeys, + getInputType, + fieldName, + AddressHolder, + cleanMultiselectString, +} from "@bloom-housing/shared-helpers" import { ApplicationSection, ListingMultiselectQuestion, @@ -44,7 +50,7 @@ const FormMultiselectQuestions = ({ fieldName( listingQuestion?.multiselectQuestion.text, applicationSection, - option.text.replace(/\.|,|'/g, "") + cleanMultiselectString(option.text) ) ) ) @@ -75,7 +81,7 @@ const FormMultiselectQuestions = ({ const optionFieldName = fieldName( question.text, applicationSection, - option.text.replace(/\.|,|'/g, "") + cleanMultiselectString(option.text) ) return ( diff --git a/sites/public/src/components/shared/FormSummaryDetails.tsx b/sites/public/src/components/shared/FormSummaryDetails.tsx index e54981ed71..36a2bacab5 100644 --- a/sites/public/src/components/shared/FormSummaryDetails.tsx +++ b/sites/public/src/components/shared/FormSummaryDetails.tsx @@ -1,7 +1,11 @@ import React, { Fragment, useEffect, useState } from "react" import { LocalizedLink, MultiLineAddress, t } from "@bloom-housing/ui-components" import { FieldValue } from "@bloom-housing/ui-seeds" -import { getUniqueUnitTypes, AddressHolder } from "@bloom-housing/shared-helpers" +import { + getUniqueUnitTypes, + AddressHolder, + cleanMultiselectString, +} from "@bloom-housing/shared-helpers" import { Address, AllExtraDataTypes, @@ -113,17 +117,18 @@ const FormSummaryDetails = ({ ) => { const initialMultiselectQuestion = listing.listingMultiselectQuestions.find( (elem) => - elem.multiselectQuestion.text.replace(/\.|,|'/g, "") === question.key.replace(/\.|,|'/g, "") + cleanMultiselectString(elem.multiselectQuestion.text) === + cleanMultiselectString(question.key) ) const initialOption = initialMultiselectQuestion?.multiselectQuestion.options.find( - (elem) => elem.text.replace(/\.|,|'/g, "") === option.key + (elem) => cleanMultiselectString(elem.text) === option.key ) const initialOptOut = initialMultiselectQuestion?.multiselectQuestion.optOutText const optOutOption = - option.key === initialOptOut?.replace(/\.|,|'/g, "") ? initialOptOut : undefined + option.key === cleanMultiselectString(initialOptOut) ? initialOptOut : undefined return initialOption?.text || optOutOption || option.key } diff --git a/sites/public/src/lib/helpers.tsx b/sites/public/src/lib/helpers.tsx index 496446aa6e..c0fd8cb7c0 100644 --- a/sites/public/src/lib/helpers.tsx +++ b/sites/public/src/lib/helpers.tsx @@ -19,6 +19,7 @@ import { imageUrlFromListing, getSummariesTable, IMAGE_FALLBACK_URL, + cleanMultiselectString, } from "@bloom-housing/shared-helpers" export const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ @@ -195,12 +196,12 @@ export const untranslateMultiselectQuestion = ( if (datum.options) { datum.options.forEach((option) => { const selectedOption = question.options.find((elem) => { - return elem.text.replace(/\.|,|'/g, "") === option.key.replace(/\.|,|'/g, "") + return cleanMultiselectString(elem.text) === cleanMultiselectString(option.key) }) if (selectedOption) { option.key = selectedOption.untranslatedText ?? selectedOption.text } else if ( - question?.optOutText?.replace(/\.|,|'/g, "") === option.key.replace(/\.|,|'/g, "") + cleanMultiselectString(question?.optOutText) === cleanMultiselectString(option.key) ) { option.key = question.untranslatedOptOutText ?? question.optOutText } From 24e807aded965efba607f7ea387c9c4e0ec27709 Mon Sep 17 00:00:00 2001 From: emilyjablonski Date: Tue, 6 Feb 2024 12:50:46 -0700 Subject: [PATCH 4/4] test: add unit test --- .../__tests__/views/multiselectQuestions.test.ts | 14 ++++++++++++++ shared-helpers/src/views/multiselectQuestions.tsx | 1 + 2 files changed, 15 insertions(+) create mode 100644 shared-helpers/__tests__/views/multiselectQuestions.test.ts diff --git a/shared-helpers/__tests__/views/multiselectQuestions.test.ts b/shared-helpers/__tests__/views/multiselectQuestions.test.ts new file mode 100644 index 0000000000..efd8090cc1 --- /dev/null +++ b/shared-helpers/__tests__/views/multiselectQuestions.test.ts @@ -0,0 +1,14 @@ +import { cleanup } from "@testing-library/react" +import { cleanMultiselectString } from "../../src/views/multiselectQuestions" + +afterEach(cleanup) + +describe("multiselectQuestions", () => { + describe("cleanMultiselectString", () => { + it("should remove expected characters", () => { + expect( + cleanMultiselectString("I'm a string, and I have a comma, period, and apostrophe.") + ).toBe("Im a string and I have a comma period and apostrophe") + }) + }) +}) diff --git a/shared-helpers/src/views/multiselectQuestions.tsx b/shared-helpers/src/views/multiselectQuestions.tsx index 1adbc1261c..8b9c398457 100644 --- a/shared-helpers/src/views/multiselectQuestions.tsx +++ b/shared-helpers/src/views/multiselectQuestions.tsx @@ -21,6 +21,7 @@ import { stateKeys } from "../utilities/formKeys" import { AddressHolder } from "../utilities/constants" import { FormAddressAlternate } from "./address/FormAddressAlternate" +// Removes periods, commas, and apostrophes export const cleanMultiselectString = (name: string | undefined) => { return name?.replace(/\.|,|'/g, "") }