From 813811071e0b874b462318bbea3a7847f6c5f945 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 15 Apr 2026 14:44:57 +0530 Subject: [PATCH 01/19] Add shouldApplyCashbackToBill field to ExpensifyCardSettingsBase type --- src/types/onyx/ExpensifyCardSettings.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/types/onyx/ExpensifyCardSettings.ts b/src/types/onyx/ExpensifyCardSettings.ts index b0bfd831b08a..bfd03987e5ee 100644 --- a/src/types/onyx/ExpensifyCardSettings.ts +++ b/src/types/onyx/ExpensifyCardSettings.ts @@ -61,6 +61,9 @@ type ExpensifyCardSettingsBase = { /** Number of the bank account used for the card settlement */ paymentBankAccountNumber?: string; + /** Whether Expensify Card cash back should be applied toward payment of the Expensify bill */ + shouldApplyCashbackToBill?: boolean; + /** Collections of form field errors */ errorFields?: OnyxCommon.ErrorFields; From 8648e3bc4a7a3feae5e92765887ab489be91a75f Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 15 Apr 2026 14:45:41 +0530 Subject: [PATCH 02/19] Create ToggleCardCashbackToBillParams API parameter type --- src/libs/API/parameters/ToggleCardCashbackToBillParams.ts | 6 ++++++ src/libs/API/parameters/index.ts | 1 + 2 files changed, 7 insertions(+) create mode 100644 src/libs/API/parameters/ToggleCardCashbackToBillParams.ts diff --git a/src/libs/API/parameters/ToggleCardCashbackToBillParams.ts b/src/libs/API/parameters/ToggleCardCashbackToBillParams.ts new file mode 100644 index 000000000000..36bc94604d9c --- /dev/null +++ b/src/libs/API/parameters/ToggleCardCashbackToBillParams.ts @@ -0,0 +1,6 @@ +type ToggleCardCashbackToBillParams = { + workspaceAccountID: number; + shouldApplyCashbackToBill: boolean; +}; + +export default ToggleCardCashbackToBillParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index d29a38b437da..d783fcc83f6b 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -368,6 +368,7 @@ export type {default as SetPolicyCategoryTaxParams} from './SetPolicyCategoryTax export type {default as SetPolicyCategoryMaxAmountParams} from './SetPolicyCategoryMaxAmountParams'; export type {default as EnablePolicyCompanyCardsParams} from './EnablePolicyCompanyCardsParams'; export type {default as ToggleCardContinuousReconciliationParams} from './ToggleCardContinuousReconciliationParams'; +export type {default as ToggleCardCashbackToBillParams} from './ToggleCardCashbackToBillParams'; export type {default as CardDeactivateParams} from './CardDeactivateParams'; export type {default as UpdateExpensifyCardLimitTypeParams} from './UpdateExpensifyCardLimitTypeParams'; export type {default as RemoveDelegateParams} from './RemoveDelegateParams'; From 104fabadd81691f293221d937b8333fb55c4badc Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 15 Apr 2026 14:46:19 +0530 Subject: [PATCH 03/19] Register TOGGLE_CARD_CASHBACK_TO_BILL write command --- src/libs/API/types.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 8bd6e60b00a0..f74d4116b8d1 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -478,6 +478,7 @@ const WRITE_COMMANDS = { REMOVE_DELEGATE: 'RemoveDelegate', UPDATE_DELEGATE_ROLE: 'UpdateDelegateRole', TOGGLE_CARD_CONTINUOUS_RECONCILIATION: 'ToggleCardContinuousReconciliation', + TOGGLE_CARD_CASHBACK_TO_BILL: 'ToggleCardCashbackToBill', SET_POLICY_TAG_APPROVER: 'SetPolicyTagApprover', SAVE_SEARCH: 'SaveSearch', DELETE_SAVED_SEARCH: 'DeleteSavedSearch', @@ -1088,6 +1089,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_DELEGATE_ROLE]: Parameters.UpdateDelegateRoleParams; [WRITE_COMMANDS.REMOVE_DELEGATE]: Parameters.RemoveDelegateParams; [WRITE_COMMANDS.TOGGLE_CARD_CONTINUOUS_RECONCILIATION]: Parameters.ToggleCardContinuousReconciliationParams; + [WRITE_COMMANDS.TOGGLE_CARD_CASHBACK_TO_BILL]: Parameters.ToggleCardCashbackToBillParams; [WRITE_COMMANDS.SAVE_SEARCH]: Parameters.SaveSearchParams; [WRITE_COMMANDS.DELETE_SAVED_SEARCH]: Parameters.DeleteSavedSearchParams; [WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY]: Parameters.UpdateCardSettlementFrequencyParams; From 090e40e2fd4a0d717dd2917458bada9187c79cf3 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 15 Apr 2026 14:46:59 +0530 Subject: [PATCH 04/19] Add toggleCashbackToBill action function --- src/libs/actions/Card.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index bb355173f9e2..d6e02cd01292 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -687,6 +687,42 @@ function updateSettlementFrequency( API.write(WRITE_COMMANDS.UPDATE_CARD_SETTLEMENT_FREQUENCY, parameters, {optimisticData, successData, failureData}); } +function toggleCashbackToBill(workspaceAccountID: number, programKey: CardProgramKey, shouldApplyCashbackToBill: boolean, currentValue?: boolean) { + const optimisticValue = {[programKey]: {shouldApplyCashbackToBill}}; + const failureValue = {[programKey]: {shouldApplyCashbackToBill: currentValue ?? true}}; + + const optimisticData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: optimisticValue, + }, + ]; + + const successData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: optimisticValue, + }, + ]; + + const failureData: Array> = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, + value: failureValue, + }, + ]; + + const parameters = { + workspaceAccountID, + shouldApplyCashbackToBill, + }; + + API.write(WRITE_COMMANDS.TOGGLE_CARD_CASHBACK_TO_BILL, parameters, {optimisticData, successData, failureData}); +} + function updateSettlementAccount( domainName: string, workspaceAccountID: number, @@ -1877,6 +1913,7 @@ export { unassignCard, updateAssignedCardName, updateAssignedCardTransactionStartDate, + toggleCashbackToBill, toggleContinuousReconciliation, updateExpensifyCardLimitType, updateSelectedFeed, From fb6801e1715ccbf55531737ea7674ecd1553d9d2 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 15 Apr 2026 14:47:45 +0530 Subject: [PATCH 05/19] Add cashback-to-bill translations for en and es --- src/languages/en.ts | 4 +++- src/languages/es.ts | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 426d4f614115..394dae576354 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5363,7 +5363,9 @@ const translations = { `Make sure this account matches your Reconciliation account (${accountNumber}) so Continuous Reconciliation works properly.`, settlementFrequency: 'Settlement frequency', settlementFrequencyDescription: 'Choose how often you’ll pay your Expensify Card balance.', - settlementFrequencyInfo: 'If you’d like to switch to monthly settlement, you’ll need to connect your bank account via Plaid and have a positive 90-day balance history.', + settlementFrequencyInfo: ‘If you’d like to switch to monthly settlement, you’ll need to connect your bank account via Plaid and have a positive 90-day balance history.’, + applyCashbackToBill: ‘Apply cash back to my Expensify bill’, + applyCashbackToBillDescription: ‘Cash back from the Expensify Card will be used towards payment for your Expensify bill.’, frequency: { daily: 'Daily', monthly: 'Monthly', diff --git a/src/languages/es.ts b/src/languages/es.ts index 502cac18df74..d9809039ebee 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -5209,6 +5209,8 @@ ${amount} para ${merchant} - ${date}`, settlementFrequencyDescription: 'Elige con qué frecuencia pagarás el saldo de tu Tarjeta Expensify', settlementFrequencyInfo: 'Si deseas cambiar a la liquidación mensual, deberás conectar tu cuenta bancaria a través de Plaid y tener un historial de saldo positivo en los últimos 90 días.', + applyCashbackToBill: 'Aplicar reembolso a mi factura de Expensify', + applyCashbackToBillDescription: 'El reembolso de la Tarjeta Expensify se utilizará para el pago de tu factura de Expensify.', frequency: { daily: 'Cada día', monthly: 'Mensual', From 3309561d34105209073b4fd1b33bc2eb48a92bad Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 15 Apr 2026 14:49:29 +0530 Subject: [PATCH 06/19] Add cashback-to-bill toggle to workspace card settings page --- .../WorkspaceCardSettingsPage.tsx | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx index 4c314f971fa8..4eb4a9d0ba3a 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx @@ -9,13 +9,17 @@ import TextLink from '@components/TextLink'; import useDefaultFundID from '@hooks/useDefaultFundID'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import usePrivateSubscription from '@hooks/usePrivateSubscription'; import useThemeStyles from '@hooks/useThemeStyles'; +import {toggleCashbackToBill} from '@libs/actions/Card'; import {getLastFourDigits} from '@libs/BankAccountUtils'; -import {getCardSettings} from '@libs/CardUtils'; +import {getCardProgramKey, getCardSettings} from '@libs/CardUtils'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; +import {isSubscriptionTypeOfInvoicing} from '@libs/SubscriptionUtils'; import Navigation from '@navigation/Navigation'; import type {SettingsNavigatorParamList} from '@navigation/types'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; @@ -32,6 +36,11 @@ function WorkspaceCardSettingsPage({route}: WorkspaceCardSettingsPageProps) { const [bankAccountList] = useOnyx(ONYXKEYS.BANK_ACCOUNT_LIST); const [cardSettings] = useOnyx(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${defaultFundID}`); const settings = getCardSettings(cardSettings); + const programKey = getCardProgramKey(cardSettings); + const privateSubscription = usePrivateSubscription(); + const isUSProgram = programKey === CONST.COUNTRY.US || programKey === CONST.EXPENSIFY_CARD.CARD_PROGRAM.CURRENT; + const shouldShowCashbackToggle = isUSProgram && !isSubscriptionTypeOfInvoicing(privateSubscription?.type); + const shouldApplyCashbackToBill = settings?.shouldApplyCashbackToBill ?? true; const paymentBankAccountID = settings?.paymentBankAccountID; const paymentBankAccountNumber = settings?.paymentBankAccountNumber; @@ -88,6 +97,23 @@ function WorkspaceCardSettingsPage({route}: WorkspaceCardSettingsPageProps) { } /> + {shouldShowCashbackToggle && ( + + { + if (!programKey) { + return; + } + toggleCashbackToBill(defaultFundID, programKey, isEnabled, settings?.shouldApplyCashbackToBill); + }} + /> + + )} From 00dbe0986612ea8f4b29d9417f0fe21901e380a5 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:04:26 +0530 Subject: [PATCH 07/19] Fix curly quote syntax error in en.ts translations --- src/languages/en.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/languages/en.ts b/src/languages/en.ts index 394dae576354..1915a04b3892 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -5363,9 +5363,9 @@ const translations = { `Make sure this account matches your Reconciliation account (${accountNumber}) so Continuous Reconciliation works properly.`, settlementFrequency: 'Settlement frequency', settlementFrequencyDescription: 'Choose how often you’ll pay your Expensify Card balance.', - settlementFrequencyInfo: ‘If you’d like to switch to monthly settlement, you’ll need to connect your bank account via Plaid and have a positive 90-day balance history.’, - applyCashbackToBill: ‘Apply cash back to my Expensify bill’, - applyCashbackToBillDescription: ‘Cash back from the Expensify Card will be used towards payment for your Expensify bill.’, + settlementFrequencyInfo: 'If you’d like to switch to monthly settlement, you’ll need to connect your bank account via Plaid and have a positive 90-day balance history.', + applyCashbackToBill: 'Apply cash back to my Expensify bill', + applyCashbackToBillDescription: 'Cash back from the Expensify Card will be used towards payment for your Expensify bill.', frequency: { daily: 'Daily', monthly: 'Monthly', From 77257800714f33ff1725c87e67e37b1f9a4a37f6 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:08:52 +0530 Subject: [PATCH 08/19] Add pendingFields to toggleCashbackToBill to drive OfflineWithFeedback --- src/libs/actions/Card.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index d6e02cd01292..c1e8f8a40fb1 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -688,8 +688,11 @@ function updateSettlementFrequency( } function toggleCashbackToBill(workspaceAccountID: number, programKey: CardProgramKey, shouldApplyCashbackToBill: boolean, currentValue?: boolean) { - const optimisticValue = {[programKey]: {shouldApplyCashbackToBill}}; - const failureValue = {[programKey]: {shouldApplyCashbackToBill: currentValue ?? true}}; + const optimisticValue = { + [programKey]: {shouldApplyCashbackToBill, pendingFields: {shouldApplyCashbackToBill: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}, + }; + const successValue = {[programKey]: {shouldApplyCashbackToBill, pendingFields: {shouldApplyCashbackToBill: null}}}; + const failureValue = {[programKey]: {shouldApplyCashbackToBill: currentValue ?? true, pendingFields: {shouldApplyCashbackToBill: null}}}; const optimisticData: Array> = [ { @@ -703,7 +706,7 @@ function toggleCashbackToBill(workspaceAccountID: number, programKey: CardProgra { onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, - value: optimisticValue, + value: successValue, }, ]; From 1db74a452d10107dd119280c02cef83a42ec9b36 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:20:39 +0530 Subject: [PATCH 09/19] Add cashback toggle translations for de --- src/languages/de.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/de.ts b/src/languages/de.ts index fa570fad5466..8ae80646ef57 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -5362,6 +5362,8 @@ _Für ausführlichere Anweisungen [besuchen Sie unsere Hilfeseite](${CONST.NETSU settlementFrequencyDescription: 'Wählen Sie, wie oft Sie den Saldo Ihrer Expensify Karte begleichen.', settlementFrequencyInfo: 'Wenn du zur monatlichen Abrechnung wechseln möchtest, musst du dein Bankkonto über Plaid verbinden und eine positive Kontohistorie der letzten 90 Tage haben.', + applyCashbackToBill: 'Cashback auf meine Expensify-Rechnung anwenden', + applyCashbackToBillDescription: 'Das Cashback von der Expensify-Karte wird zur Begleichung deiner Expensify-Rechnung verwendet.', frequency: { daily: 'Täglich', monthly: 'Monatlich', From 7cee7256a4f83a96b5cd90dd2a770bcf9c91d615 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:20:50 +0530 Subject: [PATCH 10/19] Add cashback toggle translations for fr --- src/languages/fr.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/fr.ts b/src/languages/fr.ts index e7ecb7d845d1..7218d97f1caa 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -5371,6 +5371,8 @@ _Pour des instructions plus détaillées, [visitez notre site d’aide](${CONST. settlementFrequencyDescription: 'Choisissez la fréquence à laquelle vous réglerez le solde de votre Carte Expensify.', settlementFrequencyInfo: 'Si vous souhaitez passer à un règlement mensuel, vous devrez connecter votre compte bancaire via Plaid et disposer d’un historique de solde positif sur 90 jours.', + applyCashbackToBill: 'Appliquer le cashback à ma facture Expensify', + applyCashbackToBillDescription: 'Le cashback de la carte Expensify sera utilisé pour le paiement de votre facture Expensify.', frequency: { daily: 'Quotidien', monthly: 'Mensuel', From cd66006f9fc04788834ad7bde9170b9267b9062a Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:21:00 +0530 Subject: [PATCH 11/19] Add cashback toggle translations for it --- src/languages/it.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/it.ts b/src/languages/it.ts index 6637ed2f078c..9d97a8f5cf9f 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -5342,6 +5342,8 @@ _Per istruzioni più dettagliate, [visita il nostro sito di assistenza](${CONST. settlementFrequencyDescription: 'Scegli con quale frequenza pagherai il saldo della tua Carta Expensify.', settlementFrequencyInfo: 'Se desideri passare alla liquidazione mensile, dovrai collegare il tuo conto bancario tramite Plaid e avere uno storico del saldo positivo di 90 giorni.', + applyCashbackToBill: 'Applica il cashback alla mia fattura Expensify', + applyCashbackToBillDescription: 'Il cashback della Carta Expensify verrà utilizzato per il pagamento della tua fattura Expensify.', frequency: { daily: 'Quotidiano', monthly: 'Mensile', From e60af3f469fb19611bc05e670ee80fe194e897e4 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:21:09 +0530 Subject: [PATCH 12/19] Add cashback toggle translations for ja --- src/languages/ja.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 511bf52019b4..8e469dbda765 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -5292,6 +5292,8 @@ _詳しい手順については、[ヘルプサイトをご覧ください](${CO settlementFrequency: '清算頻度', settlementFrequencyDescription: 'Expensify カードの残高を支払う頻度を選択してください。', settlementFrequencyInfo: '月次清算に切り替えるには、Plaid を通じて銀行口座を連携し、直近90日間の残高履歴がプラスである必要があります。', + applyCashbackToBill: 'キャッシュバックを Expensify 請求書に適用する', + applyCashbackToBillDescription: 'Expensify カードのキャッシュバックは、Expensify 請求書の支払いに使用されます。', frequency: { daily: '毎日', monthly: '毎月', From 1198b6d7d69a40ac52533f466820fe432898bb22 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:21:20 +0530 Subject: [PATCH 13/19] Add cashback toggle translations for nl --- src/languages/nl.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 8aea0e642a56..319412ab625a 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -5334,6 +5334,8 @@ _Voor meer gedetailleerde instructies, [bezoek onze help-site](${CONST.NETSUITE_ settlementFrequency: 'Uitbetalingsfrequentie', settlementFrequencyDescription: 'Kies hoe vaak je het saldo van je Expensify Kaart betaalt.', settlementFrequencyInfo: 'Als je wilt overschakelen naar maandelijkse afrekening, moet je je bankrekening koppelen via Plaid en een positieve saldohistorie van 90 dagen hebben.', + applyCashbackToBill: 'Cashback toepassen op mijn Expensify-factuur', + applyCashbackToBillDescription: 'De cashback van de Expensify Kaart wordt gebruikt voor het betalen van je Expensify-factuur.', frequency: { daily: 'Dagelijks', monthly: 'Maandelijks', From 929c840ff750f1d53433579cc2ea3acb2e91b15c Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:21:30 +0530 Subject: [PATCH 14/19] Add cashback toggle translations for pl --- src/languages/pl.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 22c996f2f878..abf8cde59066 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -5322,6 +5322,8 @@ _Aby uzyskać bardziej szczegółowe instrukcje, [odwiedź naszą stronę pomocy settlementFrequency: 'Częstotliwość rozliczeń', settlementFrequencyDescription: 'Wybierz, jak często będziesz spłacać saldo swojej Karty Expensify.', settlementFrequencyInfo: 'Jeśli chcesz przejść na miesięczne rozliczenie, musisz podłączyć swoje konto bankowe przez Plaid i mieć dodatnią historię salda z ostatnich 90 dni.', + applyCashbackToBill: 'Zastosuj zwrot gotówki do mojego rachunku Expensify', + applyCashbackToBillDescription: 'Zwrot gotówki z Karty Expensify zostanie wykorzystany do opłacenia Twojego rachunku Expensify.', frequency: { daily: 'Codziennie', monthly: 'Miesięcznie', From 121c2ae57f7355cb449d7f1a54ecd97794661dce Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:21:41 +0530 Subject: [PATCH 15/19] Add cashback toggle translations for pt-BR --- src/languages/pt-BR.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index aa2bc4d2859e..32c1b0c11204 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -5325,6 +5325,8 @@ _Para instruções mais detalhadas, [visite nossa central de ajuda](${CONST.NETS settlementFrequency: 'Frequência de liquidação', settlementFrequencyDescription: 'Escolha com que frequência você vai pagar o saldo do seu Cartão Expensify.', settlementFrequencyInfo: 'Se quiser mudar para liquidação mensal, você precisará conectar sua conta bancária via Plaid e ter um histórico de saldo positivo de 90 dias.', + applyCashbackToBill: 'Aplicar reembolso à minha fatura do Expensify', + applyCashbackToBillDescription: 'O reembolso do Cartão Expensify será usado para o pagamento da sua fatura do Expensify.', frequency: { daily: 'Diariamente', monthly: 'Mensal', From 2f25c7c6ea0a2bdf391ee9a067a50b01ee3e7734 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 20 Apr 2026 13:22:16 +0530 Subject: [PATCH 16/19] Add cashback toggle translations for zh-hans --- src/languages/zh-hans.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 8889f565419b..dbc6979ca452 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -5201,6 +5201,8 @@ _如需更详细的说明,请[访问我们的帮助网站](${CONST.NETSUITE_IM settlementFrequency: '结算频率', settlementFrequencyDescription: '选择支付 Expensify 卡余额的频率。', settlementFrequencyInfo: '如果你想切换为按月结算,你需要通过 Plaid 连接你的银行账户,并且拥有过去 90 天为正数的余额记录。', + applyCashbackToBill: '将返现用于抵扣我的 Expensify 账单', + applyCashbackToBillDescription: 'Expensify 卡的返现将用于支付你的 Expensify 账单。', frequency: { daily: '每日', monthly: '每月', From 373653b34503340e42851e55b4f039b5fbd5d265 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Wed, 29 Apr 2026 13:17:15 +0530 Subject: [PATCH 17/19] Add error feedback to toggleCashbackToBill failure path --- src/libs/actions/Card.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 322fd282c51d..83f7c43fa6b4 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -691,7 +691,10 @@ function toggleCashbackToBill(workspaceAccountID: number, programKey: CardProgra [programKey]: {shouldApplyCashbackToBill, pendingFields: {shouldApplyCashbackToBill: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}, }; const successValue = {[programKey]: {shouldApplyCashbackToBill, pendingFields: {shouldApplyCashbackToBill: null}}}; - const failureValue = {[programKey]: {shouldApplyCashbackToBill: currentValue ?? true, pendingFields: {shouldApplyCashbackToBill: null}}}; + const failureValue = { + [programKey]: {shouldApplyCashbackToBill: currentValue ?? true, pendingFields: {shouldApplyCashbackToBill: null}}, + errors: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), + }; const optimisticData: Array> = [ { From d301b093a4ed08c40ad89d3a6169ba92507388ac Mon Sep 17 00:00:00 2001 From: allgandaf Date: Mon, 4 May 2026 16:51:18 +0530 Subject: [PATCH 18/19] Use ToggleSettingOptionRow's built-in OfflineWithFeedback for cashback toggle --- src/libs/CardUtils.ts | 9 +++--- .../WorkspaceCardSettingsPage.tsx | 31 ++++++++++--------- src/types/onyx/ExpensifyCardSettings.ts | 13 +++++--- src/types/onyx/index.ts | 3 +- 4 files changed, 31 insertions(+), 25 deletions(-) diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index b1244341d530..f2a708aeed22 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -20,6 +20,7 @@ import type { CurrencyList, ExpensifyCardSettings, ExpensifyCardSettingsBase, + NestedExpensifyCardSettings, PersonalDetailsList, Policy, PolicyConnectionName, @@ -1256,17 +1257,17 @@ function getCardProgramKey(cardSettings: OnyxEntry): Card }); } -function getCardSettings(cardSettings: OnyxEntry, programKey?: CardProgramKey): ExpensifyCardSettingsBase | undefined { +function getCardSettings(cardSettings: OnyxEntry, programKey?: CardProgramKey): NestedExpensifyCardSettings | undefined { if (!cardSettings) { return undefined; } - const getMergedProgramSettings = (key: CardProgramKey): ExpensifyCardSettingsBase | undefined => { + const getMergedProgramSettings = (key: CardProgramKey): NestedExpensifyCardSettings | undefined => { const programSettings = cardSettings[key]; if (programSettings && typeof programSettings === 'object' && !Array.isArray(programSettings)) { // Nested program values take precedence — they are the authoritative source for // program-specific fields (e.g. paymentBankAccountID, monthlySettlementDate). - return {...cardSettings, ...programSettings} as ExpensifyCardSettingsBase; + return {...cardSettings, ...programSettings} as NestedExpensifyCardSettings; } return undefined; }; @@ -1284,7 +1285,7 @@ function getCardSettings(cardSettings: OnyxEntry, program getMergedProgramSettings(CONST.COUNTRY.US) ?? getMergedProgramSettings(CONST.EXPENSIFY_CARD.CARD_PROGRAM.CURRENT) ?? getMergedProgramSettings(CONST.COUNTRY.GB) ?? - (cardSettings as ExpensifyCardSettingsBase) + (cardSettings as NestedExpensifyCardSettings) ); } diff --git a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx index 4eb4a9d0ba3a..f22536dfbc1d 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx @@ -98,21 +98,22 @@ function WorkspaceCardSettingsPage({route}: WorkspaceCardSettingsPageProps) { /> {shouldShowCashbackToggle && ( - - { - if (!programKey) { - return; - } - toggleCashbackToBill(defaultFundID, programKey, isEnabled, settings?.shouldApplyCashbackToBill); - }} - /> - + { + if (!programKey) { + return; + } + toggleCashbackToBill(defaultFundID, programKey, isEnabled, settings?.shouldApplyCashbackToBill); + }} + /> )} diff --git a/src/types/onyx/ExpensifyCardSettings.ts b/src/types/onyx/ExpensifyCardSettings.ts index 2810aa508101..fa1dae8d8d9e 100644 --- a/src/types/onyx/ExpensifyCardSettings.ts +++ b/src/types/onyx/ExpensifyCardSettings.ts @@ -107,21 +107,24 @@ type ExpensifyCardRule = OnyxCommon.OnyxValueWithOfflineFeedback<{ action: ValueOf; }>; +/** Nested program settings with offline feedback support for optimistic updates */ +type NestedExpensifyCardSettings = OnyxCommon.OnyxValueWithOfflineFeedback; + /** Model of Expensify card settings for a workspace - can have nested feed types from backend */ type ExpensifyCardSettings = OnyxCommon.OnyxValueWithOfflineFeedback< ExpensifyCardSettingsBase & { /** Nested Expensify Card settings keyed by feed country from backend */ // eslint-disable-next-line @typescript-eslint/naming-convention - US?: ExpensifyCardSettingsBase; + US?: NestedExpensifyCardSettings; /** Nested settings for pre-2024 US card program from backend */ // eslint-disable-next-line @typescript-eslint/naming-convention - CURRENT?: ExpensifyCardSettingsBase; + CURRENT?: NestedExpensifyCardSettings; /** Nested settings for UK/EU card program from backend */ // eslint-disable-next-line @typescript-eslint/naming-convention - GB?: ExpensifyCardSettingsBase; + GB?: NestedExpensifyCardSettings; /** Nested Travel Invoicing settings from backend */ // eslint-disable-next-line @typescript-eslint/naming-convention - TRAVEL_US?: ExpensifyCardSettingsBase; + TRAVEL_US?: NestedExpensifyCardSettings; /** Spend rules for the feed keyed by rule ID - stringified JSON of ExpensifyCardRule */ cardRules?: Record; @@ -132,4 +135,4 @@ type ExpensifyCardSettings = OnyxCommon.OnyxValueWithOfflineFeedback< >; export default ExpensifyCardSettings; -export type {ExpensifyCardSettingsBase, ExpensifyCardRule, ExpensifyCardRuleFilter}; +export type {ExpensifyCardSettingsBase, NestedExpensifyCardSettings, ExpensifyCardRule, ExpensifyCardRuleFilter}; diff --git a/src/types/onyx/index.ts b/src/types/onyx/index.ts index 9f9f562b7e9c..cd0f68c18a6b 100644 --- a/src/types/onyx/index.ts +++ b/src/types/onyx/index.ts @@ -67,7 +67,7 @@ import type DuplicateWorkspace from './DuplicateWorkspace'; import type ExpenseRule from './ExpenseRule'; import type ExpensifyCardBankAccountMetadata from './ExpensifyCardBankAccountMetadata'; import type ExpensifyCardSettings from './ExpensifyCardSettings'; -import type {ExpensifyCardSettingsBase} from './ExpensifyCardSettings'; +import type {ExpensifyCardSettingsBase, NestedExpensifyCardSettings} from './ExpensifyCardSettings'; import type ExportTemplate from './ExportTemplate'; import type FrequentlyUsedEmoji from './FrequentlyUsedEmoji'; import type {FundList} from './Fund'; @@ -220,6 +220,7 @@ export type { ExpenseRule, ExpensifyCardSettings, ExpensifyCardSettingsBase, + NestedExpensifyCardSettings, ExpensifyCardBankAccountMetadata, FrequentlyUsedEmoji, Fund, From 2e26f9b9212f9d9759a5b8060665b22f0fda3758 Mon Sep 17 00:00:00 2001 From: allgandaf Date: Tue, 5 May 2026 19:59:25 +0530 Subject: [PATCH 19/19] Add onCloseError handler to dismiss cashback toggle errors --- src/libs/actions/Card.ts | 5 +++++ .../workspace/expensifyCard/WorkspaceCardSettingsPage.tsx | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Card.ts b/src/libs/actions/Card.ts index 3855eecf262b..aa3384467e67 100644 --- a/src/libs/actions/Card.ts +++ b/src/libs/actions/Card.ts @@ -733,6 +733,10 @@ function toggleCashbackToBill(workspaceAccountID: number, programKey: CardProgra API.write(WRITE_COMMANDS.TOGGLE_CARD_CASHBACK_TO_BILL, parameters, {optimisticData, successData, failureData}); } +function clearCashbackToBillError(workspaceAccountID: number) { + Onyx.merge(`${ONYXKEYS.COLLECTION.PRIVATE_EXPENSIFY_CARD_SETTINGS}${workspaceAccountID}`, {errors: null}); +} + function updateSettlementAccount( domainName: string, workspaceAccountID: number, @@ -1903,6 +1907,7 @@ export { updateAssignedCardName, updateAssignedCardTransactionStartDate, toggleCashbackToBill, + clearCashbackToBillError, toggleContinuousReconciliation, setCardReconciliationAccount, updateExpensifyCardLimitType, diff --git a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx index f22536dfbc1d..f1e65c7bcfad 100644 --- a/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx +++ b/src/pages/workspace/expensifyCard/WorkspaceCardSettingsPage.tsx @@ -11,7 +11,7 @@ import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import usePrivateSubscription from '@hooks/usePrivateSubscription'; import useThemeStyles from '@hooks/useThemeStyles'; -import {toggleCashbackToBill} from '@libs/actions/Card'; +import {clearCashbackToBillError, toggleCashbackToBill} from '@libs/actions/Card'; import {getLastFourDigits} from '@libs/BankAccountUtils'; import {getCardProgramKey, getCardSettings} from '@libs/CardUtils'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -107,6 +107,7 @@ function WorkspaceCardSettingsPage({route}: WorkspaceCardSettingsPageProps) { wrapperStyle={[styles.mv3, styles.mh5]} pendingAction={settings?.pendingFields?.shouldApplyCashbackToBill} errors={settings?.errors} + onCloseError={() => clearCashbackToBillError(defaultFundID)} onToggle={(isEnabled: boolean) => { if (!programKey) { return;