Skip to content

Commit

Permalink
Merge pull request #52117 from jayeshmangwani/workspace_downgrade_pla…
Browse files Browse the repository at this point in the history
…n_type_page

Added new route for profile plan type
  • Loading branch information
carlosmiceli authored Nov 27, 2024
2 parents bab8578 + 728afd4 commit 849b20a
Show file tree
Hide file tree
Showing 19 changed files with 346 additions and 28 deletions.
1 change: 1 addition & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -932,6 +932,7 @@ const CONST = {
CONFIGURE_REIMBURSEMENT_SETTINGS_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/workspaces/Configure-Reimbursement-Settings',
COPILOT_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/copilots-and-delegates/Assign-or-remove-a-Copilot',
DELAYED_SUBMISSION_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/reports/Automatically-submit-employee-reports',
PLAN_TYPES_AND_PRICING_HELP_URL: 'https://help.expensify.com/articles/new-expensify/billing-and-subscriptions/Plan-types-and-pricing',
// Use Environment.getEnvironmentURL to get the complete URL with port number
DEV_NEW_EXPENSIFY_URL: 'https://dev.new.expensify.com:',
NAVATTIC: {
Expand Down
10 changes: 7 additions & 3 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/profile/address',
getRoute: (policyID: string, backTo?: string) => getUrlWithBackToParam(`settings/workspaces/${policyID}/profile/address` as const, backTo),
},
WORKSPACE_PROFILE_PLAN: {
route: 'settings/workspaces/:policyID/profile/plan',
getRoute: (policyID: string, backTo?: string) => getUrlWithBackToParam(`settings/workspaces/${policyID}/profile/plan` as const, backTo),
},
WORKSPACE_ACCOUNTING: {
route: 'settings/workspaces/:policyID/accounting',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/accounting` as const,
Expand Down Expand Up @@ -974,9 +978,9 @@ const ROUTES = {
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/category/${encodeURIComponent(categoryName)}` as const,
},
WORKSPACE_UPGRADE: {
route: 'settings/workspaces/:policyID/upgrade/:featureName',
getRoute: (policyID: string, featureName: string, backTo?: string) =>
getUrlWithBackToParam(`settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName)}` as const, backTo),
route: 'settings/workspaces/:policyID/upgrade/:featureName?',
getRoute: (policyID: string, featureName?: string, backTo?: string) =>
getUrlWithBackToParam(`settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName ?? '')}` as const, backTo),
},
WORKSPACE_DOWNGRADE: {
route: 'settings/workspaces/:policyID/downgrade/',
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ const SCREENS = {
TAG_GL_CODE: 'Tag_GL_Code',
CURRENCY: 'Workspace_Profile_Currency',
ADDRESS: 'Workspace_Profile_Address',
PLAN: 'Workspace_Profile_Plan_Type',
WORKFLOWS: 'Workspace_Workflows',
WORKFLOWS_PAYER: 'Workspace_Workflows_Payer',
WORKFLOWS_APPROVALS_NEW: 'Workspace_Approvals_New',
Expand Down
32 changes: 32 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ import type {
WelcomeNoteParams,
WelcomeToRoomParams,
WeSentYouMagicSignInLinkParams,
WorkspaceLockedPlanTypeParams,
WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
YourPlanPriceParams,
ZipCodeExampleFormatParams,
Expand Down Expand Up @@ -2529,6 +2530,7 @@ const translations = {
return 'Member';
}
},
planType: 'Plan type',
submitExpense: 'Submit expenses using your workspace chat below:',
defaultCategory: 'Default category',
},
Expand Down Expand Up @@ -4270,6 +4272,19 @@ const translations = {
moreDetails: 'for more details.',
gotIt: 'Got it, thanks',
},
commonFeatures: {
title: 'Upgrade Workspace to Control',
note: 'Get access to all our most advanced functionality, including:',
benefits: {
note: 'The Control plan starts at $9 per active member per month.',
learnMore: 'Learn more',
pricing: 'about our plans and pricing.',
benefit1: 'Advanced accounting connections (NetSuite, Sage Intacct and more)',
benefit2: 'Expense rules',
benefit3: 'Multiple approval workflows',
benefit4: 'Enhanced security controls',
},
},
},
restrictedAction: {
restricted: 'Restricted',
Expand Down Expand Up @@ -4373,6 +4388,23 @@ const translations = {
andEnableWorkflows: 'and enable workflows, then add approvals to unlock this feature.',
},
},
planTypePage: {
planTypes: {
team: {
label: 'Collect',
description: 'For teams looking to automate their processes.',
},
corporate: {
label: 'Control',
description: 'For organizations with advanced requirements.',
},
},
description: "Choose a plan that's right for you. For a detailed list of features and pricing, check out our",
subscriptionLink: 'plan types and pricing help page',
lockedPlanDescription: ({subscriptionUsersCount, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) =>
`You've committed to ${subscriptionUsersCount} active users on the Control plan until your annual subscription ends on ${annualSubscriptionEndDate}. You can switch to pay-per-use subscription and downgrade to the Collect plan starting ${annualSubscriptionEndDate} by disabling auto-renew in`,
subscriptions: 'Subscriptions',
},
},
getAssistancePage: {
title: 'Get assistance',
Expand Down
32 changes: 32 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ import type {
WelcomeNoteParams,
WelcomeToRoomParams,
WeSentYouMagicSignInLinkParams,
WorkspaceLockedPlanTypeParams,
WorkspaceOwnerWillNeedToAddOrUpdatePaymentCardParams,
YourPlanPriceParams,
ZipCodeExampleFormatParams,
Expand Down Expand Up @@ -2553,6 +2554,7 @@ const translations = {
return 'Miembro';
}
},
planType: 'Tipo de plan',
submitExpense: 'Envíe los gastos utilizando el chat de su espacio de trabajo:',
defaultCategory: 'Categoría predeterminada',
},
Expand Down Expand Up @@ -4237,6 +4239,23 @@ const translations = {
confirmText: 'Sí, exportar de nuevo',
cancelText: 'Cancelar',
},
planTypePage: {
planTypes: {
team: {
label: 'Collect',
description: 'Para equipos que buscan automatizar sus procesos.',
},
corporate: {
label: 'Recolectar',
description: 'Para organizaciones con requisitos avanzados.',
},
},
description: 'Elige el plan adecuado para ti. Para ver una lista detallada de funciones y precios, consulta nuestra',
subscriptionLink: 'página de ayuda sobre tipos de planes y precios',
lockedPlanDescription: ({subscriptionUsersCount, annualSubscriptionEndDate}: WorkspaceLockedPlanTypeParams) =>
`Tienes un compromiso anual de ${subscriptionUsersCount} miembros activos en el plan Control hasta el ${annualSubscriptionEndDate}. Puedes cambiar a una suscripción de pago por uso y desmejorar al plan Recopilar a partir del ${annualSubscriptionEndDate} desactivando la renovación automática en`,
subscriptions: 'Suscripciones',
},
upgrade: {
reportFields: {
title: 'Los campos',
Expand Down Expand Up @@ -4318,6 +4337,19 @@ const translations = {
moreDetails: 'para obtener más información.',
gotIt: 'Entendido, gracias.',
},
commonFeatures: {
title: 'Actualiza tu espacio de trabajo al plan Controlar',
note: 'Obtén acceso a todas nuestras funciones más avanzadas, incluyendo:',
benefits: {
note: 'El plan Controlar comienza en $9 por miembro activo al mes.',
learnMore: 'Obtén más información',
pricing: 'sobre nuestros planes y precios.',
benefit1: 'Conexiones contables avanzadas (NetSuite, Sage Intacct y más)',
benefit2: 'Reglas de gastos',
benefit3: 'Flujos de aprobación múltiples',
benefit4: 'Controles de seguridad mejorados',
},
},
},
restrictedAction: {
restricted: 'Restringido',
Expand Down
5 changes: 5 additions & 0 deletions src/languages/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,10 @@ type CurrencyCodeParams = {
currencyCode: string;
};

type WorkspaceLockedPlanTypeParams = {
subscriptionUsersCount: number;
annualSubscriptionEndDate: string;
};
type CompanyNameParams = {
companyName: string;
};
Expand Down Expand Up @@ -760,5 +764,6 @@ export type {
AssignCardParams,
ImportedTypesParams,
CurrencyCodeParams,
WorkspaceLockedPlanTypeParams,
CompanyNameParams,
};
2 changes: 1 addition & 1 deletion src/libs/API/parameters/UpgradeToCorporateParams.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
type UpgradeToCorporateParams = {
policyID: string;
featureName: string;
featureName?: string;
};

export default UpgradeToCorporateParams;
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.CURRENCY]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceProfileCurrencyPage').default,
[SCREENS.WORKSPACE.CATEGORY_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategorySettingsPage').default,
[SCREENS.WORKSPACE.ADDRESS]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceProfileAddressPage').default,
[SCREENS.WORKSPACE.PLAN]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceProfilePlanTypePage').default,
[SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/WorkspaceCategoriesSettingsPage').default,
[SCREENS.WORKSPACE.CATEGORIES_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/ImportCategoriesPage').default,
[SCREENS.WORKSPACE.CATEGORIES_IMPORTED]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/ImportedCategoriesPage').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
[SCREENS.WORKSPACE.PROFILE]: [
SCREENS.WORKSPACE.NAME,
SCREENS.WORKSPACE.ADDRESS,
SCREENS.WORKSPACE.PLAN,
SCREENS.WORKSPACE.CURRENCY,
SCREENS.WORKSPACE.DESCRIPTION,
SCREENS.WORKSPACE.SHARE,
Expand Down
3 changes: 3 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,9 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.WORKSPACE.ADDRESS]: {
path: ROUTES.WORKSPACE_PROFILE_ADDRESS.route,
},
[SCREENS.WORKSPACE.PLAN]: {
path: ROUTES.WORKSPACE_PROFILE_PLAN.route,
},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_IMPORT]: {path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_IMPORT.route},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_CHART_OF_ACCOUNTS]: {path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CHART_OF_ACCOUNTS.route},
[SCREENS.WORKSPACE.ACCOUNTING.QUICKBOOKS_ONLINE_CLASSES]: {path: ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CLASSES.route},
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ type SettingsNavigatorParamList = {
};
[SCREENS.WORKSPACE.UPGRADE]: {
policyID: string;
featureName: string;
featureName?: string;
backTo?: Routes;
categoryId?: string;
};
Expand Down
12 changes: 12 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,17 @@ function getActivePolicy(): OnyxEntry<Policy> {
return getPolicy(activePolicyId);
}

function getUserFriendlyWorkspaceType(workspaceType: ValueOf<typeof CONST.POLICY.TYPE>) {
switch (workspaceType) {
case CONST.POLICY.TYPE.CORPORATE:
return Localize.translateLocal('workspace.type.control');
case CONST.POLICY.TYPE.TEAM:
return Localize.translateLocal('workspace.type.collect');
default:
return Localize.translateLocal('workspace.type.free');
}
}

function isPolicyAccessible(policy: OnyxEntry<Policy>): boolean {
return !isEmptyObject(policy) && (Object.keys(policy).length !== 1 || isEmptyObject(policy.errors)) && !!policy?.id;
}
Expand Down Expand Up @@ -1246,6 +1257,7 @@ export {
getNetSuiteImportCustomFieldLabel,
getAllPoliciesLength,
getActivePolicy,
getUserFriendlyWorkspaceType,
isPolicyAccessible,
areAllGroupPoliciesExpenseChatDisabled,
};
Expand Down
6 changes: 4 additions & 2 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1663,6 +1663,7 @@ function buildPolicyData(policyOwnerEmail = '', makeMeAdmin = false, policyName
outputCurrency: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
address: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
description: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
type: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD,
},
},
},
Expand Down Expand Up @@ -1735,6 +1736,7 @@ function buildPolicyData(policyOwnerEmail = '', makeMeAdmin = false, policyName
outputCurrency: null,
address: null,
description: null,
type: null,
},
},
},
Expand Down Expand Up @@ -3324,7 +3326,7 @@ function setForeignCurrencyDefault(policyID: string, taxCode: string) {
API.write(WRITE_COMMANDS.SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT, parameters, onyxData);
}

function upgradeToCorporate(policyID: string, featureName: string) {
function upgradeToCorporate(policyID: string, featureName?: string) {
const policy = getPolicy(policyID);
const optimisticData: OnyxUpdate[] = [
{
Expand Down Expand Up @@ -3376,7 +3378,7 @@ function upgradeToCorporate(policyID: string, featureName: string) {
},
];

const parameters: UpgradeToCorporateParams = {policyID, featureName};
const parameters: UpgradeToCorporateParams = {policyID, ...(featureName ? {featureName} : {})};

API.write(WRITE_COMMANDS.UPGRADE_TO_CORPORATE, parameters, {optimisticData, successData, failureData});
}
Expand Down
17 changes: 17 additions & 0 deletions src/pages/workspace/WorkspaceProfilePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function WorkspaceProfilePage({policyDraft, policy: policyProp, route}: Workspac
const onPressName = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_NAME.getRoute(policy?.id ?? '-1')), [policy?.id]);
const onPressDescription = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_DESCRIPTION.getRoute(policy?.id ?? '-1')), [policy?.id]);
const onPressShare = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_SHARE.getRoute(policy?.id ?? '-1')), [policy?.id]);
const onPressPlanType = useCallback(() => Navigation.navigate(ROUTES.WORKSPACE_PROFILE_PLAN.getRoute(policy?.id ?? '-1')), [policy?.id]);

const policyName = policy?.name ?? '';
const policyDescription =
Expand Down Expand Up @@ -267,6 +268,22 @@ function WorkspaceProfilePage({policyDraft, policy: policyProp, route}: Workspac
</View>
</OfflineWithFeedback>
)}
{!readOnly && !!policy?.type && (
<OfflineWithFeedback pendingAction={policy?.pendingFields?.type}>
<View>
<MenuItemWithTopDescription
title={PolicyUtils.getUserFriendlyWorkspaceType(policy.type)}
description={translate('workspace.common.planType')}
shouldShowRightIcon={!readOnly}
disabled={readOnly}
wrapperStyle={styles.sectionMenuItemTopDescription}
onPress={onPressPlanType}
shouldGreyOutWhenDisabled={false}
shouldUseDefaultCursorWhenDisabled
/>
</View>
</OfflineWithFeedback>
)}
{!readOnly && (
<View style={[styles.flexRow, styles.mt6, styles.mnw120]}>
<Button
Expand Down
Loading

0 comments on commit 849b20a

Please sign in to comment.