From 15c5210ac2835853cb3fc81c3851ba53641ccbfe Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Thu, 11 Jul 2024 14:33:35 +0200 Subject: [PATCH 001/338] update the pay w/ expensify selectors logic --- src/CONST.ts | 5 ++ src/components/AddPaymentMethodMenu.tsx | 47 +++++++++++++++++-- .../parameters/CompleteGuidedSetupParams.ts | 1 + src/libs/actions/Report.ts | 2 + src/types/onyx/IntroSelected.ts | 3 ++ 5 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 50df9118a74e..bfb1ae701da4 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1840,6 +1840,11 @@ const CONST = { BUSINESS_BANK_ACCOUNT: 'businessBankAccount', }, + PAYMENT_SELECTED: { + BBA: 'BBA', + PBA: 'PBA', + }, + PAYMENT_METHOD_ID_KEYS: { DEBIT_CARD: 'fundID', BANK_ACCOUNT: 'bankAccountID', diff --git a/src/components/AddPaymentMethodMenu.tsx b/src/components/AddPaymentMethodMenu.tsx index 325bab091bec..87644c4b67fc 100644 --- a/src/components/AddPaymentMethodMenu.tsx +++ b/src/components/AddPaymentMethodMenu.tsx @@ -1,18 +1,22 @@ import type {RefObject} from 'react'; -import React from 'react'; +import React, {useCallback} from 'react'; import type {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx, withOnyx} from 'react-native-onyx'; +import type {ValueOf} from 'type-fest'; import useLocalize from '@hooks/useLocalize'; +import * as OptionsListUtils from '@libs/OptionsListUtils'; import * as ReportActionsUtils from '@libs/ReportActionsUtils'; import * as ReportUtils from '@libs/ReportUtils'; +import * as ReportUserActions from '@userActions/Report'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {AnchorPosition} from '@src/styles'; -import type {Report, Session} from '@src/types/onyx'; +import type {PersonalDetails, Report, Session} from '@src/types/onyx'; import type AnchorAlignment from '@src/types/utils/AnchorAlignment'; import * as Expensicons from './Icon/Expensicons'; import type {PaymentMethod} from './KYCWall/types'; +import {usePersonalDetails} from './OnyxProvider'; import PopoverMenu from './PopoverMenu'; type AddPaymentMethodMenuOnyxProps = { @@ -70,6 +74,32 @@ function AddPaymentMethodMenu({ const canUsePersonalBankAccount = shouldShowPersonalBankAccountOption || isIOUReport; + const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED); + const isInviteOnboardingComplete = introSelected?.isInviteOnboardingComplete ?? false; + + const personalDetails = usePersonalDetails() || CONST.EMPTY_OBJECT; + const personalDetailsList = Object.values(OptionsListUtils.getPersonalDetailsForAccountIDs(session?.accountID ? [session.accountID] : [], personalDetails)) as PersonalDetails[]; + const personalDetail = personalDetailsList[0] ?? {}; + + const completeEngagement = useCallback( + (paymentSelected: ValueOf) => { + if (isInviteOnboardingComplete || !introSelected?.choice) { + return; + } + + ReportUserActions.completeOnboarding( + introSelected?.choice, + CONST.ONBOARDING_MESSAGES[introSelected?.choice], + { + firstName: personalDetail.firstName ?? '', + lastName: personalDetail.lastName ?? '', + }, + paymentSelected, + ); + }, + [isInviteOnboardingComplete, introSelected?.choice, personalDetail.firstName, personalDetail.lastName], + ); + return ( { + completeEngagement(CONST.PAYMENT_SELECTED.PBA); onItemSelected(CONST.PAYMENT_METHODS.PERSONAL_BANK_ACCOUNT); }, }, @@ -95,7 +126,10 @@ function AddPaymentMethodMenu({ { text: translate('common.businessBankAccount'), icon: Expensicons.Building, - onSelected: () => onItemSelected(CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT), + onSelected: () => { + completeEngagement(CONST.PAYMENT_SELECTED.BBA); + onItemSelected(CONST.PAYMENT_METHODS.BUSINESS_BANK_ACCOUNT); + }, }, ] : []), @@ -103,7 +137,10 @@ function AddPaymentMethodMenu({ { text: translate('common.debitCard'), icon: Expensicons.CreditCard, - onSelected: () => onItemSelected(CONST.PAYMENT_METHODS.DEBIT_CARD), + onSelected: () => { + completeEngagement(CONST.PAYMENT_SELECTED.PBA); + onItemSelected(CONST.PAYMENT_METHODS.DEBIT_CARD); + }, }, ], ]} diff --git a/src/libs/API/parameters/CompleteGuidedSetupParams.ts b/src/libs/API/parameters/CompleteGuidedSetupParams.ts index 8e1273ac6053..0b2c0b66ef0a 100644 --- a/src/libs/API/parameters/CompleteGuidedSetupParams.ts +++ b/src/libs/API/parameters/CompleteGuidedSetupParams.ts @@ -6,6 +6,7 @@ type CompleteGuidedSetupParams = { actorAccountID: number; guidedSetupData: string; engagementChoice: OnboardingPurposeType; + paymentSelected?: string; }; export default CompleteGuidedSetupParams; diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 3060f53f12c3..bc9c114442a0 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3158,6 +3158,7 @@ function completeOnboarding( }, adminsChatReportID?: string, onboardingPolicyID?: string, + paymentSelected?: string, ) { const isAccountIDOdd = AccountUtils.isAccountIDOddNumber(currentUserAccountID ?? 0); const targetEmail = isAccountIDOdd ? CONST.EMAIL.NOTIFICATIONS : CONST.EMAIL.CONCIERGE; @@ -3504,6 +3505,7 @@ function completeOnboarding( lastName, actorAccountID, guidedSetupData: JSON.stringify(guidedSetupData), + paymentSelected, }; API.write(WRITE_COMMANDS.COMPLETE_GUIDED_SETUP, parameters, {optimisticData, successData, failureData}); diff --git a/src/types/onyx/IntroSelected.ts b/src/types/onyx/IntroSelected.ts index 6850f651ca2a..6693745d2c95 100644 --- a/src/types/onyx/IntroSelected.ts +++ b/src/types/onyx/IntroSelected.ts @@ -4,6 +4,9 @@ import type {OnboardingPurposeType} from '@src/CONST'; type IntroSelected = { /** The choice that the user selected in the engagement modal */ choice: OnboardingPurposeType; + + /** Whether the onboarding is complete */ + isInviteOnboardingComplete: boolean; }; export default IntroSelected; From f0a484508ae082a765140f53ccd0e0535c4a3333 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:03:15 +0200 Subject: [PATCH 002/338] update completeEngagement in AddPaymentMethodMenu with inviteType check for choice --- src/CONST.ts | 100 ++++++++++++++++-- src/components/AddPaymentMethodMenu.tsx | 13 ++- src/libs/actions/Report.ts | 2 + .../BaseOnboardingPurpose.tsx | 2 +- src/types/onyx/IntroSelected.ts | 9 +- 5 files changed, 112 insertions(+), 14 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index a273c2c105c4..c3a977f07e26 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4,6 +4,7 @@ import dateSubtract from 'date-fns/sub'; import Config from 'react-native-config'; import * as KeyCommand from 'react-native-key-command'; import type {ValueOf} from 'type-fest'; +import type {Video} from './libs/actions/Report'; import BankAccount from './libs/models/BankAccount'; import * as Url from './libs/Url'; import SCREENS from './SCREENS'; @@ -63,7 +64,7 @@ const chatTypes = { // Explicit type annotation is required const cardActiveStates: number[] = [2, 3, 4, 7]; -const onboardingChoices = { +const selectableOnboardingChoices = { PERSONAL_SPEND: 'newDotPersonalSpend', MANAGE_TEAM: 'newDotManageTeam', EMPLOYER: 'newDotEmployer', @@ -71,8 +72,40 @@ const onboardingChoices = { LOOKING_AROUND: 'newDotLookingAround', }; +const backendOnboardingChoices = { + ADMIN: 'newDotAdmin', + SUBMIT: 'newDotSubmit', +}; + +const onboardingChoices = { + ...selectableOnboardingChoices, + ...backendOnboardingChoices, +}; + type OnboardingPurposeType = ValueOf; +const onboardingInviteTypes = { + IOU: 'iou', + INVOICE: 'invoice', + CHAT: 'chat', +}; + +type OnboardingInviteType = ValueOf; + +type OnboardingTaskType = { + type: string; + autoCompleted: boolean; + title: string; + description: string | ((params: Partial<{adminsRoomLink: string; workspaceLink: string}>) => string); +}; + +type OnboardingMessageType = { + message: string; + video?: Video; + tasks: OnboardingTaskType[]; + type?: string; +}; + const CONST = { RECENT_WAYPOINTS_NUMBER: 20, DEFAULT_DB_NAME: 'OnyxDB', @@ -4189,6 +4222,8 @@ const CONST = { ONBOARDING_INTRODUCTION: 'Let’s get you set up πŸ”§', ONBOARDING_CHOICES: {...onboardingChoices}, + SELECTABLE_ONBOARDING_CHOICES: {...selectableOnboardingChoices}, + ONBOARDING_INVITE_TYPES: {...onboardingInviteTypes}, ACTIONABLE_TRACK_EXPENSE_WHISPER_MESSAGE: 'What would you like to do with this expense?', ONBOARDING_CONCIERGE: { [onboardingChoices.EMPLOYER]: @@ -4231,7 +4266,7 @@ const CONST = { }, ONBOARDING_MESSAGES: { - [onboardingChoices.EMPLOYER]: { + [(onboardingChoices.EMPLOYER || onboardingChoices.SUBMIT)]: { message: 'Getting paid back is as easy as sending a message. Let’s go over the basics.', video: { url: `${CLOUDFRONT_URL}/videos/guided-setup-get-paid-back-v2.mp4`, @@ -4302,7 +4337,7 @@ const CONST = { type: 'meetGuide', autoCompleted: false, title: 'Meet your setup specialist', - description: ({adminsRoomLink}: {adminsRoomLink: string}) => + description: ({adminsRoomLink}) => `Meet your setup specialist, who can answer any questions as you get started with Expensify. Yes, a real human!\n` + '\n' + `Chat with the specialist in your [#admins room](${adminsRoomLink}).`, @@ -4311,7 +4346,7 @@ const CONST = { type: 'setupCategories', autoCompleted: false, title: 'Set up categories', - description: ({workspaceLink}: {workspaceLink: string}) => + description: ({workspaceLink}) => '*Set up categories* so your team can code expenses for easy reporting.\n' + '\n' + 'Here’s how to set up categories:\n' + @@ -4328,7 +4363,7 @@ const CONST = { type: 'addExpenseApprovals', autoCompleted: false, title: 'Add expense approvals', - description: ({workspaceLink}: {workspaceLink: string}) => + description: ({workspaceLink}) => '*Add expense approvals* to review your team’s spend and keep it under control.\n' + '\n' + 'Here’s how to add expense approvals:\n' + @@ -4345,7 +4380,7 @@ const CONST = { type: 'inviteTeam', autoCompleted: false, title: 'Invite your team', - description: ({workspaceLink}: {workspaceLink: string}) => + description: ({workspaceLink}) => '*Invite your team* to Expensify so they can start tracking expenses today.\n' + '\n' + 'Here’s how to invite your team:\n' + @@ -4448,12 +4483,61 @@ const CONST = { }, ], }, + [onboardingChoices.ADMIN]: { + message: "Hey πŸ‘‹\nAs an admin, learn how to manage your team's workspace and submit expenses yourself.", + video: { + url: `${CLOUDFRONT_URL}/videos/guided-setup-manage-team-v2.mp4`, + thumbnailUrl: `${CLOUDFRONT_URL}/images/guided-setup-manage-team.jpg`, + duration: 55, + width: 1280, + height: 960, + }, + tasks: [ + { + type: 'meetSetupSpecialist', + autoCompleted: false, + title: 'Meet your setup specialist', + description: + '*Meet your setup specialist* who can answer any questions as you get started with Expensify. Yes, a real human!' + + '\n' + + 'Chat with them in your #admins room or schedule a call today.', + }, + { + type: 'reviewWorkspaceSettings', + autoCompleted: false, + title: 'Review your workspace settings', + description: + "Here's how to review and update your workspace settings:" + + '\n' + + '1. Click your profile picture.' + + '2. Click *Workspaces* > [Your workspace].' + + '\n' + + "Make any changes there and we'll track them in the #admins room.", + }, + { + type: 'submitExpense', + autoCompleted: false, + title: 'Submit an expense', + description: + '*Submit an expense* by entering an amount or scanning a receipt.\n' + + '\n' + + 'Here’s how to submit an expense:\n' + + '\n' + + '1. Click the green *+* button.\n' + + '2. Choose *Submit expense*.\n' + + '3. Enter an amount or scan a receipt.\n' + + '4. Add your reimburser to the request.\n' + + '\n' + + 'Then, send your request and wait for that sweet β€œCha-ching!” when it’s complete.', + }, + ], + }, [onboardingChoices.LOOKING_AROUND]: { message: "Expensify is best known for expense and corporate card management, but we do a lot more than that. Let me know what you're interested in and I'll help get you started.", tasks: [], }, - }, + } satisfies Record, REPORT_FIELD_TITLE_FIELD_ID: 'text_title', @@ -5433,6 +5517,6 @@ type FeedbackSurveyOptionID = ValueOf; type CancellationType = ValueOf; -export type {Country, IOUAction, IOUType, RateAndUnit, OnboardingPurposeType, IOURequestType, SubscriptionType, FeedbackSurveyOptionID, CancellationType}; +export type {Country, IOUAction, IOUType, RateAndUnit, OnboardingPurposeType, IOURequestType, SubscriptionType, FeedbackSurveyOptionID, CancellationType, OnboardingInviteType}; export default CONST; diff --git a/src/components/AddPaymentMethodMenu.tsx b/src/components/AddPaymentMethodMenu.tsx index 9847aba8df2c..51ac2776b876 100644 --- a/src/components/AddPaymentMethodMenu.tsx +++ b/src/components/AddPaymentMethodMenu.tsx @@ -87,9 +87,18 @@ function AddPaymentMethodMenu({ return; } + let choice = introSelected.choice; + if (introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.IOU && paymentSelected === CONST.PAYMENT_SELECTED.BBA) { + choice = CONST.ONBOARDING_CHOICES.MANAGE_TEAM; + } + + if (introSelected.inviteType === CONST.ONBOARDING_INVITE_TYPES.INVOICE && paymentSelected !== CONST.PAYMENT_SELECTED.BBA) { + choice = CONST.ONBOARDING_CHOICES.SUBMIT; + } + ReportUserActions.completeOnboarding( - introSelected?.choice, - CONST.ONBOARDING_MESSAGES[introSelected?.choice], + choice, + CONST.ONBOARDING_MESSAGES[choice], { firstName: personalDetail.firstName ?? '', lastName: personalDetail.lastName ?? '', diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index de651ff27610..e6ccc3d274ef 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -3851,6 +3851,8 @@ function markAsManuallyExported(reportID: string) { }); } +export type {Video}; + export { searchInServer, addComment, diff --git a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx index e9d0887bdac7..8d45a4893171 100644 --- a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx +++ b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx @@ -85,7 +85,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, ro Navigation.navigate(ROUTES.ONBOARDING_PERSONAL_DETAILS.getRoute(route.params?.backTo)); }, [selectedPurpose, route]); - const menuItems: MenuItemProps[] = Object.values(CONST.ONBOARDING_CHOICES).map((choice) => { + const menuItems: MenuItemProps[] = Object.values(CONST.SELECTABLE_ONBOARDING_CHOICES).map((choice) => { const translationKey = `onboarding.purpose.${choice}` as const; const isSelected = selectedPurpose === choice; return { diff --git a/src/types/onyx/IntroSelected.ts b/src/types/onyx/IntroSelected.ts index 6693745d2c95..0e1b4ec60ae4 100644 --- a/src/types/onyx/IntroSelected.ts +++ b/src/types/onyx/IntroSelected.ts @@ -1,12 +1,15 @@ -import type {OnboardingPurposeType} from '@src/CONST'; +import type {OnboardingInviteType, OnboardingPurposeType} from '@src/CONST'; /** Model of onboarding */ -type IntroSelected = { +type IntroSelected = Partial<{ /** The choice that the user selected in the engagement modal */ choice: OnboardingPurposeType; + /** The invite type */ + inviteType: OnboardingInviteType; + /** Whether the onboarding is complete */ isInviteOnboardingComplete: boolean; -}; +}>; export default IntroSelected; From 7cea50d93f6e3e05bf7adaa211d1b049b6ffe918 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:05:00 +0200 Subject: [PATCH 003/338] fix lint, add useCallback dependency --- src/components/AddPaymentMethodMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/AddPaymentMethodMenu.tsx b/src/components/AddPaymentMethodMenu.tsx index 51ac2776b876..839ab6a0c9bb 100644 --- a/src/components/AddPaymentMethodMenu.tsx +++ b/src/components/AddPaymentMethodMenu.tsx @@ -106,7 +106,7 @@ function AddPaymentMethodMenu({ paymentSelected, ); }, - [isInviteOnboardingComplete, introSelected?.choice, personalDetail.firstName, personalDetail.lastName], + [isInviteOnboardingComplete, introSelected?.inviteType, introSelected?.choice, personalDetail.firstName, personalDetail.lastName], ); const isPersonalOnlyOption = canUsePersonalBankAccount && !canUseBusinessBankAccount; From aa98fd457e0c7277dd72ac3097279e635632b195 Mon Sep 17 00:00:00 2001 From: cdOut <88325488+cdOut@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:05:47 +0200 Subject: [PATCH 004/338] fix prettier --- src/CONST.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CONST.ts b/src/CONST.ts index c3a977f07e26..0ab391ac1a36 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -4266,7 +4266,7 @@ const CONST = { }, ONBOARDING_MESSAGES: { - [(onboardingChoices.EMPLOYER || onboardingChoices.SUBMIT)]: { + [onboardingChoices.EMPLOYER || onboardingChoices.SUBMIT]: { message: 'Getting paid back is as easy as sending a message. Let’s go over the basics.', video: { url: `${CLOUDFRONT_URL}/videos/guided-setup-get-paid-back-v2.mp4`, From 263743bd155bc191cbab9f799e2533788374d603 Mon Sep 17 00:00:00 2001 From: zfurtak Date: Tue, 30 Jul 2024 13:04:43 +0200 Subject: [PATCH 005/338] Initial refactor of import pages --- src/CONST.ts | 9 +- src/libs/PolicyUtils.ts | 9 +- src/libs/actions/connections/index.ts | 95 +-------------- .../accounting/PolicyAccountingPage.tsx | 36 ++++-- .../advanced/QuickbooksAccountSelectPage.tsx | 2 +- .../qbo/advanced/QuickbooksAdvancedPage.tsx | 24 ++-- .../QuickbooksInvoiceAccountSelectPage.tsx | 2 +- ...uickbooksCompanyCardExpenseAccountPage.tsx | 8 +- ...ompanyCardExpenseAccountSelectCardPage.tsx | 12 +- ...oksCompanyCardExpenseAccountSelectPage.tsx | 2 +- .../export/QuickbooksExportDateSelectPage.tsx | 2 +- ...ickbooksExportInvoiceAccountSelectPage.tsx | 2 +- ...NonReimbursableDefaultVendorSelectPage.tsx | 2 +- ...oksOutOfPocketExpenseAccountSelectPage.tsx | 2 +- ...ooksOutOfPocketExpenseEntitySelectPage.tsx | 8 +- ...ooksPreferredExporterConfigurationPage.tsx | 2 +- .../import/QuickbooksChartOfAccountsPage.tsx | 39 +++---- .../qbo/import/QuickbooksClassesPage.tsx | 94 +++++++-------- .../qbo/import/QuickbooksCustomersPage.tsx | 94 +++++++-------- .../qbo/import/QuickbooksImportPage.tsx | 31 ++--- .../qbo/import/QuickbooksLocationsPage.tsx | 108 ++++++++---------- .../qbo/import/QuickbooksTaxesPage.tsx | 63 ++++------ .../accounting/xero/XeroImportPage.tsx | 4 +- ...roMapTrackingCategoryConfigurationPage.tsx | 6 +- .../XeroOrganizationConfigurationPage.tsx | 4 +- .../xero/XeroTaxesConfigurationPage.tsx | 4 +- .../XeroTrackingCategoryConfigurationPage.tsx | 12 +- .../xero/advanced/XeroAdvancedPage.tsx | 20 ++-- .../XeroBillPaymentAccountSelectorPage.tsx | 6 +- .../XeroInvoiceAccountSelectorPage.tsx | 6 +- .../xero/export/XeroBankAccountSelectPage.tsx | 4 +- .../export/XeroExportConfigurationPage.tsx | 4 +- .../XeroPreferredExporterSelectPage.tsx | 4 +- .../export/XeroPurchaseBillDateSelectPage.tsx | 4 +- .../XeroPurchaseBillStatusSelectorPage.tsx | 4 +- .../xero/import/XeroChartOfAccountsPage.tsx | 6 +- .../import/XeroCustomerConfigurationPage.tsx | 4 +- 37 files changed, 302 insertions(+), 436 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 82f6e2e7bb6a..5a84d2f99951 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1079,7 +1079,7 @@ const CONST = { PROCESS_REQUEST_DELAY_MS: 1000, MAX_PENDING_TIME_MS: 10 * 1000, RECHECK_INTERVAL_MS: 60 * 1000, - MAX_REQUEST_RETRIES: 10, + MAX_REQUEST_RETRIES: 0, NETWORK_STATUS: { ONLINE: 'online', OFFLINE: 'offline', @@ -1319,12 +1319,17 @@ const CONST = { }, QUICKBOOKS_ONLINE: 'quickbooksOnline', - QUICK_BOOKS_CONFIG: { + QUICKBOOKS_CONFIG: { SYNC_CLASSES: 'syncClasses', ENABLE_NEW_CATEGORIES: 'enableNewCategories', + EXPORTER: 'exporter', SYNC_CUSTOMERS: 'syncCustomers', SYNC_LOCATIONS: 'syncLocations', SYNC_TAX: 'syncTax', + IMPORT_CLASSES: 'importClasses', + IMPORT_CUSTOMERS: 'importCustomers', + IMPORT_LOCATIONS: 'importLocation', + IMPORT_TAX_RATES: 'importTaxRates', EXPORT: 'export', EXPORT_DATE: 'exportDate', NON_REIMBURSABLE_EXPENSES_ACCOUNT: 'nonReimbursableExpensesAccount', diff --git a/src/libs/PolicyUtils.ts b/src/libs/PolicyUtils.ts index 27c9aa69f699..bed7f46f8e27 100644 --- a/src/libs/PolicyUtils.ts +++ b/src/libs/PolicyUtils.ts @@ -43,6 +43,7 @@ type ConnectionWithLastSyncData = { }; type XeroSettings = Array>, string>>; +// type QuickbooksSettings = let allPolicies: OnyxCollection; @@ -531,7 +532,7 @@ function getXeroBankAccountsWithDefaultSelect(policy: Policy | undefined, select })); } -function areXeroSettingsInErrorFields(settings?: XeroSettings, errorFields?: ErrorFields) { +function areSettingsInErrorFields(settings?: XeroSettings, errorFields?: ErrorFields) { if (settings === undefined || errorFields === undefined) { return false; } @@ -540,7 +541,7 @@ function areXeroSettingsInErrorFields(settings?: XeroSettings, errorFields?: Err return settings.some((setting) => keys.includes(setting)); } -function xeroSettingsPendingAction(settings?: XeroSettings, pendingFields?: PendingFields): PendingAction | undefined { +function settingsPendingAction(settings?: XeroSettings, pendingFields?: PendingFields): PendingAction | undefined { if (settings === undefined || pendingFields === undefined) { return null; } @@ -904,8 +905,8 @@ export { getCurrentSageIntacctEntityName, hasNoPolicyOtherThanPersonalType, getCurrentTaxID, - areXeroSettingsInErrorFields, - xeroSettingsPendingAction, + areSettingsInErrorFields, + settingsPendingAction, }; export type {MemberEmailsToAccountIDs, XeroSettings}; diff --git a/src/libs/actions/connections/index.ts b/src/libs/actions/connections/index.ts index 01dca61cdfe9..2a613894a1c4 100644 --- a/src/libs/actions/connections/index.ts +++ b/src/libs/actions/connections/index.ts @@ -68,7 +68,7 @@ function createErrorFields( +function updatePolicyConnectionConfig( policyID: string, connectionName: TConnectionName, settingName: TSettingName, @@ -137,89 +137,6 @@ function updatePolicyXeroConnectionConfig( - policyID: string, - connectionName: TConnectionName, - settingName: TSettingName, - settingValue: Partial, -) { - const optimisticData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - connections: { - [connectionName]: { - config: { - [settingName]: settingValue ?? null, - pendingFields: { - [settingName]: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE, - }, - errorFields: { - [settingName]: null, - }, - }, - }, - }, - }, - }, - ]; - - const failureData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - connections: { - [connectionName]: { - config: { - [settingName]: settingValue ?? null, - pendingFields: { - [settingName]: null, - }, - errorFields: { - [settingName]: ErrorUtils.getMicroSecondOnyxErrorWithTranslationKey('common.genericErrorMessage'), - }, - }, - }, - }, - }, - }, - ]; - - const successData: OnyxUpdate[] = [ - { - onyxMethod: Onyx.METHOD.MERGE, - key: `${ONYXKEYS.COLLECTION.POLICY}${policyID}`, - value: { - connections: { - [connectionName]: { - config: { - [settingName]: settingValue ?? null, - pendingFields: { - [settingName]: null, - }, - errorFields: { - [settingName]: null, - }, - }, - }, - }, - }, - }, - ]; - - const parameters: UpdatePolicyConnectionConfigParams = { - policyID, - connectionName, - settingName: String(settingName), - settingValue: JSON.stringify(settingValue), - idempotencyKey: String(settingName), - }; - API.write(WRITE_COMMANDS.UPDATE_POLICY_CONNECTION_CONFIG, parameters, {optimisticData, failureData, successData}); -} - /** * This method returns read command and stage in progres for a given accounting integration. * @@ -406,12 +323,4 @@ function copyExistingPolicyConnection(connectedPolicyID: string, targetPolicyID: ); } -export { - removePolicyConnection, - updatePolicyConnectionConfig, - updatePolicyXeroConnectionConfig, - updateManyPolicyConnectionConfigs, - hasSynchronizationError, - syncConnection, - copyExistingPolicyConnection, -}; +export {removePolicyConnection, updatePolicyConnectionConfig, updateManyPolicyConnectionConfigs, hasSynchronizationError, syncConnection, copyExistingPolicyConnection}; diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 2da483c884df..799a7fa2b153 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -32,14 +32,14 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import {hasSynchronizationError, removePolicyConnection, syncConnection} from '@libs/actions/connections'; import { - areXeroSettingsInErrorFields, + areSettingsInErrorFields, findCurrentXeroOrganization, getConnectedIntegration, getCurrentSageIntacctEntityName, getCurrentXeroOrganizationName, getIntegrationLastSuccessfulDate, getXeroTenants, - xeroSettingsPendingAction, + settingsPendingAction, } from '@libs/PolicyUtils'; import type {XeroSettings} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; @@ -52,6 +52,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import ROUTES from '@src/ROUTES'; import type {Policy, PolicyConnectionSyncProgress} from '@src/types/onyx'; +import type {ErrorFields, PendingFields} from '@src/types/onyx/OnyxCommon'; import type {PolicyConnectionName} from '@src/types/onyx/Policy'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import type IconAsset from '@src/types/utils/IconAsset'; @@ -79,6 +80,8 @@ type AccountingIntegration = { onAdvancedPagePress: () => void; subscribedAdvancedSettings?: XeroSettings; onCardReconciliationPagePress: () => void; + pendingFields?: PendingFields; + errorFields?: ErrorFields; }; function accountingIntegrationData( connectionName: PolicyConnectionName, @@ -101,9 +104,20 @@ function accountingIntegrationData( /> ), onImportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_IMPORT.getRoute(policyID)), + subscribedImportSettings: [ + CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES, + CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES, + CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS, + CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS, + CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES, + ], onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT.getRoute(policyID)), + subscribedExportSettings: [CONST.QUICKBOOKS_CONFIG.EXPORTER], onCardReconciliationPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_CARD_RECONCILIATION.getRoute(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO)), onAdvancedPagePress: () => Navigation.navigate(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_ADVANCED.getRoute(policyID)), + subscribedAdvancedSettings: [], + pendingFields: policy?.connections?.quickbooksOnline?.config?.pendingFields, + errorFields: policy?.connections?.quickbooksOnline?.config?.errorFields, }; case CONST.POLICY.CONNECTIONS.NAME.XERO: return { @@ -134,6 +148,8 @@ function accountingIntegrationData( CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID, ], + pendingFields: policy?.connections?.xero?.config?.pendingFields, + errorFields: policy?.connections?.xero?.config?.errorFields, }; case CONST.POLICY.CONNECTIONS.NAME.NETSUITE: return { @@ -247,8 +263,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { } Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_ORGANIZATION.getRoute(policyID, currentXeroOrganization?.id ?? '-1')); }, - pendingAction: xeroSettingsPendingAction([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.pendingFields), - brickRoadIndicator: areXeroSettingsInErrorFields([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.errorFields) + pendingAction: settingsPendingAction([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.pendingFields), + brickRoadIndicator: areSettingsInErrorFields([CONST.XERO_CONFIG.TENANT_ID], policy?.connections?.xero?.config?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, }; @@ -364,10 +380,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.import'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onImportPagePress, - brickRoadIndicator: areXeroSettingsInErrorFields(integrationData?.subscribedImportSettings, policy?.connections?.xero?.config?.errorFields) + brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedImportSettings, integrationData?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: xeroSettingsPendingAction(integrationData?.subscribedImportSettings, policy?.connections?.xero?.config?.pendingFields), + pendingAction: settingsPendingAction(integrationData?.subscribedImportSettings, integrationData?.pendingFields), }, { icon: Expensicons.Send, @@ -376,10 +392,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.export'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onExportPagePress, - brickRoadIndicator: areXeroSettingsInErrorFields(integrationData?.subscribedExportSettings, policy?.connections?.xero?.config?.errorFields) + brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedImportSettings, integrationData?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: xeroSettingsPendingAction(integrationData?.subscribedExportSettings, policy?.connections?.xero?.config?.pendingFields), + pendingAction: settingsPendingAction(integrationData?.subscribedImportSettings, integrationData?.pendingFields), }, { icon: Expensicons.ExpensifyCard, @@ -397,10 +413,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.advanced'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onAdvancedPagePress, - brickRoadIndicator: areXeroSettingsInErrorFields(integrationData?.subscribedAdvancedSettings, policy?.connections?.xero?.config?.errorFields) + brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedImportSettings, integrationData?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: xeroSettingsPendingAction(integrationData?.subscribedAdvancedSettings, policy?.connections?.xero?.config?.pendingFields), + pendingAction: settingsPendingAction(integrationData?.subscribedImportSettings, integrationData?.pendingFields), }, ]), ]; diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx index a02c0b76809f..aacc84d2b60d 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAccountSelectPage.tsx @@ -55,7 +55,7 @@ function QuickbooksAccountSelectPage({policy}: WithPolicyConnectionsProps) { const saveSelection = useCallback( ({value}: SelectorType) => { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.REIMBURSEMENT_ACCOUNT_ID, value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.REIMBURSEMENT_ACCOUNT_ID, value); Navigation.goBack(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_ADVANCED.getRoute(policyID)); }, [policyID], diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx index f8ded59659eb..a92c354474e0 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx @@ -75,12 +75,12 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { switchAccessibilityLabel: translate('workspace.qbo.advancedConfig.autoSyncDescription'), isActive: !!autoSync?.enabled, onToggle: () => - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.AUTO_SYNC, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.AUTO_SYNC, { enabled: !autoSync?.enabled, }), pendingAction: pendingFields?.autoSync, - errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.AUTO_SYNC), - onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.AUTO_SYNC), + errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.AUTO_SYNC), + onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.AUTO_SYNC), wrapperStyle: styles.mv3, }, { @@ -88,10 +88,10 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { subtitle: translate('workspace.qbo.advancedConfig.inviteEmployeesDescription'), switchAccessibilityLabel: translate('workspace.qbo.advancedConfig.inviteEmployeesDescription'), isActive: !!syncPeople, - onToggle: () => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.SYNC_PEOPLE, !syncPeople), + onToggle: () => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.SYNC_PEOPLE, !syncPeople), pendingAction: pendingFields?.syncPeople, - errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.SYNC_PEOPLE), - onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.SYNC_PEOPLE), + errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.SYNC_PEOPLE), + onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_PEOPLE), wrapperStyle: styles.mv3, }, { @@ -99,10 +99,10 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { subtitle: translate('workspace.qbo.advancedConfig.createEntitiesDescription'), switchAccessibilityLabel: translate('workspace.qbo.advancedConfig.createEntitiesDescription'), isActive: !!autoCreateVendor, - onToggle: () => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR, !autoCreateVendor), + onToggle: () => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR, !autoCreateVendor), pendingAction: pendingFields?.autoCreateVendor, - errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR), - onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR), + errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR), + onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR), wrapperStyle: styles.mv3, }, { @@ -114,12 +114,12 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { Connections.updatePolicyConnectionConfig( policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, - CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID, + CONST.QUICKBOOKS_CONFIG.COLLECTION_ACCOUNT_ID, isSyncReimbursedSwitchOn ? '' : [...qboAccountOptions, ...invoiceAccountCollectionOptions][0].id, ), pendingAction: pendingFields?.collectionAccountID, - errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID), - onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID), + errors: ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.COLLECTION_ACCOUNT_ID), + onCloseError: () => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.COLLECTION_ACCOUNT_ID), subMenuItems: syncReimbursedSubMenuItems(), wrapperStyle: styles.mv3, }, diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx index 0459f61b88d6..b365182a5ed6 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksInvoiceAccountSelectPage.tsx @@ -56,7 +56,7 @@ function QuickbooksInvoiceAccountSelectPage({policy}: WithPolicyConnectionsProps const updateAccount = useCallback( ({value}: SelectorType) => { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.COLLECTION_ACCOUNT_ID, value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.COLLECTION_ACCOUNT_ID, value); Navigation.goBack(ROUTES.WORKSPACE_ACCOUNTING_QUICKBOOKS_ONLINE_ADVANCED.getRoute(policyID)); }, [policyID], diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx index 01867a6c764d..7fe0fb348769 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx @@ -74,14 +74,14 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, { - [CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR]: isOn, - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: isOn + [CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR]: isOn, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: isOn ? policy?.connections?.quickbooksOnline?.data?.vendors?.[0]?.id ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE, }, { - [CONST.QUICK_BOOKS_CONFIG.AUTO_CREATE_VENDOR]: autoCreateVendor, - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: + [CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR]: autoCreateVendor, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: nonReimbursableBillDefaultVendorObject?.id ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE, }, ) diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx index b1af64cb2f4b..69953009a033 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectCardPage.tsx @@ -70,14 +70,14 @@ function QuickbooksCompanyCardExpenseAccountSelectCardPage({policy}: WithPolicyC policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, { - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: row.value, - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_ACCOUNT]: row.accounts[0], - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: row.defaultVendor, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: row.value, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_ACCOUNT]: row.accounts[0], + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: row.defaultVendor, }, { - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: nonReimbursableExpensesExportDestination, - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_ACCOUNT]: nonReimbursableExpensesAccount, - [CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: nonReimbursableBillDefaultVendor, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: nonReimbursableExpensesExportDestination, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_ACCOUNT]: nonReimbursableExpensesAccount, + [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR]: nonReimbursableBillDefaultVendor, }, ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx index 3c44888d782d..7fcf7afaa235 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountSelectPage.tsx @@ -59,7 +59,7 @@ function QuickbooksCompanyCardExpenseAccountSelectPage({policy}: WithPolicyConne const selectExportAccount = useCallback( (row: CardListItem) => { if (row.value.id !== nonReimbursableExpensesAccount?.id) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_ACCOUNT, row.value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_EXPENSES_ACCOUNT, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx index 64e55edeb862..0cd79e74661f 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx @@ -35,7 +35,7 @@ function QuickbooksExportDateSelectPage({policy}: WithPolicyConnectionsProps) { const selectExportDate = useCallback( (row: CardListItem) => { if (row.value !== exportDate) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.EXPORT_DATE, row.value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.EXPORT_DATE, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_DATE_SELECT.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx index b95e70fe11dd..dbc435cb52ff 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx @@ -44,7 +44,7 @@ function QuickbooksExportInvoiceAccountSelectPage({policy}: WithPolicyConnection const selectExportInvoice = useCallback( (row: CardListItem) => { if (row.value.id !== receivableAccount?.id) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.RECEIVABLE_ACCOUNT, row.value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECT.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx index 3c9e7c085578..164c5448ce5a 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksNonReimbursableDefaultVendorSelectPage.tsx @@ -42,7 +42,7 @@ function QuickbooksNonReimbursableDefaultVendorSelectPage({policy}: WithPolicyCo const selectVendor = useCallback( (row: CardListItem) => { if (row.value !== nonReimbursableBillDefaultVendor) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR, row.value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx index 50b44640642b..e260e455dc85 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx @@ -82,7 +82,7 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne const selectExportAccount = useCallback( (row: CardListItem) => { if (row.value.id !== reimbursableExpensesAccount?.id) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT, row.value); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx index 4843c192991f..edb5d294abe0 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx @@ -89,12 +89,12 @@ function QuickbooksOutOfPocketExpenseEntitySelectPage({policy}: WithPolicyConnec policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, { - [CONST.QUICK_BOOKS_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: row.value, - [CONST.QUICK_BOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT]: row.accounts[0], + [CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: row.value, + [CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT]: row.accounts[0], }, { - [CONST.QUICK_BOOKS_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: reimbursableExpensesExportDestination, - [CONST.QUICK_BOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT]: reimbursableExpensesAccount, + [CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION]: reimbursableExpensesExportDestination, + [CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT]: reimbursableExpensesAccount, }, ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx index 1618d2e921a1..af2fec4010e2 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksPreferredExporterConfigurationPage.tsx @@ -55,7 +55,7 @@ function QuickbooksPreferredExporterConfigurationPage({policy}: WithPolicyConnec const selectExporter = useCallback( (row: CardListItem) => { if (row.value !== exportConfiguration?.exporter) { - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.EXPORT, {exporter: row.value}); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.EXPORT, {exporter: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_PREFERRED_EXPORTER.getRoute(policyID)); }, diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx index 2184383370e2..0a23e8e1f2c0 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx @@ -2,22 +2,25 @@ import React from 'react'; import {View} from 'react-native'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; import Switch from '@components/Switch'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; function QuickbooksChartOfAccountsPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {enableNewCategories, pendingFields} = policy?.connections?.quickbooksOnline?.config ?? {}; + const qboConfig = policy?.connections?.quickbooksOnline?.config; return ( {translate('workspace.qbo.accountsSwitchTitle')} - - - {translate('workspace.common.enabled')} - - - - - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.ENABLE_NEW_CATEGORIES, !enableNewCategories) - } - /> - - - - - {translate('workspace.qbo.accountsSwitchDescription')} - + + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES, !qboConfig?.enableNewCategories) + } + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES)} + /> ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx index 023c676d2018..0afea5f557d2 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx @@ -1,77 +1,61 @@ import React from 'react'; -import {View} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Switch from '@components/Switch'; -import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; -import variables from '@styles/variables'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; function QuickbooksClassesPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {syncClasses, pendingFields} = policy?.connections?.quickbooksOnline?.config ?? {}; - const isSwitchOn = !!(syncClasses && syncClasses !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); - const isReportFieldsSelected = syncClasses === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; + const qboConfig = policy?.connections?.quickbooksOnline?.config; + const isSwitchOn = !!(qboConfig?.syncClasses && qboConfig.syncClasses !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); + const isReportFieldsSelected = qboConfig?.syncClasses === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; return ( - - - - - {translate('workspace.qbo.classesDescription')} - - - {translate('workspace.accounting.import')} - - - - - Connections.updatePolicyConnectionConfig( - policyID, - CONST.POLICY.CONNECTIONS.NAME.QBO, - CONST.QUICK_BOOKS_CONFIG.SYNC_CLASSES, - isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, - ) - } - /> - - - - {isSwitchOn && ( - - - - )} - - - + + Connections.updatePolicyConnectionConfig( + policyID, + CONST.POLICY.CONNECTIONS.NAME.QBO, + CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES, + isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, + ) + } + subMenuItems={ + + } + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES)} + /> + ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx index 6d4f8c8c9f1e..181ab3d3940f 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx @@ -1,76 +1,60 @@ import React from 'react'; -import {View} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Switch from '@components/Switch'; -import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; -import variables from '@styles/variables'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; function QuickbooksCustomersPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {syncCustomers, pendingFields} = policy?.connections?.quickbooksOnline?.config ?? {}; - const isSwitchOn = !!(syncCustomers && syncCustomers !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); - const isReportFieldsSelected = syncCustomers === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; + const qboConfig = policy?.connections?.quickbooksOnline?.config; + const isSwitchOn = !!(qboConfig?.syncCustomers && qboConfig?.syncCustomers !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); + const isReportFieldsSelected = qboConfig?.syncCustomers === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; return ( - - - - - {translate('workspace.qbo.customersDescription')} - - - {translate('workspace.accounting.import')} - - - - - Connections.updatePolicyConnectionConfig( - policyID, - CONST.POLICY.CONNECTIONS.NAME.QBO, - CONST.QUICK_BOOKS_CONFIG.SYNC_CUSTOMERS, - isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, - ) - } - /> - - - - {isSwitchOn && ( - - - - )} - - - + + Connections.updatePolicyConnectionConfig( + policyID, + CONST.POLICY.CONNECTIONS.NAME.QBO, + CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS, + isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, + ) + } + subMenuItems={ + + } + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS)} + /> + ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx index 4ea1b5de427a..f764ba2f5508 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx @@ -7,6 +7,7 @@ import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; @@ -14,40 +15,43 @@ import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +type QBOSectionType = { + description: string; + action: () => void; + title: string; + subscribedSettings: [string]; +}; + function QuickbooksImportPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {syncClasses, syncCustomers, syncLocations, syncTax, pendingFields} = policy?.connections?.quickbooksOnline?.config ?? {}; + const {syncClasses, syncCustomers, syncLocations, syncTax, pendingFields, errorFields} = policy?.connections?.quickbooksOnline?.config ?? {}; - const sections = [ + const sections: QBOSectionType[] = [ { description: translate('workspace.accounting.accounts'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CHART_OF_ACCOUNTS.getRoute(policyID)), - hasError: !!policy?.errors?.enableNewCategories, title: translate('workspace.accounting.importAsCategory'), - pendingAction: pendingFields?.enableNewCategories, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES], }, { description: translate('workspace.qbo.classes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CLASSES.getRoute(policyID)), - hasError: !!policy?.errors?.syncClasses, title: translate(`workspace.accounting.importTypes.${syncClasses ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE}`), - pendingAction: pendingFields?.syncClasses, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES], }, { description: translate('workspace.qbo.customers'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CUSTOMERS.getRoute(policyID)), - hasError: !!policy?.errors?.syncCustomers, title: translate(`workspace.accounting.importTypes.${syncCustomers ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE}`), - pendingAction: pendingFields?.syncCustomers, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS], }, { description: translate('workspace.qbo.locations'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_LOCATIONS.getRoute(policyID)), - hasError: !!policy?.errors?.syncLocations, title: translate(`workspace.accounting.importTypes.${syncLocations ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE}`), - pendingAction: pendingFields?.syncLocations, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS], }, ]; @@ -55,9 +59,8 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { sections.push({ description: translate('workspace.accounting.taxes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_TAXES.getRoute(policyID)), - hasError: !!policy?.errors?.syncTax, title: translate(syncTax ? 'workspace.accounting.imported' : 'workspace.accounting.notImported'), - pendingAction: pendingFields?.syncTax, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES], }); } @@ -78,14 +81,14 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { {sections.map((section) => ( ))} diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx index e1fd7ed0d160..c3c85b6d0344 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx @@ -1,87 +1,73 @@ import React from 'react'; import {View} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Switch from '@components/Switch'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; -import variables from '@styles/variables'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; function QuickbooksLocationsPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {syncLocations, pendingFields, reimbursableExpensesExportDestination, nonReimbursableExpensesExportDestination} = policy?.connections?.quickbooksOnline?.config ?? {}; - const isSwitchOn = !!(syncLocations && syncLocations !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); + const qboConfig = policy?.connections?.quickbooksOnline?.config; + const isSwitchOn = !!(qboConfig?.syncLocations && qboConfig.syncLocations !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); const canImportLocation = - reimbursableExpensesExportDestination === CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY && - nonReimbursableExpensesExportDestination !== CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.VENDOR_BILL; + qboConfig?.reimbursableExpensesExportDestination === CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY && + qboConfig?.nonReimbursableExpensesExportDestination !== CONST.QUICKBOOKS_NON_REIMBURSABLE_EXPORT_ACCOUNT_TYPE.VENDOR_BILL; const shouldBeDisabled = !canImportLocation && !isSwitchOn; - const isReportFieldsSelected = syncLocations === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; + const isReportFieldsSelected = qboConfig?.syncLocations === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; return ( - - - - - {translate('workspace.qbo.locationsDescription')} - - - {translate('workspace.accounting.import')} - - - - - Connections.updatePolicyConnectionConfig( - policyID, - CONST.POLICY.CONNECTIONS.NAME.QBO, - CONST.QUICK_BOOKS_CONFIG.SYNC_LOCATIONS, - isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, - ) - } - disabled={shouldBeDisabled} - /> - - - - {isSwitchOn && ( - - - - )} - {shouldBeDisabled && ( - - {translate('workspace.qbo.locationsAdditionalDescription')} - - )} - - - + + } + onToggle={() => + Connections.updatePolicyConnectionConfig( + policyID, + CONST.POLICY.CONNECTIONS.NAME.QBO, + CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS, + isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, + ) + } + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS)} + onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS], qboConfig?.pendingFields)} + /> + {shouldBeDisabled && ( + + {translate('workspace.qbo.locationsAdditionalDescription')} + + )} + ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx index 30680d2c935a..5acae5d4ff64 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx @@ -1,60 +1,45 @@ import React from 'react'; -import {View} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Switch from '@components/Switch'; +import ConnectionLayout from '@components/ConnectionLayout'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; -import variables from '@styles/variables'; +import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; function QuickbooksTaxesPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {syncTax, pendingFields, reimbursableExpensesExportDestination} = policy?.connections?.quickbooksOnline?.config ?? {}; - const isJournalExportEntity = reimbursableExpensesExportDestination === CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY; - + const qboConfig = policy?.connections?.quickbooksOnline?.config; + const isJournalExportEntity = qboConfig?.reimbursableExpensesExportDestination === CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY; return ( - - - - - {translate('workspace.qbo.taxesDescription')} - - - {translate('workspace.accounting.import')} - - - - Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICK_BOOKS_CONFIG.SYNC_TAX, !syncTax)} - disabled={!syncTax && isJournalExportEntity} - /> - - - - {!syncTax && isJournalExportEntity && {translate('workspace.qbo.taxesJournalEntrySwitchNote')}} - - - + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.SYNC_TAX, !qboConfig?.syncTax)} + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES)} + /> + {!qboConfig?.syncTax && isJournalExportEntity && {translate('workspace.qbo.taxesJournalEntrySwitchNote')}} + ); } diff --git a/src/pages/workspace/accounting/xero/XeroImportPage.tsx b/src/pages/workspace/accounting/xero/XeroImportPage.tsx index 2cc9b01c2504..db0252098b89 100644 --- a/src/pages/workspace/accounting/xero/XeroImportPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroImportPage.tsx @@ -75,14 +75,14 @@ function XeroImportPage({policy}: WithPolicyProps) { {sections.map((section) => ( ))} diff --git a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx index 3d662289d0d8..3dcc7990bec1 100644 --- a/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroMapTrackingCategoryConfigurationPage.tsx @@ -9,7 +9,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import * as Policy from '@userActions/Policy/Policy'; @@ -62,7 +62,7 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { const updateMapping = useCallback( (option: {value: string}) => { if (option.value !== categoryName) { - Connections.updatePolicyXeroConnectionConfig( + Connections.updatePolicyConnectionConfig( policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.MAPPINGS, @@ -88,7 +88,7 @@ function XeroMapTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_TRACKING_CATEGORIES.getRoute(policyID))} headerTitleAlreadyTranslated={translate('workspace.xero.mapTrackingCategoryTo', {categoryName})} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={xeroSettingsPendingAction([`${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`], config?.pendingFields)} + pendingAction={settingsPendingAction([`${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, `${CONST.XERO_CONFIG.TRACKING_CATEGORY_PREFIX}${categoryId}`)} diff --git a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx index 1a0f92f4cbbf..288988d86822 100644 --- a/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroOrganizationConfigurationPage.tsx @@ -9,7 +9,7 @@ import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import {updatePolicyXeroConnectionConfig} from '@libs/actions/connections'; +import {updatePolicyConnectionConfig} from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {SettingsNavigatorParamList} from '@libs/Navigation/types'; @@ -59,7 +59,7 @@ function XeroOrganizationConfigurationPage({ return; } - updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.TENANT_ID, keyForList); + updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.TENANT_ID, keyForList); Navigation.goBack(); }; diff --git a/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx index e5133a25dc76..24f6691bdecf 100644 --- a/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTaxesConfigurationPage.tsx @@ -33,10 +33,10 @@ function XeroTaxesConfigurationPage({policy}: WithPolicyProps) { title={translate('workspace.accounting.import')} switchAccessibilityLabel={translate('workspace.xero.customers')} isActive={isSwitchOn} - onToggle={() => Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TAX_RATES, !xeroConfig?.importTaxRates)} + onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TAX_RATES, !xeroConfig?.importTaxRates)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_TAX_RATES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TAX_RATES)} - pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_TAX_RATES], xeroConfig?.pendingFields)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.XERO_CONFIG.IMPORT_TAX_RATES], xeroConfig?.pendingFields)} /> ); diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 916331763703..0e9d890be933 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -9,7 +9,7 @@ import * as Connections from '@libs/actions/connections'; import {getTrackingCategories} from '@libs/actions/connections/ConnectToXero'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {areXeroSettingsInErrorFields, xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import StringUtils from '@libs/StringUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -54,14 +54,14 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { isActive={isSwitchOn} wrapperStyle={styles.mv3} onToggle={() => - Connections.updatePolicyXeroConnectionConfig( + Connections.updatePolicyConnectionConfig( policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES, !xeroConfig?.importTrackingCategories, ) } - pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES], xeroConfig?.pendingFields)} + pendingAction={settingsPendingAction([CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES], xeroConfig?.pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)} /> @@ -70,7 +70,7 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { {menuItems.map((menuItem) => ( ))} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index 7b5aa44d62e2..a137058aaf2c 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -7,7 +7,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {getCurrentXeroOrganizationName, xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {getCurrentXeroOrganizationName, settingsPendingAction} from '@libs/PolicyUtils'; import * as PolicyUtils from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -59,11 +59,11 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={styles.mv3} isActive={!!autoSync?.enabled} onToggle={() => - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.AUTO_SYNC, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.AUTO_SYNC, { enabled: !autoSync?.enabled, }) } - pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.ENABLED], pendingFields)} + pendingAction={settingsPendingAction([CONST.XERO_CONFIG.ENABLED], pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.ENABLED)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.ENABLED)} /> @@ -76,17 +76,17 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={styles.mv3} isActive={!!sync?.syncReimbursedReports} onToggle={() => - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { syncReimbursedReports: !sync?.syncReimbursedReports, }) } - pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS], pendingFields)} + pendingAction={settingsPendingAction([CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS], pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} /> {sync?.syncReimbursedReports && ( <> - + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_XERO_BILL_PAYMENT_ACCOUNT_SELECTOR.getRoute(policyID))} brickRoadIndicator={ - PolicyUtils.areXeroSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined + PolicyUtils.areSettingsInErrorFields([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined } /> - + diff --git a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx index 66ce4ca04e83..6902ac6de5c0 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroBillPaymentAccountSelectorPage.tsx @@ -11,7 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {getXeroBankAccountsWithDefaultSelect, xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {getXeroBankAccountsWithDefaultSelect, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; @@ -42,7 +42,7 @@ function XeroBillPaymentAccountSelectorPage({policy}: WithPolicyConnectionsProps const updateAccount = useCallback( ({value}: SelectorType) => { - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { reimbursementAccountID: value, }); Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)); @@ -80,7 +80,7 @@ function XeroBillPaymentAccountSelectorPage({policy}: WithPolicyConnectionsProps onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID))} title="workspace.xero.advancedConfig.xeroBillPaymentAccount" listEmptyContent={listEmptyContent} - pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], config?.pendingFields)} + pendingAction={settingsPendingAction([CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.REIMBURSEMENT_ACCOUNT_ID)} diff --git a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx index 01f32f7f8859..aed12ebb9d01 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroInvoiceAccountSelectorPage.tsx @@ -11,7 +11,7 @@ import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import {getXeroBankAccountsWithDefaultSelect, xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {getXeroBankAccountsWithDefaultSelect, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; @@ -42,7 +42,7 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { const updateAccount = useCallback( ({value}: SelectorType) => { - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.SYNC, { invoiceCollectionsAccountID: value, }); Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID)); @@ -80,7 +80,7 @@ function XeroInvoiceAccountSelectorPage({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_ADVANCED.getRoute(policyID))} title="workspace.xero.advancedConfig.xeroInvoiceCollectionAccount" listEmptyContent={listEmptyContent} - pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], config?.pendingFields)} + pendingAction={settingsPendingAction([CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.INVOICE_COLLECTIONS_ACCOUNT_ID)} diff --git a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx index 0ad5bfcfbd6b..c4e42a8bbcce 100644 --- a/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroBankAccountSelectPage.tsx @@ -46,7 +46,7 @@ function XeroBankAccountSelectPage({policy}: WithPolicyConnectionsProps) { const updateBankAccount = useCallback( ({value}: SelectorType) => { if (initiallyFocusedOptionKey !== value) { - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { nonReimbursableAccount: value, }); } @@ -84,7 +84,7 @@ function XeroBankAccountSelectPage({policy}: WithPolicyConnectionsProps) { title="workspace.xero.xeroBankAccount" listEmptyContent={listEmptyContent} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], config?.pendingFields)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.NON_REIMBURSABLE_ACCOUNT)} diff --git a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx index 07bd0406d732..52f1163588db 100644 --- a/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroExportConfigurationPage.tsx @@ -94,7 +94,7 @@ function XeroExportConfigurationPage({policy}: WithPolicyConnectionsProps) { {menuItems.map((menuItem) => ( diff --git a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx index f8f6fa3828a3..5d837248f31c 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPreferredExporterSelectPage.tsx @@ -67,7 +67,7 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { const selectExporter = useCallback( (row: CardListItem) => { if (row.value !== config?.export?.exporter) { - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {exporter: row.value}); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {exporter: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID)); }, @@ -98,7 +98,7 @@ function XeroPreferredExporterSelectPage({policy}: WithPolicyConnectionsProps) { onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} title="workspace.accounting.preferredExporter" connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.EXPORTER], config?.pendingFields)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.XERO_CONFIG.EXPORTER], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.EXPORTER)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.EXPORTER)} diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx index 16ca7a4bba6d..de6228db7713 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillDateSelectPage.tsx @@ -47,7 +47,7 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { const selectExportDate = useCallback( (row: MenuListItem) => { if (row.value !== config?.export?.billDate) { - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {billDate: row.value}); + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, {billDate: row.value}); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT_PURCHASE_BILL_DATE_SELECT.getRoute(policyID)); }, @@ -68,7 +68,7 @@ function XeroPurchaseBillDateSelectPage({policy}: WithPolicyConnectionsProps) { featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.BILL_DATE], config?.pendingFields)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.XERO_CONFIG.BILL_DATE], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.BILL_DATE)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.BILL_DATE)} diff --git a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx index 5e7d06a9ca39..251cee5137f1 100644 --- a/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx +++ b/src/pages/workspace/accounting/xero/export/XeroPurchaseBillStatusSelectorPage.tsx @@ -52,7 +52,7 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps return; } if (row.value !== invoiceStatus) { - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.EXPORT, { billStatus: {...config?.export?.billStatus, purchase: row.value}, }); } @@ -75,7 +75,7 @@ function XeroPurchaseBillStatusSelectorPage({policy}: WithPolicyConnectionsProps featureName={CONST.POLICY.MORE_FEATURES.ARE_CONNECTIONS_ENABLED} onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_XERO_EXPORT.getRoute(policyID))} connectionName={CONST.POLICY.CONNECTIONS.NAME.XERO} - pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.BILL_STATUS], config?.pendingFields)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.XERO_CONFIG.BILL_STATUS], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.XERO_CONFIG.BILL_STATUS)} errorRowStyles={[styles.ph5, styles.pv3]} onClose={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.BILL_STATUS)} diff --git a/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx b/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx index 588e1805b010..deafc50f6cfa 100644 --- a/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroChartOfAccountsPage.tsx @@ -8,7 +8,7 @@ import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; -import {xeroSettingsPendingAction} from '@libs/PolicyUtils'; +import {settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -60,9 +60,9 @@ function XeroChartOfAccountsPage({policy}: WithPolicyProps) { shouldPlaceSubtitleBelowSwitch isActive={!!xeroConfig?.enableNewCategories} onToggle={() => - Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, !xeroConfig?.enableNewCategories) + Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES, !xeroConfig?.enableNewCategories) } - pendingAction={xeroSettingsPendingAction([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], xeroConfig?.pendingFields)} + pendingAction={settingsPendingAction([CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES], xeroConfig?.pendingFields)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.ENABLE_NEW_CATEGORIES)} /> diff --git a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx index b94f51eb050a..f496df3c5223 100644 --- a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx @@ -42,10 +42,10 @@ function XeroCustomerConfigurationPage({policy}: WithPolicyProps) { /> } isActive={isSwitchOn} - onToggle={() => Connections.updatePolicyXeroConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_CUSTOMERS, !xeroConfig?.importCustomers)} + onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.XERO, CONST.XERO_CONFIG.IMPORT_CUSTOMERS, !xeroConfig?.importCustomers)} errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_CUSTOMERS)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_CUSTOMERS)} - pendingAction={PolicyUtils.xeroSettingsPendingAction([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], xeroConfig?.pendingFields)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.XERO_CONFIG.IMPORT_CUSTOMERS], xeroConfig?.pendingFields)} /> ); From ab278cb3634cbd0219a518692df3b7acc5402b01 Mon Sep 17 00:00:00 2001 From: zfurtak Date: Tue, 30 Jul 2024 17:21:06 +0200 Subject: [PATCH 006/338] Adjusted import pages and refactored advanced page --- src/CONST.ts | 8 +-- .../accounting/PolicyAccountingPage.tsx | 19 ++++--- .../qbo/advanced/QuickbooksAdvancedPage.tsx | 57 ++++++++----------- .../import/QuickbooksChartOfAccountsPage.tsx | 1 - .../qbo/import/QuickbooksClassesPage.tsx | 6 +- .../qbo/import/QuickbooksCustomersPage.tsx | 6 +- .../qbo/import/QuickbooksImportPage.tsx | 8 +-- .../qbo/import/QuickbooksLocationsPage.tsx | 6 +- .../qbo/import/QuickbooksTaxesPage.tsx | 6 +- 9 files changed, 52 insertions(+), 65 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 876c9fa2a598..5d7048d666a4 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1322,17 +1322,13 @@ const CONST = { QUICKBOOKS_ONLINE: 'quickbooksOnline', QUICKBOOKS_CONFIG: { - SYNC_CLASSES: 'syncClasses', ENABLE_NEW_CATEGORIES: 'enableNewCategories', - EXPORTER: 'exporter', + SYNC_CLASSES: 'syncClasses', SYNC_CUSTOMERS: 'syncCustomers', SYNC_LOCATIONS: 'syncLocations', SYNC_TAX: 'syncTax', - IMPORT_CLASSES: 'importClasses', - IMPORT_CUSTOMERS: 'importCustomers', - IMPORT_LOCATIONS: 'importLocation', - IMPORT_TAX_RATES: 'importTaxRates', EXPORT: 'export', + EXPORTER: 'exporter', EXPORT_DATE: 'exportDate', NON_REIMBURSABLE_EXPENSES_ACCOUNT: 'nonReimbursableExpensesAccount', NON_REIMBURSABLE_EXPENSES_EXPORT_DESTINATION: 'nonReimbursableExpensesExportDestination', diff --git a/src/pages/workspace/accounting/PolicyAccountingPage.tsx b/src/pages/workspace/accounting/PolicyAccountingPage.tsx index 9857b0fbedff..58bbce619641 100644 --- a/src/pages/workspace/accounting/PolicyAccountingPage.tsx +++ b/src/pages/workspace/accounting/PolicyAccountingPage.tsx @@ -106,10 +106,10 @@ function accountingIntegrationData( onImportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_IMPORT.getRoute(policyID)), subscribedImportSettings: [ CONST.QUICKBOOKS_CONFIG.ENABLE_NEW_CATEGORIES, - CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES, - CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS, - CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS, - CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES, + CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES, + CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS, + CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS, + CONST.QUICKBOOKS_CONFIG.SYNC_TAX, ], onExportPagePress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT.getRoute(policyID)), subscribedExportSettings: [CONST.QUICKBOOKS_CONFIG.EXPORTER], @@ -331,7 +331,8 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { return []; } const shouldShowSynchronizationError = hasSynchronizationError(policy, connectedIntegration, isSyncInProgress); - const shouldHideConfigurationOptions = isConnectionUnverified(policy, connectedIntegration); + let shouldHideConfigurationOptions = isConnectionUnverified(policy, connectedIntegration); + shouldHideConfigurationOptions = false; const integrationData = accountingIntegrationData(connectedIntegration, policyID, translate, undefined, undefined, policy); const iconProps = integrationData?.icon ? {icon: integrationData.icon, iconType: CONST.ICON_TYPE_AVATAR} : {}; return [ @@ -393,10 +394,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.export'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onExportPagePress, - brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedImportSettings, integrationData?.errorFields) + brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedExportSettings, integrationData?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: settingsPendingAction(integrationData?.subscribedImportSettings, integrationData?.pendingFields), + pendingAction: settingsPendingAction(integrationData?.subscribedExportSettings, integrationData?.pendingFields), }, { icon: Expensicons.ExpensifyCard, @@ -414,10 +415,10 @@ function PolicyAccountingPage({policy}: PolicyAccountingPageProps) { title: translate('workspace.accounting.advanced'), wrapperStyle: [styles.sectionMenuItemTopDescription], onPress: integrationData?.onAdvancedPagePress, - brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedImportSettings, integrationData?.errorFields) + brickRoadIndicator: areSettingsInErrorFields(integrationData?.subscribedAdvancedSettings, integrationData?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, - pendingAction: settingsPendingAction(integrationData?.subscribedImportSettings, integrationData?.pendingFields), + pendingAction: settingsPendingAction(integrationData?.subscribedAdvancedSettings, integrationData?.pendingFields), }, ]), ]; diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx index a92c354474e0..adc87fb43f0c 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx @@ -1,17 +1,14 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import useWaitForNavigation from '@hooks/useWaitForNavigation'; import * as Connections from '@libs/actions/connections'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -126,38 +123,32 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { ]; return ( - - - - - - {qboToggleSettingItems.map((item) => ( - - ))} - - - + {qboToggleSettingItems.map((item) => ( + + ))} + ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx index 0a23e8e1f2c0..a3efe11b1cf3 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksChartOfAccountsPage.tsx @@ -41,7 +41,6 @@ function QuickbooksChartOfAccountsPage({policy}: WithPolicyProps) { {}} /> diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx index 0afea5f557d2..bdc82d2462b8 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx @@ -51,9 +51,9 @@ function QuickbooksClassesPage({policy}: WithPolicyProps) { wrapperStyle={styles.sectionMenuItemTopDescription} /> } - pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES], qboConfig?.pendingFields)} - errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES)} - onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES)} + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES)} /> ); diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx index 181ab3d3940f..16f037e4079a 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx @@ -50,9 +50,9 @@ function QuickbooksCustomersPage({policy}: WithPolicyProps) { wrapperStyle={styles.sectionMenuItemTopDescription} /> } - pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS], qboConfig?.pendingFields)} - errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS)} - onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS)} + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS)} /> ); diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx index f764ba2f5508..983370bc270a 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksImportPage.tsx @@ -39,19 +39,19 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { description: translate('workspace.qbo.classes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CLASSES.getRoute(policyID)), title: translate(`workspace.accounting.importTypes.${syncClasses ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE}`), - subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_CLASSES], + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES], }, { description: translate('workspace.qbo.customers'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_CUSTOMERS.getRoute(policyID)), title: translate(`workspace.accounting.importTypes.${syncCustomers ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE}`), - subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_CUSTOMERS], + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS], }, { description: translate('workspace.qbo.locations'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_LOCATIONS.getRoute(policyID)), title: translate(`workspace.accounting.importTypes.${syncLocations ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE}`), - subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS], + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS], }, ]; @@ -60,7 +60,7 @@ function QuickbooksImportPage({policy}: WithPolicyProps) { description: translate('workspace.accounting.taxes'), action: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_TAXES.getRoute(policyID)), title: translate(syncTax ? 'workspace.accounting.imported' : 'workspace.accounting.notImported'), - subscribedSettings: [CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES], + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.SYNC_TAX], }); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx index c3c85b6d0344..ee56f9a4439a 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx @@ -58,9 +58,9 @@ function QuickbooksLocationsPage({policy}: WithPolicyProps) { isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, ) } - errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS)} - onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS)} - pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_LOCATIONS], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS)} + onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS)} + pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS], qboConfig?.pendingFields)} /> {shouldBeDisabled && ( diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx index 5acae5d4ff64..049fad17cd88 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksTaxesPage.tsx @@ -34,9 +34,9 @@ function QuickbooksTaxesPage({policy}: WithPolicyProps) { switchAccessibilityLabel={translate('workspace.accounting.taxes')} isActive={!!qboConfig?.syncTax} onToggle={() => Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.SYNC_TAX, !qboConfig?.syncTax)} - pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES], qboConfig?.pendingFields)} - errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES)} - onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.IMPORT_TAX_RATES)} + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.SYNC_TAX], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.SYNC_TAX)} + onCloseError={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_TAX)} /> {!qboConfig?.syncTax && isJournalExportEntity && {translate('workspace.qbo.taxesJournalEntrySwitchNote')}} From 2f73caa9d71d4e43b17242ab07ccb814c5230375 Mon Sep 17 00:00:00 2001 From: zfurtak Date: Wed, 31 Jul 2024 20:42:16 +0200 Subject: [PATCH 007/338] Further refactor --- src/CONST.ts | 1 + .../QuickbooksExportConfigurationPage.tsx | 26 +++--- .../export/QuickbooksExportDateSelectPage.tsx | 50 +++++------ ...ickbooksExportInvoiceAccountSelectPage.tsx | 49 ++++++----- ...oksOutOfPocketExpenseAccountSelectPage.tsx | 59 +++++++------ ...oksOutOfPocketExpenseConfigurationPage.tsx | 88 +++++++++++-------- ...ooksOutOfPocketExpenseEntitySelectPage.tsx | 68 +++++++------- ...ooksPreferredExporterConfigurationPage.tsx | 63 +++++++------ .../qbo/import/QuickbooksImportPage.tsx | 54 +++++------- 9 files changed, 230 insertions(+), 228 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 5d7048d666a4..3c91b8d397ea 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -1353,6 +1353,7 @@ const CONST = { ENABLE_NEW_CATEGORIES: 'enableNewCategories', EXPORT: 'export', EXPORTER: 'exporter', + EXPORT_DATE: 'exportDate', BILL_DATE: 'billDate', BILL_STATUS: 'billStatus', NON_REIMBURSABLE_ACCOUNT: 'nonReimbursableAccount', diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportConfigurationPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportConfigurationPage.tsx index b60431661f34..ebd69eb7ffc5 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportConfigurationPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportConfigurationPage.tsx @@ -1,15 +1,14 @@ import React from 'react'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import type {MenuItemProps} from '@components/MenuItem'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import type {OfflineWithFeedbackProps} from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import TextLink from '@components/TextLink'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; @@ -18,7 +17,7 @@ import * as Link from '@userActions/Link'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; -type MenuItem = MenuItemProps & {pendingAction?: OfflineWithFeedbackProps['pendingAction']}; +// type MenuItem = MenuItemProps & {pendingAction?: OfflineWithFeedbackProps['pendingAction']}; function QuickbooksExportConfigurationPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); @@ -34,22 +33,18 @@ function QuickbooksExportConfigurationPage({policy}: WithPolicyConnectionsProps) errorFields, pendingFields, } = policy?.connections?.quickbooksOnline?.config ?? {}; - const menuItems: MenuItem[] = [ + const menuItems = [ { description: translate('workspace.accounting.preferredExporter'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_PREFERRED_EXPORTER.getRoute(policyID)), - brickRoadIndicator: errorFields?.exporter ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: exportConfiguration?.exporter ?? policyOwner, - pendingAction: pendingFields?.export, - errorText: errorFields?.exporter ? translate('common.genericErrorMessage') : undefined, + subscribedSettings: [CONST.XERO_CONFIG.EXPORTER], }, { description: translate('workspace.qbo.date'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_DATE_SELECT.getRoute(policyID)), - brickRoadIndicator: errorFields?.exportDate ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: exportDate ? translate(`workspace.qbo.exportDate.values.${exportDate}.label`) : undefined, - pendingAction: pendingFields?.exportDate, - errorText: errorFields?.exportDate ? translate('common.genericErrorMessage') : undefined, + subscribedSettings: [CONST.XERO_CONFIG.EXPORT_DATE], }, { description: translate('workspace.accounting.exportOutOfPocket'), @@ -58,14 +53,13 @@ function QuickbooksExportConfigurationPage({policy}: WithPolicyConnectionsProps) title: reimbursableExpensesExportDestination ? translate(`workspace.qbo.accounts.${reimbursableExpensesExportDestination}`) : undefined, // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing pendingAction: pendingFields?.reimbursableExpensesExportDestination || pendingFields?.reimbursableExpensesAccount, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION, CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT], }, { description: translate('workspace.qbo.exportInvoices'), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECT.getRoute(policyID)), - brickRoadIndicator: errorFields?.receivableAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined, title: receivableAccount?.name, - pendingAction: pendingFields?.receivableAccount, - errorText: errorFields?.receivableAccount ? translate('common.genericErrorMessage') : undefined, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT], }, { description: translate('workspace.accounting.exportCompanyCard'), @@ -99,7 +93,7 @@ function QuickbooksExportConfigurationPage({policy}: WithPolicyConnectionsProps) {menuItems.map((menuItem) => ( diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx index 0cd79e74661f..bf6fbb76240d 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportDateSelectPage.tsx @@ -1,18 +1,18 @@ import React, {useCallback} from 'react'; import type {ValueOf} from 'type-fest'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; +import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -23,46 +23,44 @@ function QuickbooksExportDateSelectPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const policyID = policy?.id ?? '-1'; - const {exportDate} = policy?.connections?.quickbooksOnline?.config ?? {}; + const qboConfig = policy?.connections?.quickbooksOnline?.config; const data: CardListItem[] = Object.values(CONST.QUICKBOOKS_EXPORT_DATE).map((dateType) => ({ value: dateType, text: translate(`workspace.qbo.exportDate.values.${dateType}.label`), alternateText: translate(`workspace.qbo.exportDate.values.${dateType}.description`), keyForList: dateType, - isSelected: exportDate === dateType, + isSelected: qboConfig?.exportDate === dateType, })); const selectExportDate = useCallback( (row: CardListItem) => { - if (row.value !== exportDate) { + if (row.value !== qboConfig?.exportDate) { Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.EXPORT_DATE, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_DATE_SELECT.getRoute(policyID)); }, - [exportDate, policyID], + [policyID, qboConfig?.exportDate], ); return ( - - - - {translate('workspace.qbo.exportDate.description')}} - sections={[{data}]} - ListItem={RadioListItem} - onSelectRow={selectExportDate} - shouldDebounceRowSelect - initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} - /> - - + displayName={QuickbooksExportDateSelectPage.displayName} + sections={[{data}]} + listItem={RadioListItem} + headerContent={{translate('workspace.qbo.exportDate.description')}} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT.getRoute(policyID))} + onSelectRow={selectExportDate} + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + title="workspace.qbo.exportDate.label" + connectionName={CONST.POLICY.CONNECTIONS.NAME.QBO} + pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.EXPORT_DATE], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.EXPORT_DATE)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.EXPORT_DATE)} + /> ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx index dbc435cb52ff..03b7ce1636ba 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksExportInvoiceAccountSelectPage.tsx @@ -1,20 +1,20 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Illustrations from '@components/Icon/Illustrations'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; +import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {Account} from '@src/types/onyx/Policy'; @@ -27,7 +27,7 @@ function QuickbooksExportInvoiceAccountSelectPage({policy}: WithPolicyConnection const {translate} = useLocalize(); const styles = useThemeStyles(); const {accountsReceivable} = policy?.connections?.quickbooksOnline?.data ?? {}; - const {receivableAccount} = policy?.connections?.quickbooksOnline?.config ?? {}; + const qboConfig = policy?.connections?.quickbooksOnline?.config; const policyID = policy?.id ?? '-1'; const data: CardListItem[] = useMemo( @@ -36,19 +36,19 @@ function QuickbooksExportInvoiceAccountSelectPage({policy}: WithPolicyConnection value: account, text: account.name, keyForList: account.name, - isSelected: account.id === receivableAccount?.id, + isSelected: account.id === qboConfig?.receivableAccount?.id, })) ?? [], - [receivableAccount, accountsReceivable], + [qboConfig?.receivableAccount, accountsReceivable], ); const selectExportInvoice = useCallback( (row: CardListItem) => { - if (row.value.id !== receivableAccount?.id) { + if (row.value.id !== qboConfig?.receivableAccount?.id) { Connections.updatePolicyConnectionConfig(policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT, row.value); } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_INVOICE_ACCOUNT_SELECT.getRoute(policyID)); }, - [receivableAccount, policyID], + [qboConfig?.receivableAccount, policyID], ); const listEmptyContent = useMemo( @@ -66,24 +66,25 @@ function QuickbooksExportInvoiceAccountSelectPage({policy}: WithPolicyConnection ); return ( - - - - {translate('workspace.qbo.exportInvoicesDescription')}} - sections={data.length ? [{data}] : []} - ListItem={RadioListItem} - onSelectRow={selectExportInvoice} - shouldDebounceRowSelect - initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} - listEmptyContent={listEmptyContent} - /> - - + displayName={QuickbooksExportInvoiceAccountSelectPage.displayName} + sections={data.length ? [{data}] : []} + listItem={RadioListItem} + headerContent={{translate('workspace.qbo.exportInvoicesDescription')}} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT.getRoute(policyID))} + onSelectRow={selectExportInvoice} + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + title="workspace.qbo.exportInvoices" + connectionName={CONST.POLICY.CONNECTIONS.NAME.QBO} + pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT], qboConfig?.pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT)} + listEmptyContent={listEmptyContent} + /> ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx index e260e455dc85..c8485b29a577 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseAccountSelectPage.tsx @@ -1,49 +1,49 @@ import React, {useCallback, useMemo} from 'react'; import BlockingView from '@components/BlockingViews/BlockingView'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; import * as Illustrations from '@components/Icon/Illustrations'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; import type {ListItem} from '@components/SelectionList/types'; +import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import variables from '@styles/variables'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; +import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; import type {Account} from '@src/types/onyx/Policy'; type CardListItem = ListItem & { value: Account; }; - function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); const {bankAccounts, journalEntryAccounts, accountPayable} = policy?.connections?.quickbooksOnline?.data ?? {}; - - const {reimbursableExpensesExportDestination, reimbursableExpensesAccount} = policy?.connections?.quickbooksOnline?.config ?? {}; + const qboConfig = policy?.connections?.quickbooksOnline?.config; + const {reimbursableExpensesExportDestination, reimbursableExpensesAccount, pendingFields} = qboConfig ?? {}; const [title, description] = useMemo(() => { - let titleText: string | undefined; + let titleText: TranslationPaths | undefined; let descriptionText: string | undefined; switch (reimbursableExpensesExportDestination) { case CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.CHECK: - titleText = translate('workspace.qbo.bankAccount'); + titleText = 'workspace.qbo.bankAccount'; descriptionText = translate('workspace.qbo.bankAccountDescription'); break; case CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.JOURNAL_ENTRY: - titleText = translate('workspace.qbo.account'); + titleText = 'workspace.qbo.account'; descriptionText = translate('workspace.qbo.accountDescription'); break; case CONST.QUICKBOOKS_REIMBURSABLE_ACCOUNT_TYPE.VENDOR_BILL: - titleText = translate('workspace.qbo.accountsPayable'); + titleText = 'workspace.qbo.accountsPayable'; descriptionText = translate('workspace.qbo.accountsPayableDescription'); break; default: @@ -51,7 +51,7 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne } return [titleText, descriptionText]; - }, [translate, reimbursableExpensesExportDestination]); + }, [reimbursableExpensesExportDestination, translate]); const data: CardListItem[] = useMemo(() => { let accounts: Account[]; @@ -75,7 +75,7 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne keyForList: account.name, isSelected: account.id === reimbursableExpensesAccount?.id, })); - }, [accountPayable, bankAccounts, reimbursableExpensesExportDestination, reimbursableExpensesAccount, journalEntryAccounts]); + }, [reimbursableExpensesExportDestination, reimbursableExpensesAccount?.id, bankAccounts, journalEntryAccounts, accountPayable]); const policyID = policy?.id ?? '-1'; @@ -86,7 +86,7 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne } Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES.getRoute(policyID)); }, - [reimbursableExpensesAccount, policyID], + [reimbursableExpensesAccount?.id, policyID], ); const listEmptyContent = useMemo( @@ -104,24 +104,25 @@ function QuickbooksOutOfPocketExpenseAccountSelectPage({policy}: WithPolicyConne ); return ( - - - - {description}} - sections={data.length ? [{data}] : []} - ListItem={RadioListItem} - onSelectRow={selectExportAccount} - shouldDebounceRowSelect - initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} - listEmptyContent={listEmptyContent} - /> - - + displayName={QuickbooksOutOfPocketExpenseAccountSelectPage.displayName} + sections={data.length ? [{data}] : []} + listItem={RadioListItem} + headerContent={{description}} + onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES.getRoute(policyID))} + onSelectRow={selectExportAccount} + initiallyFocusedOptionKey={data.find((mode) => mode.isSelected)?.keyForList} + title={title} + connectionName={CONST.POLICY.CONNECTIONS.NAME.QBO} + pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT], pendingFields)} + errors={ErrorUtils.getLatestErrorField(qboConfig ?? {}, CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT)} + errorRowStyles={[styles.ph5, styles.pv3]} + onClose={() => Policy.clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT)} + listEmptyContent={listEmptyContent} + /> ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseConfigurationPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseConfigurationPage.tsx index 679f021e60fa..b73d1c82d139 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseConfigurationPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseConfigurationPage.tsx @@ -1,19 +1,25 @@ import React, {useMemo} from 'react'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import ScreenWrapper from '@components/ScreenWrapper'; -import ScrollView from '@components/ScrollView'; -import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; +type QBOSectionType = { + title?: string; + description?: string; + onPress: () => void; + errorText?: string; + hintText?: string; + subscribedSettings: string[]; +}; + function QuickbooksOutOfPocketExpenseConfigurationPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -47,43 +53,49 @@ function QuickbooksOutOfPocketExpenseConfigurationPage({policy}: WithPolicyConne return [hintText, description]; }, [translate, reimbursableExpensesExportDestination, isLocationEnabled, isTaxesEnabled]); + const sections: QBOSectionType[] = [ + { + title: reimbursableExpensesExportDestination ? translate(`workspace.qbo.accounts.${reimbursableExpensesExportDestination}`) : undefined, + description: translate('workspace.accounting.exportAs'), + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES_SELECT.getRoute(policyID)), + errorText: hasErrors && reimbursableExpensesExportDestination ? translate(`workspace.qbo.accounts.${reimbursableExpensesExportDestination}Error`) : undefined, + hintText: exportHintText, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_EXPORT_DESTINATION, CONST.QUICKBOOKS_CONFIG.REIMBURSABLE_EXPENSES_ACCOUNT], + }, + { + title: reimbursableExpensesAccount?.name, + description: accountDescription, + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES_ACCOUNT_SELECT.getRoute(policyID)), + errorText: errorFields?.exportAccount ? translate('common.genericErrorMessage') : undefined, + subscribedSettings: [CONST.QUICKBOOKS_CONFIG.RECEIVABLE_ACCOUNT], + }, + ]; return ( - - - - - {translate('workspace.qbo.exportOutOfPocketExpensesDescription')} - - Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES_SELECT.getRoute(policyID))} - brickRoadIndicator={hasErrors ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - shouldShowRightIcon - hintText={exportHintText} - /> - - - Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT_OUT_OF_POCKET_EXPENSES_ACCOUNT_SELECT.getRoute(policyID))} - brickRoadIndicator={errorFields?.exportAccount ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} - shouldShowRightIcon - errorText={errorFields?.exportAccount ? translate('common.genericErrorMessage') : undefined} - /> - - - - + {sections.map((section) => ( + + + + ))} + ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx index edb5d294abe0..f0b9c84fbf59 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksOutOfPocketExpenseEntitySelectPage.tsx @@ -1,19 +1,18 @@ import React, {useCallback, useMemo} from 'react'; import {View} from 'react-native'; -import type {SectionListData} from 'react-native'; -import HeaderWithBackButton from '@components/HeaderWithBackButton'; -import ScreenWrapper from '@components/ScreenWrapper'; -import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/RadioListItem'; -import type {ListItem, Section} from '@components/SelectionList/types'; +import type {ListItem} from '@components/SelectionList/types'; +import SelectionScreen from '@components/SelectionScreen'; import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; +import * as ErrorUtils from '@libs/ErrorUtils'; +import * as PolicyUtils from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; -import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; +import * as Policy from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {Account, QBOReimbursableExportAccountType} from '@src/types/onyx/Policy'; @@ -33,18 +32,16 @@ function Footer({isTaxEnabled, isLocationsEnabled}: {isTaxEnabled: boolean; isLo ); } - type CardListItem = ListItem & { value: QBOReimbursableExportAccountType; isShown: boolean; accounts: Account[]; }; -type CardsSection = SectionListData>; - function QuickbooksOutOfPocketExpenseEntitySelectPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const {reimbursableExpensesExportDestination, reimbursableExpensesAccount, syncTax, syncLocations} = policy?.connections?.quickbooksOnline?.config ?? {}; + const qboConfig = policy?.connections?.quickbooksOnline?.config; + const {reimbursableExpensesExportDestination, reimbursableExpensesAccount, syncTax, syncLocations} = qboConfig ?? {}; const {bankAccounts, accountPayable, journalEntryAccounts} = policy?.connections?.quickbooksOnline?.data ?? {}; const isLocationsEnabled = !!(syncLocations && syncLocations !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); const isTaxesEnabled = !!syncTax; @@ -80,7 +77,7 @@ function QuickbooksOutOfPocketExpenseEntitySelectPage({policy}: WithPolicyConnec [reimbursableExpensesExportDestination, isTaxesEnabled, translate, isLocationsEnabled, bankAccounts, accountPayable, journalEntryAccounts], ); - const sections: CardsSection[] = useMemo(() => [{data: data.filter((item) => item.isShown)}], [data]); + const sections = useMemo(() => [{data: data.filter((item) => item.isShown)}], [data]); const selectExportEntity = useCallback( (row: CardListItem) => { @@ -104,34 +101,33 @@ function QuickbooksOutOfPocketExpenseEntitySelectPage({policy}: WithPolicyConnec ); return ( - - - - - mode.isSelected)?.keyForList} - footerContent={ -