diff --git a/src/languages/en.ts b/src/languages/en.ts index 66a83e719377..6f246ca15588 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -483,6 +483,7 @@ const translations = { skip: 'Skip', chatWithAccountManager: ({accountManagerDisplayName}: ChatWithAccountManagerParams) => `Need something specific? Chat with your account manager, ${accountManagerDisplayName}.`, chatNow: 'Chat now', + validate: 'Validate', }, supportalNoAccess: { title: 'Not so fast', @@ -1843,7 +1844,10 @@ const translations = { toUnblock: ' to unblock your login.', }, smsDeliveryFailurePage: { - smsDeliveryFailureMessage: ({login}: OurEmailProviderParams) => `We've been unable to deliver SMS messages to ${login}, so we've suspended it for 24 hours.`, + smsDeliveryFailureMessage: ({login}: OurEmailProviderParams) => + `We've been unable to deliver SMS messages to ${login}, so we've suspended it for 24 hours. Please try validating your number:`, + validationFailed: 'Validation failed because it hasn’t been 24 hours since your last attempt.', + validationSuccess: 'Your number has been validated! Click below to send a new magic sign-in code.', }, welcomeSignUpForm: { join: 'Join', diff --git a/src/languages/es.ts b/src/languages/es.ts index 9c2b8a90f312..49678917ded5 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -474,6 +474,7 @@ const translations = { days: 'días', chatWithAccountManager: ({accountManagerDisplayName}: ChatWithAccountManagerParams) => `¿Necesitas algo específico? Habla con tu gerente de cuenta, ${accountManagerDisplayName}.`, chatNow: 'Chatear ahora', + validate: 'Validar', }, supportalNoAccess: { title: 'No tan rápido', @@ -1848,7 +1849,10 @@ const translations = { toUnblock: ' para desbloquear el inicio de sesión.', }, smsDeliveryFailurePage: { - smsDeliveryFailureMessage: ({login}: OurEmailProviderParams) => `No hemos podido entregar mensajes SMS a ${login}, por lo que lo hemos suspendido durante 24 horas.`, + smsDeliveryFailureMessage: ({login}: OurEmailProviderParams) => + `No hemos podido entregar mensajes SMS a ${login}, así que lo hemos suspendido durante 24 horas. Por favor, intenta validar tu número:`, + validationFailed: 'La validación falló porque no han pasado 24 horas desde tu último intento.', + validationSuccess: '¡Tu número ha sido validado! Haz clic abajo para enviar un nuevo código mágico de inicio de sesión.', }, welcomeSignUpForm: { join: 'Unirse', diff --git a/src/libs/API/parameters/ResetSMSDeliveryFailureParams.ts b/src/libs/API/parameters/ResetSMSDeliveryFailureParams.ts new file mode 100644 index 000000000000..f9a0bf41a218 --- /dev/null +++ b/src/libs/API/parameters/ResetSMSDeliveryFailureParams.ts @@ -0,0 +1,5 @@ +type ResetSMSDeliveryFailureParams = { + login: string; +}; + +export default ResetSMSDeliveryFailureParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 8e743777bdea..31844b69e5d4 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -356,3 +356,4 @@ export type {default as JoinAccessiblePolicyParams} from './JoinAccessiblePolicy export type {default as ImportPerDiemRatesParams} from './ImportPerDiemRatesParams'; export type {default as ExportPerDiemCSVParams} from './ExportPerDiemCSVParams'; export type {default as DismissProductTrainingParams} from './DismissProductTraining'; +export type {default as ResetSMSDeliveryFailureParams} from './ResetSMSDeliveryFailureParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 47c19c158ff6..87dec9525bc8 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -441,6 +441,7 @@ const WRITE_COMMANDS = { UPDATE_INVOICE_COMPANY_WEBSITE: 'UpdateInvoiceCompanyWebsite', VALIDATE_USER_AND_GET_ACCESSIBLE_POLICIES: 'ValidateUserAndGetAccessiblePolicies', DISMISS_PRODUCT_TRAINING: 'DismissProductTraining', + RESET_SMS_DELIVERY_FAILURE: 'ResetSMSDeliveryFailure', } as const; type WriteCommand = ValueOf; @@ -766,6 +767,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY]: Parameters.UpdateSubscriptionAddNewUsersAutomaticallyParams; [WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams; [WRITE_COMMANDS.REQUEST_TAX_EXEMPTION]: null; + [WRITE_COMMANDS.RESET_SMS_DELIVERY_FAILURE]: Parameters.ResetSMSDeliveryFailureParams; [WRITE_COMMANDS.DELETE_MONEY_REQUEST_ON_SEARCH]: Parameters.DeleteMoneyRequestOnSearchParams; [WRITE_COMMANDS.HOLD_MONEY_REQUEST_ON_SEARCH]: Parameters.HoldMoneyRequestOnSearchParams; diff --git a/src/libs/actions/Session/index.ts b/src/libs/actions/Session/index.ts index 1dbb01b008dd..8685a0363e31 100644 --- a/src/libs/actions/Session/index.ts +++ b/src/libs/actions/Session/index.ts @@ -17,6 +17,7 @@ import type { RequestAccountValidationLinkParams, RequestNewValidateCodeParams, RequestUnlinkValidationLinkParams, + ResetSMSDeliveryFailureParams, SignInUserWithLinkParams, SignUpUserParams, UnlinkLoginParams, @@ -1200,6 +1201,52 @@ function isUserOnPrivateDomain() { return false; } +/** + * To reset SMS delivery failure + */ +function resetSMSDeliveryFailure(login: string) { + const params: ResetSMSDeliveryFailureParams = {login}; + + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + errors: null, + smsDeliveryFailureStatus: { + isLoading: true, + }, + }, + }, + ]; + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + smsDeliveryFailureStatus: { + isLoading: false, + isReset: true, + }, + }, + }, + ]; + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.ACCOUNT, + value: { + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + smsDeliveryFailureStatus: { + isLoading: false, + }, + }, + }, + ]; + + API.write(WRITE_COMMANDS.RESET_SMS_DELIVERY_FAILURE, params, {optimisticData, successData, failureData}); +} + export { beginSignIn, beginAppleSignIn, @@ -1239,4 +1286,5 @@ export { signInAfterTransitionFromOldDot, validateUserAndGetAccessiblePolicies, isUserOnPrivateDomain, + resetSMSDeliveryFailure, }; diff --git a/src/pages/signin/SMSDeliveryFailurePage.tsx b/src/pages/signin/SMSDeliveryFailurePage.tsx index cb9c7674d60e..8361c3614d40 100644 --- a/src/pages/signin/SMSDeliveryFailurePage.tsx +++ b/src/pages/signin/SMSDeliveryFailurePage.tsx @@ -3,10 +3,12 @@ import React, {useEffect, useMemo} from 'react'; import {Keyboard, View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import Button from '@components/Button'; +import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import Text from '@components/Text'; import useKeyboardState from '@hooks/useKeyboardState'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as ErrorUtils from '@libs/ErrorUtils'; import * as Session from '@userActions/Session'; import ONYXKEYS from '@src/ONYXKEYS'; import ChangeExpensifyLoginLink from './ChangeExpensifyLoginLink'; @@ -27,6 +29,11 @@ function SMSDeliveryFailurePage() { }, [credentials?.login]); const SMSDeliveryFailureMessage = account?.smsDeliveryFailureStatus?.message; + const hasSMSDeliveryFailure = account?.smsDeliveryFailureStatus?.hasSMSDeliveryFailure; + const isReset = account?.smsDeliveryFailureStatus?.isReset; + + const errorText = useMemo(() => (account ? ErrorUtils.getLatestErrorMessage(account) : ''), [account]); + const shouldShowError = !!errorText; useEffect(() => { if (!isKeyboardShown) { @@ -35,22 +42,79 @@ function SMSDeliveryFailurePage() { Keyboard.dismiss(); }, [isKeyboardShown]); + if (hasSMSDeliveryFailure && isReset) { + return ( + <> + + + + {translate('smsDeliveryFailurePage.validationFailed')} {SMSDeliveryFailureMessage} + + + + +