diff --git a/assets/images/magnifying-glass-spy-mouth-closed.svg b/assets/images/magnifying-glass-spy-mouth-closed.svg
new file mode 100644
index 000000000000..d5b46a70270f
--- /dev/null
+++ b/assets/images/magnifying-glass-spy-mouth-closed.svg
@@ -0,0 +1,156 @@
+
diff --git a/src/ROUTES.ts b/src/ROUTES.ts
index aa6e54f82dd3..17dec932aae8 100644
--- a/src/ROUTES.ts
+++ b/src/ROUTES.ts
@@ -180,6 +180,10 @@ const ROUTES = {
route: 'settings/wallet/card/:cardID/report-virtual-fraud',
getRoute: (cardID: string) => `settings/wallet/card/${cardID}/report-virtual-fraud` as const,
},
+ SETTINGS_REPORT_FRAUD_CONFIRMATION: {
+ route: 'settings/wallet/card/:cardID/report-virtual-fraud-confirm',
+ getRoute: (cardID: string) => `settings/wallet/card/${cardID}/report-virtual-fraud-confirm` as const,
+ },
SETTINGS_DOMAINCARD_REPORT_FRAUD: {
route: 'settings/card/:cardID/report-virtual-fraud',
getRoute: (cardID: string) => `settings/card/${cardID}/report-virtual-fraud` as const,
diff --git a/src/SCREENS.ts b/src/SCREENS.ts
index 76456485a3a4..7449cfe179b7 100644
--- a/src/SCREENS.ts
+++ b/src/SCREENS.ts
@@ -120,6 +120,7 @@ const SCREENS = {
ENABLE_PAYMENTS: 'Settings_Wallet_EnablePayments',
CARD_ACTIVATE: 'Settings_Wallet_Card_Activate',
REPORT_VIRTUAL_CARD_FRAUD: 'Settings_Wallet_ReportVirtualCardFraud',
+ REPORT_VIRTUAL_CARD_FRAUD_CONFIRMATION: 'Settings_Wallet_ReportVirtualCardFraudConfirmation',
CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS: 'Settings_Wallet_Cards_Digital_Details_Update_Address',
VERIFY_ACCOUNT: 'Settings_Wallet_Verify_Account',
},
diff --git a/src/components/Icon/Expensicons.ts b/src/components/Icon/Expensicons.ts
index e4072504f3d6..5cfa87d472da 100644
--- a/src/components/Icon/Expensicons.ts
+++ b/src/components/Icon/Expensicons.ts
@@ -128,6 +128,7 @@ import Link from '@assets/images/link.svg';
import Location from '@assets/images/location.svg';
import Lock from '@assets/images/lock.svg';
import Luggage from '@assets/images/luggage.svg';
+import MagnifyingGlassSpyMouthClosed from '@assets/images/magnifying-glass-spy-mouth-closed.svg';
import MagnifyingGlass from '@assets/images/magnifying-glass.svg';
import Mail from '@assets/images/mail.svg';
import MakeAdmin from '@assets/images/make-admin.svg';
@@ -422,4 +423,5 @@ export {
GalleryNotFound,
Train,
boltSlash,
+ MagnifyingGlassSpyMouthClosed,
};
diff --git a/src/languages/en.ts b/src/languages/en.ts
index 3b55d6fbc75c..2c20159def2b 100755
--- a/src/languages/en.ts
+++ b/src/languages/en.ts
@@ -1614,6 +1614,11 @@ const translations = {
deactivateCard: 'Deactivate card',
reportVirtualCardFraud: 'Report virtual card fraud',
},
+ reportFraudConfirmationPage: {
+ title: 'Card fraud reported',
+ description: 'We’ve permanently deactivated your existing card. When you go back to view your card details, you’ll have a new virtual card available.',
+ buttonText: 'Got it, thanks!',
+ },
activateCardPage: {
activateCard: 'Activate card',
pleaseEnterLastFour: 'Please enter the last four digits of your card.',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index dff3dcd575c0..4ebad5946e00 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -1616,6 +1616,11 @@ const translations = {
deactivateCard: 'Desactivar tarjeta',
reportVirtualCardFraud: 'Reportar fraude con la tarjeta virtual',
},
+ reportFraudConfirmationPage: {
+ title: 'Fraude con tarjeta reportado',
+ description: 'Hemos desactivado permanentemente tu tarjeta existente. Cuando vuelvas a ver los detalles de tu tarjeta, tendrás una nueva tarjeta virtual disponible.',
+ buttonText: 'Entendido, ¡gracias!',
+ },
activateCardPage: {
activateCard: 'Activar tarjeta',
pleaseEnterLastFour: 'Introduce los cuatro últimos dígitos de la tarjeta.',
diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
index 1e5e5027dc4f..dc68820a7348 100644
--- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
+++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx
@@ -248,6 +248,7 @@ const SettingsModalStackNavigator = createModalStackNavigator require('../../../../pages/settings/Profile/PersonalDetails/PersonalAddressPage').default,
[SCREENS.SETTINGS.WALLET.DOMAIN_CARD]: () => require('../../../../pages/settings/Wallet/ExpensifyCardPage').default,
[SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD]: () => require('../../../../pages/settings/Wallet/ReportVirtualCardFraudPage').default,
+ [SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD_CONFIRMATION]: () => require('../../../../pages/settings/Wallet/ReportVirtualCardFraudConfirmationPage').default,
[SCREENS.SETTINGS.WALLET.CARD_ACTIVATE]: () => require('../../../../pages/settings/Wallet/ActivatePhysicalCardPage').default,
[SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.NAME]: () => require('../../../../pages/settings/Wallet/Card/GetPhysicalCardName').default,
[SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.PHONE]: () => require('../../../../pages/settings/Wallet/Card/GetPhysicalCardPhone').default,
diff --git a/src/libs/Navigation/linkingConfig/config.ts b/src/libs/Navigation/linkingConfig/config.ts
index 9b7061e09ccc..35612b27de22 100644
--- a/src/libs/Navigation/linkingConfig/config.ts
+++ b/src/libs/Navigation/linkingConfig/config.ts
@@ -208,6 +208,10 @@ const config: LinkingOptions['config'] = {
path: ROUTES.SETTINGS_REPORT_FRAUD.route,
exact: true,
},
+ [SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD_CONFIRMATION]: {
+ path: ROUTES.SETTINGS_REPORT_FRAUD_CONFIRMATION.route,
+ exact: true,
+ },
[SCREENS.SETTINGS.WALLET.CARD_GET_PHYSICAL.NAME]: {
path: ROUTES.SETTINGS_WALLET_CARD_GET_PHYSICAL_NAME.route,
exact: true,
diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts
index 1de3e11f08e4..2165eb019fda 100644
--- a/src/libs/Navigation/types.ts
+++ b/src/libs/Navigation/types.ts
@@ -140,6 +140,10 @@ type SettingsNavigatorParamList = {
/** cardID of selected card */
cardID: string;
};
+ [SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD_CONFIRMATION]: {
+ /** cardID of selected card */
+ cardID: string;
+ };
[SCREENS.SETTINGS.WALLET.CARD_ACTIVATE]: {
/** cardID of selected card */
cardID: string;
diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts
index 17943440c1f1..8c784029e3ca 100644
--- a/src/libs/actions/Card.ts
+++ b/src/libs/actions/Card.ts
@@ -47,6 +47,7 @@ function reportVirtualExpensifyCardFraud(card: Card, validateCode: string) {
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD,
value: {
+ cardID,
isLoading: true,
errors: null,
},
@@ -225,6 +226,10 @@ function clearCardListErrors(cardID: number) {
Onyx.merge(ONYXKEYS.CARD_LIST, {[cardID]: {errors: null, isLoading: false}});
}
+function clearReportVirtualCardFraudForm() {
+ Onyx.merge(ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, {cardID: null, isLoading: false, errors: null});
+}
+
/**
* Makes an API call to get virtual card details (pan, cvv, expiration date, address)
* This function purposefully uses `makeRequestWithSideEffects` method. For security reason
@@ -896,6 +901,7 @@ export {
requestReplacementExpensifyCard,
activatePhysicalExpensifyCard,
clearCardListErrors,
+ clearReportVirtualCardFraudForm,
clearIssueNewCardError,
reportVirtualExpensifyCardFraud,
revealVirtualCardDetails,
diff --git a/src/pages/settings/Wallet/ExpensifyCardPage.tsx b/src/pages/settings/Wallet/ExpensifyCardPage.tsx
index 32ec1d0f2439..710e3e37b493 100644
--- a/src/pages/settings/Wallet/ExpensifyCardPage.tsx
+++ b/src/pages/settings/Wallet/ExpensifyCardPage.tsx
@@ -162,7 +162,7 @@ function ExpensifyCardPage({
Navigation.goBack()}
+ onBackButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_WALLET)}
/>
diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudConfirmationPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudConfirmationPage.tsx
new file mode 100644
index 000000000000..6108e50b014d
--- /dev/null
+++ b/src/pages/settings/Wallet/ReportVirtualCardFraudConfirmationPage.tsx
@@ -0,0 +1,74 @@
+import React, {useCallback} from 'react';
+import {View} from 'react-native';
+import Button from '@components/Button';
+import HeaderWithBackButton from '@components/HeaderWithBackButton';
+import * as Expensicons from '@components/Icon/Expensicons';
+import ImageSVG from '@components/ImageSVG';
+import ScreenWrapper from '@components/ScreenWrapper';
+import Text from '@components/Text';
+import useLocalize from '@hooks/useLocalize';
+import useThemeStyles from '@hooks/useThemeStyles';
+import Navigation from '@navigation/Navigation';
+import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation/types';
+import type {SettingsNavigatorParamList} from '@navigation/types';
+import ROUTES from '@src/ROUTES';
+import type SCREENS from '@src/SCREENS';
+
+type ReportVirtualCardFraudConfirmationPageProps = PlatformStackScreenProps;
+
+function ReportVirtualCardFraudConfirmationPage({
+ route: {
+ params: {cardID = ''},
+ },
+}: ReportVirtualCardFraudConfirmationPageProps) {
+ const themeStyles = useThemeStyles();
+ const {translate} = useLocalize();
+
+ const close = useCallback(() => {
+ Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(cardID));
+ }, [cardID]);
+
+ return (
+
+
+
+
+
+
+
+ {translate('reportFraudConfirmationPage.title')}
+
+ {translate('reportFraudConfirmationPage.description')}
+
+
+
+
+
+
+ );
+}
+
+ReportVirtualCardFraudConfirmationPage.displayName = 'ReportVirtualCardFraudConfirmationPage';
+
+export default ReportVirtualCardFraudConfirmationPage;
diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx
index c3b712710f03..a8d8e2dc419f 100644
--- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx
+++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx
@@ -16,7 +16,7 @@ import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import type {SettingsNavigatorParamList} from '@libs/Navigation/types';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
-import {clearCardListErrors, reportVirtualExpensifyCardFraud} from '@userActions/Card';
+import {clearCardListErrors, clearReportVirtualCardFraudForm, reportVirtualExpensifyCardFraud} from '@userActions/Card';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type SCREENS from '@src/SCREENS';
@@ -42,7 +42,6 @@ function ReportVirtualCardFraudPage({
const latestIssuedVirtualCardID = Object.keys(cardList ?? {})?.pop();
const virtualCardError = getLatestErrorMessage(virtualCard);
const validateError = getLatestErrorMessageField(virtualCard);
- const prevVirtualCard = usePrevious(virtualCard);
const [isValidateCodeActionModalVisible, setIsValidateCodeActionModalVisible] = useState(false);
@@ -50,6 +49,10 @@ function ReportVirtualCardFraudPage({
useBeforeRemove(() => setIsValidateCodeActionModalVisible(false));
+ useEffect(() => {
+ clearReportVirtualCardFraudForm();
+ }, []);
+
useEffect(() => {
if (!prevIsLoading || formData?.isLoading) {
return;
@@ -59,17 +62,18 @@ function ReportVirtualCardFraudPage({
}
if (latestIssuedVirtualCardID) {
- Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(latestIssuedVirtualCardID));
+ Navigation.navigate(ROUTES.SETTINGS_REPORT_FRAUD_CONFIRMATION.getRoute(latestIssuedVirtualCardID));
+ setIsValidateCodeActionModalVisible(false);
}
- }, [cardID, formData?.isLoading, prevIsLoading, virtualCard?.errors, latestIssuedVirtualCardID]);
+ }, [formData?.isLoading, latestIssuedVirtualCardID, prevIsLoading, virtualCard?.errors]);
const handleValidateCodeEntered = useCallback(
(validateCode: string) => {
if (!virtualCard) {
return;
}
+
reportVirtualExpensifyCardFraud(virtualCard, validateCode);
- setIsValidateCodeActionModalVisible(false);
},
[virtualCard],
);
@@ -86,7 +90,7 @@ function ReportVirtualCardFraudPage({
setIsValidateCodeActionModalVisible(true);
}, [setIsValidateCodeActionModalVisible]);
- if (isEmptyObject(virtualCard) && isEmptyObject(prevVirtualCard)) {
+ if (isEmptyObject(virtualCard) && !formData?.cardID) {
return ;
}
@@ -102,7 +106,6 @@ function ReportVirtualCardFraudPage({
isAlertVisible={!!virtualCardError}
onSubmit={handleSubmit}
message={virtualCardError}
- isLoading={formData?.isLoading}
buttonText={translate('reportFraudPage.deactivateCard')}
containerStyles={[styles.m5]}
/>
@@ -121,6 +124,7 @@ function ReportVirtualCardFraudPage({
title={translate('cardPage.validateCardTitle')}
descriptionPrimary={translate('cardPage.enterMagicCode', {contactMethod: primaryLogin})}
hasMagicCodeBeenSent={!!loginData?.validateCodeSent}
+ isLoading={formData?.isLoading}
/>