{t('in_person_proofing.body.cta.prompt_detail')}
+{altPrompt || t('in_person_proofing.body.cta.prompt_detail')}
); diff --git a/app/javascript/packages/document-capture/components/review-issues-step.tsx b/app/javascript/packages/document-capture/components/review-issues-step.tsx index a660d881d0b..6433a52ee68 100644 --- a/app/javascript/packages/document-capture/components/review-issues-step.tsx +++ b/app/javascript/packages/document-capture/components/review-issues-step.tsx @@ -1,5 +1,5 @@ -import { useContext, useEffect, useState } from 'react'; -import { useI18n } from '@18f/identity-react-i18n'; +import { useContext, useEffect, useState, ReactNode } from 'react'; +import { useI18n, formatHTML } from '@18f/identity-react-i18n'; import { useDidUpdateEffect } from '@18f/identity-react-hooks'; import { FormStepsContext, FormStepsButton } from '@18f/identity-form-steps'; import { PageHeading } from '@18f/identity-components'; @@ -13,6 +13,13 @@ import Warning from './warning'; import AnalyticsContext from '../context/analytics'; import BarcodeAttentionWarning from './barcode-attention-warning'; import FailedCaptureAttemptsContext from '../context/failed-capture-attempts'; +import { InPersonContext } from '../context'; + +function formatWithStrongNoWrap(text: string): ReactNode { + return formatHTML(text, { + strong: ({ children }) => {children}, + }); +} type DocumentSide = 'front' | 'back'; @@ -74,12 +81,16 @@ function ReviewIssuesStep({ useDidUpdateEffect(onPageTransition, [hasDismissed]); const { onFailedSubmissionAttempt } = useContext(FailedCaptureAttemptsContext); + const { inPersonURL, inPersonCtaVariantActive } = useContext(InPersonContext); useEffect(() => onFailedSubmissionAttempt(), []); function onWarningPageDismissed() { trackEvent('IdV: Capture troubleshooting dismissed'); setHasDismissed(true); } + function onInPersonSelected() { + trackEvent('IdV: verify in person troubleshooting option clicked'); + } // let FormSteps know, via FormStepsContext, whether this page // is ready to submit form values @@ -87,38 +98,160 @@ function ReviewIssuesStep({ changeStepCanComplete(!!hasDismissed); }, [hasDismissed]); + useEffect(() => { + if (!inPersonURL || isFailedResult) { + return; + } + if (inPersonCtaVariantActive === 'in_person_variant_a') { + trackEvent('IdV: IPP CTA Variant A'); + } else if (inPersonCtaVariantActive === 'in_person_variant_b') { + trackEvent('IdV: IPP CTA Variant B'); + } else if (inPersonCtaVariantActive === 'in_person_variant_c') { + trackEvent('IdV: IPP CTA Variant C'); + } + }, []); + if (!hasDismissed) { if (pii) { return{error.message}
)} - - {remainingAttempts <= DISPLAY_ATTEMPTS && ( -- {t('idv.failure.attempts', { count: remainingAttempts })} -
- )} - - ); + if (!inPersonURL || isFailedResult) { + return ( +{error.message}
)} + + {remainingAttempts <= DISPLAY_ATTEMPTS && ( ++ {t('idv.failure.attempts', { count: remainingAttempts })} +
+ )} + + ); + } + if (inPersonCtaVariantActive === 'in_person_variant_a') { + return ( +{error.message}
)} + + {remainingAttempts <= DISPLAY_ATTEMPTS && ( ++ {remainingAttempts === 1 + ? formatWithStrongNoWrap(t('idv.failure.attempts.one_variant_a_html')) + : formatWithStrongNoWrap( + t('idv.failure.attempts.other_variant_a_html', { count: remainingAttempts }), + )} +
+ )} + + ); + } + if (inPersonCtaVariantActive === 'in_person_variant_b') { + return ( +{error.message}
)} + + {remainingAttempts <= DISPLAY_ATTEMPTS && ( ++ {remainingAttempts === 1 + ? formatWithStrongNoWrap(t('idv.failure.attempts.one_variant_b_html')) + : formatWithStrongNoWrap( + t('idv.failure.attempts.other_variant_b_html', { count: remainingAttempts }), + )} +
+ )} +{t('in_person_proofing.body.cta.prompt_detail_b')}
+ + ); + } + if (inPersonCtaVariantActive === 'in_person_variant_c') { + return ( +{error.message}
)} + + {remainingAttempts <= DISPLAY_ATTEMPTS && ( ++ + {remainingAttempts === 1 + ? t('idv.failure.attempts.one') + : t('idv.failure.attempts.other', { count: remainingAttempts })} + +
+ )} + + ); + } } return ( diff --git a/app/javascript/packages/document-capture/components/warning.tsx b/app/javascript/packages/document-capture/components/warning.tsx index 60ae578d4af..e6128770e40 100644 --- a/app/javascript/packages/document-capture/components/warning.tsx +++ b/app/javascript/packages/document-capture/components/warning.tsx @@ -20,6 +20,21 @@ interface WarningProps { */ actionOnClick?: () => void; + /** + * Secondary action button text. + */ + altActionText?: string; + + /** + * Secondary action button text. + */ + altActionOnClick?: () => void; + + /** + * Secondary action button location. + */ + altHref?: string; + /** * Component children. */ @@ -45,6 +60,9 @@ function Warning({ heading, actionText, actionOnClick, + altActionText, + altActionOnClick, + altHref, children, troubleshootingOptions, location, @@ -69,6 +87,22 @@ function Warning({ {actionText} , ]; + if (altActionText && altActionOnClick) { + actionButtons.push( + , + ); + } } return ( diff --git a/app/javascript/packages/document-capture/context/in-person.ts b/app/javascript/packages/document-capture/context/in-person.ts index 19d255cb63d..90e7fdd6ced 100644 --- a/app/javascript/packages/document-capture/context/in-person.ts +++ b/app/javascript/packages/document-capture/context/in-person.ts @@ -6,6 +6,16 @@ export interface InPersonContextProps { */ arcgisSearchEnabled?: boolean; + /** + * Whether or not A/B testing of the in-person proofing CTA is enabled. + */ + inPersonCtaVariantTestingEnabled?: boolean; + + /** + * The specific A/B testing variant that was activated for the current user session. + */ + inPersonCtaVariantActive?: string; + /** * URL to in-person proofing alternative flow, if enabled. */ @@ -14,6 +24,8 @@ export interface InPersonContextProps { const InPersonContext = createContext