Skip to content

Commit

Permalink
Merge pull request #44483 from callstack-internal/pac-guerreiro/featu…
Browse files Browse the repository at this point in the history
…re/43671-trial-ended-banner-expensify-dm-gbr-and-custom-chat-item

[Free trial] Implement and show Trial Ended banner, Expensify DM GBR and custom Expensify DM chat item in the App after Free Trial ends
  • Loading branch information
chiragsalian authored Jul 11, 2024
2 parents a8bbd47 + 531e0be commit 075e9fc
Show file tree
Hide file tree
Showing 16 changed files with 124 additions and 2 deletions.
37 changes: 37 additions & 0 deletions assets/images/simple-illustrations/simple-illustration__tire.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ const CONST = {
LIMIT: 50,
// OldDot Actions render getMessage from Web-Expensify/lib/Report/Action PHP files via getMessageOfOldDotReportAction in ReportActionsUtils.ts
TYPE: {
ACTIONABLE_ADD_PAYMENT_CARD: 'ACTIONABLEADDPAYMENTCARD',
ACTIONABLE_JOIN_REQUEST: 'ACTIONABLEJOINREQUEST',
ACTIONABLE_MENTION_WHISPER: 'ACTIONABLEMENTIONWHISPER',
ACTIONABLE_REPORT_MENTION_WHISPER: 'ACTIONABLEREPORTMENTIONWHISPER',
Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Illustrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ import SubscriptionPPU from '@assets/images/simple-illustrations/simple-illustra
import Tag from '@assets/images/simple-illustrations/simple-illustration__tag.svg';
import TeachersUnite from '@assets/images/simple-illustrations/simple-illustration__teachers-unite.svg';
import ThumbsUpStars from '@assets/images/simple-illustrations/simple-illustration__thumbsupstars.svg';
import Tire from '@assets/images/simple-illustrations/simple-illustration__tire.svg';
import TrackShoe from '@assets/images/simple-illustrations/simple-illustration__track-shoe.svg';
import TrashCan from '@assets/images/simple-illustrations/simple-illustration__trashcan.svg';
import TreasureChest from '@assets/images/simple-illustrations/simple-illustration__treasurechest.svg';
Expand Down Expand Up @@ -204,4 +205,5 @@ export {
EmptyState,
FolderWithPapers,
VirtualCard,
Tire,
};
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3984,6 +3984,10 @@ export default {
title: ({numOfDays}) => `Free trial: ${numOfDays} ${numOfDays === 1 ? 'day' : 'days'} left!`,
subtitle: 'Add a payment card to continue using all of your favorite features.',
},
trialEnded: {
title: 'Your free trial has ended',
subtitle: 'Add a payment card to continue using all of your favorite features.',
},
},
cardSection: {
title: 'Payment',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4501,6 +4501,10 @@ export default {
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.',
},
trialEnded: {
title: 'Tu prueba gratuita ha terminado',
subtitle: 'Añade una tarjeta de pago para seguir utilizando tus funciones favoritas.',
},
},
cardSection: {
title: 'Pago',
Expand Down
2 changes: 2 additions & 0 deletions src/libs/OptionsListUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -725,6 +725,8 @@ function getLastMessageTextForReport(report: OnyxEntry<Report>, lastActorDetails
lastMessageTextFromReport = ReportUtils.getIOUSubmittedMessage(reportID);
} else if (lastReportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.APPROVED) {
lastMessageTextFromReport = ReportUtils.getIOUApprovedMessage(reportID);
} else if (ReportActionUtils.isActionableAddPaymentCard(lastReportAction)) {
lastMessageTextFromReport = ReportActionUtils.getReportActionMessageText(lastReportAction);
}

return lastMessageTextFromReport || (report?.lastMessageText ?? '');
Expand Down
9 changes: 9 additions & 0 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1408,6 +1408,14 @@ function getTrackExpenseActionableWhisper(transactionID: string, chatReportID: s
return Object.values(chatReportActions).find((action: ReportAction) => isActionableTrackExpense(action) && getOriginalMessage(action)?.transactionID === transactionID);
}

/**
* Checks if a given report action corresponds to a add payment card action.
* @param reportAction
*/
function isActionableAddPaymentCard(reportAction: OnyxEntry<ReportAction>): reportAction is ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_ADD_PAYMENT_CARD> {
return reportAction?.actionName === CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_ADD_PAYMENT_CARD;
}

export {
extractLinksFromMessageHtml,
getDismissedViolationMessageText,
Expand Down Expand Up @@ -1494,6 +1502,7 @@ export {
isTripPreview,
getIOUActionForReportID,
getFilteredForOneTransactionView,
isActionableAddPaymentCard,
};

export type {LastVisibleMessage};
7 changes: 5 additions & 2 deletions src/libs/ReportUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ type OptionData = {
shouldShowAmountInput?: boolean;
amountInputProps?: MoneyRequestAmountInputProps;
tabIndex?: 0 | -1;
isConciergeChat?: boolean;
} & Report;

type OnyxDataTaskAssigneeChat = {
Expand Down Expand Up @@ -7081,8 +7082,10 @@ function shouldShowMerchantColumn(transactions: Transaction[]) {
/**
* Whether the report is a system chat or concierge chat, depending on the user's account ID (used for A/B testing purposes).
*/
function isChatUsedForOnboarding(report: OnyxEntry<Report>): boolean {
return AccountUtils.isAccountIDOddNumber(currentUserAccountID ?? -1) ? isSystemChat(report) : isConciergeChatReport(report);
function isChatUsedForOnboarding(optionOrReport: OnyxEntry<Report> | OptionData): boolean {
return AccountUtils.isAccountIDOddNumber(currentUserAccountID ?? -1)
? isSystemChat(optionOrReport)
: (optionOrReport as OptionData).isConciergeChat ?? isConciergeChatReport(optionOrReport);
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ function getOptionData({
isWaitingOnBankAccount: false,
isAllowedToComment: true,
isDeletedParentAction: false,
isConciergeChat: false,
};

const participantAccountIDs = ReportUtils.getParticipantsAccountIDsForDisplay(report);
Expand Down Expand Up @@ -305,6 +306,7 @@ function getOptionData({
result.tooltipText = ReportUtils.getReportParticipantsTitle(visibleParticipantAccountIDs);
result.hasOutstandingChildTask = report.hasOutstandingChildTask;
result.hasParentAccess = report.hasParentAccess;
result.isConciergeChat = ReportUtils.isConciergeChatReport(report);

const hasMultipleParticipants = participantPersonalDetailList.length > 1 || result.isChatRoom || result.isPolicyExpenseChat || ReportUtils.isExpenseReport(report);
const subtitle = ReportUtils.getChatRoomSubtitle(report);
Expand Down
5 changes: 5 additions & 0 deletions src/libs/shouldRenderAppPaymentCard/index.native.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type ShouldRenderAddPaymentCard from './types';

const shouldRenderAddPaymentCard: ShouldRenderAddPaymentCard = () => false;

export default shouldRenderAddPaymentCard;
5 changes: 5 additions & 0 deletions src/libs/shouldRenderAppPaymentCard/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type ShouldRenderAddPaymentCard from './types';

const shouldRenderAddPaymentCard: ShouldRenderAddPaymentCard = () => true;

export default shouldRenderAddPaymentCard;
3 changes: 3 additions & 0 deletions src/libs/shouldRenderAppPaymentCard/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type ShouldRenderAddPaymentCard = () => boolean;

export default ShouldRenderAddPaymentCard;
15 changes: 15 additions & 0 deletions src/pages/home/report/ReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import * as PolicyUtils from '@libs/PolicyUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import * as ReportUtils from '@libs/ReportUtils';
import SelectionScraper from '@libs/SelectionScraper';
import shouldRenderAddPaymentCard from '@libs/shouldRenderAppPaymentCard';
import {ReactionListContext} from '@pages/home/ReportScreenContext';
import * as BankAccounts from '@userActions/BankAccounts';
import * as EmojiPickerAction from '@userActions/EmojiPickerAction';
Expand Down Expand Up @@ -398,6 +399,20 @@ function ReportActionItem({
const attachmentContextValue = useMemo(() => ({reportID: report.reportID, type: CONST.ATTACHMENT_TYPE.REPORT}), [report.reportID]);

const actionableItemButtons: ActionableItem[] = useMemo(() => {
if (ReportActionsUtils.isActionableAddPaymentCard(action) && shouldRenderAddPaymentCard()) {
return [
{
text: 'subscription.cardSection.addCardButton',
key: `${action.reportActionID}-actionableAddPaymentCard-submit`,
onPress: () => {
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION);
},
isMediumSized: true,
isPrimary: true,
},
];
}

if (!isActionableWhisper && (!ReportActionsUtils.isActionableJoinRequest(action) || ReportActionsUtils.getOriginalMessage(action)?.choice !== ('' as JoinWorkspaceResolution))) {
return [];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import BillingBanner from './BillingBanner';

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

return (
<BillingBanner
title={translate('subscription.billingBanner.trialEnded.title')}
subtitle={translate('subscription.billingBanner.trialEnded.subtitle')}
icon={Illustrations.Tire}
/>
);
}

TrialEndedBillingBanner.displayName = 'TrialEndedBillingBanner';

export default TrialEndedBillingBanner;
3 changes: 3 additions & 0 deletions src/pages/settings/Subscription/CardSection/CardSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import ROUTES from '@src/ROUTES';
import {isEmptyObject} from '@src/types/utils/EmptyObject';
import PreTrialBillingBanner from './BillingBanner/PreTrialBillingBanner';
import SubscriptionBillingBanner from './BillingBanner/SubscriptionBillingBanner';
import TrialEndedBillingBanner from './BillingBanner/TrialEndedBillingBanner';
import TrialStartedBillingBanner from './BillingBanner/TrialStartedBillingBanner';
import CardSectionActions from './CardSectionActions';
import CardSectionDataEmpty from './CardSectionDataEmpty';
Expand Down Expand Up @@ -76,6 +77,8 @@ function CardSection() {
BillingBanner = <PreTrialBillingBanner />;
} else if (SubscriptionUtils.isUserOnFreeTrial()) {
BillingBanner = <TrialStartedBillingBanner />;
} else if (SubscriptionUtils.hasUserFreeTrialEnded()) {
BillingBanner = <TrialEndedBillingBanner />;
} else if (billingStatus) {
BillingBanner = (
<SubscriptionBillingBanner
Expand Down
7 changes: 7 additions & 0 deletions src/types/onyx/OriginalMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -414,8 +414,15 @@ type OriginalMessageUnapproved = {
expenseReportID: string;
};

/**
* Model of `Add payment card` report action
*/
type OriginalMessageAddPaymentCard = Record<string, never>;

/** The map type of original message */
type OriginalMessageMap = {
/** */
[CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_ADD_PAYMENT_CARD]: OriginalMessageAddPaymentCard;
/** */
[CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_JOIN_REQUEST]: OriginalMessageJoinPolicyChangeLog;
/** */
Expand Down

0 comments on commit 075e9fc

Please sign in to comment.