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

[NO QA]: Workspace Feed - Expensify Card #44549

Merged
merged 8 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 3 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ const CONST = {
SPOTNANA_TRAVEL: 'spotnanaTravel',
NETSUITE_ON_NEW_EXPENSIFY: 'netsuiteOnNewExpensify',
REPORT_FIELDS_FEATURE: 'reportFieldsFeature',
EXPENSIFY_CARD_FEATURE: 'expensifyCardFeature',
narefyev91 marked this conversation as resolved.
Show resolved Hide resolved
WORKSPACE_FEEDS: 'workspaceFeeds',
},
BUTTON_STATES: {
Expand Down Expand Up @@ -1725,6 +1726,7 @@ const CONST = {
ARE_WORKFLOWS_ENABLED: 'areWorkflowsEnabled',
ARE_REPORT_FIELDS_ENABLED: 'areReportFieldsEnabled',
ARE_CONNECTIONS_ENABLED: 'areConnectionsEnabled',
ARE_EXPENSIFY_CARDS_ENABLED: 'areExpensifyCardsEnabled',
ARE_TAXES_ENABLED: 'tax',
},
CATEGORIES_BULK_ACTION_TYPES: {
Expand Down Expand Up @@ -2033,6 +2035,7 @@ const CONST = {
WORKSPACE_INVOICES: 'WorkspaceSendInvoices',
WORKSPACE_TRAVEL: 'WorkspaceBookTravel',
WORKSPACE_MEMBERS: 'WorkspaceManageMembers',
WORKSPACE_EXPENSIFY_CARD: 'WorkspaceExpensifyCard',
WORKSPACE_WORKFLOWS: 'WorkspaceWorkflows',
WORKSPACE_BANK_ACCOUNT: 'WorkspaceBankAccount',
WORKSPACE_SETTINGS: 'WorkspaceSettings',
Expand Down
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,10 @@ const ROUTES = {
route: 'settings/workspaces/:policyID/distance-rates',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/distance-rates` as const,
},
WORKSPACE_EXPENSIFY_CARD: {
route: 'settings/workspaces/:policyID/expensify-card',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/expensify-card` as const,
},
narefyev91 marked this conversation as resolved.
Show resolved Hide resolved
WORKSPACE_CREATE_DISTANCE_RATE: {
route: 'settings/workspaces/:policyID/distance-rates/new',
getRoute: (policyID: string) => `settings/workspaces/${policyID}/distance-rates/new` 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 @@ -325,6 +325,7 @@ const SCREENS = {
OWNER_CHANGE_SUCCESS: 'Workspace_Owner_Change_Success',
OWNER_CHANGE_ERROR: 'Workspace_Owner_Change_Error',
DISTANCE_RATES: 'Distance_Rates',
EXPENSIFY_CARD: 'Expensify_Card',
CREATE_DISTANCE_RATE: 'Create_Distance_Rate',
DISTANCE_RATES_SETTINGS: 'Distance_Rates_Settings',
DISTANCE_RATE_DETAILS: 'Distance_Rate_Details',
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 @@ -31,6 +31,7 @@ const WIDE_LAYOUT_INACTIVE_SCREENS: string[] = [
SCREENS.WORKSPACE.TAGS,
SCREENS.WORKSPACE.TAXES,
SCREENS.WORKSPACE.REPORT_FIELDS,
SCREENS.WORKSPACE.EXPENSIFY_CARD,
SCREENS.WORKSPACE.DISTANCE_RATES,
SCREENS.SEARCH.CENTRAL_PANE,
SCREENS.SETTINGS.TROUBLESHOOT,
Expand Down
5 changes: 5 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1994,6 +1994,7 @@ export default {
moreFeatures: 'More features',
requested: 'Requested',
distanceRates: 'Distance rates',
expensifyCard: 'Expensify Card',
welcomeNote: ({workspaceName}: WelcomeNoteParams) =>
`You have been invited to ${workspaceName || 'a workspace'}! Download the Expensify mobile app at use.expensify.com/download to start tracking your expenses.`,
subscription: 'Subscription',
Expand Down Expand Up @@ -2247,6 +2248,10 @@ export default {
title: 'Distance rates',
subtitle: 'Add, update, and enforce rates.',
},
expensifyCard: {
title: 'Expensify Card',
subtitle: 'Gain insights and control over spend',
},
workflows: {
title: 'Workflows',
subtitle: 'Configure how spend is approved and paid.',
Expand Down
5 changes: 5 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1993,6 +1993,7 @@ export default {
bills: 'Pagar facturas',
invoices: 'Enviar facturas',
travel: 'Viajes',
expensifyCard: 'Tarjeta Expensify',
members: 'Miembros',
accounting: 'Contabilidad',
plan: 'Plan',
Expand Down Expand Up @@ -2278,6 +2279,10 @@ export default {
title: 'Integrar',
subtitle: 'Conecta Expensify a otros productos financieros populares.',
},
expensifyCard: {
title: 'Tarjeta Expensify',
subtitle: 'Obtén información y control sobre tus gastos',
},
distanceRates: {
title: 'Tasas de distancia',
subtitle: 'Añade, actualiza y haz cumplir las tasas.',
Expand Down
6 changes: 6 additions & 0 deletions src/libs/API/parameters/EnablePolicyExpensifyCardsParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type EnablePolicyExpensifyCardsParams = {
policyID: string;
enabled: boolean;
};
Copy link
Contributor

@allgandalf allgandalf Jun 29, 2024

Choose a reason for hiding this comment

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

Screenshot 2024-06-29 at 4 24 15 PM

From the design doc this requires one more param authToken which we seem to be missing here.

Also i checked the endpoint:
Screenshot 2024-06-29 at 4 27 50 PM

This keeps returning 404, c.c. @MariaHCD @mountiny , is the BE part not yet implemented, the api gets on called infinitely on my local setup

Also @narefyev91 , does the option of cards go from the options list? currently when i disable the option i have to either load the page again / go back and come again for the option of Expensify Card to go away.

Screen.Recording.2024-06-29.at.4.43.06.PM.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah good point - will add authToken.
Experiencing the same problem with 404 - and that is a reason with toggling off.
We have this line inside useEffect - which should add/remove left menus
Screenshot 2024-07-01 at 12 33 34
When we fire api call (which is not exists) - field is in pending state - that's why nothing happened immediately
If i just use here direct key from onyx policyFeatureStates and not state featureStates it will work
Screenshot 2024-07-01 at 12 35 33
Probably when API will be working - everything will be works as well
@allgandalf

Copy link
Contributor

@allgandalf allgandalf Jul 1, 2024

Choose a reason for hiding this comment

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

ummm, thanks for pointing that out, yes that seems logical to me, lets wait on vit and maria for their thoughts though :)

Copy link
Contributor

Choose a reason for hiding this comment

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

@MariaHCD can you weigh in here to keep it moving? Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, sorry, I missed this.

The BE API endpoint is not implemented yet. We can focus on the frontend elements / flows for now and then once the BE endpoints are implemented, we can update the FE here and retest the flow.


export default EnablePolicyExpensifyCardsParams;
1 change: 1 addition & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ export type {default as EnablePolicyTagsParams} from './EnablePolicyTagsParams';
export type {default as SetPolicyTagsEnabled} from './SetPolicyTagsEnabled';
export type {default as EnablePolicyWorkflowsParams} from './EnablePolicyWorkflowsParams';
export type {default as EnablePolicyReportFieldsParams} from './EnablePolicyReportFieldsParams';
export type {default as EnablePolicyExpensifyCardsParams} from './EnablePolicyExpensifyCardsParams';
export type {default as AcceptJoinRequestParams} from './AcceptJoinRequest';
export type {default as DeclineJoinRequestParams} from './DeclineJoinRequest';
export type {default as JoinPolicyInviteLinkParams} from './JoinPolicyInviteLink';
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 @@ -186,6 +186,7 @@ const WRITE_COMMANDS = {
ENABLE_POLICY_TAXES: 'EnablePolicyTaxes',
ENABLE_POLICY_WORKFLOWS: 'EnablePolicyWorkflows',
ENABLE_POLICY_REPORT_FIELDS: 'EnablePolicyReportFields',
ENABLE_POLICY_EXPENSIFY_CARDS: 'EnablePolicyExpensifyCards',
SET_POLICY_TAXES_CURRENCY_DEFAULT: 'SetPolicyCurrencyDefaultTax',
SET_POLICY_TAXES_FOREIGN_CURRENCY_DEFAULT: 'SetPolicyForeignCurrencyDefaultTax',
SET_POLICY_CUSTOM_TAX_NAME: 'SetPolicyCustomTaxName',
Expand Down Expand Up @@ -411,6 +412,7 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.ENABLE_POLICY_TAXES]: Parameters.EnablePolicyTaxesParams;
[WRITE_COMMANDS.ENABLE_POLICY_WORKFLOWS]: Parameters.EnablePolicyWorkflowsParams;
[WRITE_COMMANDS.ENABLE_POLICY_REPORT_FIELDS]: Parameters.EnablePolicyReportFieldsParams;
[WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS]: Parameters.EnablePolicyExpensifyCardsParams;
[WRITE_COMMANDS.JOIN_POLICY_VIA_INVITE_LINK]: Parameters.JoinPolicyInviteLinkParams;
[WRITE_COMMANDS.ACCEPT_JOIN_REQUEST]: Parameters.AcceptJoinRequestParams;
[WRITE_COMMANDS.DECLINE_JOIN_REQUEST]: Parameters.DeclineJoinRequestParams;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const CENTRAL_PANE_WORKSPACE_SCREENS = {
[SCREENS.WORKSPACE.TAGS]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceTagsPage').default,
[SCREENS.WORKSPACE.TAXES]: () => require<ReactComponentModule>('../../../../pages/workspace/taxes/WorkspaceTaxesPage').default,
[SCREENS.WORKSPACE.REPORT_FIELDS]: () => require<ReactComponentModule>('../../../../pages/workspace/reportFields/WorkspaceReportFieldsPage').default,
[SCREENS.WORKSPACE.EXPENSIFY_CARD]: () => require<ReactComponentModule>('../../../../pages/workspace/expensifyCard/WorkspaceExpensifyCardPage').default,
[SCREENS.WORKSPACE.DISTANCE_RATES]: () => require<ReactComponentModule>('../../../../pages/workspace/distanceRates/PolicyDistanceRatesPage').default,
} satisfies Screens;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const FULL_SCREEN_TO_RHP_MAPPING: Partial<Record<FullScreenName, string[]>> = {
SCREENS.WORKSPACE.DISTANCE_RATE_DETAILS,
],
[SCREENS.WORKSPACE.REPORT_FIELDS]: [],
[SCREENS.WORKSPACE.EXPENSIFY_CARD]: [],
};

export default FULL_SCREEN_TO_RHP_MAPPING;
3 changes: 3 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,9 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.WORKSPACE.REPORT_FIELDS]: {
path: ROUTES.WORKSPACE_REPORT_FIELDS.route,
},
[SCREENS.WORKSPACE.EXPENSIFY_CARD]: {
path: ROUTES.WORKSPACE_EXPENSIFY_CARD.route,
},
[SCREENS.WORKSPACE.DISTANCE_RATES]: {
path: ROUTES.WORKSPACE_DISTANCE_RATES.route,
},
Expand Down
3 changes: 3 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,9 @@ type FullScreenNavigatorParamList = {
[SCREENS.WORKSPACE.WORKFLOWS]: {
policyID: string;
};
[SCREENS.WORKSPACE.EXPENSIFY_CARD]: {
policyID: string;
};
[SCREENS.WORKSPACE.WORKFLOWS_APPROVER]: {
policyID: string;
};
Expand Down
5 changes: 5 additions & 0 deletions src/libs/Permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ function canUseReportFieldsFeature(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.REPORT_FIELDS_FEATURE) || canUseAllBetas(betas);
}

function canUseExpensifyCardFeature(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.EXPENSIFY_CARD_FEATURE) || canUseAllBetas(betas);
}

narefyev91 marked this conversation as resolved.
Show resolved Hide resolved
function canUseWorkspaceFeeds(betas: OnyxEntry<Beta[]>): boolean {
return !!betas?.includes(CONST.BETAS.WORKSPACE_FEEDS) || canUseAllBetas(betas);
}
Expand All @@ -71,5 +75,6 @@ export default {
canUseSpotnanaTravel,
canUseNetSuiteIntegration,
canUseReportFieldsFeature,
canUseExpensifyCardFeature,
canUseWorkspaceFeeds,
};
50 changes: 50 additions & 0 deletions src/libs/actions/Policy/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
DeleteWorkspaceAvatarParams,
DeleteWorkspaceParams,
EnablePolicyConnectionsParams,
EnablePolicyExpensifyCardsParams,
EnablePolicyReportFieldsParams,
EnablePolicyTaxesParams,
EnablePolicyWorkflowsParams,
Expand Down Expand Up @@ -2461,6 +2462,54 @@ function enablePolicyConnections(policyID: string, enabled: boolean) {
}
}

function enableExpensifyCard(policyID: string, enabled: boolean) {
const onyxData: OnyxData = {
optimisticData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
areExpensifyCardsEnabled: enabled,
pendingFields: {
areExpensifyCardsEnabled: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE,
},
},
},
],
successData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
pendingFields: {
areExpensifyCardsEnabled: null,
},
},
},
],
failureData: [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`,
value: {
areExpensifyCardsEnabled: !enabled,
pendingFields: {
areExpensifyCardsEnabled: null,
},
},
},
],
};

const parameters: EnablePolicyExpensifyCardsParams = {policyID, enabled};

API.write(WRITE_COMMANDS.ENABLE_POLICY_EXPENSIFY_CARDS, parameters, onyxData);

if (enabled && getIsNarrowLayout()) {
navigateWhenEnableFeature(policyID);
}
}

function enablePolicyReportFields(policyID: string, enabled: boolean) {
const onyxData: OnyxData = {
optimisticData: [
Expand Down Expand Up @@ -3005,6 +3054,7 @@ export {
getPrimaryPolicy,
createDraftWorkspace,
buildPolicyData,
enableExpensifyCard,
createPolicyExpenseChats,
clearNetSuiteErrorField,
};
Expand Down
11 changes: 11 additions & 0 deletions src/pages/workspace/WorkspaceInitialPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type WorkspaceMenuItem = {
| typeof SCREENS.WORKSPACE.MORE_FEATURES
| typeof SCREENS.WORKSPACE.PROFILE
| typeof SCREENS.WORKSPACE.MEMBERS
| typeof SCREENS.WORKSPACE.EXPENSIFY_CARD
| typeof SCREENS.WORKSPACE.REPORT_FIELDS;
};

Expand Down Expand Up @@ -106,6 +107,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, reimbursementAcc
[CONST.POLICY.MORE_FEATURES.ARE_TAGS_ENABLED]: policy?.areTagsEnabled,
[CONST.POLICY.MORE_FEATURES.ARE_TAXES_ENABLED]: policy?.tax?.trackingEnabled,
[CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED]: policy?.areConnectionsEnabled,
[CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED]: policy?.areExpensifyCardsEnabled,
[CONST.POLICY.MORE_FEATURES.ARE_REPORT_FIELDS_ENABLED]: policy?.areReportFieldsEnabled,
}),
[policy],
Expand Down Expand Up @@ -231,6 +233,15 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, reimbursementAcc
});
}

if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED]) {
protectedCollectPolicyMenuItems.push({
translationKey: 'workspace.common.expensifyCard',
icon: Expensicons.CreditCard,
action: singleExecution(waitForNavigate(() => Navigation.navigate(ROUTES.WORKSPACE_EXPENSIFY_CARD.getRoute(policyID)))),
routeName: SCREENS.WORKSPACE.EXPENSIFY_CARD,
});
}

if (featureStates?.[CONST.POLICY.MORE_FEATURES.ARE_WORKFLOWS_ENABLED]) {
protectedCollectPolicyMenuItems.push({
translationKey: 'workspace.common.workflows',
Expand Down
15 changes: 14 additions & 1 deletion src/pages/workspace/WorkspaceMoreFeaturesPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro
const styles = useThemeStyles();
const {isSmallScreenWidth} = useWindowDimensions();
const {translate} = useLocalize();
const {canUseReportFieldsFeature} = usePermissions();
const {canUseReportFieldsFeature, canUseExpensifyCardFeature} = usePermissions();
const hasAccountingConnection = !!policy?.areConnectionsEnabled && !isEmptyObject(policy?.connections);
const isSyncTaxEnabled = !!policy?.connections?.quickbooksOnline?.config?.syncTax || !!policy?.connections?.xero?.config?.importTaxRates;
const policyID = policy?.id ?? '';
Expand Down Expand Up @@ -88,6 +88,19 @@ function WorkspaceMoreFeaturesPage({policy, route}: WorkspaceMoreFeaturesPagePro
},
];

if (canUseExpensifyCardFeature) {
spendItems.splice(1, 0, {
icon: Illustrations.HandCard,
titleTranslationKey: 'workspace.moreFeatures.expensifyCard.title',
subtitleTranslationKey: 'workspace.moreFeatures.expensifyCard.subtitle',
isActive: policy?.areExpensifyCardsEnabled ?? false,
pendingAction: policy?.pendingFields?.areExpensifyCardsEnabled,
action: (isEnabled: boolean) => {
Policy.enableExpensifyCard(policy?.id ?? '-1', isEnabled);
Copy link
Contributor

Choose a reason for hiding this comment

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

What does is expected to happen if we call Policy.enableExpensifyCard with policyID = -1? I guess the server will throw an error... shouldn't we instead be writing the code like:

action: (isEnabled: boolean) => {
  if (!policy?.id) {
    return;
  }
  Policy.enableExpensifyCard(policy.id, isEnabled);
}

and disable this button if we don't have a policy.id with disabled: !isEmptyObject(cardsList) || policy?.id,

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point, @aldo-expensify!

@narefyev91 Can we update to not call Policy.enableExpensifyCard with policyID -1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

sure

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BTW @MariaHCD @aldo-expensify we have the same logic for all menu items
Screenshot 2024-08-05 at 13 49 49
And probably all those API calls will failed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A little bit confusing if we just re-write only one menu item - and leave everything else as it is. And why such behaviour was not implemented? Probably we do not block action even if policy id is not exists?

Copy link
Contributor

Choose a reason for hiding this comment

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

Got it. I'm not quite following what the situation is exactly that you need advice on, but if I can be helpful, please let me know and we can keep discussing.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think this matters more from a code perspective rather than UI, since it may be impossible for this to happen in a normal user case? 🤷

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok I will make that changes and push a PR to clean up code

Copy link
Contributor

Choose a reason for hiding this comment

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

Wanted to say that this screen has the policyID in the URL so probably not possible to access.

I do like the clarity though from the code perspective so feel free to clean this up but noting this is lower priority task so try to prioritize other release related work and. Focus on this if you do not have other tasks to handle @narefyev91 thanks!

Thanks @aldo-expensify for raising

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mountiny yeah - i'm happy to help with anything for upcoming releases - but probably for now have some time to pick this one (until something else will come up). Probably waiting when Third-party workspace card feed doc will reviewed and start on that project

},
});
}

const organizeItems: Item[] = [
{
icon: Illustrations.FolderOpen,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type {StackScreenProps} from '@react-navigation/stack';
import React from 'react';
import {View} from 'react-native';
import * as Illustrations from '@components/Icon/Illustrations';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import useWindowDimensions from '@hooks/useWindowDimensions';
import type {FullScreenNavigatorParamList} from '@libs/Navigation/types';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import WorkspacePageWithSections from '@pages/workspace/WorkspacePageWithSections';
import CONST from '@src/CONST';
import type SCREENS from '@src/SCREENS';

type WorkspaceExpensifyCardPageProps = StackScreenProps<FullScreenNavigatorParamList, typeof SCREENS.WORKSPACE.EXPENSIFY_CARD>;

function WorkspaceExpensifyCardPage({route}: WorkspaceExpensifyCardPageProps) {
const {translate} = useLocalize();
const styles = useThemeStyles();
const {isSmallScreenWidth} = useWindowDimensions();

return (
<AccessOrNotFoundWrapper
policyID={route.params.policyID}
featureName={CONST.POLICY.MORE_FEATURES.ARE_EXPENSIFY_CARDS_ENABLED}
>
<WorkspacePageWithSections
shouldUseScrollView
icon={Illustrations.HandCard}
headerText={translate('workspace.common.expensifyCard')}
route={route}
guidesCallTaskID={CONST.GUIDES_CALL_TASK_IDS.WORKSPACE_EXPENSIFY_CARD}
shouldShowOfflineIndicatorInWideScreen
>
<View style={[styles.mt3, isSmallScreenWidth ? styles.workspaceSectionMobile : styles.workspaceSection]} />
</WorkspacePageWithSections>
</AccessOrNotFoundWrapper>
);
}

WorkspaceExpensifyCardPage.displayName = 'WorkspaceExpensifyCardPage';

export default WorkspaceExpensifyCardPage;
1 change: 1 addition & 0 deletions src/pages/workspace/withPolicy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type PolicyRoute = RouteProp<
| typeof SCREENS.WORKSPACE.BILLS
| typeof SCREENS.WORKSPACE.MORE_FEATURES
| typeof SCREENS.WORKSPACE.MEMBERS
| typeof SCREENS.WORKSPACE.EXPENSIFY_CARD
| typeof SCREENS.WORKSPACE.INVITE
| typeof SCREENS.WORKSPACE.INVITE_MESSAGE
| typeof SCREENS.WORKSPACE.WORKFLOWS_PAYER
Expand Down
3 changes: 3 additions & 0 deletions src/types/onyx/Policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,9 @@ type Policy = OnyxCommon.OnyxValueWithOfflineFeedback<
/** Whether the Distance Rates feature is enabled */
areDistanceRatesEnabled?: boolean;

/** Whether the Expensify Card feature is enabled */
areExpensifyCardsEnabled?: boolean;

/** Whether the workflows feature is enabled */
areWorkflowsEnabled?: boolean;

Expand Down
Loading