diff --git a/src/languages/de.ts b/src/languages/de.ts index 752170ba678a..9b46cfbe93dc 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -3536,6 +3536,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automatisieren Sie die Reisekosten und Essenslieferungskosten in Ihrem gesamten Unternehmen.', + autoRemove: 'Neue Workspace-Mitglieder zu Uber for Business einladen', + autoInvite: 'Entfernte Workspace-Mitglieder von Uber for Business deaktivieren', + manageInvites: 'Einladungen verwalten', }, }, perDiem: { @@ -4672,6 +4675,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Uber trennen', disconnectText: 'Um diese Funktion zu deaktivieren, trennen Sie bitte zuerst die Uber for Business Integration.', + description: 'Möchten Sie diese Integration wirklich trennen?', confirmText: 'Verstanden', }, workflowWarningModal: { diff --git a/src/languages/en.ts b/src/languages/en.ts index 917877ab5191..dee500576f1b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -3533,6 +3533,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automate travel and meal delivery expenses across your organization.', + autoRemove: 'Invite new workspace members to Uber for Business', + autoInvite: 'Deactivate removed workspace members from Uber for Business', + manageInvites: 'Manage invites', }, }, perDiem: { @@ -4655,6 +4658,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Disconnect Uber', disconnectText: 'To disable this feature, please disconnect the Uber for Business integration first.', + description: 'Are you sure you want to disconnect this integration?', confirmText: 'Got it', }, workflowWarningModal: { diff --git a/src/languages/es.ts b/src/languages/es.ts index ea35a8ecb40d..07052dda86b8 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -3521,6 +3521,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automatice los gastos de viajes y entrega de comidas en toda su organización.', + autoRemove: 'Invitar a nuevos miembros del espacio de trabajo a Uber para Empresas', + autoInvite: 'Desactivar miembros del espacio de trabajo eliminados de Uber para Empresas', + manageInvites: 'Administrar invitaciones', }, }, perDiem: { @@ -4665,6 +4668,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Desconectar Uber', disconnectText: 'Para desactivar esta función, desconecta primero la integración de Uber for Business.', + description: '¿Está seguro de que desea desconectar esta integración?', confirmText: 'Entendido', }, workflowWarningModal: { diff --git a/src/languages/fr.ts b/src/languages/fr.ts index e7044633bb12..d676f289eea5 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -3544,6 +3544,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automatisez les dépenses de déplacement et de livraison de repas dans toute votre organisation.', + autoRemove: "Inviter de nouveaux membres de l'espace de travail sur Uber", + autoInvite: "Désactiver les membres supprimés de l'espace de travail sur Uber", + manageInvites: 'Gérer les invitations', }, }, perDiem: { @@ -4688,6 +4691,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Déconnecter Uber', disconnectText: "Pour désactiver cette fonctionnalité, veuillez d'abord déconnecter l'intégration Uber for Business.", + description: 'Êtes-vous sûr de vouloir déconnecter cette intégration?', confirmText: 'Compris', }, workflowWarningModal: { diff --git a/src/languages/it.ts b/src/languages/it.ts index 659febb37c78..96a4aed028a2 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -3549,6 +3549,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automatizza le spese di viaggio e di consegna dei pasti in tutta la tua organizzazione.', + autoRemove: "Invita nuovi membri dell'area di lavoro su Uber for Business", + autoInvite: "Disattiva i membri dell'area di lavoro rimossi da Uber for Business", + manageInvites: 'Gestisci inviti', }, }, perDiem: { @@ -4687,6 +4690,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Disconnetti Uber', disconnectText: "Per disabilitare questa funzionalità, disconnetti prima l'integrazione Uber for Business.", + description: 'Sei sicuro di voler disconnettere questa integrazione?', confirmText: 'Capito', }, workflowWarningModal: { diff --git a/src/languages/ja.ts b/src/languages/ja.ts index eb6dc42bbb24..d5dad88e0f84 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -3549,6 +3549,9 @@ const translations = { receiptPartners: { uber: { subtitle: '組織全体で出張費や食事の配達費を自動化します。', + autoRemove: 'Uber for Business に新しいワークスペースメンバーを招待する', + autoInvite: 'Uber for Business から削除されたワークスペースメンバーを非アクティブ化する', + manageInvites: '招待を管理する', }, }, perDiem: { @@ -4666,6 +4669,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Uberを切断', disconnectText: 'この機能を無効にするには、まずUber for Business統合を切断してください。', + description: 'この統合を切断してもよろしいですか?', confirmText: '了解', }, workflowWarningModal: { diff --git a/src/languages/nl.ts b/src/languages/nl.ts index d0f3d810d259..dfa59eab5dd2 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -3556,6 +3556,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automatiseer reis- en maaltijdbezorgkosten binnen uw organisatie.', + autoRemove: 'Nodig nieuwe werkruimteleden uit voor Uber for Business', + autoInvite: 'Deactiveer verwijderde werkruimteleden van Uber for Business', + manageInvites: 'Beheer uitnodigingen', }, }, perDiem: { @@ -4689,6 +4692,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Uber verbreken', disconnectText: 'Om deze functie uit te schakelen, verbreek eerst de Uber for Business integratie.', + description: 'Weet u zeker dat u deze integratie wilt verbreken?', confirmText: 'Begrepen', }, workflowWarningModal: { diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 74ced0c3316c..5cfabe7696c1 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -3549,6 +3549,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Zautomatyzuj wydatki na podróże i dostawę posiłków w swojej organizacji.', + autoRemove: 'Zaproś nowych członków przestrzeni roboczej do Ubera dla Firm', + autoInvite: 'Dezaktywuj usuniętych członków przestrzeni roboczej w Uberze dla Firm', + manageInvites: 'Zarządzaj zaproszeniami', }, }, perDiem: { @@ -4678,6 +4681,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Rozłącz Uber', disconnectText: 'Aby wyłączyć tę funkcję, najpierw rozłącz integrację Uber for Business.', + description: 'Czy na pewno chcesz rozłączyć tę integrację?', confirmText: 'Rozumiem', }, workflowWarningModal: { diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 1c273852c533..955b0f3ef0f2 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -3554,6 +3554,9 @@ const translations = { receiptPartners: { uber: { subtitle: 'Automatize despesas de viagens e entrega de refeições em toda a sua organização.', + autoRemove: 'Convidar novos membros do espaço de trabalho para o Uber for Business', + autoInvite: 'Desativar membros removidos do espaço de trabalho do Uber for Business', + manageInvites: 'Gerenciar convites', }, }, perDiem: { @@ -4684,6 +4687,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: 'Desconectar Uber', disconnectText: 'Para desativar este recurso, desconecte primeiro a integração do Uber for Business.', + description: 'Tem certeza de que deseja desconectar esta integração?', confirmText: 'Entendi', }, workflowWarningModal: { diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 80e852e878fc..53d55e29afc8 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -3507,6 +3507,9 @@ const translations = { receiptPartners: { uber: { subtitle: '自动化整个组织的差旅和送餐费用。', + autoRemove: '邀请新工作区成员加入 Uber for Business', + autoInvite: '停用已从 Uber for Business 移除的工作区成员', + manageInvites: '管理邀请', }, }, perDiem: { @@ -4603,6 +4606,7 @@ const translations = { receiptPartnersWarningModal: { featureEnabledTitle: '断开Uber连接', disconnectText: '要禁用此功能,请先断开Uber for Business集成。', + description: '您确定要断开此集成吗?', confirmText: '明白了', }, workflowWarningModal: { diff --git a/src/libs/API/parameters/RemovePolicyReceiptPartnersConnectionParams.ts b/src/libs/API/parameters/RemovePolicyReceiptPartnersConnectionParams.ts new file mode 100644 index 000000000000..180753f035b2 --- /dev/null +++ b/src/libs/API/parameters/RemovePolicyReceiptPartnersConnectionParams.ts @@ -0,0 +1,6 @@ +type RemovePolicyReceiptPartnersConnectionParams = { + policyID: string; + partnerName: string; +}; + +export default RemovePolicyReceiptPartnersConnectionParams; diff --git a/src/libs/API/parameters/TogglePolicyUberAutoInvitePageParams.ts b/src/libs/API/parameters/TogglePolicyUberAutoInvitePageParams.ts new file mode 100644 index 000000000000..c4e3ca50b640 --- /dev/null +++ b/src/libs/API/parameters/TogglePolicyUberAutoInvitePageParams.ts @@ -0,0 +1,6 @@ +type TogglePolicyUberAutoInvitePageParams = { + policyID: string; + enabled: boolean; +}; + +export default TogglePolicyUberAutoInvitePageParams; diff --git a/src/libs/API/parameters/TogglePolicyUberAutoRemovePageParams.ts b/src/libs/API/parameters/TogglePolicyUberAutoRemovePageParams.ts new file mode 100644 index 000000000000..270af33badb9 --- /dev/null +++ b/src/libs/API/parameters/TogglePolicyUberAutoRemovePageParams.ts @@ -0,0 +1,6 @@ +type TogglePolicyUberAutoRemovePageParams = { + policyID: string; + enabled: boolean; +}; + +export default TogglePolicyUberAutoRemovePageParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 4f7d6985372d..d951fe4f2f7f 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -26,10 +26,12 @@ export type {default as SyncPolicyToNetSuiteParams} from './SyncPolicyToNetSuite export type {default as UpdateNetSuiteAccountingMethodParams} from './UpdateNetSuiteAccountingMethodParams'; export type {default as UpdateQuickbooksOnlineAccountingMethodParams} from './UpdateQuickbooksOnlineAccountingMethodParams'; export type {default as UpdateXeroAccountingMethodParams} from './UpdateXeroAccountingMethodParams'; +export type {default as RemovePolicyReceiptPartnersConnectionParams} from './RemovePolicyReceiptPartnersConnectionParams'; export type {default as SyncPolicyToQuickbooksDesktopParams} from './SyncPolicyToQuickbooksDesktopParams'; export type {default as DeleteContactMethodParams} from './DeleteContactMethodParams'; export type {default as DeletePaymentBankAccountParams} from './DeletePaymentBankAccountParams'; export type {default as DeletePaymentCardParams} from './DeletePaymentCardParams'; +export type {default as TogglePolicyUberAutoInvitePageParams} from './TogglePolicyUberAutoInvitePageParams'; export type {default as DismissReferralBannerParams} from './DismissReferralBannerParams'; export type {default as ExpandURLPreviewParams} from './ExpandURLPreviewParams'; export type {default as GetMissingOnyxMessagesParams} from './GetMissingOnyxMessagesParams'; @@ -122,6 +124,7 @@ export type {default as AddEmojiReactionParams} from './AddEmojiReactionParams'; export type {default as RemoveEmojiReactionParams} from './RemoveEmojiReactionParams'; export type {default as LeaveRoomParams} from './LeaveRoomParams'; export type {default as LeaveGroupChatParams} from './LeaveGroupChatParams'; +export type {default as TogglePolicyUberAutoRemovePageParams} from './TogglePolicyUberAutoRemovePageParams'; export type {default as InviteToRoomParams} from './InviteToRoomParams'; export type {default as InviteToGroupChatParams} from './InviteToGroupChatParams'; export type {default as RemoveFromRoomParams} from './RemoveFromRoomParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index fba8bf561787..b7626b016177 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -50,6 +50,8 @@ const WRITE_COMMANDS = { CARD_DEACTIVATE: 'Card_Deactivate', CHRONOS_REMOVE_OOO_EVENT: 'Chronos_RemoveOOOEvent', MAKE_DEFAULT_PAYMENT_METHOD: 'MakeDefaultPaymentMethod', + POLICY_UBER_AUTO_INVITE: 'PolicyUberAutoInvite', + POLICY_UBER_AUTO_REMOVE: 'PolicyUberAutoRemove', ADD_PAYMENT_CARD: 'AddPaymentCard', ADD_PAYMENT_CARD_SCA: 'AddPaymentCardSCA', VERIFY_SETUP_INTENT: 'User_VerifySetupIntent', @@ -298,6 +300,7 @@ const WRITE_COMMANDS = { UPDATE_QUICKBOOKS_DESKTOP_SYNC_CUSTOMERS: 'UpdateQuickbooksDesktopSyncCustomers', UPDATE_QUICKBOOKS_DESKTOP_SYNC_ITEMS: 'UpdateQuickbooksDesktopSyncItems', REMOVE_POLICY_CONNECTION: 'RemovePolicyConnection', + DISCONNECT_WORKSPACE_RECEIPT_PARTNER: 'DisconnectWorkspaceReceiptPartner', SET_POLICY_TAXES_ENABLED: 'SetPolicyTaxesEnabled', DELETE_POLICY_TAXES: 'DeletePolicyTaxes', UPDATE_POLICY_TAX_VALUE: 'UpdatePolicyTaxValue', @@ -525,6 +528,8 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_EXPENSIFY_CARD_LIMIT_TYPE]: Parameters.UpdateExpensifyCardLimitTypeParams; [WRITE_COMMANDS.CARD_DEACTIVATE]: Parameters.CardDeactivateParams; [WRITE_COMMANDS.MAKE_DEFAULT_PAYMENT_METHOD]: Parameters.MakeDefaultPaymentMethodParams; + [WRITE_COMMANDS.POLICY_UBER_AUTO_INVITE]: Parameters.TogglePolicyUberAutoInvitePageParams; + [WRITE_COMMANDS.POLICY_UBER_AUTO_REMOVE]: Parameters.TogglePolicyUberAutoRemovePageParams; [WRITE_COMMANDS.ADD_PAYMENT_CARD]: Parameters.AddPaymentCardParams; [WRITE_COMMANDS.ADD_PAYMENT_CARD_SCA]: Parameters.AddPaymentCardParams; [WRITE_COMMANDS.VERIFY_SETUP_INTENT]: Parameters.VerifySetupIntentParams; @@ -600,6 +605,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_REPORT_NOTIFICATION_PREFERENCE]: Parameters.UpdateReportNotificationPreferenceParams; [WRITE_COMMANDS.UPDATE_ROOM_VISIBILITY]: Parameters.UpdateRoomVisibilityParams; [WRITE_COMMANDS.UPDATE_ROOM_DESCRIPTION]: Parameters.UpdateRoomDescriptionParams; + [WRITE_COMMANDS.DISCONNECT_WORKSPACE_RECEIPT_PARTNER]: Parameters.RemovePolicyReceiptPartnersConnectionParams; [WRITE_COMMANDS.UPDATE_REPORT_WRITE_CAPABILITY]: Parameters.UpdateReportWriteCapabilityParams; [WRITE_COMMANDS.ADD_WORKSPACE_ROOM]: Parameters.AddWorkspaceRoomParams; [WRITE_COMMANDS.UPDATE_POLICY_ROOM_NAME]: Parameters.UpdatePolicyRoomNameParams; diff --git a/src/libs/actions/Policy/Policy.ts b/src/libs/actions/Policy/Policy.ts index 8ae8032c8213..5d6d9143d7a5 100644 --- a/src/libs/actions/Policy/Policy.ts +++ b/src/libs/actions/Policy/Policy.ts @@ -36,6 +36,7 @@ import type { OpenPolicyWorkflowsPageParams, OpenWorkspaceInvitePageParams, OpenWorkspaceParams, + RemovePolicyReceiptPartnersConnectionParams, RequestExpensifyCardLimitIncreaseParams, SetNameValuePairParams, SetPolicyAutomaticApprovalLimitParams, @@ -53,6 +54,8 @@ import type { SetWorkspacePayerParams, SetWorkspaceReimbursementParams, TogglePolicyReceiptPartnersParams, + TogglePolicyUberAutoInvitePageParams, + TogglePolicyUberAutoRemovePageParams, UpdateInvoiceCompanyNameParams, UpdateInvoiceCompanyWebsiteParams, UpdatePolicyAddressParams, @@ -110,7 +113,7 @@ import type { TransactionViolations, } from '@src/types/onyx'; import type {Errors} from '@src/types/onyx/OnyxCommon'; -import type {Attributes, CompanyAddress, CustomUnit, NetSuiteCustomList, NetSuiteCustomSegment, ProhibitedExpenses, Rate, TaxRate} from '@src/types/onyx/Policy'; +import type {Attributes, CompanyAddress, CustomUnit, NetSuiteCustomList, NetSuiteCustomSegment, ProhibitedExpenses, Rate, TaxRate, UberReceiptPartner} from '@src/types/onyx/Policy'; import type {CustomFieldType} from '@src/types/onyx/PolicyEmployee'; import type {NotificationPreference} from '@src/types/onyx/Report'; import type {OnyxData} from '@src/types/onyx/Request'; @@ -2515,6 +2518,120 @@ function openPolicyReceiptPartnersPage(policyID?: string) { API.read(READ_COMMANDS.OPEN_POLICY_RECEIPT_PARTNERS_PAGE, params); } +function removePolicyReceiptPartnersConnection(policyID: string, partnerName: string, receiptPartnerData?: UberReceiptPartner) { + const optimisticData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + receiptPartners: { + [partnerName]: {pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE}, + }, + }, + }, + ]; + + const successData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + receiptPartners: { + [partnerName]: {pendingAction: null}, + }, + }, + }, + ]; + + const failureData: OnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + value: { + receiptPartners: { + [partnerName]: {...receiptPartnerData, errorFields: {name: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage')}, pendingAction: null}, + }, + }, + }, + ]; + + const parameters: RemovePolicyReceiptPartnersConnectionParams = { + policyID, + partnerName, + }; + API.write(WRITE_COMMANDS.DISCONNECT_WORKSPACE_RECEIPT_PARTNER, parameters, {optimisticData, failureData, successData}); +} + +function togglePolicyUberAutoInvite(policyID: string | undefined, enabled: boolean) { + if (!policyID) { + Log.warn('togglePolicyUberAutoInvite invalid params', {policyID}); + return; + } + + const optimisticData: OnyxUpdate[] = [ + { + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + onyxMethod: Onyx.METHOD.MERGE, + value: { + receiptPartners: {uber: {autoInvite: enabled, pendingFields: {autoInvite: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}, + }, + }, + ]; + const successData: OnyxUpdate[] = [ + { + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + onyxMethod: Onyx.METHOD.MERGE, + value: {receiptPartners: {uber: {pendingFields: null}}}, + }, + ]; + const failureData: OnyxUpdate[] = [ + { + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + onyxMethod: Onyx.METHOD.MERGE, + value: {receiptPartners: {uber: {autoInvite: !enabled, pendingFields: null}}}, + }, + ]; + + const params: TogglePolicyUberAutoInvitePageParams = {policyID, enabled}; + + API.write(WRITE_COMMANDS.POLICY_UBER_AUTO_INVITE, params, {optimisticData, successData, failureData}); +} + +function togglePolicyUberAutoRemove(policyID: string | undefined, enabled: boolean) { + if (!policyID) { + Log.warn('togglePolicyUberAutoRemove invalid params', {policyID}); + return; + } + + const optimisticData: OnyxUpdate[] = [ + { + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + onyxMethod: Onyx.METHOD.MERGE, + value: { + receiptPartners: {uber: {autoRemove: enabled, pendingFields: {autoRemove: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}}}, + }, + }, + ]; + const successData: OnyxUpdate[] = [ + { + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + onyxMethod: Onyx.METHOD.MERGE, + value: {receiptPartners: {uber: {pendingFields: null}}}, + }, + ]; + const failureData: OnyxUpdate[] = [ + { + key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, + onyxMethod: Onyx.METHOD.MERGE, + value: {receiptPartners: {uber: {autoRemove: !enabled, pendingFields: null}}}, + }, + ]; + + const params: TogglePolicyUberAutoRemovePageParams = {policyID, enabled}; + + API.write(WRITE_COMMANDS.POLICY_UBER_AUTO_REMOVE, params, {optimisticData, successData, failureData}); +} + /** * Returns the accountIDs of the members of the policy whose data is passed in the parameters */ @@ -5843,9 +5960,12 @@ export { clearGetAccessiblePoliciesErrors, calculateBillNewDot, payAndDowngrade, + togglePolicyUberAutoInvite, + togglePolicyUberAutoRemove, clearBillingReceiptDetailsErrors, clearQuickbooksOnlineAutoSyncErrorField, setIsForcedToChangeCurrency, + removePolicyReceiptPartnersConnection, openPolicyReceiptPartnersPage, setIsComingFromGlobalReimbursementsFlow, setPolicyAttendeeTrackingEnabled, diff --git a/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx b/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx index aceb5354448f..3d163a816a51 100644 --- a/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx +++ b/src/pages/workspace/receiptPartners/WorkspaceReceiptPartnersPage.tsx @@ -1,13 +1,16 @@ -import React, {useCallback, useEffect, useMemo} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; import {ActivityIndicator, View} from 'react-native'; import Button from '@components/Button'; +import ConfirmModal from '@components/ConfirmModal'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import * as Expensicons from '@components/Icon/Expensicons'; import * as Illustrations from '@components/Icon/Illustrations'; import MenuItem from '@components/MenuItem'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import Section from '@components/Section'; +import ThreeDotsMenu from '@components/ThreeDotsMenu'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import usePolicy from '@hooks/usePolicy'; @@ -20,10 +23,12 @@ import type {PlatformStackScreenProps} from '@navigation/PlatformStackNavigation import type {WorkspaceSplitNavigatorParamList} from '@navigation/types'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {MenuItemData} from '@pages/workspace/accounting/types'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import {openExternalLink} from '@userActions/Link'; -import {openPolicyReceiptPartnersPage} from '@userActions/Policy/Policy'; +import {openPolicyReceiptPartnersPage, removePolicyReceiptPartnersConnection, togglePolicyUberAutoInvite, togglePolicyUberAutoRemove} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import type SCREENS from '@src/SCREENS'; +import type {AnchorPosition} from '@src/styles'; import {getReceiptPartnersIntegrationData} from './utils'; type WorkspaceReceiptPartnersPageProps = PlatformStackScreenProps; @@ -37,13 +42,22 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps const receiptPartnerNames = CONST.POLICY.RECEIPT_PARTNERS.NAME; const receiptPartnerIntegrations = Object.values(receiptPartnerNames); const {isOffline} = useNetwork(); + const threeDotsMenuContainerRef = useRef(null); const policy = usePolicy(policyID); const theme = useTheme(); + const [selectedPartner, setSelectedPartner] = useState(null); const isLoading = policy?.isLoading; + const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false); const integrations = policy?.receiptPartners; + const isAutoRemove = !!integrations?.uber?.autoRemove; + const isAutoInvite = !!integrations?.uber?.autoInvite; + const [isConnected, setIsConnected] = useState(false); + const isUberConnected = !!integrations?.uber?.organizationID || isConnected; const startIntegrationFlow = useCallback( ({name}: {name: string}) => { + // TODO remove this when integration flow will be ready + setIsConnected(true); switch (name) { case CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER: { const {connectFormData} = integrations?.uber ?? {}; @@ -72,6 +86,72 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const calculateAndSetThreeDotsMenuPosition = useCallback(() => { + if (shouldUseNarrowLayout) { + return Promise.resolve({horizontal: 0, vertical: 0}); + } + return new Promise((resolve) => { + threeDotsMenuContainerRef.current?.measureInWindow((x, y, width, height) => { + resolve({ + horizontal: x + width, + vertical: y + height, + }); + }); + }); + }, [shouldUseNarrowLayout]); + + const toggleWorkspaceUberAutoInvite = useCallback(() => { + togglePolicyUberAutoInvite(policyID, !isAutoInvite); + }, [isAutoInvite, policyID]); + + const toggleWorkspaceUberAutoRemove = useCallback(() => { + togglePolicyUberAutoRemove(policyID, !isAutoRemove); + }, [isAutoRemove, policyID]); + + const getOverflowMenu = useCallback( + (integration: string) => { + switch (integration) { + case CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER: + return [ + { + icon: Expensicons.Key, + text: translate('workspace.accounting.enterCredentials'), + onSelected: () => startIntegrationFlow({name: CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER}), + shouldCallAfterModalHide: true, + disabled: isOffline, + iconRight: Expensicons.NewWindow, + }, + { + icon: Expensicons.Trashcan, + text: translate('workspace.accounting.disconnect'), + onSelected: () => { + setIsDisconnectModalOpen(true); + setSelectedPartner(CONST.POLICY.RECEIPT_PARTNERS.NAME.UBER); + }, + shouldCallAfterModalHide: true, + }, + ]; + default: + return []; + } + }, + [translate, isOffline, startIntegrationFlow], + ); + + const onCloseModal = useCallback(() => { + setIsDisconnectModalOpen(false); + setSelectedPartner(null); + }, []); + + const onDisconnectPartner = useCallback(() => { + if (!policyID || !selectedPartner) { + return; + } + removePolicyReceiptPartnersConnection(policyID, selectedPartner, integrations?.[selectedPartner]); + setIsConnected(false); + onCloseModal(); + }, [policyID, selectedPartner, integrations, onCloseModal]); + const connectionsMenuItems: MenuItemData[] = useMemo(() => { if (policyID) { return receiptPartnerIntegrations @@ -80,6 +160,7 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps if (!integrationData) { return undefined; } + const overflowMenu = getOverflowMenu(integration); const iconProps = integrationData?.icon ? { @@ -97,7 +178,19 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps numberOfLinesDescription: 5, titleContainerStyle: [styles.pr2], description: integrationData?.description, - rightComponent: ( + brickRoadIndicator: policy?.receiptPartners?.uber?.errorFields ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, + rightComponent: isUberConnected ? ( + + + + ) : (