diff --git a/products/statement-generator/src/helpers/statementGenerators.ts b/products/statement-generator/src/helpers/statementGenerators.ts index 1ff1411e..414dbfa4 100644 --- a/products/statement-generator/src/helpers/statementGenerators.ts +++ b/products/statement-generator/src/helpers/statementGenerators.ts @@ -15,12 +15,12 @@ export function generateIntroduction(formState: IStepState): string { ? `My name is ${introduction.fullName}, and I am ${introduction.age} years old.` : ''; - const veteranSentance = + const veteranSentence = introduction.isVeteran === 'Yes' ? 'I am also a proud veteran of the United States Armed Forces.' : ''; - return `${nameSentence} ${veteranSentance} ${lastSentence}`; + return `${nameSentence} ${veteranSentence} ${lastSentence}`; } /** @@ -40,7 +40,10 @@ export function generateInvolvementJob(formState: IStepState): string { return ''; } - return `I have been working at ${companyName} as a ${jobTitle}. At ${companyName}, ${jobDescription} Having my record cleared would help me continue to advance in my career.`; + // Determine the correct article "a" or "an" based on the first letter of the jobTitle + const article = generateArticle(jobTitle); + + return `I have been working at ${companyName} as ${article} ${jobTitle}. At ${companyName}, ${jobDescription} Having my record cleared would help me continue to advance in my career.`; } /** @@ -209,3 +212,43 @@ export function generateClosing(formState: IStepState): string { return `Sincerely,\n\n${fullName}`; } + +export function capitalizeSentences(text: string): string { + let formattedText = text.trim(); + formattedText = formattedText.replace(/(^\s*\w|[.!?]\s*\w)/g, (c) => + c.toUpperCase() + ); + if (!/[.!?]$/.test(formattedText)) { + formattedText += '.'; + } + return formattedText; +} + +export function capitalizeEachWord(text: string): string { + return text + .trim() + .replace(/[.,/#!$%^&*;:?{}=_`~()-]+$/, '') // Remove unwanted punctuation + .split(' ') + .map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()) + .join(' '); +} + +export function removePunctuationAndCapitalizeFirstWord(text: string): string { + let formattedText = text.trim(); + formattedText = formattedText.replace(/[.,/#!$%^&*;:?{}=_`~()-]+$/, ''); + formattedText = + formattedText.charAt(0).toUpperCase() + formattedText.slice(1); + return formattedText; +} + +export function removePunctuation(text: string): string { + return text.trim().replace(/[.,/#!$%^&*;:?{}=_`~()-]+$/, ''); +} + +export function generateArticle(word: string): string { + return /^[aeiou]/i.test(word) ? 'an' : 'a'; +} + +export function capitalizeStandaloneI(text: string): string { + return text.replace(/\bi\b/g, 'I'); +} diff --git a/products/statement-generator/src/pages-form/GoalsStep.tsx b/products/statement-generator/src/pages-form/GoalsStep.tsx index f8532d12..5eb8a38f 100644 --- a/products/statement-generator/src/pages-form/GoalsStep.tsx +++ b/products/statement-generator/src/pages-form/GoalsStep.tsx @@ -7,6 +7,10 @@ import FlowNavigation from 'components-layout/FlowNavigation'; import ContentContainer from 'components-layout/ContentContainer'; import Textarea from 'components/Textarea'; +import { + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function GoalsStep() { const { t } = useTranslation(); @@ -21,7 +25,22 @@ function GoalsStep() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'goals') { + formattedValue = capitalizeSentences(value); + } else if (id === 'goalsHow') { + formattedValue = value + .replace(/(^\s*i\s|[.!?]\s*\w)/g, (c) => c.toUpperCase()) + .trim(); + if (!/[.!?]$/.test(formattedValue)) { + formattedValue += '.'; + } + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ goalsState: { ...formState.goalsState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/IntroductionStep.tsx b/products/statement-generator/src/pages-form/IntroductionStep.tsx index 22d77dcd..f39cfd30 100644 --- a/products/statement-generator/src/pages-form/IntroductionStep.tsx +++ b/products/statement-generator/src/pages-form/IntroductionStep.tsx @@ -9,6 +9,7 @@ import RadioGroup from 'components/RadioGroup'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { removePunctuation } from 'helpers/statementGenerators'; export function IntroductionStep() { const { t } = useTranslation(); @@ -21,7 +22,18 @@ export function IntroductionStep() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let finalValue = value.trim(); + + if (id === 'fullName') { + finalValue = removePunctuation(value) + .split(' ') + .map( + (part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase() + ) + .join(' '); + } + + const changes = { [id]: finalValue }; updateStepToForm({ introduction: { ...formState.introduction, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementCommunityServiceFlow.tsx b/products/statement-generator/src/pages-form/InvolvementCommunityServiceFlow.tsx index 1f1bfe0e..a3122623 100644 --- a/products/statement-generator/src/pages-form/InvolvementCommunityServiceFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementCommunityServiceFlow.tsx @@ -9,6 +9,11 @@ import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeEachWord, + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; import Input from '../components/Input'; function InvolvementCommunityServiceFlow() { @@ -25,7 +30,17 @@ function InvolvementCommunityServiceFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'organizationName') { + formattedValue = capitalizeEachWord(value); + } else if (id === 'serviceDescription') { + formattedValue = capitalizeSentences(value); + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ communityServiceState: { ...formState.communityServiceState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementJobFlow.tsx b/products/statement-generator/src/pages-form/InvolvementJobFlow.tsx index adf7705b..1e3c608e 100644 --- a/products/statement-generator/src/pages-form/InvolvementJobFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementJobFlow.tsx @@ -9,6 +9,11 @@ import Textarea from 'components/Textarea'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeEachWord, + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function InvolvementJobFlow() { const { t } = useTranslation(); @@ -27,7 +32,17 @@ function InvolvementJobFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'companyName' || id === 'jobTitle') { + formattedValue = capitalizeEachWord(value); + } else if (id === 'jobDescription') { + formattedValue = capitalizeSentences(value); + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ involvementJobState: { ...formState.involvementJobState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementParentingFlow.tsx b/products/statement-generator/src/pages-form/InvolvementParentingFlow.tsx index d22b6ba2..ae18f4bd 100644 --- a/products/statement-generator/src/pages-form/InvolvementParentingFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementParentingFlow.tsx @@ -9,6 +9,10 @@ import Textarea from 'components/Textarea'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function InvolvementParentingFlow() { const { t } = useTranslation(); @@ -21,7 +25,15 @@ function InvolvementParentingFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'parentDescription') { + formattedValue = capitalizeSentences(value); + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ parentingState: { ...formState.parentingState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementRecoveryFlow.tsx b/products/statement-generator/src/pages-form/InvolvementRecoveryFlow.tsx index d1d56335..6763653b 100644 --- a/products/statement-generator/src/pages-form/InvolvementRecoveryFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementRecoveryFlow.tsx @@ -9,6 +9,11 @@ import Textarea from 'components/Textarea'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeSentences, + removePunctuationAndCapitalizeFirstWord, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function InvolvementRecoveryFlow() { const { t } = useTranslation(); @@ -21,7 +26,17 @@ function InvolvementRecoveryFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'recoveryName') { + formattedValue = removePunctuationAndCapitalizeFirstWord(value); + } else if (id === 'recoveryDescription') { + formattedValue = capitalizeSentences(value); + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ recoveryState: { ...formState.recoveryState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementSchoolFlow.tsx b/products/statement-generator/src/pages-form/InvolvementSchoolFlow.tsx index 959965f1..ca1b8a27 100644 --- a/products/statement-generator/src/pages-form/InvolvementSchoolFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementSchoolFlow.tsx @@ -9,6 +9,11 @@ import Textarea from 'components/Textarea'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeEachWord, + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function InvolvementSchoolFlow() { const { t } = useTranslation(); @@ -23,7 +28,17 @@ function InvolvementSchoolFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'schoolName' || id === 'studyName') { + formattedValue = capitalizeEachWord(value); + } else if (id === 'passionDescription') { + formattedValue = capitalizeSentences(value); + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ schoolState: { ...formState.schoolState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementSomethingElseFlow.tsx b/products/statement-generator/src/pages-form/InvolvementSomethingElseFlow.tsx index 5d7c8c58..19503e85 100644 --- a/products/statement-generator/src/pages-form/InvolvementSomethingElseFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementSomethingElseFlow.tsx @@ -9,6 +9,11 @@ import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeSentences, + removePunctuation, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; import Input from '../components/Input'; function InvolvementSomethingElseFlow() { @@ -22,7 +27,17 @@ function InvolvementSomethingElseFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + if (id === 'activityName') { + formattedValue = removePunctuation(value); + } else if (id === 'activityDescription') { + formattedValue = capitalizeSentences(value); + } + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ somethingElseState: { ...formState.somethingElseState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/InvolvementUnemploymentFlow.tsx b/products/statement-generator/src/pages-form/InvolvementUnemploymentFlow.tsx index eff6113a..fcee6ce5 100644 --- a/products/statement-generator/src/pages-form/InvolvementUnemploymentFlow.tsx +++ b/products/statement-generator/src/pages-form/InvolvementUnemploymentFlow.tsx @@ -8,6 +8,10 @@ import Textarea from 'components/Textarea'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function InvolvementUnemploymentFlow() { const { t } = useTranslation(); @@ -19,7 +23,13 @@ function InvolvementUnemploymentFlow() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + formattedValue = capitalizeSentences(value); + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ unemploymentState: { ...formState.unemploymentState, ...changes }, }); diff --git a/products/statement-generator/src/pages-form/WhyStep.tsx b/products/statement-generator/src/pages-form/WhyStep.tsx index a8ba92ce..8116efcc 100644 --- a/products/statement-generator/src/pages-form/WhyStep.tsx +++ b/products/statement-generator/src/pages-form/WhyStep.tsx @@ -8,6 +8,10 @@ import Textarea from 'components/Textarea'; import ContentContainer from 'components-layout/ContentContainer'; import FlowNavigation from 'components-layout/FlowNavigation'; import FormContainer from 'components-layout/FormContainer'; +import { + capitalizeSentences, + capitalizeStandaloneI, +} from 'helpers/statementGenerators'; function WhyStep() { const { t } = useTranslation(); @@ -22,7 +26,13 @@ function WhyStep() { const onInputChange = (evt: React.ChangeEvent) => { const { id, value } = evt.currentTarget; - const changes = { [id]: value }; + let formattedValue = value.trim(); + + formattedValue = capitalizeSentences(value); + + formattedValue = capitalizeStandaloneI(formattedValue); + + const changes = { [id]: formattedValue }; updateStepToForm({ whyState: { ...formState.whyState, ...changes }, });