diff --git a/src/CONST.ts b/src/CONST.ts index b6b297f7fb47..097b4a393612 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -745,6 +745,8 @@ const CONST = { HOW_TO_CONNECT_TO_SAGE_INTACCT: 'https://help.expensify.com/articles/expensify-classic/integrations/accounting-integrations/Sage-Intacct#how-to-connect-to-sage-intacct', PRICING: `https://www.expensify.com/pricing`, COMPANY_CARDS_HELP: 'https://help.expensify.com/articles/expensify-classic/connect-credit-cards/company-cards/Commercial-Card-Feeds', + COMPANY_CARDS_CONNECT_CREDIT_CARDS_HELP_URL: + 'https://help.expensify.com/articles/expensify-classic/connect-credit-cards/company-cards/Commercial-Card-Feeds#what-is-the-difference-between-commercial-card-feeds-and-your-direct-bank-connections', CUSTOM_REPORT_NAME_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/spending-insights/Custom-Templates', CONFIGURE_REIMBURSEMENT_SETTINGS_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/workspaces/Configure-Reimbursement-Settings', COPILOT_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Assign-or-remove-a-Copilot', @@ -2556,6 +2558,7 @@ const CONST = { CONNECTION_ERROR: 'connectionError', STEP: { SELECT_BANK: 'SelectBank', + SELECT_FEED_TYPE: 'SelectFeedType', CARD_TYPE: 'CardType', CARD_INSTRUCTIONS: 'CardInstructions', CARD_NAME: 'CardName', @@ -2566,6 +2569,10 @@ const CONST = { VISA: 'visa', MASTERCARD: 'mastercard', }, + FEED_TYPE: { + CUSTOM: 'customFeed', + DIRECT: 'directFeed', + }, BANKS: { AMEX: 'American Express', BANK_OF_AMERICA: 'Bank of America', diff --git a/src/languages/en.ts b/src/languages/en.ts index 343990813197..6ca1cb58f9ad 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3039,6 +3039,13 @@ const translations = { }, yourCardProvider: `Who's your card provider?`, whoIsYourBankAccount: 'Who’s your bank?', + howDoYouWantToConnect: 'How do you want to connect to your bank?', + learnMoreAboutConnections: { + text: 'Learn more about the ', + linkText: 'connection methods', + }, + customFeedDetails: 'Requires setup with your bank. This is most common for larger companies, and the best option, if you qualify.', + directFeedDetails: 'Connect now using your master credentials. This is most common.', enableFeed: { title: ({provider}: GoBackMessageParams) => `Enable your ${provider} feed`, heading: 'We have a direct integration with your card issuer and can import your transaction data into Expensify quickly and accurately.\n\nTo get started, simply:', @@ -3067,11 +3074,13 @@ const translations = { error: { pleaseSelectProvider: 'Please select a card provider before continuing.', pleaseSelectBankAccount: 'Please select a bank account before continuing.', + pleaseSelectFeedType: 'Please select a feed type before continuing.', }, }, assignCard: 'Assign card', cardNumber: 'Card number', customFeed: 'Custom feed', + directFeed: 'Direct feed', whoNeedsCardAssigned: 'Who needs a card assigned?', chooseCard: 'Choose a card', chooseCardFor: ({assignee, feed}: AssignCardParams) => `Choose a card for ${assignee} from the ${feed} cards feed.`, diff --git a/src/languages/es.ts b/src/languages/es.ts index 50ee28d488c6..86a3ebe7f927 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3077,6 +3077,13 @@ const translations = { }, yourCardProvider: `¿Quién es su proveedor de tarjetas?`, whoIsYourBankAccount: '¿Cuál es tu banco?', + howDoYouWantToConnect: '¿Cómo deseas conectarte a tu banco?', + learnMoreAboutConnections: { + text: 'Obtén más información sobre ', + linkText: 'los métodos de conexión', + }, + customFeedDetails: 'Requiere configuración con tu banco. Esto es más común para empresas grandes, y la mejor opción, si calificas.', + directFeedDetails: 'Conéctate ahora usando tus credenciales maestras. Esto es lo más común.', enableFeed: { title: ({provider}: GoBackMessageParams) => `Habilita tu feed ${provider}`, heading: @@ -3106,11 +3113,13 @@ const translations = { error: { pleaseSelectProvider: 'Seleccione un proveedor de tarjetas antes de continuar.', pleaseSelectBankAccount: 'Seleccione una cuenta bancaria antes de continuar.', + pleaseSelectFeedType: 'Seleccione un tipo de pienso antes de continuar.', }, }, assignCard: 'Asignar tarjeta', cardNumber: 'Número de la tarjeta', customFeed: 'Fuente personalizada', + directFeed: 'Fuente directa', whoNeedsCardAssigned: '¿Quién necesita una tarjeta?', chooseCard: 'Elige una tarjeta', chooseCardFor: ({assignee, feed}: AssignCardParams) => `Elige una tarjeta para ${assignee} del feed de tarjetas ${feed}.`, diff --git a/src/libs/CardUtils.ts b/src/libs/CardUtils.ts index bd8499fa168f..bd55808b95ff 100644 --- a/src/libs/CardUtils.ts +++ b/src/libs/CardUtils.ts @@ -242,6 +242,42 @@ const getBankCardDetailsImage = (bank: ValueOf return iconMap[bank]; }; +// We will simplify the logic below once we have #50450 #50451 implemented +const getCorrectStepForSelectedBank = (selectedBank: ValueOf) => { + const banksWithFeedType = [ + CONST.COMPANY_CARDS.BANKS.BANK_OF_AMERICA, + CONST.COMPANY_CARDS.BANKS.CAPITAL_ONE, + CONST.COMPANY_CARDS.BANKS.CHASE, + CONST.COMPANY_CARDS.BANKS.CITI_BANK, + CONST.COMPANY_CARDS.BANKS.WELLS_FARGO, + ]; + + if (selectedBank === CONST.COMPANY_CARDS.BANKS.STRIPE) { + // TODO https://github.com/Expensify/App/issues/50450 + return; + } + + if (selectedBank === CONST.COMPANY_CARDS.BANKS.AMEX) { + // TODO https://github.com/Expensify/App/issues/50451 + return; + } + + if (selectedBank === CONST.COMPANY_CARDS.BANKS.BREX) { + // TODO Skip the step to submit + return; + } + + if (selectedBank === CONST.COMPANY_CARDS.BANKS.OTHER) { + return CONST.COMPANY_CARDS.STEP.CARD_TYPE; + } + + if (banksWithFeedType.includes(selectedBank)) { + return CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE; + } + + return CONST.COMPANY_CARDS.STEP.CARD_TYPE; +}; + export { isExpensifyCard, isCorporateCard, @@ -261,4 +297,5 @@ export { getCardDetailsImage, getMemberCards, getBankCardDetailsImage, + getCorrectStepForSelectedBank, }; diff --git a/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx b/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx index 9b263299739b..9951a7a62d18 100644 --- a/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx +++ b/src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx @@ -9,6 +9,7 @@ import CardNameStep from './CardNameStep'; import CardTypeStep from './CardTypeStep'; import DetailsStep from './DetailsStep'; import SelectBankStep from './SelectBankStep'; +import SelectFeedType from './SelectFeedType'; function AddNewCardPage() { const [addNewCardFeed] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD); @@ -20,6 +21,8 @@ function AddNewCardPage() { switch (currentStep) { case CONST.COMPANY_CARDS.STEP.SELECT_BANK: return ; + case CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE: + return ; case CONST.COMPANY_CARDS.STEP.CARD_TYPE: return ; case CONST.COMPANY_CARDS.STEP.CARD_INSTRUCTIONS: diff --git a/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx b/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx index be0479327832..40c55e185cd8 100644 --- a/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx +++ b/src/pages/workspace/companyCards/addNew/SelectBankStep.tsx @@ -29,9 +29,8 @@ function SelectBankStep() { if (!bankSelected) { setHasError(true); } else { - // TODO: https://github.com/Expensify/App/issues/50447 - update the navigation when new screen exists CompanyCards.setAddNewCompanyCardStepAndData({ - step: bankSelected === CONST.COMPANY_CARDS.BANKS.OTHER ? CONST.COMPANY_CARDS.STEP.CARD_TYPE : CONST.COMPANY_CARDS.STEP.CARD_TYPE, + step: CardUtils.getCorrectStepForSelectedBank(bankSelected), data: { selectedBank: bankSelected, }, diff --git a/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx b/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx new file mode 100644 index 000000000000..113ca1b7e051 --- /dev/null +++ b/src/pages/workspace/companyCards/addNew/SelectFeedType.tsx @@ -0,0 +1,107 @@ +import React, {useEffect, useState} from 'react'; +import {View} from 'react-native'; +import {useOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; +import FormHelpMessage from '@components/FormHelpMessage'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ScreenWrapper from '@components/ScreenWrapper'; +import SelectionList from '@components/SelectionList'; +import RadioListItem from '@components/SelectionList/RadioListItem'; +import Text from '@components/Text'; +import TextLink from '@components/TextLink'; +import useLocalize from '@hooks/useLocalize'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as CompanyCards from '@userActions/CompanyCards'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; + +function SelectFeedType() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const [addNewCard] = useOnyx(ONYXKEYS.ADD_NEW_COMPANY_CARD); + const [typeSelected, setTypeSelected] = useState>(); + const [hasError, setHasError] = useState(false); + + const submit = () => { + if (!typeSelected) { + setHasError(true); + } else { + // TODO: https://github.com/Expensify/App/issues/50448 - update the navigation when new screen exists + } + }; + + useEffect(() => { + setTypeSelected(addNewCard?.data.selectedFeedType); + }, [addNewCard?.data.selectedFeedType]); + + const handleBackButtonPress = () => { + CompanyCards.setAddNewCompanyCardStepAndData({step: CONST.COMPANY_CARDS.STEP.SELECT_BANK}); + }; + + const data = [ + { + value: CONST.COMPANY_CARDS.FEED_TYPE.CUSTOM, + text: translate('workspace.companyCards.customFeed'), + alternateText: translate('workspace.companyCards.addNewCard.customFeedDetails'), + keyForList: CONST.COMPANY_CARDS.FEED_TYPE.CUSTOM, + isSelected: typeSelected === CONST.COMPANY_CARDS.FEED_TYPE.CUSTOM, + }, + { + value: CONST.COMPANY_CARDS.FEED_TYPE.DIRECT, + text: translate('workspace.companyCards.directFeed'), + alternateText: translate('workspace.companyCards.addNewCard.directFeedDetails'), + keyForList: CONST.COMPANY_CARDS.FEED_TYPE.DIRECT, + isSelected: typeSelected === CONST.COMPANY_CARDS.FEED_TYPE.DIRECT, + }, + ]; + + return ( + + + + {translate('workspace.companyCards.addNewCard.howDoYouWantToConnect')} + + {`${translate('workspace.companyCards.addNewCard.learnMoreAboutConnections.text')}`} + {`${translate('workspace.companyCards.addNewCard.learnMoreAboutConnections.linkText')}.`} + + + { + setTypeSelected(value); + setHasError(false); + }} + sections={[{data}]} + shouldSingleExecuteRowSelect + isAlternateTextMultilineSupported + alternateTextNumberOfLines={3} + initiallyFocusedOptionKey={addNewCard?.data.selectedFeedType} + shouldUpdateFocusedIndex + showConfirmButton + confirmButtonText={translate('common.next')} + onConfirm={submit} + > + {hasError && ( + + + + )} + + + ); +} + +SelectFeedType.displayName = 'SelectFeedType'; + +export default SelectFeedType; diff --git a/src/types/onyx/CardFeeds.ts b/src/types/onyx/CardFeeds.ts index 32c54824b9ac..508218897eab 100644 --- a/src/types/onyx/CardFeeds.ts +++ b/src/types/onyx/CardFeeds.ts @@ -52,6 +52,9 @@ type AddNewCardFeedData = { /** Selected bank */ selectedBank: ValueOf; + /** Selected feed type */ + selectedFeedType: ValueOf; + /** Name of the card */ cardTitle: string; };