Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/add assigned card tile and display expensify cards #26862

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ const CONST = {
CLOSED: 6,
STATE_SUSPENDED: 7,
},
ACTIVE_STATES: [2, 3, 4, 7],
Copy link
Member

@rushatgabhane rushatgabhane Oct 13, 2023

Choose a reason for hiding this comment

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

   STATE: {
        OPEN: 3,
        NOT_ACTIVATED: 4,
        STATE_DEACTIVATED: 5,
        CLOSED: 6,
        STATE_SUSPENDED: 7,
    },

What is state 2 in Active_States? it's not in the State object.

Copy link
Contributor

@grgia grgia Oct 13, 2023

Choose a reason for hiding this comment

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

Ah it's the Card Not Issued state. I think this is a typo from the design doc. Let's Remove 2 @pac-guerreiro.
But also I'd consider this as NAB for now considering the priority of this PR

},
AVATAR_ROW_SIZE: {
DEFAULT: 4,
Expand Down
3 changes: 3 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,9 @@ export default {
bankAccounts: 'Bank accounts',
addBankAccountToSendAndReceive: 'Add a bank account to send and receive payments directly in the app.',
addBankAccount: 'Add bank account',
assignedCards: 'Assigned cards',
assignedCardsDescription: 'These are cards assigned by a Workspace admin to manage company spend.',
pac-guerreiro marked this conversation as resolved.
Show resolved Hide resolved
expensifyCard: 'Expensify Card',
},
cardPage: {
expensifyCard: 'Expensify Card',
Expand Down
3 changes: 3 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,9 @@ export default {
bankAccounts: 'Cuentas bancarias',
addBankAccountToSendAndReceive: 'Añade una cuenta bancaria para enviar y recibir pagos directamente en la aplicación.',
addBankAccount: 'Agregar cuenta bancaria',
assignedCards: 'Tarjetas asignadas',
assignedCardsDescription: 'Son tarjetas asignadas por un administrador del Espacio de Trabajo para gestionar los gastos de la empresa.',
expensifyCard: 'Tarjeta Expensify',
},
cardPage: {
expensifyCard: 'Tarjeta Expensify',
Expand Down
4 changes: 2 additions & 2 deletions src/libs/CardUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ function getCompanyCards(cardList: {string: Card}) {
*/
function getDomainCards(cardList: Record<string, OnyxTypes.Card>) {
// eslint-disable-next-line you-dont-need-lodash-underscore/filter
const activeCards = lodash.filter(cardList, (card) => [2, 3, 4, 7].includes(card.state));
return lodash.groupBy(activeCards, (card) => card.domainName.toLowerCase());
const activeCards = lodash.filter(cardList, (card) => (CONST.EXPENSIFY_CARD.ACTIVE_STATES as ReadonlyArray<OnyxTypes.Card['state']>).includes(card.state));
return lodash.groupBy(activeCards, (card) => card.domainName);
}

/**
Expand Down
48 changes: 43 additions & 5 deletions src/pages/settings/Wallet/PaymentMethodList.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
import * as PaymentMethods from '../../../libs/actions/PaymentMethods';
import Log from '../../../libs/Log';
import stylePropTypes from '../../../styles/stylePropTypes';
import Navigation from '../../../libs/Navigation/Navigation';
import ROUTES from '../../../ROUTES';
import getBankIcon from '../../../components/Icon/BankIcons';
import assignedCardPropTypes from './assignedCardPropTypes';

const propTypes = {
/** What to do when a menu item is pressed */
Expand All @@ -31,12 +35,21 @@ const propTypes = {
/** List of bank accounts */
bankAccountList: PropTypes.objectOf(bankAccountPropTypes),

/** List of assigned cards */
cardList: PropTypes.objectOf(assignedCardPropTypes),

/** List of user's cards */
fundList: PropTypes.objectOf(cardPropTypes),

/** Whether the add bank account button should be shown on the list */
shouldShowAddBankAccount: PropTypes.bool,

/** Whether the add Payment button be shown on the list */
shouldShowAddPaymentMethodButton: PropTypes.bool,

/** Whether the assigned cards should be shown on the list */
shouldShowAssignedCards: PropTypes.bool,

/** Whether the empty list message should be shown when the list is empty */
shouldShowEmptyListMessage: PropTypes.bool,

Expand Down Expand Up @@ -84,13 +97,16 @@ const propTypes = {

const defaultProps = {
bankAccountList: {},
cardList: {},
fundList: null,
userWallet: {
walletLinkedAccountID: 0,
walletLinkedAccountType: '',
},
isLoadingPaymentMethods: true,
shouldShowAddBankAccount: true,
shouldShowAddPaymentMethodButton: true,
shouldShowAssignedCards: false,
shouldShowEmptyListMessage: true,
filterType: '',
actionPaymentMethodType: '',
Expand Down Expand Up @@ -161,6 +177,7 @@ function PaymentMethodList({
activePaymentMethodID,
bankAccountList,
buttonRef,
cardList,
fundList,
filterType,
isLoadingPaymentMethods,
Expand All @@ -171,13 +188,30 @@ function PaymentMethodList({
shouldEnableScroll,
shouldShowSelectedState,
shouldShowAddPaymentMethodButton,
shouldShowAddBankAccount,
shouldShowEmptyListMessage,
shouldShowAssignedCards,
selectedMethodID,
style,
translate,
}) {
const filteredPaymentMethods = useMemo(() => {
const paymentCardList = fundList || {};

if (shouldShowAssignedCards) {
const assignedCards = _.filter(cardList, (card) => CONST.EXPENSIFY_CARD.ACTIVE_STATES.includes(card.state));
return _.map(assignedCards, (card) => {
const icon = getBankIcon(card.bank);
return {
key: card.key,
title: translate('walletPage.expensifyCard'),
description: card.domainName,
onPress: () => Navigation.navigate(ROUTES.SETTINGS_WALLET_DOMAINCARDS.getRoute(card.domainName)),
...icon,
};
});
}

// Hide any billing cards that are not P2P debit cards for now because you cannot make them your default method, or delete them
const filteredCardList = _.filter(paymentCardList, (card) => card.accountData.additionalData.isP2PDebitCard);
let combinedPaymentMethods = PaymentUtils.formatPaymentMethods(bankAccountList, filteredCardList);
Expand All @@ -204,14 +238,14 @@ function PaymentMethodList({
}));

return combinedPaymentMethods;
}, [actionPaymentMethodType, activePaymentMethodID, bankAccountList, filterType, network, onPress, fundList]);
}, [fundList, shouldShowAssignedCards, bankAccountList, filterType, network.isOffline, cardList, translate, actionPaymentMethodType, activePaymentMethodID, onPress]);

/**
* Render placeholder when there are no payments methods
*
* @return {React.Component}
*/
const renderListEmptyComponent = useCallback(() => <Text style={[styles.popoverMenuItem]}>{translate('paymentMethodList.addFirstPaymentMethod')}</Text>, [translate]);
const renderListEmptyComponent = () => <Text style={[styles.popoverMenuItem]}>{translate('paymentMethodList.addFirstPaymentMethod')}</Text>;

const renderListFooterComponent = useCallback(
() => (
Expand Down Expand Up @@ -252,12 +286,13 @@ function PaymentMethodList({
iconWidth={item.iconSize}
badgeText={shouldShowDefaultBadge(filteredPaymentMethods, item.isDefault) ? translate('paymentMethodList.defaultPaymentMethod') : null}
wrapperStyle={styles.paymentMethod}
shouldShowRightIcon={shouldShowAssignedCards}
Copy link
Contributor

Choose a reason for hiding this comment

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

Coming from #38643, this PaymentMethodList is also used in Transfer account screen, in that screen, we don't show the right icon by original design

shouldShowSelectedState={shouldShowSelectedState}
isSelected={selectedMethodID === item.methodID}
/>
</OfflineWithFeedback>
),
[filteredPaymentMethods, translate, shouldShowSelectedState, selectedMethodID],
[filteredPaymentMethods, translate, shouldShowAssignedCards, shouldShowSelectedState, selectedMethodID],
);

return (
Expand All @@ -266,9 +301,9 @@ function PaymentMethodList({
data={filteredPaymentMethods}
renderItem={renderItem}
keyExtractor={(item) => item.key}
ListEmptyComponent={shouldShowEmptyListMessage ? renderListEmptyComponent(translate) : null}
ListEmptyComponent={shouldShowEmptyListMessage ? renderListEmptyComponent : null}
ListHeaderComponent={listHeaderComponent}
ListFooterComponent={renderListFooterComponent}
ListFooterComponent={shouldShowAddBankAccount ? renderListFooterComponent : null}
onContentSizeChange={onListContentSizeChange}
scrollEnabled={shouldEnableScroll}
style={style}
Expand Down Expand Up @@ -307,6 +342,9 @@ export default compose(
bankAccountList: {
key: ONYXKEYS.BANK_ACCOUNT_LIST,
},
cardList: {
key: ONYXKEYS.CARD_LIST,
},
fundList: {
key: ONYXKEYS.FUND_LIST,
},
Expand Down
21 changes: 21 additions & 0 deletions src/pages/settings/Wallet/WalletPage/WalletPage.js
grgia marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,27 @@ function WalletPage({bankAccountList, betas, cardList, fundList, isLoadingPaymen
</>
</WalletSection>
)}
{hasAssignedCard ? (
<WalletSection
icon={Illustrations.CreditCardsNew}
subtitle={translate('walletPage.assignedCardsDescription')}
title={translate('walletPage.assignedCards')}
>
<PaymentMethodList
shouldShowAddBankAccount={false}
shouldShowAddPaymentMethodButton={false}
shouldShowAssignedCards
shouldShowEmptyListMessage={false}
onPress={paymentMethodPressed}
style={styles.mt5}
isAddPaymentMenuActive={shouldShowAddPaymentMenu}
actionPaymentMethodType={shouldShowDefaultDeleteMenu ? paymentMethod.selectedPaymentMethodType : ''}
activePaymentMethodID={shouldShowDefaultDeleteMenu ? getSelectedPaymentMethodID() : ''}
buttonRef={addPaymentMethodAnchorRef}
onListContentSizeChange={shouldShowAddPaymentMenu || shouldShowDefaultDeleteMenu ? setMenuPosition : () => {}}
/>
</WalletSection>
) : null}
<WalletSection
icon={Illustrations.BankArrow}
subtitle={translate('walletPage.addBankAccountToSendAndReceive')}
Expand Down
5 changes: 1 addition & 4 deletions src/pages/settings/Wallet/assignedCardPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@ const assignedCardPropTypes = PropTypes.shape({
bank: PropTypes.string,
availableSpend: PropTypes.number,
domainName: PropTypes.string,
lastFourPAN: PropTypes.string,
cardName: PropTypes.string,
maskedPan: PropTypes.string,
isVirtual: PropTypes.bool,
fraud: PropTypes.oneOf([CONST.EXPENSIFY_CARD.FRAUD_TYPES.DOMAIN, CONST.EXPENSIFY_CARD.FRAUD_TYPES.USER, CONST.EXPENSIFY_CARD.FRAUD_TYPES.NONE]),
cardholderFirstName: PropTypes.string,
cardholderLastName: PropTypes.string,
errors: PropTypes.objectOf(PropTypes.string),
isLoading: PropTypes.bool,
});

export default assignedCardPropTypes;
Loading