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 6 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
2 changes: 2 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1725,6 +1725,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 @@ -2052,6 +2053,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 @@ -798,6 +798,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/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
11 changes: 9 additions & 2 deletions src/components/Switch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,27 @@ type SwitchProps = {

/** Whether to show the lock icon even if the switch is enabled */
showLockIcon?: boolean;

/** Callback to fire when the switch is toggled in disabled state */
disabledAction?: () => void;
};

const OFFSET_X = {
OFF: 0,
ON: 20,
};

function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon}: SwitchProps) {
function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon, disabledAction}: SwitchProps) {
const styles = useThemeStyles();
const offsetX = useRef(new Animated.Value(isOn ? OFFSET_X.ON : OFFSET_X.OFF));
const theme = useTheme();

const handleSwitchPress = () => {
InteractionManager.runAfterInteractions(() => {
if (disabled) {
disabledAction?.();
return;
}
onToggle(!isOn);
});
};
Expand All @@ -51,7 +58,7 @@ function Switch({isOn, onToggle, accessibilityLabel, disabled, showLockIcon}: Sw

return (
<PressableWithFeedback
disabled={disabled}
disabled={!disabledAction && disabled}
style={[styles.switchTrack, !isOn && styles.switchInactive]}
onPress={handleSwitchPress}
onLongPress={handleSwitchPress}
Expand Down
8 changes: 8 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2001,6 +2001,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 @@ -2254,6 +2255,13 @@ export default {
title: 'Distance rates',
subtitle: 'Add, update, and enforce rates.',
},
expensifyCard: {
title: 'Expensify Card',
subtitle: 'Gain insights and control over spend',
disableCardTitle: 'Disable Expensify Card',
disableCardPrompt: 'You can’t disable the Expensify Card because it’s already in use. Reach out to Concierge for next steps.',
disableCardButton: 'Chat with Concierge',
},
workflows: {
title: 'Workflows',
subtitle: 'Configure how spend is approved and paid.',
Expand Down
8 changes: 8 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2000,6 +2000,7 @@ export default {
bills: 'Pagar facturas',
invoices: 'Enviar facturas',
travel: 'Viajes',
expensifyCard: 'Tarjeta Expensify',
members: 'Miembros',
accounting: 'Contabilidad',
plan: 'Plan',
Expand Down Expand Up @@ -2285,6 +2286,13 @@ 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',
disableCardTitle: 'Deshabilitar la Tarjeta Expensify',
disableCardButton: 'Chatear con Concierge',
disableCardPrompt: 'No puedes deshabilitar la Tarjeta Expensify porque ya está en uso. Por favor, contacta con Concierge para conocer los pasos a seguir.',
},
narefyev91 marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -188,6 +188,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 @@ -414,6 +415,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;
7 changes: 3 additions & 4 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,6 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.WORKSPACE.SHARE]: {
path: ROUTES.WORKSPACE_PROFILE_SHARE.route,
},
// TODO: uncomment after development
// [SCREENS.WORKSPACE.EXPENSIFY_CARD]: {
// path: ROUTES.WORKSPACE_EXPENSIFY_CARD,
// },
[SCREENS.WORKSPACE.EXPENSIFY_CARD_ISSUE_NEW]: {
path: ROUTES.WORKSPACE_EXPENSIFY_CARD_ISSUE_NEW,
},
Expand Down Expand Up @@ -825,6 +821,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
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 @@ -2456,6 +2457,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 @@ -3000,6 +3049,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
Loading
Loading