Skip to content

Commit

Permalink
Merge pull request Expensify#44371 from callstack-internal/pac-guerre…
Browse files Browse the repository at this point in the history
…iro/feature/43672-implement-and-show-free-trial-banner-and-badges-after-free-trial-starts

[Free trial] Implement and show Free Trial banner and badges in the App after Free Trial starts
  • Loading branch information
chiragsalian authored Jul 2, 2024
2 parents 7f3f120 + ffa0da3 commit f1366b4
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 3 deletions.
9 changes: 9 additions & 0 deletions src/components/LHNOptionsList/OptionRowLHN.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, {useCallback, useRef, useState} from 'react';
import type {GestureResponderEvent, ViewStyle} from 'react-native';
import {StyleSheet, View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import Badge from '@components/Badge';
import DisplayNames from '@components/DisplayNames';
import Hoverable from '@components/Hoverable';
import Icon from '@components/Icon';
Expand All @@ -25,6 +26,7 @@ import * as OptionsListUtils from '@libs/OptionsListUtils';
import Performance from '@libs/Performance';
import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager';
import * as ReportUtils from '@libs/ReportUtils';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
Expand Down Expand Up @@ -227,6 +229,13 @@ function OptionRowLHN({reportID, isFocused = false, onSelectRow = () => {}, opti
ReportUtils.isSystemChat(report)
}
/>
{ReportUtils.isChatUsedForOnboarding(report) && SubscriptionUtils.isUserOnFreeTrial() && (
<Badge
success
text={translate('subscription.badge.freeTrial', {numOfDays: SubscriptionUtils.calculateRemainingFreeTrialDays()})}
badgeStyles={[styles.mnh0, styles.pl2, styles.pr2, styles.ml1]}
/>
)}
{isStatusVisible && (
<Tooltip
text={statusContent}
Expand Down
7 changes: 7 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3463,6 +3463,9 @@ export default {
},
subscription: {
mobileReducedFunctionalityMessage: 'You can’t make changes to your subscription in the mobile app.',
badge: {
freeTrial: ({numOfDays}) => `Free trial: ${numOfDays} ${numOfDays === 1 ? 'day' : 'days'} left`,
},
billingBanner: {
policyOwnerAmountOwed: {
title: 'Your payment info is outdated',
Expand Down Expand Up @@ -3518,6 +3521,10 @@ export default {
subtitle: 'To get started, ',
subtitleLink: 'complete your setup checklist here.',
},
trialStarted: {
title: ({numOfDays}) => `Free trial: ${numOfDays} ${numOfDays === 1 ? 'day' : 'days'} left!`,
subtitle: 'Add a payment card to continue using all of your favorite features.',
},
},
cardSection: {
title: 'Payment',
Expand Down
7 changes: 7 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3963,6 +3963,9 @@ export default {
},
subscription: {
mobileReducedFunctionalityMessage: 'No puedes hacer cambios en tu suscripción en la aplicación móvil.',
badge: {
freeTrial: ({numOfDays}) => `Prueba gratuita: ${numOfDays === 1 ? `queda 1 día` : `quedan ${numOfDays} días`}`,
},
billingBanner: {
policyOwnerAmountOwed: {
title: 'Tu información de pago está desactualizada',
Expand Down Expand Up @@ -4020,6 +4023,10 @@ export default {
subtitle: 'Para empezar, ',
subtitleLink: 'completa la lista de configuración aquí.',
},
trialStarted: {
title: ({numOfDays}) => `Prueba gratuita: ¡${numOfDays === 1 ? `queda 1 día` : `quedan ${numOfDays} días`}!`,
subtitle: 'Añade una tarjeta de pago para seguir utilizando tus funciones favoritas.',
},
},
cardSection: {
title: 'Pago',
Expand Down
2 changes: 1 addition & 1 deletion src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ const isPolicyAdmin = (policy: OnyxInputOrEntry<Policy>, currentUserLogin?: stri
(policy?.role ?? (currentUserLogin && policy?.employeeList?.[currentUserLogin]?.role)) === CONST.POLICY.ROLE.ADMIN;

/**
* Checks if the current user is an user of the policy.
* Checks if the current user is of the role "user" on the policy.
*/
const isPolicyUser = (policy: OnyxInputOrEntry<Policy>, currentUserLogin?: string): boolean =>
(policy?.role ?? (currentUserLogin && policy?.employeeList?.[currentUserLogin]?.role)) === CONST.POLICY.ROLE.USER;
Expand Down
8 changes: 8 additions & 0 deletions src/pages/home/HeaderView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {memo, useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import {withOnyx} from 'react-native-onyx';
import Badge from '@components/Badge';
import Button from '@components/Button';
import CaretWrapper from '@components/CaretWrapper';
import ConfirmModal from '@components/ConfirmModal';
Expand All @@ -27,6 +28,7 @@ import * as HeaderUtils from '@libs/HeaderUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import * as ReportUtils from '@libs/ReportUtils';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import * as Link from '@userActions/Link';
import * as Report from '@userActions/Report';
import * as Session from '@userActions/Session';
Expand Down Expand Up @@ -346,6 +348,12 @@ function HeaderView({
)}
</PressableWithoutFeedback>
<View style={[styles.reportOptions, styles.flexRow, styles.alignItemsCenter]}>
{ReportUtils.isChatUsedForOnboarding(report) && SubscriptionUtils.isUserOnFreeTrial() && (
<Badge
success
text={translate('subscription.badge.freeTrial', {numOfDays: SubscriptionUtils.calculateRemainingFreeTrialDays()})}
/>
)}
{isTaskReport && !shouldUseNarrowLayout && ReportUtils.isOpenTaskReport(report, parentReportAction) && <TaskHeaderActionButton report={report} />}
{canJoin && !shouldUseNarrowLayout && joinButton}
{shouldShowThreeDotsButton && (
Expand Down
10 changes: 8 additions & 2 deletions src/pages/settings/InitialSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import useWaitForNavigation from '@hooks/useWaitForNavigation';
import * as CurrencyUtils from '@libs/CurrencyUtils';
import Navigation from '@libs/Navigation/Navigation';
import shouldShowSubscriptionsMenu from '@libs/shouldShowSubscriptionsMenu';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import * as UserUtils from '@libs/UserUtils';
import {hasGlobalWorkspaceSettingsRBR} from '@libs/WorkspacesSettingsUtils';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
Expand Down Expand Up @@ -90,6 +91,8 @@ type MenuData = {
title?: string;
shouldShowRightIcon?: boolean;
iconRight?: IconAsset;
badgeText?: string;
badgeStyle?: ViewStyle;
};

type Menu = {sectionStyle: StyleProp<ViewStyle>; sectionTranslationKey: TranslationPaths; items: MenuData[]};
Expand Down Expand Up @@ -209,6 +212,8 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa
shouldShowRightIcon: true,
iconRight: Expensicons.NewWindow,
link: () => Link.buildOldDotURL(CONST.OLDDOT_URLS.ADMIN_POLICIES_URL),
badgeText: SubscriptionUtils.isUserOnFreeTrial() ? translate('subscription.badge.freeTrial', {numOfDays: SubscriptionUtils.calculateRemainingFreeTrialDays()}) : undefined,
badgeStyle: SubscriptionUtils.isUserOnFreeTrial() ? styles.badgeSuccess : undefined,
});
}

Expand All @@ -217,7 +222,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa
sectionTranslationKey: 'common.workspaces',
items,
};
}, [policies, styles.workspaceSettingsSectionContainer]);
}, [policies, styles.badgeSuccess, styles.workspaceSettingsSectionContainer, translate]);

/**
* Retuns a list of menu items data for general section
Expand Down Expand Up @@ -316,7 +321,8 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa
}
})}
iconStyles={item.iconStyles}
badgeText={getWalletBalance(isPaymentItem)}
badgeText={item.badgeText ?? getWalletBalance(isPaymentItem)}
badgeStyle={item.badgeStyle}
fallbackIcon={item.fallbackIcon}
brickRoadIndicator={item.brickRoadIndicator}
floatRightAvatars={item.floatRightAvatars}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import BillingBanner from './BillingBanner';

function TrialStartedBillingBanner() {
const {translate} = useLocalize();

return (
<BillingBanner
title={translate('subscription.billingBanner.trialStarted.title', {numOfDays: SubscriptionUtils.calculateRemainingFreeTrialDays()})}
subtitle={translate('subscription.billingBanner.trialStarted.subtitle')}
icon={Illustrations.TreasureChest}
/>
);
}

TrialStartedBillingBanner.displayName = 'TrialStartedBillingBanner';

export default TrialStartedBillingBanner;
4 changes: 4 additions & 0 deletions src/pages/settings/Subscription/CardSection/CardSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import useThemeStyles from '@hooks/useThemeStyles';
import * as User from '@libs/actions/User';
import DateUtils from '@libs/DateUtils';
import Navigation from '@libs/Navigation/Navigation';
import * as SubscriptionUtils from '@libs/SubscriptionUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import PreTrialBillingBanner from './BillingBanner/PreTrialBillingBanner';
import SubscriptionBillingBanner from './BillingBanner/SubscriptionBillingBanner';
import TrialStartedBillingBanner from './BillingBanner/TrialStartedBillingBanner';
import CardSectionActions from './CardSectionActions';
import CardSectionDataEmpty from './CardSectionDataEmpty';
import CardSectionUtils from './utils';
Expand Down Expand Up @@ -54,6 +56,8 @@ function CardSection() {
let BillingBanner: React.ReactNode | undefined;
if (CardSectionUtils.shouldShowPreTrialBillingBanner()) {
BillingBanner = <PreTrialBillingBanner />;
} else if (SubscriptionUtils.isUserOnFreeTrial()) {
BillingBanner = <TrialStartedBillingBanner />;
} else if (billingStatus) {
BillingBanner = (
<SubscriptionBillingBanner
Expand Down

0 comments on commit f1366b4

Please sign in to comment.