diff --git a/login-workflow/docs/API.md b/login-workflow/docs/API.md index 497895c0..70c6ed48 100644 --- a/login-workflow/docs/API.md +++ b/login-workflow/docs/API.md @@ -27,7 +27,7 @@ The `RegistrationContextProvider` manages the state of the registration workflow - A function that is used to accept the EULA. This function will be called when the user clicks the Next button on the EULA screen. - **requestRegistrationCode**: _`(email: string) => Promise`_ - A function that is used to request a registration code. This function will be called when the user lands on the Verify Code screen as well as when a user clicks the Resend Verification Code button. -- **validateUserRegistrationRequest**: _`(validationCode: string, validationEmail?: string) => Promise`_ +- **validateUserRegistrationRequest**: _`(validationCode: string, validationEmail?: string) => Promise<{codeValid: boolean | string; accountExists?: boolean}>`_ - A function that is used to validate a registration code. This function will be called when the user clicks the Next button on the Verify Code screen screen. - **createPassword**: _`(password: string) => Promise`_ - A function that is used to create a password. This function will be called when the user clicks the Next button on the Create Password screen. diff --git a/login-workflow/docs/registration-workflow.md b/login-workflow/docs/registration-workflow.md index e3eea4f0..cd320f56 100644 --- a/login-workflow/docs/registration-workflow.md +++ b/login-workflow/docs/registration-workflow.md @@ -79,7 +79,7 @@ For a detailed explanation of setting up routes, see the [Routing](./routing.md) | loadEula | `(language: string) => Promise` | A function that is used to load the Eula content. This function will be called when the Eula screen is loaded. | | | acceptEula | `() => Promise` | A function that is called when the user has accepted the Eula and hit the Next button. | | | requestRegistrationCode | `(email: string) => Promise` | A function that is used to request a registration code. This function will be called when the user clicks the Next button on the Create Account screen or Resend button on Verify Code screen. | | -| validateUserRegistrationRequest | `(validationCode: string, validationEmail?: string) => Promise` | A function that is used to verify registration code. This function will be called when the user clicks the Next button on the Verify Code screen. | | +| validateUserRegistrationRequest | `(validationCode: string, validationEmail?: string) => Promise<{codeValid: boolean | string; accountExists?: boolean}>` | A function that is used to verify registration code. This function will be called when the user clicks the Next button on the Verify Code screen. | | | createPassword | `(password: string) => Promise` | A function that is used to create password. This function will be called when the user clicks the Next button on the Create Password screen. | | | setAccountDetails | `(details: { firstName: string; lastName: string; extra?: { [key: string]: boolean \| string \| number }}) => Promise` | A function that is used to set account details. This function will be called when the user clicks the Next button on the Account Details screen. | | | completeRegistration | `(userData: any, validationCode: number \| string, validationEmail: string) => Promise<{ email: string; organizationName: string }>` | A function that is used to complete the registration workflow. This function will be called when the user clicks the Next button on the last registration workflow screen. | | diff --git a/login-workflow/example/src/actions/RegistrationUIActions.tsx b/login-workflow/example/src/actions/RegistrationUIActions.tsx index 615aad89..200b593b 100644 --- a/login-workflow/example/src/actions/RegistrationUIActions.tsx +++ b/login-workflow/example/src/actions/RegistrationUIActions.tsx @@ -92,13 +92,16 @@ export const ProjectRegistrationUIActions: () => RegistrationUIActions = () => ( * @returns Resolves when the code is valid. True if registration is complete, False if account information is needed. * If the code is not valid a rejection will occur with an error message. */ - validateUserRegistrationRequest: async (validationCode: string, validationEmail?: string): Promise => { + validateUserRegistrationRequest: async ( + validationCode: string, + validationEmail?: string + ): Promise<{ codeValid: boolean | string; accountExists?: boolean }> => { await sleep(800); if (isRandomFailure()) { throw new Error('Sorry, there was a problem sending your request.'); } - return isRandomFailure(); + return { codeValid: true, accountExists: false }; }, completeRegistration: async (userData: object): Promise<{ email: string; organizationName: string }> => { diff --git a/login-workflow/src/components/RegistrationWorkflow/RegistrationWorkflow.tsx b/login-workflow/src/components/RegistrationWorkflow/RegistrationWorkflow.tsx index 857b8cef..372eceb8 100644 --- a/login-workflow/src/components/RegistrationWorkflow/RegistrationWorkflow.tsx +++ b/login-workflow/src/components/RegistrationWorkflow/RegistrationWorkflow.tsx @@ -12,6 +12,7 @@ import { import { parseQueryString } from '../../utils'; import { useErrorManager } from '../../contexts/ErrorContext/useErrorManager'; import ErrorManager, { ErrorManagerProps } from '../Error/ErrorManager'; +import { useLanguageLocale } from '../../hooks'; /** * Component that contain the registration workflow and index of screens. @@ -56,12 +57,16 @@ export type RegistrationWorkflowProps = { export const RegistrationWorkflow: React.FC> = (props) => { const [isAccountExist, setIsAccountExist] = useState(false); const { triggerError, errorManagerConfig } = useErrorManager(); + const { t } = useLanguageLocale(); + const { actions, navigate } = useRegistrationContext(); + const errorDisplayConfig = { ...errorManagerConfig, ...props.errorDisplayConfig, onClose: (): void => { if (props.errorDisplayConfig && props.errorDisplayConfig.onClose) props.errorDisplayConfig.onClose(); if (errorManagerConfig.onClose) errorManagerConfig?.onClose(); + navigate(-1); }, }; const { @@ -90,7 +95,6 @@ export const RegistrationWorkflow: React.FC totalScreens - 1 ? totalScreens - 1 : initialScreenIndex ); const [showSuccessScreen, setShowSuccessScreen] = useState(false); - const { actions, navigate } = useRegistrationContext(); const [screenData, setScreenData] = useState({ Eula: { @@ -116,7 +120,11 @@ export const RegistrationWorkflow: React.FC { const { Other }: { [key: string]: any } = screenData; - const { screenId, values } = data; + const { screenId, values, isAccountExist: accountExists } = data; + + setIsAccountExist(accountExists); + setShowSuccessScreen(accountExists); + if (!Object.keys(screenData).includes(screenId)) { setScreenData((oldData) => ({ ...oldData, @@ -169,7 +177,21 @@ export const RegistrationWorkflow: React.FC => { try { - isAccExist = await actions.validateUserRegistrationRequest(params.code, params.email); + const { codeValid, accountExists } = await actions.validateUserRegistrationRequest( + params.code, + params.email + ); + isAccExist = accountExists; + + if (!isAccExist) { + if (typeof codeValid === 'string') { + triggerError(new Error(codeValid)); + } else if (typeof codeValid === 'boolean' && !codeValid) { + triggerError( + new Error(t('bluiRegistration:SELF_REGISTRATION.VERIFY_EMAIL.CODE_VALIDATOR_ERROR')) + ); + } + } } catch (_error) { triggerError(_error as Error); } finally { diff --git a/login-workflow/src/contexts/RegistrationContext/types.ts b/login-workflow/src/contexts/RegistrationContext/types.ts index 338a9174..102f7f1b 100644 --- a/login-workflow/src/contexts/RegistrationContext/types.ts +++ b/login-workflow/src/contexts/RegistrationContext/types.ts @@ -37,7 +37,10 @@ export type RegistrationUIActions = { * @param {string} validationEmail - the provided email address * @returns Promise */ - validateUserRegistrationRequest?: (validationCode: string, validationEmail?: string) => Promise; + validateUserRegistrationRequest?: ( + validationCode: string, + validationEmail?: string + ) => Promise<{ codeValid: boolean | string; accountExists?: boolean }>; /** * A function that is used to create a password. This function will be called when the user clicks the Next button on the Create Password screen diff --git a/login-workflow/src/screens/VerifyCodeScreen/VerifyCodeScreen.tsx b/login-workflow/src/screens/VerifyCodeScreen/VerifyCodeScreen.tsx index d3f70f14..e8e82669 100644 --- a/login-workflow/src/screens/VerifyCodeScreen/VerifyCodeScreen.tsx +++ b/login-workflow/src/screens/VerifyCodeScreen/VerifyCodeScreen.tsx @@ -29,7 +29,7 @@ export const VerifyCodeScreen: React.FC = (props) => { const { t } = useLanguageLocale(); const regWorkflow = useRegistrationWorkflowContext(); const { actions } = useRegistrationContext(); - const { nextScreen, previousScreen, screenData, currentScreen, totalScreens } = regWorkflow; + const { nextScreen, previousScreen, screenData, currentScreen, totalScreens, updateScreenData } = regWorkflow; const { emailAddress } = screenData.CreateAccount; const { triggerError, errorManagerConfig } = useErrorManager(); const errorDisplayConfig = { @@ -72,19 +72,34 @@ export const VerifyCodeScreen: React.FC = (props) => { async (code: string) => { try { setIsLoading(true); - const isAccExist = await actions.validateUserRegistrationRequest(code); - void nextScreen({ - screenId: 'VerifyCode', - values: { code: code }, - isAccountExist: isAccExist, - }); + const { codeValid, accountExists } = await actions.validateUserRegistrationRequest(code); + + if (accountExists) { + updateScreenData({ screenId: 'VerifyCode', values: { code }, isAccountExist: accountExists }); + } else { + if (typeof codeValid === 'boolean') { + if (codeValid) + void nextScreen({ + screenId: 'VerifyCode', + values: { code }, + isAccountExist: accountExists, + }); + else { + triggerError( + new Error(t('bluiRegistration:SELF_REGISTRATION.VERIFY_EMAIL.CODE_VALIDATOR_ERROR')) + ); + } + } else { + triggerError(new Error(codeValid)); + } + } } catch (_error) { triggerError(_error as Error); } finally { setIsLoading(false); } }, - [actions, nextScreen, triggerError] + [t, actions, nextScreen, triggerError, updateScreenData] ); const onPrevious = (code: string): void => {