Skip to content

Commit

Permalink
Merge pull request #43822 from allroundexperts/feat-workspace-upgrade
Browse files Browse the repository at this point in the history
Add workspace upgrade flow
  • Loading branch information
youssef-lr committed Jul 5, 2024
2 parents 45f76be + d05ccd7 commit 3a2de49
Show file tree
Hide file tree
Showing 19 changed files with 375 additions and 3 deletions.
15 changes: 14 additions & 1 deletion src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,7 @@ const CONST = {
UPDATE_TIME_ENABLED: 'POLICYCHANGELOG_UPDATE_TIME_ENABLED',
UPDATE_TIME_RATE: 'POLICYCHANGELOG_UPDATE_TIME_RATE',
LEAVE_POLICY: 'POLICYCHANGELOG_LEAVE_POLICY',
CORPORATE_UPGRADE: 'POLICYCHANGELOG_CORPORATE_UPGRADE',
},
ROOM_CHANGE_LOG: {
INVITE_TO_ROOM: 'INVITETOROOM',
Expand Down Expand Up @@ -2032,6 +2033,9 @@ const CONST = {
PAID: 'paid',
ADMIN: 'admin',
},
DEFAULT_MAX_EXPENSE_AGE: 90,
DEFAULT_MAX_EXPENSE_AMOUNT: 200000,
DEFAULT_MAX_AMOUNT_NO_RECEIPT: 2500,
},

CUSTOM_UNITS: {
Expand Down Expand Up @@ -5123,7 +5127,16 @@ const CONST = {
},

EXCLUDE_FROM_LAST_VISITED_PATH: [SCREENS.NOT_FOUND, SCREENS.SAML_SIGN_IN, SCREENS.VALIDATE_LOGIN] as string[],

UPGRADE_FEATURE_INTRO_MAPPING: [
{
id: 'reportFields',
alias: 'report-fields',
name: 'Report Fields',
title: 'workspace.upgrade.reportFields.title',
description: 'workspace.upgrade.reportFields.description',
icon: 'Pencil',
},
],
REPORT_FIELD_TYPES: {
TEXT: 'text',
DATE: 'date',
Expand Down
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/categories/:categoryName',
getRoute: (policyID: string, categoryName: string) => `settings/workspaces/${policyID}/categories/${encodeURIComponent(categoryName)}` as const,
},
WORKSPACE_UPGRADE: {
route: 'settings/workspaces/:policyID/upgrade/:featureName',
getRoute: (policyID: string, featureName: string) => `settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName)}` as const,
},
WORKSPACE_CATEGORIES_SETTINGS: {
route: 'settings/workspaces/:policyID/categories/settings',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/categories/settings` as const,
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ const SCREENS = {
DISTANCE_RATE_EDIT: 'Distance_Rate_Edit',
DISTANCE_RATE_TAX_RECLAIMABLE_ON_EDIT: 'Distance_Rate_Tax_Reclaimable_On_Edit',
DISTANCE_RATE_TAX_RATE_EDIT: 'Distance_Rate_Tax_Rate_Edit',
UPGRADE: 'Workspace_Upgrade',
},

EDIT_REQUEST: {
Expand Down
2 changes: 1 addition & 1 deletion src/components/ConfirmationPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ type ConfirmationPageProps = {
heading: string;

/** Description of the confirmation page */
description: string;
description: React.ReactNode;

/** The text for the button label */
buttonText?: string;
Expand Down
25 changes: 25 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ export default {
shared: 'Shared',
drafts: 'Drafts',
finished: 'Finished',
upgrade: 'Upgrade',
companyID: 'Company ID',
userID: 'User ID',
disable: 'Disable',
Expand Down Expand Up @@ -3083,6 +3084,30 @@ export default {
errorDescriptionPartTwo: 'reach out to Concierge',
errorDescriptionPartThree: 'for help.',
},
upgrade: {
reportFields: {
title: 'Report fields',
description: `Report fields let you specify header-level details, distinct from tags that pertain to expenses on individual line items. These details can encompass specific project names, business trip information, locations, and more.`,
pricing: {
onlyAvailableOnPlan: 'Report fields are only available on the Control plan, starting at ',
amount: '$9 ',
perActiveMember: 'per active member per month.',
},
},
note: {
upgradeWorkspace: 'Upgrade your workspace to access this feature, or',
learnMore: 'learn more',
aboutOurPlans: 'about our plans and pricing.',
},
upgradeToUnlock: 'Unlock this feature',
completed: {
headline: `You've upgraded your workspace!`,
successMessage: (policyName: string) => `You've successfully upgraded your ${policyName} workspace to the Control plan!`,
viewSubscription: 'View your subscription',
moreDetails: 'for more details.',
gotIt: 'Got it, thanks',
},
},
restrictedAction: {
restricted: 'Restricted',
actionsAreCurrentlyRestricted: ({workspaceName}) => `Actions on the ${workspaceName} workspace are currently restricted`,
Expand Down
25 changes: 25 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ export default {
shared: 'Compartidos',
drafts: 'Borradores',
finished: 'Finalizados',
upgrade: 'Mejora',
companyID: 'Empresa ID',
userID: 'Usuario ID',
disable: 'Deshabilitar',
Expand Down Expand Up @@ -3126,6 +3127,30 @@ export default {
errorDescriptionPartTwo: 'contacta con el conserje',
errorDescriptionPartThree: 'por ayuda.',
},
upgrade: {
reportFields: {
title: 'Los campos',
description: `Los campos de informe permiten especificar detalles a nivel de cabecera, distintos de las etiquetas que pertenecen a los gastos en partidas individuales. Estos detalles pueden incluir nombres de proyectos específicos, información sobre viajes de negocios, ubicaciones, etc.`,
pricing: {
onlyAvailableOnPlan: 'Los campos de informe sólo están disponibles en el plan Control, a partir de ',
amount: '$9 ',
perActiveMember: 'por miembro activo al mes.',
},
},
note: {
upgradeWorkspace: 'Mejore su espacio de trabajo para acceder a esta función, o',
learnMore: 'más información',
aboutOurPlans: 'sobre nuestros planes y precios.',
},
upgradeToUnlock: 'Desbloquear esta función',
completed: {
headline: 'Has mejorado tu espacio de trabajo.',
successMessage: (policyName: string) => `Ha mejorado correctamente su espacio de trabajo ${policyName} al plan Control.`,
viewSubscription: 'Ver su suscripción',
moreDetails: 'para obtener más información.',
gotIt: 'Entendido, gracias.',
},
},
restrictedAction: {
restricted: 'Restringido',
actionsAreCurrentlyRestricted: ({workspaceName}) => `Las acciones en el espacio de trabajo ${workspaceName} están actualmente restringidas`,
Expand Down
6 changes: 6 additions & 0 deletions src/libs/API/parameters/UpgradeToCorporateParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type UpgradeToCorporateParams = {
policyID: string;
featureName: string;
};

export default UpgradeToCorporateParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ export type {default as UpdateSubscriptionAutoRenewParams} from './UpdateSubscri
export type {default as UpdateSubscriptionAddNewUsersAutomaticallyParams} from './UpdateSubscriptionAddNewUsersAutomaticallyParams';
export type {default as GenerateSpotnanaTokenParams} from './GenerateSpotnanaTokenParams';
export type {default as UpdateSubscriptionSizeParams} from './UpdateSubscriptionSizeParams';
export type {default as UpgradeToCorporateParams} from './UpgradeToCorporateParams';
export type {default as DeleteMoneyRequestOnSearchParams} from './DeleteMoneyRequestOnSearchParams';
export type {default as HoldMoneyRequestOnSearchParams} from './HoldMoneyRequestOnSearchParams';
export type {default as UnholdMoneyRequestOnSearchParams} from './UnholdMoneyRequestOnSearchParams';
Expand Down
2 changes: 2 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ const WRITE_COMMANDS = {
UPDATE_SUBSCRIPTION_AUTO_RENEW: 'UpdateSubscriptionAutoRenew',
UPDATE_SUBSCRIPTION_ADD_NEW_USERS_AUTOMATICALLY: 'UpdateSubscriptionAddNewUsersAutomatically',
UPDATE_SUBSCRIPTION_SIZE: 'UpdateSubscriptionSize',
UPGRADE_TO_CORPORATE: 'UpgradeToCorporate',
DELETE_MONEY_REQUEST_ON_SEARCH: 'DeleteMoneyRequestOnSearch',
HOLD_MONEY_REQUEST_ON_SEARCH: 'HoldMoneyRequestOnSearch',
UNHOLD_MONEY_REQUEST_ON_SEARCH: 'UnholdMoneyRequestOnSearch',
Expand Down Expand Up @@ -505,6 +506,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.REQUEST_REFUND]: null;
[WRITE_COMMANDS.CONNECT_POLICY_TO_SAGE_INTACCT]: Parameters.ConnectPolicyToSageIntacctParams;

[WRITE_COMMANDS.UPGRADE_TO_CORPORATE]: Parameters.UpgradeToCorporateParams;
// Netsuite parameters
[WRITE_COMMANDS.UPDATE_NETSUITE_SUBSIDIARY]: Parameters.UpdateNetSuiteSubsidiaryParams;
[WRITE_COMMANDS.CONNECT_POLICY_TO_NETSUITE]: Parameters.ConnectPolicyToNetSuiteParams;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ const SettingsModalStackNavigator = createModalStackNavigator<SettingsNavigatorP
[SCREENS.WORKSPACE.CATEGORY_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/CategorySettingsPage').default,
[SCREENS.WORKSPACE.ADDRESS]: () => require<ReactComponentModule>('../../../../pages/workspace/WorkspaceProfileAddressPage').default,
[SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/categories/WorkspaceCategoriesSettingsPage').default,
[SCREENS.WORKSPACE.UPGRADE]: () => require<ReactComponentModule>('../../../../pages/workspace/upgrade/WorkspaceUpgradePage').default,
[SCREENS.WORKSPACE.MEMBER_DETAILS]: () => require<ReactComponentModule>('../../../../pages/workspace/members/WorkspaceMemberDetailsPage').default,
[SCREENS.WORKSPACE.OWNER_CHANGE_CHECK]: () => require<ReactComponentModule>('@pages/workspace/members/WorkspaceOwnerChangeWrapperPage').default,
[SCREENS.WORKSPACE.OWNER_CHANGE_SUCCESS]: () => require<ReactComponentModule>('../../../../pages/workspace/members/WorkspaceOwnerChangeSuccessPage').default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import type {FullScreenName} from '@libs/Navigation/types';
import SCREENS from '@src/SCREENS';

const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
[SCREENS.WORKSPACE.PROFILE]: [SCREENS.WORKSPACE.NAME, SCREENS.WORKSPACE.ADDRESS, SCREENS.WORKSPACE.CURRENCY, SCREENS.WORKSPACE.DESCRIPTION, SCREENS.WORKSPACE.SHARE],
[SCREENS.WORKSPACE.PROFILE]: [
SCREENS.WORKSPACE.NAME,
SCREENS.WORKSPACE.ADDRESS,
SCREENS.WORKSPACE.CURRENCY,
SCREENS.WORKSPACE.DESCRIPTION,
SCREENS.WORKSPACE.SHARE,
SCREENS.WORKSPACE.UPGRADE,
],
[SCREENS.WORKSPACE.REIMBURSE]: [SCREENS.WORKSPACE.RATE_AND_UNIT, SCREENS.WORKSPACE.RATE_AND_UNIT_RATE, SCREENS.WORKSPACE.RATE_AND_UNIT_UNIT],
[SCREENS.WORKSPACE.MEMBERS]: [
SCREENS.WORKSPACE.INVITE,
Expand Down
6 changes: 6 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,12 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
categoryName: (categoryName: string) => decodeURIComponent(categoryName),
},
},
[SCREENS.WORKSPACE.UPGRADE]: {
path: ROUTES.WORKSPACE_UPGRADE.route,
parse: {
featureName: (featureName: string) => decodeURIComponent(featureName),
},
},
[SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: {
path: ROUTES.WORKSPACE_CATEGORIES_SETTINGS.route,
},
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,11 @@ type SettingsNavigatorParamList = {
categoryName: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.UPGRADE]: {
policyID: string;
featureName: string;
backTo?: Routes;
};
[SCREENS.WORKSPACE.CATEGORIES_SETTINGS]: {
policyID: string;
backTo?: Routes;
Expand Down
55 changes: 55 additions & 0 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import type {
UpdateWorkspaceCustomUnitAndRateParams,
UpdateWorkspaceDescriptionParams,
UpdateWorkspaceGeneralSettingsParams,
UpgradeToCorporateParams,
} from '@libs/API/parameters';
import type UpdatePolicyAddressParams from '@libs/API/parameters/UpdatePolicyAddressParams';
import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types';
Expand Down Expand Up @@ -3019,6 +3020,59 @@ function setForeignCurrencyDefault(policyID: string, taxCode: string) {
API.write(WRITE_COMMANDS.SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT, parameters, onyxData);
}

function upgradeToCorporate(policyID: string, featureName: string) {
const policy = getPolicy(policyID);
const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `policy_${policyID}`,
value: {
isPendingUpgrade: true,
type: CONST.POLICY.TYPE.CORPORATE,
maxExpenseAge: CONST.POLICY.DEFAULT_MAX_EXPENSE_AGE,
maxExpenseAmount: CONST.POLICY.DEFAULT_MAX_EXPENSE_AMOUNT,
maxExpenseAmountNoReceipt: CONST.POLICY.DEFAULT_MAX_AMOUNT_NO_RECEIPT,
glCodes: true,
...(PolicyUtils.isInstantSubmitEnabled(policy) && {
autoReporting: true,
autoReportingFrequency: CONST.POLICY.AUTO_REPORTING_FREQUENCIES.MANUAL,
}),
},
},
];

const successData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `policy_${policyID}`,
value: {
isPendingUpgrade: false,
},
},
];

const failureData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `policy_${policyID}`,
value: {
isPendingUpgrade: false,
type: policy?.type,
maxExpenseAge: policy?.maxExpenseAge ?? null,
maxExpenseAmount: policy?.maxExpenseAmount ?? null,
maxExpenseAmountNoReceipt: policy?.maxExpenseAmountNoReceipt ?? null,
glCodes: policy?.glCodes ?? null,
autoReporting: policy?.autoReporting ?? null,
autoReportingFrequency: policy?.autoReportingFrequency ?? null,
},
},
];

const parameters: UpgradeToCorporateParams = {policyID, featureName};

API.write(WRITE_COMMANDS.UPGRADE_TO_CORPORATE, parameters, {optimisticData, successData, failureData});
}

function getPoliciesConnectedToSageIntacct(): Policy[] {
return Object.values(allPolicies ?? {}).filter<Policy>((policy): policy is Policy => !!policy && !!policy?.connections?.intacct);
}
Expand Down Expand Up @@ -3088,6 +3142,7 @@ export {
buildPolicyData,
enableExpensifyCard,
createPolicyExpenseChats,
upgradeToCorporate,
openPolicyExpensifyCardsPage,
requestExpensifyCardLimitIncrease,
getPoliciesConnectedToSageIntacct,
Expand Down
40 changes: 40 additions & 0 deletions src/pages/workspace/upgrade/UpgradeConfirmation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import ConfirmationPage from '@components/ConfirmationPage';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import ROUTES from '@src/ROUTES';

type Props = {
policyName: string;
policyID: string;
};

function UpgradeConfirmation({policyName, policyID}: Props) {
const {translate} = useLocalize();
const styles = useThemeStyles();

return (
<ConfirmationPage
heading={translate('workspace.upgrade.completed.headline')}
description={
<>
{translate('workspace.upgrade.completed.successMessage', policyName)}{' '}
<TextLink
style={styles.link}
onPress={() => Navigation.navigate(ROUTES.SETTINGS_SUBSCRIPTION)}
>
{translate('workspace.upgrade.completed.viewSubscription')}
</TextLink>{' '}
{translate('workspace.upgrade.completed.moreDetails')}
</>
}
shouldShowButton
onButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_PROFILE.getRoute(policyID))}
buttonText={translate('workspace.upgrade.completed.gotIt')}
/>
);
}

export default UpgradeConfirmation;
Loading

0 comments on commit 3a2de49

Please sign in to comment.