Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
4e1e6b9
feat: release 2.6 & 2.7 - reveal cvv flow
ikevin127 Jan 18, 2026
2b3be0d
fix: eslint, svg compression
ikevin127 Jan 18, 2026
6f347f0
fix: codex - validate code sent
ikevin127 Jan 18, 2026
1465e37
Merge branch 'main' of https://github.com/Expensify/App into ikevin12…
ikevin127 Jan 29, 2026
cb0ea07
chore: submodule sync
ikevin127 Jan 29, 2026
ed9d1af
Merge branch 'main' of https://github.com/Expensify/App into ikevin12…
ikevin127 Jan 29, 2026
92b3b88
fix: updated illustration & styles
ikevin127 Jan 29, 2026
9648d86
chore: submodule sync
ikevin127 Jan 29, 2026
f877d09
Merge branch 'main' of https://github.com/Expensify/App into ikevin12…
ikevin127 Jan 30, 2026
3897ab3
refactor: code review requests and organizing
ikevin127 Jan 30, 2026
2aadfb2
chore: submodule sync
ikevin127 Jan 31, 2026
d90c259
chore: eslint
ikevin127 Jan 31, 2026
dd0e56b
chore: main sync
ikevin127 Feb 4, 2026
bad99b1
fix: travel card basis and copy change
ikevin127 Feb 4, 2026
c3c8078
Merge branch 'main' of https://github.com/Expensify/App into ikevin12…
ikevin127 Feb 5, 2026
4c10f82
Merge branch 'main' of https://github.com/Expensify/App into ikevin12…
ikevin127 Feb 7, 2026
e0fe493
chore: post-merge updates
ikevin127 Feb 7, 2026
181ba1c
chore: submodule sync
ikevin127 Feb 7, 2026
9c831e9
chore: merge main
ikevin127 Feb 9, 2026
4bcb32a
Merge branch 'ikevin127-travel-invoicing-26/27' of https://github.com…
ikevin127 Feb 16, 2026
900501b
fix: clear travel CVV from context on page unmount
ikevin127 Feb 16, 2026
66dac68
chore: submodule sync
ikevin127 Feb 16, 2026
5b97f8d
Merge branch 'main' of https://github.com/Expensify/App into ikevin12…
ikevin127 Feb 16, 2026
19f8f3e
chore: submodule sync
ikevin127 Feb 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions __mocks__/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const CompanyCardsPendingState = 'CompanyCardsPendingState';
const VisaCompanyCardDetail = 'VisaCompanyCardDetail';
const MasterCardCompanyCardDetail = 'MasterCardCompanyCardDetail';
const AmexCardCompanyCardDetail = 'AmexCardCompanyCardDetail';
const TravelCVV = 'TravelCVV';
const TurtleInShell = 'TurtleInShell';
const BankOfAmericaCompanyCardDetail = 'BankOfAmericaCompanyCardDetail';
const BrexCompanyCardDetail = 'BrexCompanyCardDetail';
Expand Down Expand Up @@ -212,6 +213,7 @@ export {
VisaCompanyCardDetail,
MasterCardCompanyCardDetail,
AmexCardCompanyCardDetail,
TravelCVV,
TurtleInShell,
BankOfAmericaCompanyCardDetail,
BrexCompanyCardDetail,
Expand Down
1 change: 1 addition & 0 deletions assets/images/travel-cvv.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import OnyxUpdateManager from './libs/actions/OnyxUpdateManager';
import './libs/HybridApp';
import {AttachmentModalContextProvider} from './pages/media/AttachmentModalScreen/AttachmentModalContext';
import ExpensifyCardContextProvider from './pages/settings/Wallet/ExpensifyCardPage/ExpensifyCardContextProvider';
import TravelCVVContextProvider from './pages/settings/Wallet/TravelCVVPage/TravelCVVContextProvider';
import './setup/backgroundLocationTrackingTask';
import './setup/backgroundTask';
import './setup/fraudProtection';
Expand Down Expand Up @@ -131,6 +132,7 @@ function App() {
ModalProvider,
SidePanelContextProvider,
ExpensifyCardContextProvider,
TravelCVVContextProvider,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is a good idea to add this provider here. It will increase the app TTI time. This CVV is only needed in workspace settings so we should move this down the chain.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's all good / completely expected and already present in other flows (e.g. Expensify card) where this was inspired by, see this comment for details.

KYCWallContextProvider,
WideRHPContextProvider,
]}
Expand Down
2 changes: 2 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,8 @@ const ROUTES = {
route: 'settings/wallet/card/:cardID/activate',
getRoute: (cardID: string) => `settings/wallet/card/${cardID}/activate` as const,
},
SETTINGS_WALLET_TRAVEL_CVV: 'settings/wallet/travel-cvv',
SETTINGS_WALLET_TRAVEL_CVV_VERIFY_ACCOUNT: `settings/wallet/travel-cvv/${VERIFY_ACCOUNT}`,
SETTINGS_RULES: 'settings/rules',
SETTINGS_RULES_ADD: {
route: 'settings/rules/new/:field?',
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ const SCREENS = {
UNSHARE_BANK_ACCOUNT: 'Settings_Wallet_Unshare_Bank_Account',
ENABLE_GLOBAL_REIMBURSEMENTS: 'Settings_Wallet_Enable_Global_Reimbursements',
SHARE_BANK_ACCOUNT: 'Settings_Wallet_Share_Bank_Account',
TRAVEL_CVV: 'Settings_Wallet_Travel_CVV',
TRAVEL_CVV_VERIFY_ACCOUNT: 'Settings_Wallet_Travel_CVV_VerifyAccount',
PERSONAL_CARD_DETAILS: 'Settings_Wallet_Personal_Card_Details',
PERSONAL_CARD_EDIT_NAME: 'Settings_Wallet_Personal_Card_Edit_Name',
PERSONAL_CARD_EDIT_TRANSACTION_START_DATE: 'Settings_Wallet_Personal_Card_Edit_Transaction_Start_Date',
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import Mailbox from '@assets/images/simple-illustrations/simple-illustration__ma
import Pencil from '@assets/images/simple-illustrations/simple-illustration__pencil.svg';
import ThumbsUpStars from '@assets/images/simple-illustrations/simple-illustration__thumbsupstars.svg';
import ExpensifyApprovedLogo from '@assets/images/subscription-details__approvedlogo.svg';
import TravelCVV from '@assets/images/travel-cvv.svg';
import TurtleInShell from '@assets/images/turtle-in-shell.svg';

export {
Expand Down Expand Up @@ -96,6 +97,7 @@ export {
Pencil,
PendingTravel,
Puzzle,
TravelCVV,
ThumbsUpStars,
TurtleInShell,
};
2 changes: 2 additions & 0 deletions src/components/Icon/chunks/illustrations.chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ import VirtualCard from '@assets/images/simple-illustrations/simple-illustration
import WalletAlt2 from '@assets/images/simple-illustrations/simple-illustration__wallet-alt2.svg';
import Workflows from '@assets/images/simple-illustrations/simple-illustration__workflows.svg';
import ExpensifyApprovedLogo from '@assets/images/subscription-details__approvedlogo.svg';
import TravelCVV from '@assets/images/travel-cvv.svg';
import TurtleInShell from '@assets/images/turtle-in-shell.svg';

// Create the illustrations object with all imported illustrations
Expand Down Expand Up @@ -258,6 +259,7 @@ const Illustrations = {
RunningTurtle,
Shutter,
ExpensifyApprovedLogo,
TravelCVV,
TurtleInShell,

// Simple Illustrations
Expand Down
5 changes: 5 additions & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} wird den Zugriff auf dieses Geschäftskonto verlieren. Wir schließen dennoch alle laufenden Zahlungen ab.`,
reachOutForHelp: 'Sie wird mit der Expensify Card verwendet. <concierge-link>Wende dich an Concierge</concierge-link>, wenn du sie nicht mehr teilen möchtest.',
unshareErrorModalTitle: 'Bankkonto kann nicht freigegeben werden',
travelCVV: {
title: 'Reise-CVV',
subtitle: 'Verwenden Sie dies bei der Buchung von Reisen',
description: 'Verwende diese Karte für deine Expensify Travel-Buchungen. Sie wird beim Bezahlen als “Travel Card” angezeigt.',
},
chaseAccountNumberDifferent: 'Warum ist meine Kontonummer anders?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2201,6 +2201,11 @@ const translations = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} will lose access to this business bank account. We’ll still complete any payments in process.`,
reachOutForHelp: 'It’s being used with the Expensify Card. <concierge-link>Reach out to Concierge</concierge-link> if you need to unshare it.',
unshareErrorModalTitle: `Can't unshare bank account`,
travelCVV: {
title: 'Travel CVV',
subtitle: 'Use this when booking travel',
description: "Use this card for your Expensify Travel bookings. It'll show as “Travel Card” at checkout.",
},
chaseAccountNumberDifferent: 'Why is my account number different?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1985,6 +1985,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perderá el acceso a esta cuenta bancaria comercial. Seguiremos completando los pagos en proceso.`,
reachOutForHelp: 'Se está usando con la tarjeta Expensify. <concierge-link>Contacte con Concierge</concierge-link> si necesita dejar de compartirla.',
unshareErrorModalTitle: 'No se puede dejar de compartir la cuenta bancaria',
travelCVV: {
title: 'CVV de viaje',
subtitle: 'Úsalo al reservar viajes',
description: 'Usa esta tarjeta para tus reservas de Expensify Travel. Aparecerá como “Travel Card” al pagar.',
},
chaseAccountNumberDifferent: '¿Por qué es diferente el número de mi cuenta?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2180,6 +2180,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perdra l’accès à ce compte bancaire professionnel. Nous terminerons tout de même les paiements en cours.`,
reachOutForHelp: 'Elle est utilisée avec la carte Expensify. <concierge-link>Contactez Concierge</concierge-link> si vous devez arrêter de la partager.',
unshareErrorModalTitle: 'Impossible d’annuler le partage du compte bancaire',
travelCVV: {
title: 'Cryptogramme visuel de la carte de voyage (CVV)',
subtitle: 'À utiliser lors de la réservation de voyages',
description: 'Utilisez cette carte pour vos réservations Expensify Travel. Elle apparaîtra comme “Travel Card” lors du paiement.',
},
chaseAccountNumberDifferent: 'Pourquoi mon numéro de compte est-il différent ?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2168,6 +2168,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perderà l’accesso a questo conto bancario aziendale. Completeremo comunque tutti i pagamenti in corso.`,
reachOutForHelp: 'Viene usato con la Expensify Card. <concierge-link>Contatta Concierge</concierge-link> se hai bisogno di interrompere la condivisione.',
unshareErrorModalTitle: 'Impossibile annullare la condivisione del conto bancario',
travelCVV: {
title: 'CVV di viaggio',
subtitle: 'Usa questo quando prenoti viaggi',
description: 'Usa questa carta per le tue prenotazioni con Expensify Travel. Verrà visualizzata come “Travel Card” al momento del pagamento.',
},
chaseAccountNumberDifferent: 'Perché il mio numero di conto è diverso?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2159,6 +2159,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} はこのビジネス銀行口座へのアクセス権を失います。処理中の支払いは引き続き完了します。`,
reachOutForHelp: 'そのレポートは Expensify Card と一緒に使用されています。共有を解除する必要がある場合は、<concierge-link>Concierge に連絡してください</concierge-link>。',
unshareErrorModalTitle: '銀行口座の共有を解除できません',
travelCVV: {
title: 'トラベルCVV',
subtitle: '出張を予約するときにこれを使用してください',
description: 'このカードをExpensify Travelでの予約に使用してください。チェックアウト時には「Travel Card」と表示されます。',
},
chaseAccountNumberDifferent: '口座番号が異なるのはなぜですか?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,11 @@ const translations: TranslationDeepObject<typeof en> = {
`${admin} verliest de toegang tot deze zakelijke bankrekening. We verwerken nog steeds alle betalingen die al in behandeling zijn.`,
reachOutForHelp: 'Het wordt gebruikt met de Expensify Card. <concierge-link>Neem contact op met Concierge</concierge-link> als je het moet stoppen met delen.',
unshareErrorModalTitle: 'Kan betaalrekening niet meer ontkoppelen',
travelCVV: {
title: 'Reis-CVV',
subtitle: 'Gebruik dit bij het boeken van reizen',
description: 'Gebruik deze kaart voor je Expensify Travel-boekingen. Hij wordt weergegeven als “Travel Card” bij het afrekenen.',
},
chaseAccountNumberDifferent: 'Waarom is mijn rekeningnummer anders?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2166,6 +2166,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} straci dostęp do tego firmowego konta bankowego. Nadal zrealizujemy wszystkie płatności w toku.`,
reachOutForHelp: 'Jest używany z kartą Expensify. <concierge-link>Skontaktuj się z Concierge</concierge-link>, jeśli musisz przestać się nim dzielić.',
unshareErrorModalTitle: 'Nie można cofnąć udostępniania konta bankowego',
travelCVV: {
title: 'CVV podróży',
subtitle: 'Użyj tego podczas rezerwacji podróży',
description: 'Użyj tej karty do rezerwacji w Expensify Travel. Podczas płatności będzie wyświetlana jako “Travel Card”.',
},
chaseAccountNumberDifferent: 'Dlaczego mój numer konta jest inny?',
},
cardPage: {
Expand Down
5 changes: 5 additions & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2164,6 +2164,11 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} perderá o acesso a esta conta bancária empresarial. Ainda concluiremos quaisquer pagamentos em andamento.`,
reachOutForHelp: 'Ela está sendo usada com o Cartão Expensify. <concierge-link>Entre em contato com o Concierge</concierge-link> se precisar parar de compartilhá-la.',
unshareErrorModalTitle: 'Não é possível parar de compartilhar a conta bancária',
travelCVV: {
title: 'CVV de viagem',
subtitle: 'Use isto ao reservar viagens',
description: 'Use este cartão para suas reservas no Expensify Travel. Ele aparecerá como “Travel Card” no checkout.',
},
chaseAccountNumberDifferent: 'Por que meu número de conta é diferente?',
},
cardPage: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2136,6 +2136,7 @@ const translations: TranslationDeepObject<typeof en> = {
unshareBankAccountWarning: ({admin}: {admin?: string | null}) => `${admin} 将失去对此企业银行账户的访问权限。我们仍会完成任何正在处理中的付款。`,
reachOutForHelp: '它正在与 Expensify Card 一起使用。若需要取消共享,请<concierge-link>联系 Concierge</concierge-link>。',
unshareErrorModalTitle: '无法取消共享银行账户',
travelCVV: {title: '旅行 CVV', subtitle: '预订差旅时使用此选项', description: '使用此卡预订 Expensify Travel 行程。结账时它会显示为“Travel Card”。'},
chaseAccountNumberDifferent: '为什么我的账户号码不同?',
},
cardPage: {
Expand Down
9 changes: 8 additions & 1 deletion src/libs/Environment/Environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ function isDevelopment(): boolean {
return (Config?.ENVIRONMENT ?? CONST.ENVIRONMENT.DEV) === CONST.ENVIRONMENT.DEV;
}

/**
* Are we running the app in staging?
*/
function isStaging(): boolean {
return (Config?.ENVIRONMENT ?? CONST.ENVIRONMENT.DEV) === CONST.ENVIRONMENT.STAGING;
}

/**
* Are we running the app in production?
*/
Expand Down Expand Up @@ -62,4 +69,4 @@ function getOldDotEnvironmentURL(): Promise<string> {
return getEnvironment().then((environment) => OLDDOT_ENVIRONMENT_URLS[environment]);
}

export {getEnvironment, isInternalTestBuild, isDevelopment, isProduction, getEnvironmentURL, getOldDotEnvironmentURL, getOldDotURLFromEnvironment};
export {getEnvironment, isInternalTestBuild, isDevelopment, isStaging, isProduction, getEnvironmentURL, getOldDotEnvironmentURL, getOldDotURLFromEnvironment};
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.SETTINGS.WALLET.UNSHARE_BANK_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/UnshareBankAccount/UnshareBankAccount').default,
[SCREENS.SETTINGS.WALLET.ENABLE_GLOBAL_REIMBURSEMENTS]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/EnableGlobalReimbursements').default,
[SCREENS.SETTINGS.WALLET.SHARE_BANK_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/ShareBankAccount/ShareBankAccount').default,
[SCREENS.SETTINGS.WALLET.TRAVEL_CVV]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/TravelCVVPage/TravelCVVPage').default,
[SCREENS.SETTINGS.WALLET.TRAVEL_CVV_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/TravelCVVPage/TravelCVVVerifyAccountPage').default,
[SCREENS.SETTINGS.ADD_DEBIT_CARD]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/AddDebitCardPage').default,
[SCREENS.SETTINGS.ADD_BANK_ACCOUNT_VERIFY_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/NewBankAccountVerifyAccountPage').default,
[SCREENS.SETTINGS.ADD_BANK_ACCOUNT]: () => require<ReactComponentModule>('../../../../pages/settings/Wallet/InternationalDepositAccount').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ const SETTINGS_TO_RHP: Partial<Record<keyof SettingsSplitNavigatorParamList, str
SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD_CONFIRM_MAGIC_CODE,
SCREENS.SETTINGS.WALLET.REPORT_VIRTUAL_CARD_FRAUD_CONFIRMATION,
SCREENS.SETTINGS.WALLET.CARDS_DIGITAL_DETAILS_UPDATE_ADDRESS,
SCREENS.SETTINGS.WALLET.TRAVEL_CVV,
SCREENS.SETTINGS.WALLET.TRAVEL_CVV_VERIFY_ACCOUNT,
SCREENS.SETTINGS.BANK_ACCOUNT_PURPOSE,
SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED,
SCREENS.SETTINGS.REPORT_CARD_LOST_OR_DAMAGED_CONFIRM_MAGIC_CODE,
Expand Down
Loading
Loading