Skip to content

Commit

Permalink
Merge pull request #50602 from waterim/feat-50447
Browse files Browse the repository at this point in the history
[No QA] Feat: Adding Direct Card Feed: Selecting feed type
  • Loading branch information
mountiny authored Oct 15, 2024
2 parents e0735fc + 108275c commit fcddf6a
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 2 deletions.
7 changes: 7 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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',
Expand All @@ -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',
Expand Down
9 changes: 9 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:',
Expand Down Expand Up @@ -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.`,
Expand Down
9 changes: 9 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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}.`,
Expand Down
37 changes: 37 additions & 0 deletions src/libs/CardUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,42 @@ const getBankCardDetailsImage = (bank: ValueOf<typeof CONST.COMPANY_CARDS.BANKS>
return iconMap[bank];
};

// We will simplify the logic below once we have #50450 #50451 implemented
const getCorrectStepForSelectedBank = (selectedBank: ValueOf<typeof CONST.COMPANY_CARDS.BANKS>) => {
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,
Expand All @@ -261,4 +297,5 @@ export {
getCardDetailsImage,
getMemberCards,
getBankCardDetailsImage,
getCorrectStepForSelectedBank,
};
3 changes: 3 additions & 0 deletions src/pages/workspace/companyCards/addNew/AddNewCardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -20,6 +21,8 @@ function AddNewCardPage() {
switch (currentStep) {
case CONST.COMPANY_CARDS.STEP.SELECT_BANK:
return <SelectBankStep />;
case CONST.COMPANY_CARDS.STEP.SELECT_FEED_TYPE:
return <SelectFeedType />;
case CONST.COMPANY_CARDS.STEP.CARD_TYPE:
return <CardTypeStep />;
case CONST.COMPANY_CARDS.STEP.CARD_INSTRUCTIONS:
Expand Down
3 changes: 1 addition & 2 deletions src/pages/workspace/companyCards/addNew/SelectBankStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down
107 changes: 107 additions & 0 deletions src/pages/workspace/companyCards/addNew/SelectFeedType.tsx
Original file line number Diff line number Diff line change
@@ -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<ValueOf<typeof CONST.COMPANY_CARDS.FEED_TYPE>>();
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 (
<ScreenWrapper
testID={SelectFeedType.displayName}
includeSafeAreaPaddingBottom={false}
shouldEnablePickerAvoiding={false}
shouldEnableMaxHeight
>
<HeaderWithBackButton
title={translate('workspace.companyCards.addCardFeed')}
onBackButtonPress={handleBackButtonPress}
/>

<Text style={[styles.textHeadlineLineHeightXXL, styles.ph5, styles.mv3]}>{translate('workspace.companyCards.addNewCard.howDoYouWantToConnect')}</Text>
<Text style={[styles.textSupporting, styles.ph5, styles.mb6]}>
{`${translate('workspace.companyCards.addNewCard.learnMoreAboutConnections.text')}`}
<TextLink href={CONST.COMPANY_CARDS_CONNECT_CREDIT_CARDS_HELP_URL}>{`${translate('workspace.companyCards.addNewCard.learnMoreAboutConnections.linkText')}.`}</TextLink>
</Text>

<SelectionList
ListItem={RadioListItem}
onSelectRow={({value}) => {
setTypeSelected(value);
setHasError(false);
}}
sections={[{data}]}
shouldSingleExecuteRowSelect
isAlternateTextMultilineSupported
alternateTextNumberOfLines={3}
initiallyFocusedOptionKey={addNewCard?.data.selectedFeedType}
shouldUpdateFocusedIndex
showConfirmButton
confirmButtonText={translate('common.next')}
onConfirm={submit}
>
{hasError && (
<View style={[styles.ph5, styles.mb3]}>
<FormHelpMessage
isError={hasError}
message={translate('workspace.companyCards.addNewCard.error.pleaseSelectFeedType')}
/>
</View>
)}
</SelectionList>
</ScreenWrapper>
);
}

SelectFeedType.displayName = 'SelectFeedType';

export default SelectFeedType;
3 changes: 3 additions & 0 deletions src/types/onyx/CardFeeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ type AddNewCardFeedData = {
/** Selected bank */
selectedBank: ValueOf<typeof CONST.COMPANY_CARDS.BANKS>;

/** Selected feed type */
selectedFeedType: ValueOf<typeof CONST.COMPANY_CARDS.FEED_TYPE>;

/** Name of the card */
cardTitle: string;
};
Expand Down

0 comments on commit fcddf6a

Please sign in to comment.