From 50a5f90cce820581913ae87e88946a22f3367b4d Mon Sep 17 00:00:00 2001 From: sumo_slonik Date: Fri, 17 Jan 2025 16:11:35 +0100 Subject: [PATCH 1/7] Added working animation to switch in accounting page with configurable first animation. --- src/hooks/useAccordionAnimation.ts | 21 ++++ .../advanced/SageIntacctAdvancedPage.tsx | 14 ++- ...SageIntacctNonReimbursableExpensesPage.tsx | 91 +++++++++++------ .../SageIntacctReimbursableExpensesPage.tsx | 76 +++++++++----- .../import/SageIntacctToggleMappingsPage.tsx | 38 ++++--- .../workspace/accounting/intacct/types.ts | 21 +++- .../advanced/NetSuiteAdvancedPage.tsx | 99 ++++++++++++------- .../advanced/NetSuiteAutoSyncPage.tsx | 13 ++- .../NetSuiteImportCustomersOrProjectsPage.tsx | 12 ++- .../workspace/accounting/netsuite/types.ts | 29 +++++- ...ksDesktopCompanyCardExpenseAccountPage.tsx | 16 ++- .../import/QuickbooksDesktopClassesPage.tsx | 15 ++- .../import/QuickbooksDesktopCustomersPage.tsx | 15 ++- .../qbo/advanced/QuickbooksAdvancedPage.tsx | 19 +++- ...uickbooksCompanyCardExpenseAccountPage.tsx | 18 +++- .../qbo/import/QuickbooksClassesPage.tsx | 15 ++- .../qbo/import/QuickbooksCustomersPage.tsx | 27 ++++- .../qbo/import/QuickbooksLocationsPage.tsx | 23 +++-- .../XeroTrackingCategoryConfigurationPage.tsx | 12 ++- .../xero/advanced/XeroAdvancedPage.tsx | 12 ++- .../import/XeroCustomerConfigurationPage.tsx | 1 + 21 files changed, 435 insertions(+), 152 deletions(-) create mode 100644 src/hooks/useAccordionAnimation.ts diff --git a/src/hooks/useAccordionAnimation.ts b/src/hooks/useAccordionAnimation.ts new file mode 100644 index 000000000000..a42ffe77173c --- /dev/null +++ b/src/hooks/useAccordionAnimation.ts @@ -0,0 +1,21 @@ +import {useEffect} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; + +const useAccordionAnimation = (isExpanded: boolean) => { + const isAccordionExpanded = useSharedValue(isExpanded); + const shouldAnimateAccordionSection = useSharedValue(false); + const hasMounted = useSharedValue(false); + + useEffect(() => { + isAccordionExpanded.set(isExpanded); + if (hasMounted.get()) { + shouldAnimateAccordionSection.set(true); + } else { + hasMounted.set(true); + } + }, [hasMounted, isAccordionExpanded, isExpanded, shouldAnimateAccordionSection]); + + return {isAccordionExpanded, shouldAnimateAccordionSection}; +}; + +export default useAccordionAnimation; diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 2d2480835f6e..646ac71fc86a 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -1,7 +1,9 @@ import React, {useMemo} from 'react'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; @@ -34,6 +36,8 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { const {importEmployees, autoSync, sync, pendingFields, errorFields} = policy?.connections?.intacct?.config ?? {}; const {data, config} = policy?.connections?.intacct ?? {}; + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!sync?.syncReimbursedReports); + const toggleSections = useMemo( () => [ { @@ -113,20 +117,24 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { /> ))} - {!!sync?.syncReimbursedReports && ( + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_PAYMENT_ACCOUNT.getRoute(policyID))} brickRoadIndicator={areSettingsInErrorFields([CONST.SAGE_INTACCT_CONFIG.REIMBURSEMENT_ACCOUNT_ID], errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} /> - )} + ); } diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx index 91256a3c0f4e..5675908dae72 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx @@ -1,13 +1,15 @@ import React from 'react'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, getSageIntacctNonReimbursableActiveDefaultVendor, settingsPendingAction} from '@libs/PolicyUtils'; -import type {MenuItem, ToggleItem} from '@pages/workspace/accounting/intacct/types'; +import type {ExtendedMenuItemWithSubscribedSettings, MenuItemToRender} from '@pages/workspace/accounting/intacct/types'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -17,10 +19,6 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import {getDefaultVendorName} from './utils'; -type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; - -type ToggleItemWithKey = ToggleItem & {key: string}; - function SageIntacctNonReimbursableExpensesPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const policyID = policy?.id ?? '-1'; @@ -29,8 +27,31 @@ function SageIntacctNonReimbursableExpensesPage({policy}: WithPolicyConnectionsP const activeDefaultVendor = getSageIntacctNonReimbursableActiveDefaultVendor(policy); const defaultVendorName = getDefaultVendorName(activeDefaultVendor, intacctData?.vendors); + const expandedCondition = !( + !config?.export.nonReimbursable || + (config?.export.nonReimbursable === CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE && !config?.export.nonReimbursableCreditCardChargeDefaultVendor) + ); + + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(expandedCondition); + + const renderDefault = (item: MenuItemToRender) => { + return ( + + + + ); + }; - const menuItems: Array = [ + const menuItems: ExtendedMenuItemWithSubscribedSettings[] = [ { type: 'menuitem', title: config?.export.nonReimbursable @@ -62,6 +83,8 @@ function SageIntacctNonReimbursableExpensesPage({policy}: WithPolicyConnectionsP onToggle: (enabled) => { const vendor = enabled ? policy?.connections?.intacct?.data?.vendors?.[0].id ?? '' : ''; updateSageIntacctDefaultVendor(policyID, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR, vendor, config?.export.nonReimbursableCreditCardChargeDefaultVendor); + isAccordionExpanded.set(enabled); + shouldAnimateAccordionSection.set(true); }, onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR), pendingAction: settingsPendingAction([CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR], config?.pendingFields), @@ -69,20 +92,29 @@ function SageIntacctNonReimbursableExpensesPage({policy}: WithPolicyConnectionsP shouldHide: config?.export.nonReimbursable !== CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE, }, { - type: 'menuitem', - title: defaultVendorName && defaultVendorName !== '' ? defaultVendorName : translate('workspace.sageIntacct.notConfigured'), - description: translate('workspace.sageIntacct.defaultVendor'), - onPress: () => { - Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_DEFAULT_VENDOR.getRoute(policyID, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE.toLowerCase())); - }, - subscribedSettings: [ - config?.export.nonReimbursable === CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL - ? CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_VENDOR - : CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR, + type: 'accordion', + children: [ + { + type: 'menuitem', + title: defaultVendorName && defaultVendorName !== '' ? defaultVendorName : translate('workspace.sageIntacct.notConfigured'), + description: translate('workspace.sageIntacct.defaultVendor'), + onPress: () => { + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_DEFAULT_VENDOR.getRoute(policyID, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE.toLowerCase())); + }, + subscribedSettings: [ + config?.export.nonReimbursable === CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.VENDOR_BILL + ? CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_VENDOR + : CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR, + ], + shouldHide: + !config?.export.nonReimbursable || + (config?.export.nonReimbursable === CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE && + !config?.export.nonReimbursableCreditCardChargeDefaultVendor), + }, ], - shouldHide: - !config?.export.nonReimbursable || - (config?.export.nonReimbursable === CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE && !config?.export.nonReimbursableCreditCardChargeDefaultVendor), + shouldHide: false, + shouldExpand: isAccordionExpanded, + shouldAnimateSection: shouldAnimateAccordionSection, }, ]; @@ -114,21 +146,18 @@ function SageIntacctNonReimbursableExpensesPage({policy}: WithPolicyConnectionsP wrapperStyle={[styles.mv3, styles.ph5]} /> ); - default: + case 'accordion': return ( - - - + {item.children.map((child) => renderDefault(child))} + ); + default: + return renderDefault(item); } })} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx index 10edee426ff5..0dbd418177ac 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx @@ -1,13 +1,15 @@ import React from 'react'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; -import type {MenuItem, ToggleItem} from '@pages/workspace/accounting/intacct/types'; +import type {ExtendedMenuItemWithSubscribedSettings, MenuItemToRender} from '@pages/workspace/accounting/intacct/types'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; @@ -17,10 +19,6 @@ import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import {getDefaultVendorName} from './utils'; -type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; - -type ToggleItemWithKey = ToggleItem & {key: string}; - function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const policyID = policy?.id ?? '-1'; @@ -30,7 +28,26 @@ function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProp const defaultVendorName = getDefaultVendorName(reimbursableExpenseReportDefaultVendor, intacctData?.vendors); - const menuItems: Array = [ + const expandedCondition = !(reimbursable !== CONST.SAGE_INTACCT_REIMBURSABLE_EXPENSE_TYPE.EXPENSE_REPORT || !reimbursableExpenseReportDefaultVendor); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(expandedCondition); + + const renderDefault = (item: MenuItemToRender) => { + return ( + + + + ); + }; + const menuItems: ExtendedMenuItemWithSubscribedSettings[] = [ { type: 'menuitem', title: reimbursable ? translate(`workspace.sageIntacct.reimbursableExpenses.values.${reimbursable}`) : translate('workspace.sageIntacct.notConfigured'), @@ -50,6 +67,8 @@ function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProp onToggle: (enabled) => { const vendor = enabled ? policy?.connections?.intacct?.data?.vendors?.[0].id ?? '' : ''; updateSageIntacctDefaultVendor(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR, vendor, config?.export.reimbursableExpenseReportDefaultVendor); + isAccordionExpanded.set(enabled); + shouldAnimateAccordionSection.set(true); }, onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR), pendingAction: settingsPendingAction([CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR], config?.pendingFields), @@ -57,14 +76,22 @@ function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProp shouldHide: reimbursable !== CONST.SAGE_INTACCT_REIMBURSABLE_EXPENSE_TYPE.EXPENSE_REPORT, }, { - type: 'menuitem', - title: defaultVendorName && defaultVendorName !== '' ? defaultVendorName : translate('workspace.sageIntacct.notConfigured'), - description: translate('workspace.sageIntacct.defaultVendor'), - onPress: () => { - Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_DEFAULT_VENDOR.getRoute(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE)); - }, - subscribedSettings: [CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR], - shouldHide: reimbursable !== CONST.SAGE_INTACCT_REIMBURSABLE_EXPENSE_TYPE.EXPENSE_REPORT || !reimbursableExpenseReportDefaultVendor, + type: 'accordion', + children: [ + { + type: 'menuitem', + title: defaultVendorName && defaultVendorName !== '' ? defaultVendorName : translate('workspace.sageIntacct.notConfigured'), + description: translate('workspace.sageIntacct.defaultVendor'), + onPress: () => { + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_DEFAULT_VENDOR.getRoute(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE)); + }, + subscribedSettings: [CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR], + shouldHide: reimbursable !== CONST.SAGE_INTACCT_REIMBURSABLE_EXPENSE_TYPE.EXPENSE_REPORT || !reimbursableExpenseReportDefaultVendor, + }, + ], + shouldHide: false, + shouldExpand: isAccordionExpanded, + shouldAnimateSection: shouldAnimateAccordionSection, }, ]; @@ -96,21 +123,18 @@ function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProp wrapperStyle={[styles.mv3, styles.ph5]} /> ); - default: + case 'accordion': return ( - - - + {item.children.map((child) => renderDefault(child))} + ); + default: + return renderDefault(item); } })} diff --git a/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx b/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx index af85a65a39c9..b62586350ec7 100644 --- a/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx +++ b/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx @@ -1,5 +1,7 @@ import {Str} from 'expensify-common'; -import React from 'react'; +import React, {useEffect, useState} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -51,10 +53,23 @@ function SageIntacctToggleMappingsPage({route}: SageIntacctToggleMappingsPagePro const policy = usePolicy(route.params.policyID); const mappingName: SageIntacctMappingName = route.params.mapping; const policyID: string = policy?.id ?? '-1'; - const config = policy?.connections?.intacct?.config; - const translationKeys = getDisplayTypeTranslationKeys(config?.mappings?.[mappingName]); const isImportMappingEnable = config?.mappings?.[mappingName] !== CONST.SAGE_INTACCT_MAPPING_VALUE.NONE; + const isAccordionExpanded = useSharedValue(isImportMappingEnable); + const shouldAnimateAccordionSection = useSharedValue(false); + + // We are storing translation keys in the local state for animation purposes. + // Otherwise, the values change to undefined immediately after clicking, before the closing animation finishes, + // resulting in a janky animation effect. + const [translationKeys, setTranslationKey] = useState(undefined); + + useEffect(() => { + if (!isImportMappingEnable) { + return; + } + setTranslationKey(getDisplayTypeTranslationKeys(config?.mappings?.[mappingName])); + }, [isImportMappingEnable, config?.mappings, mappingName]); + return ( { const mappingValue = enabled ? CONST.SAGE_INTACCT_MAPPING_VALUE.TAG : CONST.SAGE_INTACCT_MAPPING_VALUE.NONE; updateSageIntacctMappingValue(policyID, mappingName, mappingValue, config?.mappings?.[mappingName]); + isAccordionExpanded.set(enabled); + shouldAnimateAccordionSection.set(true); }} pendingAction={settingsPendingAction([mappingName], config?.pendingFields)} errors={ErrorUtils.getLatestErrorField(config ?? {}, mappingName)} onCloseError={() => clearSageIntacctErrorField(policyID, mappingName)} /> - {isImportMappingEnable && ( + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_SAGE_INTACCT_MAPPINGS_TYPE.getRoute(policyID, mappingName))} brickRoadIndicator={areSettingsInErrorFields([mappingName], config?.errorFields) ? 'error' : undefined} + hintText={translationKeys?.descriptionKey ? translate(translationKeys?.descriptionKey) : undefined} /> - - {translationKeys?.descriptionKey ? translate(translationKeys?.descriptionKey) : undefined} - - )} + ); } diff --git a/src/pages/workspace/accounting/intacct/types.ts b/src/pages/workspace/accounting/intacct/types.ts index 79883a0c9104..0d3b339f09e1 100644 --- a/src/pages/workspace/accounting/intacct/types.ts +++ b/src/pages/workspace/accounting/intacct/types.ts @@ -1,7 +1,18 @@ +import type {SharedValue} from 'react-native-reanimated'; import type {MenuItemProps} from '@components/MenuItem'; import type {OfflineWithFeedbackProps} from '@components/OfflineWithFeedback'; import type {ToggleSettingOptionRowProps} from '@pages/workspace/workflows/ToggleSettingsOptionRow'; +type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; + +type ToggleItemWithKey = ToggleItem & {key: string}; + +type ExtendedMenuItemWithSubscribedSettings = MenuItemToRender | ToggleItemWithKey | AccordionItem; + +type MenuItemToRender = MenuItemWithSubscribedSettings & { + hintText?: string; +}; + type MenuItem = MenuItemProps & { /** Type of the item */ type: 'menuitem'; @@ -27,4 +38,12 @@ type ToggleItem = ToggleSettingOptionRowProps & { shouldHide?: boolean; }; -export type {MenuItem, ToggleItem}; +type AccordionItem = { + type: 'accordion'; + children: MenuItemToRender[]; + shouldHide: boolean; + shouldExpand: SharedValue; + shouldAnimateSection: SharedValue; +}; + +export type {MenuItem, ToggleItem, MenuItemWithSubscribedSettings, AccordionItem, ExtendedMenuItemWithSubscribedSettings, MenuItemToRender}; diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx index c6da14d9efd1..740b52e3b791 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx @@ -1,6 +1,8 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React, {useMemo} from 'react'; import {View} from 'react-native'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -17,7 +19,7 @@ import { getFilteredReimbursableAccountOptions, settingsPendingAction, } from '@libs/PolicyUtils'; -import type {DividerLineItem, MenuItem, ToggleItem} from '@pages/workspace/accounting/netsuite/types'; +import type {ExtendedMenuItemWithSubscribedSettings, MenuItemToRender} from '@pages/workspace/accounting/netsuite/types'; import { shouldHideCustomFormIDOptions, shouldHideExportJournalsTo, @@ -33,8 +35,6 @@ import CONST from '@src/CONST'; import type {TranslationPaths} from '@src/languages/types'; import ROUTES from '@src/ROUTES'; -type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; - function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); @@ -45,6 +45,9 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { const accountingMethod = policy?.connections?.netsuite?.options?.config?.accountingMethod; const {payableList} = policy?.connections?.netsuite?.options?.data ?? {}; + const shouldShowCustomFormIDOptions = useSharedValue(!shouldHideCustomFormIDOptions(config)); + const shouldAnimateAccordionSection = useSharedValue(false); + const selectedReimbursementAccount = useMemo( () => findSelectedBankAccountWithDefaultSelect(getFilteredReimbursableAccountOptions(payableList), config?.reimbursementAccountID), [payableList, config?.reimbursementAccountID], @@ -63,7 +66,25 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { return findSelectedBankAccountWithDefaultSelect(getFilteredApprovalAccountOptions(payableList), config?.approvalAccount); }, [config?.approvalAccount, payableList, translate]); - const menuItems: Array = [ + const renderDefaultMenuItem = (item: MenuItemToRender) => { + return ( + + + + ); + }; + + const menuItems: ExtendedMenuItemWithSubscribedSettings[] = [ { type: 'menuitem', title: autoSyncConfig?.autoSync?.enabled ? translate('common.enabled') : translate('common.disabled'), @@ -201,25 +222,37 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { switchAccessibilityLabel: translate('workspace.netsuite.advancedConfig.customFormIDDescription'), shouldPlaceSubtitleBelowSwitch: true, onCloseError: () => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_ENABLED), - onToggle: (isEnabled) => Connections.updateNetSuiteCustomFormIDOptionsEnabled(policyID, isEnabled), + onToggle: (isEnabled) => { + Connections.updateNetSuiteCustomFormIDOptionsEnabled(policyID, isEnabled); + shouldShowCustomFormIDOptions.set(isEnabled); + shouldAnimateAccordionSection.set(true); + }, pendingAction: settingsPendingAction([CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_ENABLED], config?.pendingFields), errors: ErrorUtils.getLatestErrorField(config, CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_ENABLED), }, { - type: 'menuitem', - description: translate('workspace.netsuite.advancedConfig.customFormIDReimbursable'), - onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE)), - title: config?.customFormIDOptions?.reimbursable?.[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.reimbursableExpensesExportDestination]], - subscribedSettings: [CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.REIMBURSABLE], - shouldHide: shouldHideCustomFormIDOptions(config), - }, - { - type: 'menuitem', - description: translate('workspace.netsuite.advancedConfig.customFormIDNonReimbursable'), - onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.NON_REIMBURSABLE)), - title: config?.customFormIDOptions?.nonReimbursable?.[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.nonreimbursableExpensesExportDestination]], - subscribedSettings: [CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.NON_REIMBURSABLE], - shouldHide: shouldHideCustomFormIDOptions(config), + type: 'accordion', + children: [ + { + type: 'menuitem', + description: translate('workspace.netsuite.advancedConfig.customFormIDReimbursable'), + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.REIMBURSABLE)), + title: config?.customFormIDOptions?.reimbursable?.[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.reimbursableExpensesExportDestination]], + subscribedSettings: [CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.REIMBURSABLE], + shouldHide: shouldHideCustomFormIDOptions(config), + }, + { + type: 'menuitem', + description: translate('workspace.netsuite.advancedConfig.customFormIDNonReimbursable'), + onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_CUSTOM_FORM_ID.getRoute(policyID, CONST.NETSUITE_EXPENSE_TYPE.NON_REIMBURSABLE)), + title: config?.customFormIDOptions?.nonReimbursable?.[CONST.NETSUITE_MAP_EXPORT_DESTINATION[config.nonreimbursableExpensesExportDestination]], + subscribedSettings: [CONST.NETSUITE_CONFIG.CUSTOM_FORM_ID_TYPE.NON_REIMBURSABLE], + shouldHide: shouldHideCustomFormIDOptions(config), + }, + ], + shouldHide: false, + shouldExpand: shouldShowCustomFormIDOptions, + shouldAnimateSection: shouldAnimateAccordionSection, }, ]; @@ -236,7 +269,7 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { connectionName={CONST.POLICY.CONNECTIONS.NAME.NETSUITE} > {menuItems - .filter((item) => !item.shouldHide) + .filter((item) => !item?.shouldHide) .map((item) => { switch (item.type) { case 'divider': @@ -257,24 +290,20 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { wrapperStyle={[styles.mv3, styles.ph5]} /> ); - default: + case 'accordion': return ( - - - + {item.children.map((child) => { + return renderDefaultMenuItem(child); + })} + ); + default: + return renderDefaultMenuItem(item); } })} diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx index 992b42dd9478..6c7f997d78ea 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx @@ -1,9 +1,11 @@ import {CONST as COMMON_CONST} from 'expensify-common'; import React from 'react'; +import Accordion from '@components/Accordion'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ScreenWrapper from '@components/ScreenWrapper'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections/NetSuiteCommands'; @@ -29,6 +31,8 @@ function NetSuiteAutoSyncPage({policy, route}: WithPolicyConnectionsProps) { const pendingAction = settingsPendingAction([CONST.NETSUITE_CONFIG.AUTO_SYNC], autoSyncConfig?.pendingFields) ?? settingsPendingAction([CONST.NETSUITE_CONFIG.ACCOUNTING_METHOD], config?.pendingFields); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!autoSyncConfig?.autoSync?.enabled); + return ( - {!!autoSyncConfig?.autoSync?.enabled && ( + + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_NETSUITE_ACCOUNTING_METHOD.getRoute(policyID))} /> - )} + ); diff --git a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectsPage.tsx b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectsPage.tsx index bb94ca59e630..895ed6b63705 100644 --- a/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectsPage.tsx +++ b/src/pages/workspace/accounting/netsuite/import/NetSuiteImportCustomersOrProjectsPage.tsx @@ -1,9 +1,11 @@ import React, {useCallback} from 'react'; import {View} from 'react-native'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import RenderHTML from '@components/RenderHTML'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import {updateNetSuiteCrossSubsidiaryCustomersConfiguration, updateNetSuiteImportMapping} from '@libs/actions/connections/NetSuiteCommands'; @@ -31,6 +33,7 @@ function NetSuiteImportCustomersOrProjectsPage({policy}: WithPolicyConnectionsPr const importCustomer = importMappings?.customers ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT; const importJobs = importMappings?.jobs ?? CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT; const importedValue = importMappings?.customers !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT ? importCustomer : importJobs; + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(importedValue !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT); const updateMapping = useCallback( (importField: ImportField, isEnabled: boolean) => { @@ -95,7 +98,10 @@ function NetSuiteImportCustomersOrProjectsPage({policy}: WithPolicyConnectionsPr errors={ErrorUtils.getLatestErrorField(config ?? {}, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.CUSTOMER_MAPPINGS.JOBS)} onCloseError={() => Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.CUSTOMER_MAPPINGS.JOBS)} /> - {importedValue !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT && ( + Policy.clearNetSuiteErrorField(policyID, CONST.NETSUITE_CONFIG.SYNC_OPTIONS.CROSS_SUBSIDIARY_CUSTOMERS)} /> - )} - {importedValue !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NETSUITE_DEFAULT && ( - )} + ); } diff --git a/src/pages/workspace/accounting/netsuite/types.ts b/src/pages/workspace/accounting/netsuite/types.ts index 1bb872d3dd92..80a525067a21 100644 --- a/src/pages/workspace/accounting/netsuite/types.ts +++ b/src/pages/workspace/accounting/netsuite/types.ts @@ -1,3 +1,4 @@ +import type {SharedValue} from 'react-native-reanimated'; import type {ValueOf} from 'type-fest'; import type {MenuItemProps} from '@components/MenuItem'; import type {OfflineWithFeedbackProps} from '@components/OfflineWithFeedback'; @@ -9,6 +10,14 @@ import type {NetSuiteCustomFieldForm} from '@src/types/form'; import type {Policy} from '@src/types/onyx'; import type {NetSuiteCustomList, NetSuiteCustomSegment} from '@src/types/onyx/Policy'; +type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; + +type MenuItemToRender = MenuItemWithSubscribedSettings & { + hintText?: string; +}; + +type ExtendedMenuItemWithSubscribedSettings = MenuItemToRender | ToggleItem | DividerLineItem | AccordionItem; + type MenuItem = MenuItemProps & { /** Type of the item */ type: 'menuitem'; @@ -45,6 +54,14 @@ type ToggleItem = ToggleSettingOptionRowProps & { shouldHide?: boolean; }; +type AccordionItem = { + type: 'accordion'; + children: MenuItemToRender[]; + shouldHide: boolean; + shouldExpand: SharedValue; + shouldAnimateSection: SharedValue; +}; + type ExpenseRouteParams = { expenseType: ValueOf; }; @@ -78,4 +95,14 @@ type CustomListSelectorType = SelectorType & { id: string; }; -export type {MenuItem, DividerLineItem, ToggleItem, ExpenseRouteParams, CustomFieldSubStepWithPolicy, CustomListSelectorType}; +export type { + MenuItem, + MenuItemToRender, + DividerLineItem, + ToggleItem, + AccordionItem, + ExpenseRouteParams, + CustomFieldSubStepWithPolicy, + CustomListSelectorType, + ExtendedMenuItemWithSubscribedSettings, +}; diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx index 3c4d781804fb..baa868a5916c 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx @@ -1,7 +1,10 @@ -import React, {useMemo} from 'react'; +import React, {useEffect, useMemo} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop'; @@ -34,6 +37,8 @@ function QuickbooksDesktopCompanyCardExpenseAccountPage({policy}: WithPolicyConn return qbdReimbursableAccounts.find(({id}) => nonReimbursableAccount === id)?.name || qbdReimbursableAccounts.at(0)?.name || translate('workspace.qbd.notConfigured'); }, [policy?.connections?.quickbooksDesktop, nonReimbursable, translate, nonReimbursableAccount]); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!qbdConfig?.shouldAutoCreateVendor); + const sections = [ { title: nonReimbursable ? translate(`workspace.qbd.accounts.${nonReimbursable}`) : undefined, @@ -96,7 +101,12 @@ function QuickbooksDesktopCompanyCardExpenseAccountPage({policy}: WithPolicyConn onToggle={(isOn) => QuickbooksDesktop.updateQuickbooksDesktopShouldAutoCreateVendor(policyID, isOn)} onCloseError={() => clearQBDErrorField(policyID, CONST.QUICKBOOKS_DESKTOP_CONFIG.SHOULD_AUTO_CREATE_VENDOR)} /> - {!!qbdConfig?.shouldAutoCreateVendor && ( + + - )} + )} diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx index 6ce56c44c680..7323dc48f028 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx @@ -1,7 +1,10 @@ -import React from 'react'; +import React, {useEffect} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop'; @@ -23,6 +26,8 @@ function QuickbooksDesktopClassesPage({policy}: WithPolicyProps) { const isSwitchOn = !!(qbdConfig?.mappings?.classes && qbdConfig.mappings.classes !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); const isReportFieldsSelected = qbdConfig?.mappings?.classes === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(isSwitchOn); + return ( clearQBDErrorField(policyID, CONST.QUICKBOOKS_DESKTOP_CONFIG.MAPPINGS.CLASSES)} /> - {isSwitchOn && ( + - )} + ); } diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx index 3f0300dc2bf4..6b817af680b4 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx @@ -1,7 +1,10 @@ -import React from 'react'; +import React, {useEffect} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as QuickbooksDesktop from '@libs/actions/connections/QuickbooksDesktop'; @@ -23,6 +26,8 @@ function QuickbooksDesktopCustomersPage({policy}: WithPolicyProps) { const isSwitchOn = !!(qbdConfig?.mappings?.customers && qbdConfig.mappings.customers !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); const isReportFieldsSelected = qbdConfig?.mappings?.customers === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(isSwitchOn); + return ( clearQBDErrorField(policyID, CONST.QUICKBOOKS_DESKTOP_CONFIG.MAPPINGS.CUSTOMERS)} /> - {isSwitchOn && ( + - )} + ); } diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx index f01d35c8a349..c10e7270af6d 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx @@ -1,8 +1,11 @@ -import React, {useMemo} from 'react'; +import React, {useEffect, useMemo} from 'react'; import {View} from 'react-native'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import useWaitForNavigation from '@hooks/useWaitForNavigation'; @@ -47,7 +50,9 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { const autoCreateVendorConst = CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR; const defaultVendorConst = CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR; - const sectionMenuItems = [ + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(isSyncReimbursedSwitchOn); + + const AccordionMenuItems = [ { title: selectedQboAccountName, description: translate('workspace.qbo.advancedConfig.qboBillPaymentAccount'), @@ -68,7 +73,7 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { const syncReimbursedSubMenuItems = () => ( - {sectionMenuItems.map((item) => ( + {AccordionMenuItems.map((item) => ( clearQBOErrorField(policyID, item.subscribedSetting)} /> ))} - {isSyncReimbursedSwitchOn && syncReimbursedSubMenuItems()} + + {syncReimbursedSubMenuItems()} + ); } diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx index 0fcb6540e3d3..0c59f1b197ee 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx @@ -1,7 +1,10 @@ -import React from 'react'; +import React, {useEffect} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Connections from '@libs/actions/connections'; @@ -19,11 +22,13 @@ import ROUTES from '@src/ROUTES'; function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnectionsProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); - const policyID = policy?.id ?? `${CONST.DEFAULT_NUMBER_ID}`; + const policyID = policy?.id ?? '-1'; const qboConfig = policy?.connections?.quickbooksOnline?.config; const {vendors} = policy?.connections?.quickbooksOnline?.data ?? {}; const nonReimbursableBillDefaultVendorObject = vendors?.find((vendor) => vendor.id === qboConfig?.nonReimbursableBillDefaultVendor); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!qboConfig?.autoCreateVendor); + const sections = [ { title: qboConfig?.nonReimbursableExpensesExportDestination ? translate(`workspace.qbo.accounts.${qboConfig?.nonReimbursableExpensesExportDestination}`) : undefined, @@ -73,7 +78,6 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections switchAccessibilityLabel={translate('workspace.qbo.defaultVendorDescription')} wrapperStyle={[styles.ph5, styles.mb3, styles.mt1]} isActive={!!qboConfig?.autoCreateVendor} - shouldPlaceSubtitleBelowSwitch pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR], qboConfig?.pendingFields)} errors={ErrorUtils.getLatestErrorField(qboConfig, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR)} onToggle={(isOn) => @@ -94,7 +98,11 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections } onCloseError={() => clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR)} /> - {qboConfig?.autoCreateVendor && ( + - )} + )} diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx index ae72999ad975..bc8eed3fd4da 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx @@ -1,7 +1,10 @@ -import React from 'react'; +import React, {useEffect} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as QuickbooksOnline from '@libs/actions/connections/QuickbooksOnline'; @@ -23,6 +26,8 @@ function QuickbooksClassesPage({policy}: WithPolicyProps) { const isSwitchOn = !!(qboConfig?.syncClasses && qboConfig.syncClasses !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); const isReportFieldsSelected = qboConfig?.syncClasses === CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD; + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(isSwitchOn); + return ( clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES)} /> - {isSwitchOn && ( + - )} + ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx index 8b842e737de6..cff03aba1712 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx @@ -1,4 +1,6 @@ -import React from 'react'; +import React, {useEffect} from 'react'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; @@ -22,6 +24,20 @@ function QuickbooksCustomersPage({policy}: WithPolicyProps) { 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; + + const isAccordionExpanded = useSharedValue(isSwitchOn); + const shouldAnimateAccordionSection = useSharedValue(false); + const hasMounted = useSharedValue(false); + + useEffect(() => { + isAccordionExpanded.set(isSwitchOn); + if (hasMounted.get()) { + shouldAnimateAccordionSection.set(true); + } else { + hasMounted.set(true); + } + }, [hasMounted, isAccordionExpanded, isSwitchOn, shouldAnimateAccordionSection]); + return ( clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_CUSTOMERS)} /> - {isSwitchOn && ( + + - )} + ); } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx index 3f405f8a3f8f..39c67b7f51b4 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx @@ -1,9 +1,9 @@ import React, {useCallback, useEffect} from 'react'; -import {View} from 'react-native'; +import {useSharedValue} from 'react-native-reanimated'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; -import Text from '@components/Text'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as QuickbooksOnline from '@libs/actions/connections/QuickbooksOnline'; @@ -18,6 +18,7 @@ import {clearQBOErrorField} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {IntegrationEntityMap} from '@src/types/onyx/Policy'; +import useAccordionAnimation from "@hooks/useAccordionAnimation"; function QuickbooksLocationsPage({policy}: WithPolicyProps) { const {translate} = useLocalize(); @@ -27,6 +28,7 @@ function QuickbooksLocationsPage({policy}: WithPolicyProps) { const isSwitchOn = !!(qboConfig?.syncLocations && qboConfig?.syncLocations !== CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE); const isTagsSelected = qboConfig?.syncLocations === CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG; const shouldShowLineItemsRestriction = shouldShowLocationsLineItemsRestriction(qboConfig); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(isSwitchOn); const updateQuickbooksOnlineSyncLocations = useCallback( (settingValue: IntegrationEntityMap) => { @@ -48,6 +50,8 @@ function QuickbooksLocationsPage({policy}: WithPolicyProps) { updateQuickbooksOnlineSyncLocations(CONST.INTEGRATION_ENTITY_MAP_TYPES.REPORT_FIELD); }, [qboConfig, updateQuickbooksOnlineSyncLocations]); + + return ( clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS)} pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.SYNC_LOCATIONS], qboConfig?.pendingFields)} /> - {isSwitchOn && ( + - )} - - {shouldShowLineItemsRestriction && isSwitchOn && ( - - {translate('workspace.qbo.locationsLineItemsRestrictionDescription')} - - )} + ); } diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index 91096880c938..fb29d8111476 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -1,8 +1,10 @@ import React, {useMemo} from 'react'; import {View} from 'react-native'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Xero from '@libs/actions/connections/Xero'; @@ -26,6 +28,8 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { const xeroConfig = policy?.connections?.xero?.config; const isSwitchOn = !!xeroConfig?.importTrackingCategories; + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!xeroConfig?.importTrackingCategories); + const menuItems = useMemo(() => { const trackingCategories = Xero.getTrackingCategories(policy); return trackingCategories.map((category: XeroTrackingCategory & {value: string}) => ({ @@ -61,7 +65,11 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { errors={ErrorUtils.getLatestErrorField(xeroConfig ?? {}, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)} onCloseError={() => Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.IMPORT_TRACKING_CATEGORIES)} /> - {!!xeroConfig?.importTrackingCategories && ( + {menuItems.map((menuItem) => ( ))} - )} + ); } diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index bcf24942047d..2f78d0f743a5 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -1,7 +1,9 @@ import React, {useMemo} from 'react'; +import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; import * as ErrorUtils from '@libs/ErrorUtils'; @@ -39,6 +41,8 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { const currentXeroOrganizationName = useMemo(() => getCurrentXeroOrganizationName(policy ?? undefined), [policy]); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(!!sync?.syncReimbursedReports); + return ( Policy.clearXeroErrorField(policyID, CONST.XERO_CONFIG.SYNC_REIMBURSED_REPORTS)} /> - {!!sync?.syncReimbursedReports && ( + <> - )} + ); } diff --git a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx index 25e9af97ebba..1d5c51642af5 100644 --- a/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/import/XeroCustomerConfigurationPage.tsx @@ -33,6 +33,7 @@ function XeroCustomerConfigurationPage({policy}: WithPolicyProps) { Date: Fri, 17 Jan 2025 16:20:46 +0100 Subject: [PATCH 2/7] describe types --- src/pages/workspace/accounting/intacct/types.ts | 10 ++++++++++ src/pages/workspace/accounting/netsuite/types.ts | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/pages/workspace/accounting/intacct/types.ts b/src/pages/workspace/accounting/intacct/types.ts index 0d3b339f09e1..4ad6348054f3 100644 --- a/src/pages/workspace/accounting/intacct/types.ts +++ b/src/pages/workspace/accounting/intacct/types.ts @@ -10,6 +10,7 @@ type ToggleItemWithKey = ToggleItem & {key: string}; type ExtendedMenuItemWithSubscribedSettings = MenuItemToRender | ToggleItemWithKey | AccordionItem; type MenuItemToRender = MenuItemWithSubscribedSettings & { + /** Optional hint text passed to the MenuItemWithTopDescription */ hintText?: string; }; @@ -39,10 +40,19 @@ type ToggleItem = ToggleSettingOptionRowProps & { }; type AccordionItem = { + /** Type of the item */ type: 'accordion'; + + /** Items nested inside the accordion */ children: MenuItemToRender[]; + + /** Whether the item should be hidden */ shouldHide: boolean; + + /** Indicates if the accordion is expanded */ shouldExpand: SharedValue; + + /** Indicates if the accordion opening and closing should be animated */ shouldAnimateSection: SharedValue; }; diff --git a/src/pages/workspace/accounting/netsuite/types.ts b/src/pages/workspace/accounting/netsuite/types.ts index 80a525067a21..f4b1a885c667 100644 --- a/src/pages/workspace/accounting/netsuite/types.ts +++ b/src/pages/workspace/accounting/netsuite/types.ts @@ -13,6 +13,7 @@ import type {NetSuiteCustomList, NetSuiteCustomSegment} from '@src/types/onyx/Po type MenuItemWithSubscribedSettings = Pick & {subscribedSettings?: string[]}; type MenuItemToRender = MenuItemWithSubscribedSettings & { + /** Optional hint text passed to the MenuItemWithTopDescription */ hintText?: string; }; @@ -55,10 +56,19 @@ type ToggleItem = ToggleSettingOptionRowProps & { }; type AccordionItem = { + /** Type of the item */ type: 'accordion'; + + /** Items nested inside the accordion */ children: MenuItemToRender[]; + + /** Whether the item should be hidden */ shouldHide: boolean; + + /** Indicates if the accordion is expanded */ shouldExpand: SharedValue; + + /** Indicates if the accordion opening and closing should be animated */ shouldAnimateSection: SharedValue; }; From 07bdd508c98fcaa48ce4fd18a9c3b62c5bb8f965 Mon Sep 17 00:00:00 2001 From: sumo_slonik Date: Fri, 17 Jan 2025 16:31:29 +0100 Subject: [PATCH 3/7] add hook to ToggleRow to --- .../workflows/ToggleSettingsOptionRow.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pages/workspace/workflows/ToggleSettingsOptionRow.tsx b/src/pages/workspace/workflows/ToggleSettingsOptionRow.tsx index acad531db94c..abcd8e248fbf 100644 --- a/src/pages/workspace/workflows/ToggleSettingsOptionRow.tsx +++ b/src/pages/workspace/workflows/ToggleSettingsOptionRow.tsx @@ -9,6 +9,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import RenderHTML from '@components/RenderHTML'; import Switch from '@components/Switch'; import Text from '@components/Text'; +import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useThemeStyles from '@hooks/useThemeStyles'; import Parser from '@libs/Parser'; import type {Errors, PendingAction} from '@src/types/onyx/OnyxCommon'; @@ -104,12 +105,11 @@ function ToggleSettingOptionRow({ showLockIcon = false, }: ToggleSettingOptionRowProps) { const styles = useThemeStyles(); - const isExpanded = useSharedValue(isActive); - const isToggleTriggered = useSharedValue(false); + const {isAccordionExpanded, shouldAnimateAccordionSection} = useAccordionAnimation(isActive); useEffect(() => { - isExpanded.set(isActive); - }, [isExpanded, isActive]); + isAccordionExpanded.set(isActive); + }, [isAccordionExpanded, isActive]); const subtitleHtml = useMemo(() => { if (!subtitle || !shouldParseSubtitle || typeof subtitle !== 'string') { @@ -184,7 +184,7 @@ function ToggleSettingOptionRow({ disabledAction={disabledAction} accessibilityLabel={switchAccessibilityLabel} onToggle={(isOn) => { - isToggleTriggered.set(true); + shouldAnimateAccordionSection.set(true); onToggle(isOn); }} isOn={isActive} @@ -194,9 +194,9 @@ function ToggleSettingOptionRow({ {shouldPlaceSubtitleBelowSwitch && subtitle && subTitleView} {subMenuItems} From b529661c0af2609bbedfeaf1debdd1523f9f202b Mon Sep 17 00:00:00 2001 From: sumo_slonik Date: Tue, 21 Jan 2025 13:35:28 +0100 Subject: [PATCH 4/7] changes after review, fix imports --- src/hooks/useAccordionAnimation.ts | 9 +++++-- .../advanced/SageIntacctAdvancedPage.tsx | 20 +++++++------- ...SageIntacctNonReimbursableExpensesPage.tsx | 8 +++--- .../SageIntacctReimbursableExpensesPage.tsx | 8 +++--- ...ksDesktopCompanyCardExpenseAccountPage.tsx | 3 +-- .../import/QuickbooksDesktopClassesPage.tsx | 3 +-- .../import/QuickbooksDesktopCustomersPage.tsx | 3 +-- .../qbo/advanced/QuickbooksAdvancedPage.tsx | 3 +-- ...uickbooksCompanyCardExpenseAccountPage.tsx | 27 +++++++++---------- .../qbo/import/QuickbooksClassesPage.tsx | 15 ++++------- .../qbo/import/QuickbooksLocationsPage.tsx | 5 +--- .../workflows/ToggleSettingsOptionRow.tsx | 1 - 12 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/hooks/useAccordionAnimation.ts b/src/hooks/useAccordionAnimation.ts index a42ffe77173c..d3995493ff8e 100644 --- a/src/hooks/useAccordionAnimation.ts +++ b/src/hooks/useAccordionAnimation.ts @@ -1,7 +1,12 @@ import {useEffect} from 'react'; import {useSharedValue} from 'react-native-reanimated'; -const useAccordionAnimation = (isExpanded: boolean) => { +/** + * @returns two values: isExpanded, which manages the expansion of the accordion component, + * and shouldAnimateAccordionSection, which determines whether we should animate + * the expanding and collapsing of the accordion based on changes in isExpanded. + */ +function useAccordionAnimation(isExpanded: boolean) { const isAccordionExpanded = useSharedValue(isExpanded); const shouldAnimateAccordionSection = useSharedValue(false); const hasMounted = useSharedValue(false); @@ -16,6 +21,6 @@ const useAccordionAnimation = (isExpanded: boolean) => { }, [hasMounted, isAccordionExpanded, isExpanded, shouldAnimateAccordionSection]); return {isAccordionExpanded, shouldAnimateAccordionSection}; -}; +} export default useAccordionAnimation; diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 646ac71fc86a..8d57379ab3b4 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -6,7 +6,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; +import {getLatestErrorField} from '@libs/ErrorUtils'; import {areSettingsInErrorFields, getCurrentSageIntacctEntityName, settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; @@ -19,7 +19,7 @@ import { updateSageIntacctSyncReimbursedReports, updateSageIntacctSyncReimbursementAccountID, } from '@userActions/connections/SageIntacct'; -import * as Policy from '@userActions/Policy/Policy'; +import {clearSageIntacctErrorField} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import type {SageIntacctDataElement} from '@src/types/onyx/Policy'; @@ -46,8 +46,8 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { isActive: !!autoSync?.enabled, onToggle: (enabled: boolean) => updateSageIntacctAutoSync(policyID, enabled), subscribedSettings: [CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED], - error: ErrorUtils.getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), - onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), + error: getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), + onCloseError: () => clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.AUTO_SYNC_ENABLED), }, { label: translate('workspace.sageIntacct.inviteEmployees'), @@ -58,12 +58,10 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { updateSageIntacctApprovalMode(policyID, enabled); }, subscribedSettings: [CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE], - error: - ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES) ?? - ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE), + error: getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES) ?? getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE), onCloseError: () => { - Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES); - Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE); + clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.IMPORT_EMPLOYEES); + clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.APPROVAL_MODE); }, }, { @@ -79,9 +77,9 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { } }, subscribedSettings: [CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS], - error: ErrorUtils.getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS), + error: getLatestErrorField(config ?? {}, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS), onCloseError: () => { - Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS); + clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.SYNC_REIMBURSED_REPORTS); }, }, ], diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx index 5675908dae72..40993871ebe5 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctNonReimbursableExpensesPage.tsx @@ -6,7 +6,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; +import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, getSageIntacctNonReimbursableActiveDefaultVendor, settingsPendingAction} from '@libs/PolicyUtils'; import type {ExtendedMenuItemWithSubscribedSettings, MenuItemToRender} from '@pages/workspace/accounting/intacct/types'; @@ -14,7 +14,7 @@ import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnec import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import {updateSageIntacctDefaultVendor} from '@userActions/connections/SageIntacct'; -import * as Policy from '@userActions/Policy/Policy'; +import {clearSageIntacctErrorField} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import {getDefaultVendorName} from './utils'; @@ -86,9 +86,9 @@ function SageIntacctNonReimbursableExpensesPage({policy}: WithPolicyConnectionsP isAccordionExpanded.set(enabled); shouldAnimateAccordionSection.set(true); }, - onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR), + onCloseError: () => clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR), pendingAction: settingsPendingAction([CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR], config?.pendingFields), - errors: ErrorUtils.getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR), + errors: getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.NON_REIMBURSABLE_CREDIT_CARD_VENDOR), shouldHide: config?.export.nonReimbursable !== CONST.SAGE_INTACCT_NON_REIMBURSABLE_EXPENSE_TYPE.CREDIT_CARD_CHARGE, }, { diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx index 0dbd418177ac..1f190a9313c1 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx @@ -6,7 +6,7 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as ErrorUtils from '@libs/ErrorUtils'; +import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import type {ExtendedMenuItemWithSubscribedSettings, MenuItemToRender} from '@pages/workspace/accounting/intacct/types'; @@ -14,7 +14,7 @@ import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnec import withPolicyConnections from '@pages/workspace/withPolicyConnections'; import ToggleSettingOptionRow from '@pages/workspace/workflows/ToggleSettingsOptionRow'; import {updateSageIntacctDefaultVendor} from '@userActions/connections/SageIntacct'; -import * as Policy from '@userActions/Policy/Policy'; +import {clearSageIntacctErrorField} from '@userActions/Policy/Policy'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; import {getDefaultVendorName} from './utils'; @@ -70,9 +70,9 @@ function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProp isAccordionExpanded.set(enabled); shouldAnimateAccordionSection.set(true); }, - onCloseError: () => Policy.clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR), + onCloseError: () => clearSageIntacctErrorField(policyID, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR), pendingAction: settingsPendingAction([CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR], config?.pendingFields), - errors: ErrorUtils.getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR), + errors: getLatestErrorField(config, CONST.SAGE_INTACCT_CONFIG.REIMBURSABLE_VENDOR), shouldHide: reimbursable !== CONST.SAGE_INTACCT_REIMBURSABLE_EXPENSE_TYPE.EXPENSE_REPORT, }, { diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx index baa868a5916c..7fc6109cab16 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx @@ -1,5 +1,4 @@ -import React, {useEffect, useMemo} from 'react'; -import {useSharedValue} from 'react-native-reanimated'; +import React, {useMemo} from 'react'; import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx index 7323dc48f028..fc7c9b11fa2a 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopClassesPage.tsx @@ -1,5 +1,4 @@ -import React, {useEffect} from 'react'; -import {useSharedValue} from 'react-native-reanimated'; +import React from 'react'; import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx index 6b817af680b4..033f2803edfe 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx @@ -1,5 +1,4 @@ -import React, {useEffect} from 'react'; -import {useSharedValue} from 'react-native-reanimated'; +import React from 'react'; import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx index c10e7270af6d..ac135dca2263 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx @@ -1,6 +1,5 @@ -import React, {useEffect, useMemo} from 'react'; +import React, {useMemo} from 'react'; import {View} from 'react-native'; -import {useSharedValue} from 'react-native-reanimated'; import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx index 0c59f1b197ee..26c426376f6e 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx @@ -1,5 +1,4 @@ -import React, {useEffect} from 'react'; -import {useSharedValue} from 'react-native-reanimated'; +import React from 'react'; import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; @@ -7,10 +6,10 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Connections from '@libs/actions/connections'; -import * as ConnectionUtils from '@libs/ConnectionUtils'; -import * as ErrorUtils from '@libs/ErrorUtils'; -import * as PolicyUtils from '@libs/PolicyUtils'; +import {updateManyPolicyConnectionConfigs} from '@libs/actions/connections'; +import {getQBONonReimbursableExportAccountType} from '@libs/ConnectionUtils'; +import {getLatestErrorField} from '@libs/ErrorUtils'; +import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import Navigation from '@navigation/Navigation'; import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections'; import withPolicyConnections from '@pages/workspace/withPolicyConnections'; @@ -39,7 +38,7 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections }, { title: qboConfig?.nonReimbursableExpensesAccount?.name ?? translate('workspace.qbo.notConfigured'), - description: ConnectionUtils.getQBONonReimbursableExportAccountType(qboConfig?.nonReimbursableExpensesExportDestination), + description: getQBONonReimbursableExportAccountType(qboConfig?.nonReimbursableExpensesExportDestination), onPress: () => Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_COMPANY_CARD_EXPENSE_ACCOUNT_SELECT.getRoute(policyID)), subscribedSettings: [CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_EXPENSE_ACCOUNT], }, @@ -59,12 +58,12 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections onBackButtonPress={() => Navigation.goBack(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_EXPORT.getRoute(policyID))} > {sections.map((section) => ( - + @@ -78,10 +77,10 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections switchAccessibilityLabel={translate('workspace.qbo.defaultVendorDescription')} wrapperStyle={[styles.ph5, styles.mb3, styles.mt1]} isActive={!!qboConfig?.autoCreateVendor} - pendingAction={PolicyUtils.settingsPendingAction([CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR], qboConfig?.pendingFields)} - errors={ErrorUtils.getLatestErrorField(qboConfig, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR)} + pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR], qboConfig?.pendingFields)} + errors={getLatestErrorField(qboConfig, CONST.QUICKBOOKS_CONFIG.AUTO_CREATE_VENDOR)} onToggle={(isOn) => - Connections.updateManyPolicyConnectionConfigs( + updateManyPolicyConnectionConfigs( policyID, CONST.POLICY.CONNECTIONS.NAME.QBO, { @@ -103,13 +102,13 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections style={styles.overflowHidden} isToggleTriggered={shouldAnimateAccordionSection} > - + Navigation.navigate(ROUTES.POLICY_ACCOUNTING_QUICKBOOKS_ONLINE_NON_REIMBURSABLE_DEFAULT_VENDOR_SELECT.getRoute(policyID))} brickRoadIndicator={ - PolicyUtils.areSettingsInErrorFields([CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR], qboConfig?.errorFields) + areSettingsInErrorFields([CONST.QUICKBOOKS_CONFIG.NON_REIMBURSABLE_BILL_DEFAULT_VENDOR], qboConfig?.errorFields) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined } diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx index bc8eed3fd4da..d2e537f3d561 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx @@ -1,5 +1,4 @@ -import React, {useEffect} from 'react'; -import {useSharedValue} from 'react-native-reanimated'; +import React from 'react'; import Accordion from '@components/Accordion'; import ConnectionLayout from '@components/ConnectionLayout'; import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; @@ -7,8 +6,8 @@ import OfflineWithFeedback from '@components/OfflineWithFeedback'; import useAccordionAnimation from '@hooks/useAccordionAnimation'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as QuickbooksOnline from '@libs/actions/connections/QuickbooksOnline'; -import * as ErrorUtils from '@libs/ErrorUtils'; +import {updateQuickbooksOnlineSyncClasses} from '@libs/actions/connections/QuickbooksOnline'; +import {getLatestErrorField} from '@libs/ErrorUtils'; import Navigation from '@libs/Navigation/Navigation'; import {areSettingsInErrorFields, settingsPendingAction} from '@libs/PolicyUtils'; import type {WithPolicyProps} from '@pages/workspace/withPolicy'; @@ -45,14 +44,10 @@ function QuickbooksClassesPage({policy}: WithPolicyProps) { switchAccessibilityLabel={translate('workspace.qbo.classes')} isActive={isSwitchOn} onToggle={() => - QuickbooksOnline.updateQuickbooksOnlineSyncClasses( - policyID, - isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, - qboConfig?.syncClasses, - ) + updateQuickbooksOnlineSyncClasses(policyID, isSwitchOn ? CONST.INTEGRATION_ENTITY_MAP_TYPES.NONE : CONST.INTEGRATION_ENTITY_MAP_TYPES.TAG, qboConfig?.syncClasses) } pendingAction={settingsPendingAction([CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES], qboConfig?.pendingFields)} - errors={ErrorUtils.getLatestErrorField(qboConfig, CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES)} + errors={getLatestErrorField(qboConfig, CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES)} onCloseError={() => clearQBOErrorField(policyID, CONST.QUICKBOOKS_CONFIG.SYNC_CLASSES)} /> Date: Wed, 5 Feb 2025 11:32:48 +0100 Subject: [PATCH 5/7] fix hover files --- src/components/Accordion/index.tsx | 20 +++++++++++++++---- .../advanced/SageIntacctAdvancedPage.tsx | 1 - ...SageIntacctNonReimbursableExpensesPage.tsx | 1 - .../SageIntacctReimbursableExpensesPage.tsx | 1 - .../import/SageIntacctToggleMappingsPage.tsx | 1 - .../advanced/NetSuiteAdvancedPage.tsx | 1 - .../advanced/NetSuiteAutoSyncPage.tsx | 1 - ...ksDesktopCompanyCardExpenseAccountPage.tsx | 1 - .../import/QuickbooksDesktopClassesPage.tsx | 1 - .../import/QuickbooksDesktopCustomersPage.tsx | 1 - .../qbo/advanced/QuickbooksAdvancedPage.tsx | 1 - ...uickbooksCompanyCardExpenseAccountPage.tsx | 1 - .../qbo/import/QuickbooksClassesPage.tsx | 1 - .../qbo/import/QuickbooksCustomersPage.tsx | 1 - .../qbo/import/QuickbooksLocationsPage.tsx | 1 - .../XeroTrackingCategoryConfigurationPage.tsx | 1 - .../xero/advanced/XeroAdvancedPage.tsx | 1 - 17 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx index 9715f3902c03..8fd5b19e74ef 100644 --- a/src/components/Accordion/index.tsx +++ b/src/components/Accordion/index.tsx @@ -24,6 +24,7 @@ type AccordionProps = { function Accordion({isExpanded, children, duration = 300, isToggleTriggered, style}: AccordionProps) { const height = useSharedValue(0); + const isAnimating = useSharedValue(false); const derivedHeight = useDerivedValue(() => { if (!isToggleTriggered.get()) { @@ -41,10 +42,19 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty return isExpanded.get() ? 1 : 0; } - return withTiming(isExpanded.get() ? 1 : 0, { - duration, - easing: Easing.inOut(Easing.quad), - }); + isAnimating.set(true); + return withTiming( + isExpanded.get() ? 1 : 0, + { + duration, + easing: Easing.inOut(Easing.quad), + }, + (finished) => { + if (finished) { + isAnimating.set(false); + } + }, + ); }); const animatedStyle = useAnimatedStyle(() => { @@ -57,7 +67,9 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty return { height: !isToggleTriggered.get() ? undefined : derivedHeight.get(), + maxHeight: !isToggleTriggered.get() ? undefined : derivedHeight.get(), opacity: derivedOpacity.get(), + overflow: isAnimating.get() ? 'hidden' : 'visible', }; }); diff --git a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx index 8d57379ab3b4..fa410a0e376b 100644 --- a/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx +++ b/src/pages/workspace/accounting/intacct/advanced/SageIntacctAdvancedPage.tsx @@ -117,7 +117,6 @@ function SageIntacctAdvancedPage({policy}: WithPolicyProps) { {item.children.map((child) => renderDefault(child))} diff --git a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx index 1f190a9313c1..12265912fc9e 100644 --- a/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx +++ b/src/pages/workspace/accounting/intacct/export/SageIntacctReimbursableExpensesPage.tsx @@ -127,7 +127,6 @@ function SageIntacctReimbursableExpensesPage({policy}: WithPolicyConnectionsProp return ( {item.children.map((child) => renderDefault(child))} diff --git a/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx b/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx index b62586350ec7..67203416f497 100644 --- a/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx +++ b/src/pages/workspace/accounting/intacct/import/SageIntacctToggleMappingsPage.tsx @@ -105,7 +105,6 @@ function SageIntacctToggleMappingsPage({route}: SageIntacctToggleMappingsPagePro /> diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx index edd39992eb0f..5d7df8b7a876 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAdvancedPage.tsx @@ -301,7 +301,6 @@ function NetSuiteAdvancedPage({policy}: WithPolicyConnectionsProps) { return ( {item.children.map((child) => { diff --git a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx index 6c7f997d78ea..2836b3d60075 100644 --- a/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx +++ b/src/pages/workspace/accounting/netsuite/advanced/NetSuiteAutoSyncPage.tsx @@ -65,7 +65,6 @@ function NetSuiteAutoSyncPage({policy, route}: WithPolicyConnectionsProps) { diff --git a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx index 7fc6109cab16..75ad8a86eff5 100644 --- a/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbd/export/QuickbooksDesktopCompanyCardExpenseAccountPage.tsx @@ -103,7 +103,6 @@ function QuickbooksDesktopCompanyCardExpenseAccountPage({policy}: WithPolicyConn diff --git a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx index 033f2803edfe..3f7a9f1606c4 100644 --- a/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbd/import/QuickbooksDesktopCustomersPage.tsx @@ -56,7 +56,6 @@ function QuickbooksDesktopCustomersPage({policy}: WithPolicyProps) { /> diff --git a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx index ac135dca2263..14be50461112 100644 --- a/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx +++ b/src/pages/workspace/accounting/qbo/advanced/QuickbooksAdvancedPage.tsx @@ -179,7 +179,6 @@ function QuickbooksAdvancedPage({policy}: WithPolicyConnectionsProps) { ))} {syncReimbursedSubMenuItems()} diff --git a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx index 26c426376f6e..ec9eb50415bf 100644 --- a/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx +++ b/src/pages/workspace/accounting/qbo/export/QuickbooksCompanyCardExpenseAccountPage.tsx @@ -99,7 +99,6 @@ function QuickbooksCompanyCardExpenseAccountPage({policy}: WithPolicyConnections /> diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx index d2e537f3d561..c436f332a8c0 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksClassesPage.tsx @@ -52,7 +52,6 @@ function QuickbooksClassesPage({policy}: WithPolicyProps) { /> diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx index cff03aba1712..551849415198 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksCustomersPage.tsx @@ -68,7 +68,6 @@ function QuickbooksCustomersPage({policy}: WithPolicyProps) { diff --git a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx index addd041923ab..26916ca207ce 100644 --- a/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx +++ b/src/pages/workspace/accounting/qbo/import/QuickbooksLocationsPage.tsx @@ -81,7 +81,6 @@ function QuickbooksLocationsPage({policy}: WithPolicyProps) { /> diff --git a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx index fb29d8111476..898b4dc326bd 100644 --- a/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx +++ b/src/pages/workspace/accounting/xero/XeroTrackingCategoryConfigurationPage.tsx @@ -67,7 +67,6 @@ function XeroTrackingCategoryConfigurationPage({policy}: WithPolicyProps) { /> diff --git a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx index 2f78d0f743a5..bb49e2a160ea 100644 --- a/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx +++ b/src/pages/workspace/accounting/xero/advanced/XeroAdvancedPage.tsx @@ -90,7 +90,6 @@ function XeroAdvancedPage({policy}: WithPolicyConnectionsProps) { /> <> From 562ee23bb5652aa2b1ef483dbdfd44672b47f572 Mon Sep 17 00:00:00 2001 From: sumo_slonik Date: Wed, 5 Feb 2025 11:58:17 +0100 Subject: [PATCH 6/7] fix eslint --- src/components/Accordion/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx index 8fd5b19e74ef..ffc3f5ee6ed8 100644 --- a/src/components/Accordion/index.tsx +++ b/src/components/Accordion/index.tsx @@ -50,9 +50,10 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty easing: Easing.inOut(Easing.quad), }, (finished) => { - if (finished) { - isAnimating.set(false); + if (!finished) { + return; } + isAnimating.set(false); }, ); }); From a0a28430c264f9f716a32018bc829b9fad1a292c Mon Sep 17 00:00:00 2001 From: sumo_slonik Date: Fri, 7 Feb 2025 14:22:37 +0100 Subject: [PATCH 7/7] fixed custom id --- src/components/Accordion/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/Accordion/index.tsx b/src/components/Accordion/index.tsx index ffc3f5ee6ed8..d70b8db835dd 100644 --- a/src/components/Accordion/index.tsx +++ b/src/components/Accordion/index.tsx @@ -50,7 +50,7 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty easing: Easing.inOut(Easing.quad), }, (finished) => { - if (!finished) { + if (!finished || !isExpanded.get()) { return; } isAnimating.set(false); @@ -63,6 +63,7 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty return { height: 0, opacity: 0, + display: 'none', }; } @@ -71,6 +72,7 @@ function Accordion({isExpanded, children, duration = 300, isToggleTriggered, sty maxHeight: !isToggleTriggered.get() ? undefined : derivedHeight.get(), opacity: derivedOpacity.get(), overflow: isAnimating.get() ? 'hidden' : 'visible', + display: isExpanded.get() ? 'inline' : 'none', }; });