diff --git a/src/libs/actions/PaymentMethods.ts b/src/libs/actions/PaymentMethods.ts index 5276f56d59bd..893540e1dfac 100644 --- a/src/libs/actions/PaymentMethods.ts +++ b/src/libs/actions/PaymentMethods.ts @@ -418,7 +418,11 @@ function hasPaymentMethodError(bankList: OnyxEntry, fundList: O return Object.values(combinedPaymentMethods).some((item) => Object.keys(item.errors ?? {}).length); } -type PaymentListKey = typeof ONYXKEYS.BANK_ACCOUNT_LIST | typeof ONYXKEYS.FUND_LIST; +type PaymentListKey = + | typeof ONYXKEYS.BANK_ACCOUNT_LIST + | typeof ONYXKEYS.FUND_LIST + | typeof ONYXKEYS.CARD_LIST + | `${typeof ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${string}_${typeof CONST.EXPENSIFY_CARD.BANK}`; /** * Clears the error for the specified payment item diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index 46f6ded27cbd..23d0b5ab6550 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -36,6 +36,7 @@ import type {Errors} from '@src/types/onyx/OnyxCommon'; import type PaymentMethod from '@src/types/onyx/PaymentMethod'; import type {FilterMethodPaymentType} from '@src/types/onyx/WalletTransfer'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; +import isLoadingOnyxValue from '@src/types/utils/isLoadingOnyxValue'; type PaymentMethodListProps = { /** Type of active/highlighted payment method */ @@ -117,9 +118,15 @@ type PaymentMethodItem = PaymentMethod & { errors?: Errors; iconRight?: React.FC; isMethodActive?: boolean; + cardID?: number; } & BankIcon; -function dismissError(item: PaymentMethod) { +function dismissError(item: PaymentMethodItem) { + if (item.cardID) { + PaymentMethods.clearDeletePaymentMethodError(ONYXKEYS.CARD_LIST, item.cardID); + return; + } + const isBankAccount = item.accountType === CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT; const paymentList = isBankAccount ? ONYXKEYS.BANK_ACCOUNT_LIST : ONYXKEYS.FUND_LIST; const paymentID = isBankAccount ? item.accountData?.bankAccountID ?? '' : item.accountData?.fundID ?? ''; @@ -188,11 +195,14 @@ function PaymentMethodList({ const {isOffline} = useNetwork(); const [isUserValidated] = useOnyx(ONYXKEYS.USER, {selector: (user) => !!user?.validated}); - const [bankAccountList = {}] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); - const [cardList = {}] = useOnyx(ONYXKEYS.CARD_LIST); + const [bankAccountList = {}, bankAccountListResult] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); + const isLoadingBankAccountList = isLoadingOnyxValue(bankAccountListResult); + const [cardList = {}, cardListResult] = useOnyx(ONYXKEYS.CARD_LIST); + const isLoadingCardList = isLoadingOnyxValue(cardListResult); // Temporarily disabled because P2P debit cards are disabled. // const [fundList = {}] = useOnyx(ONYXKEYS.FUND_LIST); - const [isLoadingPaymentMethods = true] = useOnyx(ONYXKEYS.IS_LOADING_PAYMENT_METHODS); + const [isLoadingPaymentMethods = true, isLoadingPaymentMethodsResult] = useOnyx(ONYXKEYS.IS_LOADING_PAYMENT_METHODS); + const isLoadingPaymentMethodsOnyx = isLoadingOnyxValue(isLoadingPaymentMethodsResult); const getDescriptionForPolicyDomainCard = (domainName: string): string => { // A domain name containing a policyID indicates that this is a workspace feed @@ -206,7 +216,7 @@ function PaymentMethodList({ const filteredPaymentMethods = useMemo(() => { if (shouldShowAssignedCards) { - const assignedCards = Object.values(cardList ?? {}) + const assignedCards = Object.values(isLoadingCardList ? {} : cardList ?? {}) // Filter by active cards associated with a domain .filter((card) => !!card.domainName && CONST.EXPENSIFY_CARD.ACTIVE_STATES.includes(card.state ?? 0)); const assignedCardsSorted = lodashSortBy(assignedCards, (card) => !CardUtils.isExpensifyCard(card.cardID)); @@ -255,6 +265,7 @@ function PaymentMethodList({ title: card?.nameValuePairs?.cardTitle || card.bank, description: getDescriptionForPolicyDomainCard(card.domainName), onPress: () => Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARD.getRoute(String(card.cardID))), + cardID: card.cardID, isGroupedCardDomain: !isAdminIssuedVirtualCard, shouldShowRightIcon: true, interactive: true, @@ -275,7 +286,7 @@ function PaymentMethodList({ // const paymentCardList = fundList ?? {}; // const filteredCardList = Object.values(paymentCardList).filter((card) => !!card.accountData?.additionalData?.isP2PDebitCard); const filteredCardList = {}; - let combinedPaymentMethods = PaymentUtils.formatPaymentMethods(bankAccountList ?? {}, filteredCardList, styles); + let combinedPaymentMethods = PaymentUtils.formatPaymentMethods(isLoadingBankAccountList ? {} : bankAccountList ?? {}, filteredCardList, styles); if (filterType !== '') { combinedPaymentMethods = combinedPaymentMethods.filter((paymentMethod) => paymentMethod.accountType === filterType); @@ -313,7 +324,21 @@ function PaymentMethodList({ }; }); return combinedPaymentMethods; - }, [shouldShowAssignedCards, bankAccountList, styles, filterType, isOffline, cardList, actionPaymentMethodType, activePaymentMethodID, StyleUtils, shouldShowRightIcon, onPress]); + }, [ + shouldShowAssignedCards, + bankAccountList, + styles, + filterType, + isOffline, + cardList, + actionPaymentMethodType, + activePaymentMethodID, + StyleUtils, + shouldShowRightIcon, + onPress, + isLoadingBankAccountList, + isLoadingCardList, + ]); /** * Render placeholder when there are no payments methods @@ -418,7 +443,7 @@ function PaymentMethodList({ icon={Expensicons.CreditCard} onPress={onPress} // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - isDisabled={isLoadingPaymentMethods || isFormOffline} + isDisabled={isLoadingPaymentMethods || isFormOffline || isLoadingPaymentMethodsOnyx} style={[styles.mh4, styles.buttonCTA]} key="addPaymentMethodButton" success diff --git a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx index 22761c40da9c..373314df08ac 100644 --- a/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx +++ b/src/pages/settings/Wallet/ReportVirtualCardFraudPage.tsx @@ -1,8 +1,7 @@ import type {StackScreenProps} from '@react-navigation/stack'; import React, {useEffect} from 'react'; import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormAlertWithSubmitButton from '@components/FormAlertWithSubmitButton'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; @@ -18,32 +17,22 @@ import * as Card from '@userActions/Card'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type SCREENS from '@src/SCREENS'; -import type {ReportVirtualCardFraudForm} from '@src/types/form'; -import type {Card as OnyxCard} from '@src/types/onyx'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; -type ReportVirtualCardFraudPageOnyxProps = { - /** Form data propTypes */ - formData: OnyxEntry; - - /** Card list propTypes */ - cardList: OnyxEntry>; -}; - -type ReportVirtualCardFraudPageProps = ReportVirtualCardFraudPageOnyxProps & StackScreenProps; +type ReportVirtualCardFraudPageProps = StackScreenProps; function ReportVirtualCardFraudPage({ route: { params: {cardID = ''}, }, - cardList, - formData, }: ReportVirtualCardFraudPageProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); + const [cardList] = useOnyx(ONYXKEYS.CARD_LIST); + const [formData] = useOnyx(ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD); const virtualCard = cardList?.[cardID]; - const virtualCardError = ErrorUtils.getLatestErrorMessage(virtualCard?.errors ?? {}); + const virtualCardError = ErrorUtils.getLatestErrorMessage(virtualCard); const prevIsLoading = usePrevious(formData?.isLoading); @@ -85,11 +74,4 @@ function ReportVirtualCardFraudPage({ ReportVirtualCardFraudPage.displayName = 'ReportVirtualCardFraudPage'; -export default withOnyx({ - cardList: { - key: ONYXKEYS.CARD_LIST, - }, - formData: { - key: ONYXKEYS.FORMS.REPORT_VIRTUAL_CARD_FRAUD, - }, -})(ReportVirtualCardFraudPage); +export default ReportVirtualCardFraudPage; diff --git a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx index 25de151bbb6d..ef38cb509e78 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceExpensifyCardListPage.tsx @@ -16,8 +16,10 @@ import usePolicy from '@hooks/usePolicy'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import * as CardUtils from '@libs/CardUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {FullScreenNavigatorParamList} from '@navigation/types'; +import * as PaymentMethods from '@userActions/PaymentMethods'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -44,6 +46,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList}: WorkspaceExpensifyCa const policyID = route.params.policyID; const policy = usePolicy(policyID); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST); + const workspaceAccountID = PolicyUtils.getWorkspaceAccountID(policyID); const policyCurrency = useMemo(() => policy?.outputCurrency ?? CONST.CURRENCY.USD, [policy]); @@ -79,6 +82,7 @@ function WorkspaceExpensifyCardListPage({route, cardsList}: WorkspaceExpensifyCa pendingAction={item.pendingAction} errorRowStyles={styles.ph5} errors={item.errors} + onClose={() => PaymentMethods.clearDeletePaymentMethodError(`${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${workspaceAccountID}_${CONST.EXPENSIFY_CARD.BANK}`, item.cardID)} > ), - [personalDetails, policyCurrency, policyID, styles], + [personalDetails, policyCurrency, policyID, workspaceAccountID, styles], ); const renderListHeader = useCallback(() => , [policyID]);