Skip to content
Open
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
8 changes: 8 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2789,6 +2789,14 @@ const CONST = {
CONFIRM: 'confirm',
},
},

SUBSCRIPTION_SIZE: {
PAGE_NAME: {
SIZE: 'size',
CONFIRM: 'confirm',
},
},

MISSING_PERSONAL_DETAILS_INDEXES: {
MAPPING: {
LEGAL_NAME: 0,
Expand Down
4 changes: 2 additions & 2 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,8 +280,8 @@ const ROUTES = {
getRoute: (backTo?: string) => getUrlWithBackToParam('settings/subscription', backTo),
},
SETTINGS_SUBSCRIPTION_SIZE: {
route: 'settings/subscription/subscription-size',
getRoute: (canChangeSize: 0 | 1) => `settings/subscription/subscription-size?canChangeSize=${canChangeSize as number}` as const,
route: 'settings/subscription/subscription-size/:subPage',
getRoute: (subPage: string) => `settings/subscription/subscription-size/${subPage}` as const,
},
SETTINGS_SUBSCRIPTION_SETTINGS_DETAILS: 'settings/subscription/details',
SETTINGS_SUBSCRIPTION_ADD_PAYMENT_CARD: 'settings/subscription/add-payment-card',
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useSubPage/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type {Route} from '@src/ROUTES';

type SubPageProps = {
/** value indicating whether user is editing one of the sub pages */
isEditing: boolean;
isEditing?: boolean;

/** continues to next sub page */
onNext: (data?: unknown) => void;
Expand Down
2 changes: 2 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,8 @@ type SettingsNavigatorParamList = {
};
[SCREENS.SETTINGS.SUBSCRIPTION.SIZE]: {
canChangeSize: 0 | 1;
subPage?: string;
action?: 'edit';
};
[SCREENS.SETTINGS.SUBSCRIPTION.SETTINGS_DETAILS]: undefined;
[SCREENS.SETTINGS.SUBSCRIPTION.ADD_PAYMENT_CARD]: undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function SubscriptionSettings() {
return;
}
if (privateSubscription?.type === CONST.SUBSCRIPTION.TYPE.ANNUAL && option === CONST.SUBSCRIPTION.TYPE.PAY_PER_USE && !account?.canDowngrade) {
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(0));
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_DOWNGRADE_BLOCKED.route);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The canChangeSize param is used to show the downgrade blocked view when trying to downgrade from an annual to a pay-per-use plan, so instead of conditionally rendering it based on the params that can be easily changed by the user, I navigate to the already existing downgrade blocked page.

return;
}

Expand All @@ -87,7 +87,7 @@ function SubscriptionSettings() {
showDelegateNoAccessModal();
return;
}
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(1));
Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(CONST.SUBSCRIPTION_SIZE.PAGE_NAME.SIZE));
};
const illustrations = useMemoizedLazyIllustrations(['SubscriptionAnnual', 'SubscriptionPPU']);

Expand Down
35 changes: 17 additions & 18 deletions src/pages/settings/Subscription/SubscriptionSize/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,43 @@
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePrivateSubscription from '@hooks/usePrivateSubscription';
import useSubStep from '@hooks/useSubStep';
import type {SubStepProps} from '@hooks/useSubStep/types';
import useSubPage from '@hooks/useSubPage';
import {clearDraftValues} from '@libs/actions/FormActions';
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types';
import {isSubscriptionTypeOfInvoicing} from '@libs/SubscriptionUtils';
import type {SettingsNavigatorParamList} from '@navigation/types';
import NotFoundPage from '@pages/ErrorPage/NotFoundPage';
import {updateSubscriptionSize} from '@userActions/Subscription';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type SCREENS from '@src/SCREENS';
import ROUTES from '@src/ROUTES';
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];
const pages = [
{pageName: CONST.SUBSCRIPTION_SIZE.PAGE_NAME.SIZE, component: Size},
{pageName: CONST.SUBSCRIPTION_SIZE.PAGE_NAME.CONFIRM, component: Confirmation},
];

type SubscriptionSizePageProps = PlatformStackScreenProps<SettingsNavigatorParamList, typeof SCREENS.SETTINGS.SUBSCRIPTION.SIZE>;

function SubscriptionSizePage({route}: SubscriptionSizePageProps) {
function SubscriptionSizePage() {
const privateSubscription = usePrivateSubscription();
const [subscriptionSizeFormDraft] = useOnyx(ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM_DRAFT, {canBeMissing: false});
const {translate} = useLocalize();
const canChangeSubscriptionSize = !!(route.params?.canChangeSize ?? 1);
const startFrom = canChangeSubscriptionSize ? 0 : 1;

const onFinished = () => {
updateSubscriptionSize(subscriptionSizeFormDraft ? Number(subscriptionSizeFormDraft[INPUT_IDS.SUBSCRIPTION_SIZE]) : 0, privateSubscription?.userCount ?? 0);
Navigation.goBack();
Navigation.goBack(ROUTES.SETTINGS_SUBSCRIPTION_SETTINGS_DETAILS);
};

const {componentToRender: SubStep, screenIndex, nextScreen, prevScreen, moveTo} = useSubStep({bodyContent, startFrom, onFinished});
const {CurrentPage, pageIndex, prevPage, nextPage, moveTo} = useSubPage({
pages,
onFinished,
buildRoute: (pageName) => ROUTES.SETTINGS_SUBSCRIPTION_SIZE.getRoute(pageName),
});

const onBackButtonPress = () => {
if (screenIndex !== 0 && startFrom === 0) {
prevScreen();
if (pageIndex !== 0) {
prevPage();
return;
}

Expand Down Expand Up @@ -77,9 +77,8 @@
title={translate('subscription.subscriptionSize.title')}
onBackButtonPress={onBackButtonPress}
/>
<SubStep
isEditing={canChangeSubscriptionSize}
onNext={nextScreen}
<CurrentPage

Check failure on line 80 in src/pages/settings/Subscription/SubscriptionSize/index.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Property 'isEditing' is missing in type '{ onNext: (finishData?: unknown) => void; onMove: (step: number, turnOnEditMode?: boolean | undefined) => void; }' but required in type 'SubStepProps'.
onNext={nextPage}
onMove={moveTo}
/>
</DelegateNoAccessWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,27 @@ import {View} from 'react-native';
import Button from '@components/Button';
import FixedFooter from '@components/FixedFooter';
import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription';
import SubscriptionPlanDowngradeBlocked from '@components/SubscriptionPlanDowngradeBlocked';
import Text from '@components/Text';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import usePrivateSubscription from '@hooks/usePrivateSubscription';
import type {SubStepProps} from '@hooks/useSubStep/types';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@navigation/Navigation';
import {formatSubscriptionEndDate, getNewSubscriptionRenewalDate} from '@pages/settings/Subscription/utils';
import {getNewSubscriptionRenewalDate} from '@pages/settings/Subscription/utils';
import ONYXKEYS from '@src/ONYXKEYS';
import INPUT_IDS from '@src/types/form/SubscriptionSizeForm';

type ConfirmationProps = SubStepProps;

function Confirmation({onNext, isEditing}: ConfirmationProps) {
function Confirmation({onNext}: ConfirmationProps) {

Choose a reason for hiding this comment

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

P1 Badge Reinstate downgrade guard on subscription size confirmation

Removing isEditing here also removed the account.canDowngrade check that previously blocked annual-plan seat decreases. In the current flow, users with canDowngrade === false can go through Subscription Size, enter a smaller member count, and still reach Save, which sends an updateSubscriptionSize request instead of showing the downgrade-blocked state. That is a behavior regression for restricted downgrade scenarios.

Useful? React with 👍 / 👎.

const {translate} = useLocalize();
const styles = useThemeStyles();
const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: false});
const privateSubscription = usePrivateSubscription();
const [subscriptionSizeFormDraft] = useOnyx(ONYXKEYS.FORMS.SUBSCRIPTION_SIZE_FORM_DRAFT, {canBeMissing: true});
const subscriptionRenewalDate = getNewSubscriptionRenewalDate();
const subscriptionSizeDraft = subscriptionSizeFormDraft ? Number(subscriptionSizeFormDraft[INPUT_IDS.SUBSCRIPTION_SIZE]) : 0;
const subscriptionSize = subscriptionSizeDraft || (privateSubscription?.userCount ?? 0);

const isTryingToIncreaseSubscriptionSize = subscriptionSizeDraft > (privateSubscription?.userCount ?? 0);
const canChangeSubscriptionSize = (account?.canDowngrade ?? false) || (isTryingToIncreaseSubscriptionSize && isEditing);
const formattedSubscriptionEndDate = formatSubscriptionEndDate(privateSubscription?.endDate);

const onClosePress = () => {
Navigation.goBack();
};

if (!canChangeSubscriptionSize) {
return (
<SubscriptionPlanDowngradeBlocked
privateSubscription={privateSubscription}
formattedSubscriptionEndDate={formattedSubscriptionEndDate}
onClosePress={onClosePress}
/>
);
}

return (
<View style={[styles.flexGrow1]}>
<Text style={[styles.ph5, styles.pb3]}>{translate('subscription.subscriptionSize.confirmDetails')}</Text>
Expand Down
Loading