diff --git a/src/languages/en.ts b/src/languages/en.ts index 1889c9095d2a..aeda0dea475b 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2803,6 +2803,7 @@ const translations = { cardStatus: { active: 'Active', inactive: 'Inactive', + pending: 'Pending', fixConnection: 'Please fix this connection', fixConnectionIn: (companyCardsRoute: string) => `Please fix this connection in company cards`, askAdminToFixConnection: 'Please ask an admin to fix this connection', diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index e165989b3e12..7377cfcfed2b 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -136,6 +136,7 @@ type CardConnectionStatusDisplayParams = { isCardBroken: boolean; shouldShowRBR: boolean; isCardInactive: boolean; + isCardPending: boolean; isExpensifyCard: boolean; isPersonalCard: boolean; isAdminForCardPolicy: boolean; @@ -1439,6 +1440,7 @@ function getCardConnectionStatusDisplay({ isCardBroken, shouldShowRBR, isCardInactive: isCardInactiveStatus, + isCardPending: isCardPendingStatus, isExpensifyCard: isExpensifyCardStatus, isPersonalCard: isPersonalCardStatus, isAdminForCardPolicy, @@ -1454,10 +1456,14 @@ function getCardConnectionStatusDisplay({ // is right for it in any state. It still reports its status so the row keeps the background, hover and press // styling every other row in the list gets, which hangs off the status being present rather than the message. if (isExpensifyCardStatus) { - return { - statusKey: isCardInactiveStatus ? 'walletPage.cardStatus.inactive' : 'walletPage.cardStatus.active', - statusTone: isCardInactiveStatus ? 'default' : 'success', - }; + if (isCardInactiveStatus) { + return {statusKey: 'walletPage.cardStatus.inactive', statusTone: 'default'}; + } + // A card waiting to be issued or activated cannot be spent on yet, so it reads neither active nor inactive. + if (isCardPendingStatus) { + return {statusKey: 'walletPage.cardStatus.pending', statusTone: 'default'}; + } + return {statusKey: 'walletPage.cardStatus.active', statusTone: 'success'}; } const shouldShowMessage = isCardBroken || shouldShowRBR || isCardInactiveStatus; diff --git a/src/pages/settings/Wallet/PaymentMethodList.tsx b/src/pages/settings/Wallet/PaymentMethodList.tsx index 60ebd41d123f..eeda43b71125 100644 --- a/src/pages/settings/Wallet/PaymentMethodList.tsx +++ b/src/pages/settings/Wallet/PaymentMethodList.tsx @@ -28,6 +28,8 @@ import { doesCardConnectionNeedReauthentication, isCardFrozen, isCardInactive, + isCardPendingActivate, + isCardPendingIssue, isExpensifyCard, isExpensifyCardPendingAction, isExpiredCard, @@ -317,6 +319,7 @@ function PaymentMethodList({ isCardBroken, shouldShowRBR, isCardInactive: isCardInactiveState, + isCardPending: isCardPendingIssue(card) || isCardPendingActivate(card), isExpensifyCard: isUserExpensifyCard, isPersonalCard: isUserPersonalCard, isAdminForCardPolicy, diff --git a/tests/unit/CardUtilsTest.ts b/tests/unit/CardUtilsTest.ts index 8b36482771b6..ea6f0e20690e 100644 --- a/tests/unit/CardUtilsTest.ts +++ b/tests/unit/CardUtilsTest.ts @@ -4845,6 +4845,7 @@ describe('getCardConnectionStatusDisplay', () => { isCardBroken: false, shouldShowRBR: false, isCardInactive: false, + isCardPending: false, isExpensifyCard: false, isPersonalCard: false, isAdminForCardPolicy: false, @@ -4930,6 +4931,29 @@ describe('getCardConnectionStatusDisplay', () => { }); }); + // A card waiting to be issued or activated is not spendable yet, so it reads neither Active nor Inactive. + it('reports a pending status for an Expensify Card waiting to be issued or activated', () => { + expect(getCardConnectionStatusDisplay({...defaultParams, isExpensifyCard: true, isCardPending: true})).toEqual({ + statusKey: 'walletPage.cardStatus.pending', + statusTone: 'default', + }); + }); + + // Suspended outranks pending, so a card the back end turned off never reads as merely waiting. + it('keeps an inactive Expensify Card inactive even while it is pending', () => { + expect(getCardConnectionStatusDisplay({...defaultParams, isExpensifyCard: true, isCardPending: true, isCardInactive: true})).toEqual({ + statusKey: 'walletPage.cardStatus.inactive', + statusTone: 'default', + }); + }); + + it('leaves a non-pending Expensify Card active', () => { + expect(getCardConnectionStatusDisplay({...defaultParams, isExpensifyCard: true})).toEqual({ + statusKey: 'walletPage.cardStatus.active', + statusTone: 'success', + }); + }); + it('does not show a company-cards link without a policy ID', () => { expect(getCardConnectionStatusDisplay({...defaultParams, shouldShowRBR: true, isAdminForCardPolicy: true})).toEqual({ statusKey: 'walletPage.cardStatus.inactive',