Skip to content

Commit

Permalink
Merge pull request #56561 from ikevin127/ikevin127-expensifyCardPromo…
Browse files Browse the repository at this point in the history
…tion

Add Expensify Card promoting banner to Company cards page
  • Loading branch information
luacmartins authored Feb 12, 2025
2 parents 94a3868 + 56c5f26 commit fb2eb3f
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 5 deletions.
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/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import ConciergeBubble from '@assets/images/simple-illustrations/simple-illustra
import ConciergeNew from '@assets/images/simple-illustrations/simple-illustration__concierge.svg';
import CreditCardsNew from '@assets/images/simple-illustrations/simple-illustration__credit-cards.svg';
import CreditCardEyes from '@assets/images/simple-illustrations/simple-illustration__creditcardeyes.svg';
import CreditCardsNewGreen from '@assets/images/simple-illustrations/simple-illustration__creditcards--green.svg';
import EmailAddress from '@assets/images/simple-illustrations/simple-illustration__email-address.svg';
import EmptyState from '@assets/images/simple-illustrations/simple-illustration__empty-state.svg';
import EnvelopeReceipt from '@assets/images/simple-illustrations/simple-illustration__envelopereceipt.svg';
Expand Down Expand Up @@ -198,6 +199,7 @@ export {
MoneyReceipts,
PinkBill,
CreditCardsNew,
CreditCardsNewGreen,
InvoiceBlue,
LaptopwithSecondScreenandHourglass,
LockOpen,
Expand Down
3 changes: 3 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3804,6 +3804,9 @@ const translations = {
noAccountsFound: 'No accounts found',
defaultCard: 'Default card',
noAccountsFoundDescription: ({connection}: ConnectionParams) => `Please add the account in ${connection} and sync the connection again.`,
expensifyCardBannerTitle: 'Get the Expensify Card',
expensifyCardBannerSubtitle: 'Enjoy cash back on every US purchase, up to 50% off your Expensify bill, unlimited virtual cards, and so much more.',
expensifyCardBannerLearnMoreButton: 'Learn more',
},
workflows: {
title: 'Workflows',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3850,6 +3850,10 @@ const translations = {
noAccountsFound: 'No se han encontrado cuentas',
defaultCard: 'Tarjeta predeterminada',
noAccountsFoundDescription: ({connection}: ConnectionParams) => `Añade la cuenta en ${connection} y sincroniza la conexión de nuevo.`,
expensifyCardBannerTitle: 'Obtén la Tarjeta Expensify',
expensifyCardBannerSubtitle:
'Disfruta de una devolución en cada compra en Estados Unidos, hasta un 50% de descuento en tu factura de Expensify, tarjetas virtuales ilimitadas y mucho más.',
expensifyCardBannerLearnMoreButton: 'Más información',
},
workflows: {
title: 'Flujos de trabajo',
Expand Down
7 changes: 7 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,12 @@ function goBackWhenEnableFeature(policyID: string) {
}, CONST.WORKSPACE_ENABLE_FEATURE_REDIRECT_DELAY);
}

function navigateToExpensifyCardPage(policyID: string) {
Navigation.setNavigationActionToMicrotaskQueue(() => {
Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID));
});
}

function getConnectedIntegration(policy: Policy | undefined, accountingIntegrations?: ConnectionName[]) {
return (accountingIntegrations ?? Object.values(CONST.POLICY.CONNECTIONS.NAME)).find((integration) => !!policy?.connections?.[integration]);
}
Expand Down Expand Up @@ -1422,6 +1428,7 @@ export {
sortWorkspacesBySelected,
removePendingFieldsFromCustomUnit,
goBackWhenEnableFeature,
navigateToExpensifyCardPage,
getIntegrationLastSuccessfulDate,
getCurrentConnectionName,
getCustomersOrJobsLabelNetSuite,
Expand Down
9 changes: 7 additions & 2 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ import * as NumberUtils from '@libs/NumberUtils';
import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils';
import * as PhoneNumber from '@libs/PhoneNumber';
import * as PolicyUtils from '@libs/PolicyUtils';
import {goBackWhenEnableFeature} from '@libs/PolicyUtils';
import {goBackWhenEnableFeature, navigateToExpensifyCardPage} from '@libs/PolicyUtils';
import * as ReportUtils from '@libs/ReportUtils';
import type {PolicySelector} from '@pages/home/sidebar/FloatingActionButtonAndPopover';
import * as PaymentMethods from '@userActions/PaymentMethods';
Expand Down Expand Up @@ -2851,7 +2851,7 @@ function savePreferredExportMethod(policyID: string, exportMethod: ReportExportT
Onyx.merge(`${ONYXKEYS.LAST_EXPORT_METHOD}`, {[policyID]: exportMethod});
}

function enableExpensifyCard(policyID: string, enabled: boolean) {
function enableExpensifyCard(policyID: string, enabled: boolean, shouldNavigateToExpensifyCardPage = false) {
const authToken = NetworkStore.getAuthToken();
if (!authToken) {
return;
Expand Down Expand Up @@ -2898,6 +2898,11 @@ function enableExpensifyCard(policyID: string, enabled: boolean) {

API.write(WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS, parameters, onyxData);

if (enabled && shouldNavigateToExpensifyCardPage) {
navigateToExpensifyCardPage(policyID);
return;
}

if (enabled && getIsNarrowLayout()) {
goBackWhenEnableFeature(policyID);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, {useCallback, useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import Button from '@components/Button';
import {CreditCardsNewGreen} from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import useResponsiveLayout from '@hooks/useResponsiveLayout';
import useStyleUtils from '@hooks/useStyleUtils';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import {enableExpensifyCard} from '@libs/actions/Policy/Policy';
import {navigateToExpensifyCardPage} from '@libs/PolicyUtils';
import BillingBanner from '@pages/settings/Subscription/CardSection/BillingBanner/BillingBanner';
import type {Policy} from '@src/types/onyx';

type WorkspaceCompanyCardExpensifyCardPromotionBannerProps = {
policy: OnyxEntry<Policy>;
};

function WorkspaceCompanyCardExpensifyCardPromotionBanner({policy}: WorkspaceCompanyCardExpensifyCardPromotionBannerProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
const StyleUtils = useStyleUtils();
const {shouldUseNarrowLayout} = useResponsiveLayout();
const policyID = policy?.id;
const areExpensifyCardsEnabled = policy?.areExpensifyCardsEnabled;

const handleLearnMore = useCallback(() => {
if (!policyID) {
return;
}

if (areExpensifyCardsEnabled) {
navigateToExpensifyCardPage(policyID);
return;
}

enableExpensifyCard(policyID, true, true);
}, [policyID, areExpensifyCardsEnabled]);

const rightComponent = useMemo(() => {
const smallScreenStyle = shouldUseNarrowLayout ? [styles.flex0, styles.flexBasis100, styles.justifyContentCenter] : [];
return (
<View style={[styles.flexRow, styles.gap2, smallScreenStyle]}>
<Button
success
onPress={handleLearnMore}
style={shouldUseNarrowLayout && styles.flex1}
text={translate('workspace.moreFeatures.companyCards.expensifyCardBannerLearnMoreButton')}
/>
</View>
);
}, [styles, shouldUseNarrowLayout, translate, handleLearnMore]);

return (
<View style={[styles.ph4, styles.mb4]}>
<BillingBanner
icon={CreditCardsNewGreen}
title={translate('workspace.moreFeatures.companyCards.expensifyCardBannerTitle')}
titleStyle={StyleUtils.getTextColorStyle(theme.text)}
subtitle={translate('workspace.moreFeatures.companyCards.expensifyCardBannerSubtitle')}
subtitleStyle={[styles.mt1, styles.textLabel]}
style={[styles.borderRadiusComponentLarge]}
rightComponent={rightComponent}
/>
</View>
);
}

export default WorkspaceCompanyCardExpensifyCardPromotionBanner;
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ import Navigation from '@libs/Navigation/Navigation';
import withPolicyAndFullscreenLoading from '@pages/workspace/withPolicyAndFullscreenLoading';
import type {WithPolicyAndFullscreenLoadingProps} from '@pages/workspace/withPolicyAndFullscreenLoading';
import colors from '@styles/theme/colors';
import * as CompanyCards from '@userActions/CompanyCards';
import {clearAddNewCardFlow} from '@userActions/CompanyCards';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import WorkspaceCompanyCardExpensifyCardPromotionBanner from './WorkspaceCompanyCardExpensifyCardPromotionBanner';

const companyCardFeatures: FeatureListItem[] = [
{
Expand All @@ -40,16 +41,20 @@ function WorkspaceCompanyCardPageEmptyState({policy}: WithPolicyAndFullscreenLoa
const [isNoDelegateAccessMenuVisible, setIsNoDelegateAccessMenuVisible] = useState(false);

const handleCtaPress = useCallback(() => {
if (!policy?.id) {
return;
}
if (isActingAsDelegate) {
setIsNoDelegateAccessMenuVisible(true);
return;
}
CompanyCards.clearAddNewCardFlow();
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.getRoute(policy?.id ?? '-1'));
clearAddNewCardFlow();
Navigation.navigate(ROUTES.WORKSPACE_COMPANY_CARDS_ADD_NEW.getRoute(policy.id));
}, [policy, isActingAsDelegate]);

return (
<View style={[styles.mt3, shouldUseNarrowLayout ? styles.workspaceSectionMobile : styles.workspaceSection]}>
<WorkspaceCompanyCardExpensifyCardPromotionBanner policy={policy} />
<FeatureList
menuItems={companyCardFeatures}
title={translate('workspace.moreFeatures.companyCards.feed.title')}
Expand Down

0 comments on commit fb2eb3f

Please sign in to comment.