diff --git a/src/pages/settings/Subscription/CardSection/BillingBanner/BillingBanner.tsx b/src/pages/settings/Subscription/CardSection/BillingBanner/BillingBanner.tsx
index 059aede65634..bbb06dac4549 100644
--- a/src/pages/settings/Subscription/CardSection/BillingBanner/BillingBanner.tsx
+++ b/src/pages/settings/Subscription/CardSection/BillingBanner/BillingBanner.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, {useMemo} from 'react';
import type {StyleProp, TextStyle, ViewStyle} from 'react-native';
import {View} from 'react-native';
import type {ValueOf} from 'type-fest';
@@ -48,30 +48,37 @@ function BillingBanner({title, subtitle, icon, brickRoadIndicator, style, titleS
const styles = useThemeStyles();
const theme = useTheme();
- const rightIconComponent = () => {
- if (!rightIcon) {
- return null;
- }
-
- return onRightIconPress && rightIconAccessibilityLabel ? (
-
+ const rightIconComponent = useMemo(() => {
+ if (rightIcon) {
+ return onRightIconPress && rightIconAccessibilityLabel ? (
+
+
+
+ ) : (
-
- ) : (
-
+ );
+ }
+
+ return (
+ !!brickRoadIndicator && (
+
+ )
);
- };
+ }, [brickRoadIndicator, onRightIconPress, rightIcon, rightIconAccessibilityLabel, styles.touchableButtonImage, theme.danger, theme.icon, theme.success]);
return (
@@ -85,14 +92,7 @@ function BillingBanner({title, subtitle, icon, brickRoadIndicator, style, titleS
{typeof title === 'string' ? {title} : title}
{typeof subtitle === 'string' ? {subtitle} : subtitle}
- {rightIcon
- ? rightIconComponent()
- : !!brickRoadIndicator && (
-
- )}
+ {rightIconComponent}
);
}
diff --git a/src/pages/settings/Subscription/CardSection/CardSection.tsx b/src/pages/settings/Subscription/CardSection/CardSection.tsx
index 05a3841444fd..b5225b14437a 100644
--- a/src/pages/settings/Subscription/CardSection/CardSection.tsx
+++ b/src/pages/settings/Subscription/CardSection/CardSection.tsx
@@ -40,27 +40,15 @@ function CardSection() {
const cardMonth = useMemo(() => DateUtils.getMonthNames(preferredLocale)[(defaultCard?.accountData?.cardMonth ?? 1) - 1], [defaultCard?.accountData?.cardMonth, preferredLocale]);
- const [billingStatus, setBillingStatus] = useState(
- CardSectionUtils.getBillingStatus(translate, defaultCard?.accountData?.cardNumber ?? '', defaultCard?.accountData?.cardMonth ?? 0, defaultCard?.accountData?.cardYear ?? 0),
- );
+ const [billingStatus, setBillingStatus] = useState(CardSectionUtils.getBillingStatus(translate, defaultCard?.accountData ?? {}));
const nextPaymentDate = !isEmptyObject(privateSubscription) ? CardSectionUtils.getNextBillingDate() : undefined;
const sectionSubtitle = defaultCard && !!nextPaymentDate ? translate('subscription.cardSection.cardNextPayment', {nextPaymentDate}) : translate('subscription.cardSection.subtitle');
useEffect(() => {
- setBillingStatus(
- CardSectionUtils.getBillingStatus(translate, defaultCard?.accountData?.cardNumber ?? '', defaultCard?.accountData?.cardMonth ?? 0, defaultCard?.accountData?.cardYear ?? 0),
- );
- }, [
- subscriptionRetryBillingStatusPending,
- subscriptionRetryBillingStatusSuccessful,
- subscriptionRetryBillingStatusFailed,
- translate,
- defaultCard?.accountData?.cardNumber,
- defaultCard?.accountData?.cardMonth,
- defaultCard?.accountData?.cardYear,
- ]);
+ setBillingStatus(CardSectionUtils.getBillingStatus(translate, defaultCard?.accountData ?? {}));
+ }, [subscriptionRetryBillingStatusPending, subscriptionRetryBillingStatusSuccessful, subscriptionRetryBillingStatusFailed, translate, defaultCard?.accountData]);
const handleRetryPayment = () => {
Subscription.clearOutstandingBalance();
diff --git a/src/pages/settings/Subscription/CardSection/utils.ts b/src/pages/settings/Subscription/CardSection/utils.ts
index 970496ae4a6f..9a797d98e025 100644
--- a/src/pages/settings/Subscription/CardSection/utils.ts
+++ b/src/pages/settings/Subscription/CardSection/utils.ts
@@ -6,6 +6,7 @@ import type {Phrase, PhraseParameters} from '@libs/Localize';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import CONST from '@src/CONST';
import type {TranslationPaths} from '@src/languages/types';
+import type {AccountData} from '@src/types/onyx/Fund';
import type IconAsset from '@src/types/utils/IconAsset';
type BillingStatusResult = {
@@ -21,10 +22,10 @@ type BillingStatusResult = {
function getBillingStatus(
translate: (phraseKey: TKey, ...phraseParameters: PhraseParameters>) => string,
- cardEnding: string,
- cardMonth: number,
- cardYear: number,
+ accountData?: AccountData,
): BillingStatusResult | undefined {
+ const cardEnding = accountData?.cardNumber ?? '';
+
const amountOwed = SubscriptionUtils.getAmountOwed();
const subscriptionStatus = SubscriptionUtils.getSubscriptionStatus();
@@ -33,7 +34,7 @@ function getBillingStatus(
const endDateFormatted = endDate ? DateUtils.formatWithUTCTimeZone(fromUnixTime(endDate).toUTCString(), CONST.DATE.MONTH_DAY_YEAR_FORMAT) : null;
- const isCurrentCardExpired = DateUtils.isCardExpired(cardMonth, cardYear);
+ const isCurrentCardExpired = DateUtils.isCardExpired(accountData?.cardMonth ?? 0, accountData?.cardYear ?? 0);
switch (subscriptionStatus?.status) {
case SubscriptionUtils.PAYMENT_STATUS.POLICY_OWNER_WITH_AMOUNT_OWED:
diff --git a/tests/unit/CardsSectionUtilsTest.ts b/tests/unit/CardsSectionUtilsTest.ts
index 9318bced5fda..ca13045c96f7 100644
--- a/tests/unit/CardsSectionUtilsTest.ts
+++ b/tests/unit/CardsSectionUtilsTest.ts
@@ -12,11 +12,14 @@ function translateMock(key: TKey, ...phraseParame
return key;
}
-const CARD_ENDING = '1234';
const AMOUNT_OWED = 100;
const GRACE_PERIOD_DATE = 1750819200;
-const CARD_MONTH = 12;
-const CARD_YEAR = 2024;
+
+const ACCOUNT_DATA = {
+ cardNumber: '1234',
+ cardMonth: 12,
+ cardYear: 2024,
+};
const mockGetSubscriptionStatus = jest.fn();
@@ -81,7 +84,7 @@ describe('CardSectionUtils', () => {
});
it('should return undefined by default', () => {
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toBeUndefined();
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toBeUndefined();
});
it('should return POLICY_OWNER_WITH_AMOUNT_OWED variant', () => {
@@ -89,7 +92,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.POLICY_OWNER_WITH_AMOUNT_OWED,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.policyOwnerAmountOwed.title',
subtitle: 'subscription.billingBanner.policyOwnerAmountOwed.subtitle',
isError: true,
@@ -102,7 +105,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.POLICY_OWNER_WITH_AMOUNT_OWED_OVERDUE,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.policyOwnerAmountOwedOverdue.title',
subtitle: 'subscription.billingBanner.policyOwnerAmountOwedOverdue.subtitle',
isError: true,
@@ -114,7 +117,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.OWNER_OF_POLICY_UNDER_INVOICING,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.policyOwnerUnderInvoicing.title',
subtitle: 'subscription.billingBanner.policyOwnerUnderInvoicing.subtitle',
isError: true,
@@ -127,7 +130,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.OWNER_OF_POLICY_UNDER_INVOICING_OVERDUE,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.policyOwnerUnderInvoicingOverdue.title',
subtitle: 'subscription.billingBanner.policyOwnerUnderInvoicingOverdue.subtitle',
isError: true,
@@ -140,7 +143,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.BILLING_DISPUTE_PENDING,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.billingDisputePending.title',
subtitle: 'subscription.billingBanner.billingDisputePending.subtitle',
isError: true,
@@ -153,7 +156,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.CARD_AUTHENTICATION_REQUIRED,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.cardAuthenticationRequired.title',
subtitle: 'subscription.billingBanner.cardAuthenticationRequired.subtitle',
isError: true,
@@ -166,7 +169,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.INSUFFICIENT_FUNDS,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.insufficientFunds.title',
subtitle: 'subscription.billingBanner.insufficientFunds.subtitle',
isError: true,
@@ -179,14 +182,14 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.CARD_EXPIRED,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR - 1)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, {...ACCOUNT_DATA, cardYear: 2023})).toEqual({
title: 'subscription.billingBanner.cardExpired.title',
subtitle: 'subscription.billingBanner.cardExpired.subtitle',
isError: true,
isRetryAvailable: false,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.cardExpired.title',
subtitle: 'subscription.billingBanner.cardExpired.subtitle',
isError: true,
@@ -199,7 +202,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.CARD_EXPIRE_SOON,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.cardExpireSoon.title',
subtitle: 'subscription.billingBanner.cardExpireSoon.subtitle',
isError: false,
@@ -212,7 +215,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.RETRY_BILLING_SUCCESS,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.retryBillingSuccess.title',
subtitle: 'subscription.billingBanner.retryBillingSuccess.subtitle',
isError: false,
@@ -225,7 +228,7 @@ describe('CardSectionUtils', () => {
status: PAYMENT_STATUS.RETRY_BILLING_ERROR,
});
- expect(CardSectionUtils.getBillingStatus(translateMock, CARD_ENDING, CARD_MONTH, CARD_YEAR)).toEqual({
+ expect(CardSectionUtils.getBillingStatus(translateMock, ACCOUNT_DATA)).toEqual({
title: 'subscription.billingBanner.retryBillingError.title',
subtitle: 'subscription.billingBanner.retryBillingError.subtitle',
isError: true,