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: add upgrade screen to more features #45131

Merged
merged 12 commits into from
Jul 17, 2024
25 changes: 19 additions & 6 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5248,24 +5248,37 @@ const CONST = {
},

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

EMPTY_STATE_MEDIA: {
ANIMATION: 'animation',
ILLUSTRATION: 'illustration',
VIDEO: 'video',
},

UPGRADE_FEATURE_INTRO_MAPPING: [
{
UPGRADE_FEATURE_INTRO_MAPPING: {
reportFields: {
id: 'reportFields',
alias: 'report-fields',
name: 'Report Fields',
title: 'workspace.upgrade.reportFields.title',
description: 'workspace.upgrade.reportFields.description',
icon: 'Pencil',
},
],

netSuite: {
id: 'netSuite',
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
alias: 'netsuite',
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
name: 'NetSuite',
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
title: 'workspace.upgrade.netSuite.title',
description: 'workspace.upgrade.netSuite.description',
icon: 'NetSuiteSquare',
},
sageIntacct: {
id: 'sageIntacct',
alias: 'sage-intacct',
name: 'Sage Intacct',
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
title: 'workspace.upgrade.sageIntacct.title',
description: 'workspace.upgrade.sageIntacct.description',
icon: 'IntacctSquare',
},
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
},
REPORT_FIELD_TYPES: {
TEXT: 'text',
DATE: 'date',
Expand Down
3 changes: 2 additions & 1 deletion src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,8 @@ const ROUTES = {
},
WORKSPACE_UPGRADE: {
route: 'settings/workspaces/:policyID/upgrade/:featureName',
getRoute: (policyID: string, featureName: string) => `settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName)}` as const,
getRoute: (policyID: string, featureName: string, backTo?: string) =>
getUrlWithBackToParam(`settings/workspaces/${policyID}/upgrade/${encodeURIComponent(featureName)}` as const, backTo),
},
WORKSPACE_CATEGORIES_SETTINGS: {
route: 'settings/workspaces/:policyID/categories/settings',
Expand Down
8 changes: 8 additions & 0 deletions src/components/ConnectToNetSuiteButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, {useState} from 'react';
import {useOnyx} from 'react-native-onyx';
import AccountingConnectionConfirmationModal from '@components/AccountingConnectionConfirmationModal';
import Button from '@components/Button';
import useLocalize from '@hooks/useLocalize';
Expand All @@ -7,20 +8,27 @@ import useThemeStyles from '@hooks/useThemeStyles';
import {removePolicyConnection} from '@libs/actions/connections';
import Navigation from '@libs/Navigation/Navigation';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {ConnectToNetSuiteButtonProps} from './types';

function ConnectToNetSuiteButton({policyID, shouldDisconnectIntegrationBeforeConnecting, integrationToDisconnect}: ConnectToNetSuiteButtonProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {isOffline} = useNetwork();
const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);

const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);

return (
<>
<Button
onPress={() => {
if (policy?.type !== CONST.POLICY.TYPE.CORPORATE) {
Navigation.navigate(ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.netSuite.alias, ROUTES.WORKSPACE_ACCOUNTING.getRoute(policyID)));
return;
}

if (shouldDisconnectIntegrationBeforeConnecting && integrationToDisconnect) {
setIsDisconnectModalOpen(true);
return;
Expand Down
11 changes: 11 additions & 0 deletions src/components/ConnectToSageIntacctButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {useRef, useState} from 'react';
import type {View} from 'react-native';
import {useOnyx} from 'react-native-onyx';
import AccountingConnectionConfirmationModal from '@components/AccountingConnectionConfirmationModal';
import Button from '@components/Button';
import * as Expensicons from '@components/Icon/Expensicons';
Expand All @@ -13,6 +14,7 @@ import {getPoliciesConnectedToSageIntacct} from '@libs/actions/Policy/Policy';
import Navigation from '@libs/Navigation/Navigation';
import type {AnchorPosition} from '@styles/index';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ROUTES from '@src/ROUTES';
import type {PolicyConnectionName} from '@src/types/onyx/Policy';

Expand All @@ -27,6 +29,8 @@ function ConnectToSageIntacctButton({policyID, shouldDisconnectIntegrationBefore
const {translate} = useLocalize();
const {isOffline} = useNetwork();

const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`);

const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);

const hasPoliciesConnectedToSageIntacct = !!getPoliciesConnectedToSageIntacct().length;
Expand Down Expand Up @@ -57,6 +61,13 @@ function ConnectToSageIntacctButton({policyID, shouldDisconnectIntegrationBefore
<>
<Button
onPress={() => {
if (policy?.type !== CONST.POLICY.TYPE.CORPORATE) {
Navigation.navigate(
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.sageIntacct.alias, ROUTES.WORKSPACE_ACCOUNTING.getRoute(policyID)),
);
return;
}

if (shouldDisconnectIntegrationBeforeConnecting && integrationToDisconnect) {
setIsDisconnectModalOpen(true);
return;
Expand Down
20 changes: 15 additions & 5 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3298,11 +3298,21 @@ export default {
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.',
},
onlyAvailableOnPlan: 'Report fields are only available on the Control plan, starting at ',
},
netSuite: {
title: 'NetSuite',
description: `Enjoy automated syncing and reduce manual entries with the Expensify + NetSuite integration. Gain in-depth, realtime financial insights with native and custom segment support, including project and customer mapping.`,
allroundexperts marked this conversation as resolved.
Show resolved Hide resolved
onlyAvailableOnPlan: 'Our NetSuite integration is only available on the Control plan, starting at ',
},
sageIntacct: {
title: 'Sage Intacct',
description: `Enjoy automated syncing and reduce manual entries with the Expensify + Sage Intacct integration. Gain in-depth, real-time financial insights with user-defined dimensions, as well as expense coding by department, class, location, customer, and project (job).`,
onlyAvailableOnPlan: 'Our Sage Intacct integration is only available on the Control plan, starting at ',
},
pricing: {
amount: '$9 ',
perActiveMember: 'per active member per month.',
},
note: {
upgradeWorkspace: 'Upgrade your workspace to access this feature, or',
Expand Down
20 changes: 15 additions & 5 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3346,17 +3346,27 @@ export default {
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.',
},
onlyAvailableOnPlan: 'Los campos de informe sólo están disponibles en el plan Control, a partir de ',
},
netSuite: {
title: 'NetSuite',
description: `Disfruta de la sincronización automática y reduce las entradas manuales con la integración Expensify + NetSuite. Obtén información financiera en profundidad y en tiempo real con la compatibilidad nativa y personalizada con segmentos, incluida la asignación de proyectos y clientes.`,
onlyAvailableOnPlan: 'Nuestra integración NetSuite sólo está disponible en el plan Control, a partir de ',
},
sageIntacct: {
title: 'Sage Intacct',
description: `Disfruta de una sincronización automatizada y reduce las entradas manuales con la integración Expensify + Sage Intacct. Obtén información financiera en profundidad y en tiempo real con dimensiones definidas por el usuario, así como codificación de gastos por departamento, clase, ubicación, cliente y proyecto (trabajo).`,
onlyAvailableOnPlan: 'Nuestra integración Sage Intacct sólo está disponible en el plan Control, a partir de ',
},
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.',
},
pricing: {
amount: '$9 ',
perActiveMember: 'por miembro activo al mes.',
},
upgradeToUnlock: 'Desbloquear esta función',
completed: {
headline: 'Has mejorado tu espacio de trabajo.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,7 @@ 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.UPGRADE,
],
[SCREENS.WORKSPACE.PROFILE]: [SCREENS.WORKSPACE.NAME, SCREENS.WORKSPACE.ADDRESS, SCREENS.WORKSPACE.CURRENCY, SCREENS.WORKSPACE.DESCRIPTION, SCREENS.WORKSPACE.SHARE],
[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
7 changes: 7 additions & 0 deletions src/pages/workspace/WorkspaceMoreFeaturesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro
return;
}
if (isEnabled) {
if (policy?.type !== CONST.POLICY.TYPE.CORPORATE) {
Copy link
Member

@rushatgabhane rushatgabhane Jul 10, 2024

Choose a reason for hiding this comment

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

NAB: Could you please replace this with the util function: isControlPolicy().
Reason: Code is duplicated 3 times

https://github.com/Expensify/App/pull/43151/files#diff-89601c1d4ab7d6fb789ea45b8f8e16ead0f925cf0db25d9b5c3561816d7a94c1

The function is currently not in main, so you can just take it from there. Hope that's okay : )

Navigation.navigate(
ROUTES.WORKSPACE_UPGRADE.getRoute(policyID, CONST.UPGRADE_FEATURE_INTRO_MAPPING.reportFields.alias, ROUTES.WORKSPACE_MORE_FEATURES.getRoute(policyID)),
);
return;
}

Policy.enablePolicyReportFields(policyID, true);
return;
}
Expand Down
12 changes: 7 additions & 5 deletions src/pages/workspace/upgrade/UpgradeIntro.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import {View} from 'react-native';
import type {ValueOf} from 'type-fest';
import Badge from '@components/Badge';
import Button from '@components/Button';
import Icon from '@components/Icon';
Expand All @@ -18,21 +19,22 @@ import ROUTES from '@src/ROUTES';
type Props = {
buttonDisabled?: boolean;
loading?: boolean;
feature: (typeof CONST.UPGRADE_FEATURE_INTRO_MAPPING)[0];
feature: ValueOf<typeof CONST.UPGRADE_FEATURE_INTRO_MAPPING>;
onUpgrade: () => void;
};

function UpgradeIntro({feature, onUpgrade, buttonDisabled, loading}: Props) {
const styles = useThemeStyles();
const {isExtraSmallScreenWidth, isSmallScreenWidth} = useResponsiveLayout();
const {translate} = useLocalize();
const iconSrc = feature.icon in Illustrations ? Illustrations[feature.icon as keyof typeof Illustrations] : Expensicon[feature.icon as keyof typeof Expensicon];

return (
<View style={styles.p5}>
<View style={styles.workspaceUpgradeIntroBox({isExtraSmallScreenWidth, isSmallScreenWidth})}>
<View style={[styles.mb3, styles.flexRow, styles.justifyContentBetween]}>
<Icon
src={Illustrations[feature.icon]}
src={iconSrc}
width={variables.iconSizeExtraLarge}
height={variables.iconSizeExtraLarge}
/>
Expand All @@ -46,9 +48,9 @@ function UpgradeIntro({feature, onUpgrade, buttonDisabled, loading}: Props) {
<Text style={[styles.textHeadlineH1, styles.mb4]}>{translate(feature.title)}</Text>
<Text style={[styles.textNormal, styles.textSupporting, styles.mb4]}>{translate(feature.description)}</Text>
<Text style={[styles.textNormal, styles.textSupporting]}>
{translate(`workspace.upgrade.${feature.id}.pricing.onlyAvailableOnPlan`)}
<Text style={[styles.themeTextColor, styles.textBold]}>{translate(`workspace.upgrade.${feature.id}.pricing.amount`)}</Text>
{translate(`workspace.upgrade.${feature.id}.pricing.perActiveMember`)}
{translate(`workspace.upgrade.${feature.id}.onlyAvailableOnPlan`)}
<Text style={[styles.themeTextColor, styles.textBold]}>{translate(`workspace.upgrade.pricing.amount`)}</Text>
{translate(`workspace.upgrade.pricing.perActiveMember`)}
</Text>
</View>
<Button
Expand Down
4 changes: 2 additions & 2 deletions src/pages/workspace/upgrade/WorkspaceUpgradePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type WorkspaceUpgradePageProps = StackScreenProps<SettingsNavigatorParamList, ty

function WorkspaceUpgradePage({route}: WorkspaceUpgradePageProps) {
const policyID = route.params.policyID;
const feature = CONST.UPGRADE_FEATURE_INTRO_MAPPING.find((f) => f.alias === route.params.featureName);
const feature = Object.values(CONST.UPGRADE_FEATURE_INTRO_MAPPING).find((f) => f.alias === route.params.featureName);
const {translate} = useLocalize();
const [policy] = useOnyx(`policy_${policyID}`);
const {isOffline} = useNetwork();
Expand All @@ -41,7 +41,7 @@ function WorkspaceUpgradePage({route}: WorkspaceUpgradePageProps) {
>
<HeaderWithBackButton
title={translate('common.upgrade')}
onBackButtonPress={() => Navigation.goBack(ROUTES.WORKSPACE_PROFILE.getRoute(policyID))}
onBackButtonPress={() => Navigation.goBack(route.params.backTo ?? ROUTES.WORKSPACE_PROFILE.getRoute(policyID))}
/>
{isUpgraded && (
<UpgradeConfirmation
Expand Down
Loading