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

feat: Subscription size backend integration #43484

Merged
Merged
Show file tree
Hide file tree
Changes from 14 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
5 changes: 4 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@ const ROUTES = {
SETTINGS_PRONOUNS: 'settings/profile/pronouns',
SETTINGS_PREFERENCES: 'settings/preferences',
SETTINGS_SUBSCRIPTION: 'settings/subscription',
SETTINGS_SUBSCRIPTION_SIZE: 'settings/subscription/subscription-size',
SETTINGS_SUBSCRIPTION_SIZE: {
route: 'settings/subscription/subscription-size',
getRoute: (canChangeSize: 0 | 1) => `settings/subscription/subscription-size?canChangeSize=${canChangeSize}` as const,
},
SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD: 'settings/subscription/add-payment-card',
SETTINGS_SUBSCRIPTION_DISABLE_AUTO_RENEW_SURVEY: 'settings/subscription/disable-auto-renew-survey',
SETTINGS_PRIORITY_MODE: 'settings/preferences/priority-mode',
Expand Down
1 change: 1 addition & 0 deletions src/components/FocusTrap/WIDE_LAYOUT_INACTIVE_SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = [
SCREENS.SETTINGS.WALLET.ROOT,
SCREENS.SETTINGS.ABOUT,
SCREENS.SETTINGS.WORKSPACES,
SCREENS.SETTINGS.SUBSCRIPTION.ROOT,
SCREENS.WORKSPACE.INITIAL,
SCREENS.WORKSPACE.PROFILE,
SCREENS.WORKSPACE.CARD,
Expand Down
1 change: 1 addition & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3276,6 +3276,7 @@ export default {
`You already committed to an annual subscription size of ${size} active members per month until ${date}. You can switch to a pay-per-use subscription on ${date} by disabling auto-renew.`,
error: {
size: 'Please enter a valid subscription size.',
sameSize: 'Please enter a number different than your current subscription size.',
},
},
paymentCard: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3783,6 +3783,7 @@ export default {
`Ya se ha comprometido a un tamaño de suscripción anual de ${size} miembros activos al mes hasta el ${date}. Puede cambiar a una suscripción de pago por uso en ${date} desactivando la auto-renovación.`,
error: {
size: 'Por favor ingrese un tamaño de suscripción valido.',
sameSize: 'Por favor, introduce un número diferente al de tu subscripción actual.',
},
},
paymentCard: {
Expand Down
5 changes: 5 additions & 0 deletions src/libs/API/parameters/UpdateSubscriptionSizeParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type UpdateSubscriptionSizeParams = {
userCount: number;
};

export default UpdateSubscriptionSizeParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,4 @@ export type {default as PayInvoiceParams} from './PayInvoiceParams';
export type {default as MarkAsCashParams} from './MarkAsCashParams';
export type {default as UpdateSubscriptionTypeParams} from './UpdateSubscriptionTypeParams';
export type {default as SignUpUserParams} from './SignUpUserParams';
export type {default as UpdateSubscriptionSizeParams} from './UpdateSubscriptionSizeParams';
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ const WRITE_COMMANDS = {
MARK_AS_CASH: 'MarkAsCash',
UPDATE_SUBSCRIPTION_TYPE: 'UpdateSubscriptionType',
SIGN_UP_USER: 'SignUpUser',
UPDATE_SUBSCRIPTION_SIZE: 'UpdateSubscriptionSize',
} as const;

type WriteCommand = ValueOf<typeof WRITE_COMMANDS>;
Expand Down Expand Up @@ -446,6 +447,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.MARK_AS_CASH]: Parameters.MarkAsCashParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_TYPE]: Parameters.UpdateSubscriptionTypeParams;
[WRITE_COMMANDS.SIGN_UP_USER]: Parameters.SignUpUserParams;
[WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE]: Parameters.UpdateSubscriptionSizeParams;
};

const READ_COMMANDS = {
Expand Down
5 changes: 4 additions & 1 deletion src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,10 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
path: ROUTES.SETTINGS_STATUS_CLEAR_AFTER_TIME,
},
[SCREENS.SETTINGS.SUBSCRIPTION.SIZE]: {
path: ROUTES.SETTINGS_SUBSCRIPTION_SIZE,
path: ROUTES.SETTINGS_SUBSCRIPTION_SIZE.route,
parse: {
canChangeSize: Number,
},
},
[SCREENS.SETTINGS.SUBSCRIPTION.DISABLE_AUTO_RENEW_SURVEY]: {
path: ROUTES.SETTINGS_SUBSCRIPTION_DISABLE_AUTO_RENEW_SURVEY,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ type SettingsNavigatorParamList = {
orderWeight: number;
tagName: string;
};
[SCREENS.SETTINGS.SUBSCRIPTION.ROOT]: undefined;
[SCREENS.SETTINGS.SUBSCRIPTION.SIZE]: {
canChangeSize: 0 | 1;
};
[SCREENS.SETTINGS.SUBSCRIPTION.ADD_PAYMENT_CARD]: undefined;
[SCREENS.WORKSPACE.TAXES_SETTINGS]: {
policyID: string;
Expand Down
64 changes: 63 additions & 1 deletion src/libs/actions/Subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import Onyx from 'react-native-onyx';
import * as API from '@libs/API';
import type {UpdateSubscriptionTypeParams} from '@libs/API/parameters';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
import * as ErrorUtils from '@libs/ErrorUtils';
import type {SubscriptionType} from '@src/CONST';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {OnyxData} from '@src/types/onyx/Request';

/**
* Fetches data when the user opens the SubscriptionSettingsPage
Expand Down Expand Up @@ -61,4 +63,64 @@ function updateSubscriptionType(type: SubscriptionType) {
});
}

export {openSubscriptionPage, updateSubscriptionType};
function updateSubscriptionSize(newSubscriptionSize: number, currentSubscriptionSize: number) {
const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION,
value: {
userCount: newSubscriptionSize,
errorFields: {
userCount: null,
},
pendingFields: {
userCount: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION,
value: {
userCount: newSubscriptionSize,
errorFields: {
userCount: null,
},
pendingFields: {
MrMuzyk marked this conversation as resolved.
Show resolved Hide resolved
userCount: null,
},
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION,
value: {
userCount: currentSubscriptionSize,
errorFields: {
userCount: ErrorUtils.getMicroSecondOnyxError('common.genericErrorMessage'),
},
amyevans marked this conversation as resolved.
Show resolved Hide resolved
pendingFields: {
userCount: null,
},
},
},
],
};

API.write(WRITE_COMMANDS.UPDATE_SUBSCRIPTION_SIZE, {userCount: newSubscriptionSize}, onyxData);
}

function clearUpdateSubscriptionSizeError() {
Onyx.merge(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION, {
errorFields: {
userCount: null,
},
});
}

export {openSubscriptionPage, updateSubscriptionType, updateSubscriptionSize, clearUpdateSubscriptionSizeError};
31 changes: 22 additions & 9 deletions src/pages/settings/Subscription/SubscriptionDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,25 +42,38 @@ function SubscriptionDetails() {
const [account] = useOnyx(ONYXKEYS.ACCOUNT);

const onOptionSelected = (option: SubscriptionType) => {
if (privateSubscription?.type === CONST.SUBSCRIPTION.TYPE.ANNUAL && option === CONST.SUBSCRIPTION.TYPE.PAYPERUSE) {
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(0));
return;
}
amyevans marked this conversation as resolved.
Show resolved Hide resolved

Subscription.updateSubscriptionType(option);
};

const onSubscriptionSizePress = () => {
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE);
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(1));
};

// This section is only shown when the subscription is annual
const subscriptionSizeSection: React.JSX.Element | null =
privateSubscription?.type === CONST.SUBSCRIPTION.TYPE.ANNUAL ? (
<>
<MenuItemWithTopDescription
description={translate('subscription.details.subscriptionSize')}
shouldShowRightIcon
onPress={onSubscriptionSizePress}
wrapperStyle={styles.sectionMenuItemTopDescription}
style={styles.mt5}
title={`${privateSubscription?.userCount ?? ''}`}
/>
<OfflineWithFeedback
pendingAction={privateSubscription?.pendingFields?.userCount}
errors={privateSubscription?.errorFields?.userCount}
onClose={() => {
Subscription.clearUpdateSubscriptionSizeError();
}}
>
<MenuItemWithTopDescription
description={translate('subscription.details.subscriptionSize')}
shouldShowRightIcon
onPress={onSubscriptionSizePress}
wrapperStyle={styles.sectionMenuItemTopDescription}
style={styles.mt5}
title={`${privateSubscription?.userCount ?? ''}`}
/>
</OfflineWithFeedback>
{!privateSubscription?.userCount && <Text style={[styles.mt2, styles.textLabelSupporting, styles.textLineHeightNormal]}>{translate('subscription.details.headsUp')}</Text>}
</>
) : null;
Expand Down
28 changes: 15 additions & 13 deletions src/pages/settings/Subscription/SubscriptionSize/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React from 'react';
import {useOnyx} from 'react-native-onyx';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
Expand All @@ -6,31 +7,31 @@ import useLocalize from '@hooks/useLocalize';
import useSubStep from '@hooks/useSubStep';
import type {SubStepProps} from '@hooks/useSubStep/types';
import Navigation from '@libs/Navigation/Navigation';
import type {SettingsNavigatorParamList} from '@navigation/types';
import * as Subscription from '@userActions/Subscription';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import INPUT_IDS from '@src/types/form/SubscriptionSizeForm';
import Confirmation from './substeps/Confirmation';
import Size from './substeps/Size';

const bodyContent: Array<React.ComponentType<SubStepProps>> = [Size, Confirmation];

function SubscriptionSizePage() {
type SubscriptionSizePageProps = StackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.SUBSCRIPTION.SIZE>;

function SubscriptionSizePage({route}: SubscriptionSizePageProps) {
const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
const [subscriptionSizeFormDraft] = useOnyx(ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM_DRAFT);
const {translate} = useLocalize();
// TODO startFrom variable will get it's value based on ONYX data, it will be implemented in next phase (account?.canDowngrade field)
const CAN_DOWNGRADE = true;
const startFrom = CAN_DOWNGRADE ? 0 : 1;
const canChangeSubscriptionSize = !!(route.params?.canChangeSize ?? 0);
const startFrom = canChangeSubscriptionSize ? 0 : 1;

const onFinished = () => {
if (CAN_DOWNGRADE) {
// TODO this is temporary solution for the time being, API call will be implemented in next phase
// eslint-disable-next-line no-console
console.log(subscriptionSizeFormDraft);
return;
}

Subscription.updateSubscriptionSize(subscriptionSizeFormDraft ? Number(subscriptionSizeFormDraft[INPUT_IDS.SUBSCRIPTION_SIZE]) : 0, privateSubscription?.userCount ?? 0);
Navigation.goBack();
};

const {componentToRender: SubStep, isEditing, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent, startFrom, onFinished});
const {componentToRender: SubStep, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent, startFrom, onFinished});

const onBackButtonPress = () => {
if (screenIndex !== 0 && startFrom === 0) {
Expand All @@ -47,13 +48,14 @@ function SubscriptionSizePage() {
includeSafeAreaPaddingBottom={false}
shouldEnablePickerAvoiding={false}
shouldEnableMaxHeight
shouldShowOfflineIndicatorInWideScreen
>
<HeaderWithBackButton
title={translate('subscription.subscriptionSize.title')}
onBackButtonPress={onBackButtonPress}
/>
<SubStep
isEditing={isEditing}
isEditing={canChangeSubscriptionSize}
onNext={nextScreen}
onMove={moveTo}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {format} from 'date-fns';
import React from 'react';
import {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
Expand All @@ -6,31 +7,37 @@ import FixedFooter from '@components/FixedFooter';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import type {SubStepProps} from '@hooks/useSubStep/types';
import useThemeStyles from '@hooks/useThemeStyles';
import {getNewSubscriptionRenewalDate} from '@pages/settings/Subscription/SubscriptionSize/utils';
import Navigation from '@navigation/Navigation';
import getNewSubscriptionRenewalDate from '@pages/settings/Subscription/SubscriptionSize/utils';
import * as FormActions from '@userActions/FormActions';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import INPUT_IDS from '@src/types/form/SubscriptionSizeForm';

type ConfirmationProps = SubStepProps;

function Confirmation({onNext}: ConfirmationProps) {
function Confirmation({onNext, isEditing}: ConfirmationProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const {isOffline} = useNetwork();
const [account] = useOnyx(ONYXKEYS.ACCOUNT);
const [privateSubscription] = useOnyx(ONYXKEYS.NVP_PRIVATE_SUBSCRIPTION);
const [subscriptionSizeFormDraft] = useOnyx(ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM_DRAFT);
const subscriptionRenewalDate = getNewSubscriptionRenewalDate();

// TODO this is temporary and will be replaced in next phase once data in ONYX is ready
// we will have to check if the amount of active members is less than the current amount of active members and if account?.canDowngrade is true - if so then we can't downgrade
const CAN_DOWNGRADE = true;
// TODO this is temporary and will be replaced in next phase once data in ONYX is ready
const SUBSCRIPTION_UNTIL = subscriptionRenewalDate;
const isTryingToIncreaseSubscriptionSize = (subscriptionSizeFormDraft ? Number(subscriptionSizeFormDraft[INPUT_IDS.SUBSCRIPTION_SIZE]) : 0) > (privateSubscription?.userCount ?? 0);
const canChangeSubscriptionSize = (account?.canDowngrade ?? false) || (isTryingToIncreaseSubscriptionSize && isEditing);
const newSubscriptionEndDate = privateSubscription?.endDate ? format(new Date(privateSubscription?.endDate), CONST.DATE.MONTH_DAY_YEAR_ABBR_FORMAT) : '';
amyevans marked this conversation as resolved.
Show resolved Hide resolved

const onClosePress = () => {
FormActions.clearDraftValues(ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM);
Navigation.goBack();
};

return (
<View style={[styles.flexGrow1]}>
{CAN_DOWNGRADE ? (
{canChangeSubscriptionSize ? (
<>
<Text style={[styles.ph5, styles.pb3]}>{translate('subscription.subscriptionSize.confirmDetails')}</Text>
<MenuItemWithTopDescription
Expand All @@ -49,20 +56,28 @@ function Confirmation({onNext}: ConfirmationProps) {
<Text style={[styles.ph5, styles.pb5, styles.textNormalThemeText]}>{translate('subscription.subscriptionSize.youCantDowngrade')}</Text>
<Text style={[styles.ph5, styles.textNormalThemeText]}>
{translate('subscription.subscriptionSize.youAlreadyCommitted', {
size: subscriptionSizeFormDraft ? subscriptionSizeFormDraft[INPUT_IDS.SUBSCRIPTION_SIZE] : 0,
date: SUBSCRIPTION_UNTIL,
size: privateSubscription?.userCount ?? 0,
date: newSubscriptionEndDate,
})}
</Text>
</>
)}
<FixedFooter style={[styles.mtAuto]}>
<Button
isDisabled={isOffline}
success
large
onPress={onNext}
text={translate(CAN_DOWNGRADE ? 'common.save' : 'common.close')}
/>
{canChangeSubscriptionSize ? (
<Button
success
large
onPress={onNext}
text={translate('common.save')}
/>
) : (
<Button
success
large
onPress={onClosePress}
text={translate('common.close')}
/>
)}
</FixedFooter>
</View>
);
Expand Down
Loading
Loading