Skip to content

Commit

Permalink
Merge pull request #41980 from narefyev91/add-skeleton-for-loading-ac…
Browse files Browse the repository at this point in the history
…counting

Add skeleton to loading Accounting options
  • Loading branch information
youssef-lr authored May 15, 2024
2 parents 5cf2550 + b6dbb99 commit b928739
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 29 deletions.
34 changes: 34 additions & 0 deletions src/components/AccountingListSkeletonView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import {Circle, Rect} from 'react-native-svg';
import ItemListSkeletonView from './Skeletons/ItemListSkeletonView';

type AccountingListSkeletonViewProps = {
shouldAnimate?: boolean;
};

function AccountingListSkeletonView({shouldAnimate = true}: AccountingListSkeletonViewProps) {
return (
<ItemListSkeletonView
shouldAnimate={shouldAnimate}
renderSkeletonItem={() => (
<>
<Circle
cx="20"
cy="32"
r="20"
/>
<Rect
x="54"
y="28"
width="40%"
height="8"
/>
</>
)}
/>
);
}

AccountingListSkeletonView.displayName = 'AccountingListSkeletonView';

export default AccountingListSkeletonView;
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Modal from '@components/Modal';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import {removePolicyConnection} from '@libs/actions/connections';
import {getQuickBooksOnlineSetupLink} from '@libs/actions/connections/QuickBooksOnline';
Expand All @@ -34,6 +35,7 @@ function ConnectToQuickbooksOnlineButton({
const {translate} = useLocalize();
const webViewRef = useRef<WebView>(null);
const [isWebViewOpen, setWebViewOpen] = useState(false);
const {isOffline} = useNetwork();

const authToken = session?.authToken ?? null;

Expand All @@ -52,6 +54,7 @@ function ConnectToQuickbooksOnlineButton({
text={translate('workspace.accounting.setup')}
style={styles.justifyContentCenter}
small
isDisabled={isOffline}
/>
{shouldDisconnectIntegrationBeforeConnecting && integrationToDisconnect && isDisconnectModalOpen && (
<ConfirmModal
Expand Down
3 changes: 3 additions & 0 deletions src/components/ConnectToQuickbooksOnlineButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Button from '@components/Button';
import ConfirmModal from '@components/ConfirmModal';
import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import {removePolicyConnection} from '@libs/actions/connections';
import {getQuickBooksOnlineSetupLink} from '@libs/actions/connections/QuickBooksOnline';
Expand All @@ -14,6 +15,7 @@ function ConnectToQuickbooksOnlineButton({policyID, shouldDisconnectIntegrationB
const styles = useThemeStyles();
const {translate} = useLocalize();
const {environmentURL} = useEnvironment();
const {isOffline} = useNetwork();

const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);

Expand All @@ -27,6 +29,7 @@ function ConnectToQuickbooksOnlineButton({policyID, shouldDisconnectIntegrationB
}
Link.openLink(getQuickBooksOnlineSetupLink(policyID), environmentURL);
}}
isDisabled={isOffline}
text={translate('workspace.accounting.setup')}
style={styles.justifyContentCenter}
small
Expand Down
3 changes: 3 additions & 0 deletions src/components/ConnectToXeroButton/index.native.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
import Modal from '@components/Modal';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import {removePolicyConnection} from '@libs/actions/connections';
import {getXeroSetupLink} from '@libs/actions/connections/ConnectToXero';
Expand All @@ -30,6 +31,7 @@ function ConnectToXeroButton({policyID, session, shouldDisconnectIntegrationBefo
const [isWebViewOpen, setWebViewOpen] = useState(false);

const authToken = session?.authToken ?? null;
const {isOffline} = useNetwork();

const renderLoading = () => <FullScreenLoadingIndicator />;
const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);
Expand All @@ -47,6 +49,7 @@ function ConnectToXeroButton({policyID, session, shouldDisconnectIntegrationBefo
text={translate('workspace.accounting.setup')}
style={styles.justifyContentCenter}
small
isDisabled={isOffline}
/>
{shouldDisconnectIntegrationBeforeConnecting && isDisconnectModalOpen && integrationToDisconnect && (
<ConfirmModal
Expand Down
3 changes: 3 additions & 0 deletions src/components/ConnectToXeroButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Button from '@components/Button';
import ConfirmModal from '@components/ConfirmModal';
import useEnvironment from '@hooks/useEnvironment';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useThemeStyles from '@hooks/useThemeStyles';
import {removePolicyConnection} from '@libs/actions/connections';
import {getXeroSetupLink} from '@libs/actions/connections/ConnectToXero';
Expand All @@ -14,6 +15,7 @@ function ConnectToXeroButton({policyID, shouldDisconnectIntegrationBeforeConnect
const styles = useThemeStyles();
const {translate} = useLocalize();
const {environmentURL} = useEnvironment();
const {isOffline} = useNetwork();

const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);

Expand All @@ -30,6 +32,7 @@ function ConnectToXeroButton({policyID, shouldDisconnectIntegrationBeforeConnect
text={translate('workspace.accounting.setup')}
style={styles.justifyContentCenter}
small
isDisabled={isOffline}
/>
{shouldDisconnectIntegrationBeforeConnecting && isDisconnectModalOpen && integrationToDisconnect && (
<ConfirmModal
Expand Down
42 changes: 26 additions & 16 deletions src/pages/workspace/accounting/PolicyAccountingPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, {useMemo, useRef, useState} from 'react';
import {ActivityIndicator, View} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import type {OnyxEntry} from 'react-native-onyx';
import AccountingListSkeletonView from '@components/AccountingListSkeletonView';
import CollapsibleSection from '@components/CollapsibleSection';
import ConfirmModal from '@components/ConfirmModal';
import ConnectToQuickbooksOnlineButton from '@components/ConnectToQuickbooksOnlineButton';
Expand All @@ -28,7 +29,7 @@ import {syncConnection} from '@libs/actions/connections/QuickBooksOnline';
import {findCurrentXeroOrganization, getCurrentXeroOrganizationName, getXeroTenants} from '@libs/PolicyUtils';
import Navigation from '@navigation/Navigation';
import AccessOrNotFoundWrapper from '@pages/workspace/AccessOrNotFoundWrapper';
import type {WithPolicyProps} from '@pages/workspace/withPolicy';
import type {WithPolicyConnectionsProps} from '@pages/workspace/withPolicyConnections';
import withPolicyConnections from '@pages/workspace/withPolicyConnections';
import type {AnchorPosition} from '@styles/index';
import CONST from '@src/CONST';
Expand All @@ -43,7 +44,7 @@ type PolicyAccountingPageOnyxProps = {
connectionSyncProgress: OnyxEntry<PolicyConnectionSyncProgress>;
};

type PolicyAccountingPageProps = WithPolicyProps &
type PolicyAccountingPageProps = WithPolicyConnectionsProps &
PolicyAccountingPageOnyxProps & {
// This is not using OnyxEntry<OnyxTypes.Policy> because the HOC withPolicyConnections will only render this component if there is a policy
policy: Policy;
Expand Down Expand Up @@ -100,7 +101,7 @@ function accountingIntegrationData(
}
}

function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccountingPageProps) {
function PolicyAccountingPage({policy, connectionSyncProgress, isConnectionDataFetchNeeded}: PolicyAccountingPageProps) {
const theme = useTheme();
const styles = useThemeStyles();
const {translate} = useLocalize();
Expand Down Expand Up @@ -335,22 +336,30 @@ function PolicyAccountingPage({policy, connectionSyncProgress}: PolicyAccounting
titleStyles={styles.accountSettingsSectionTitle}
childrenStyles={styles.pt5}
>
<MenuItemList
menuItems={connectionsMenuItems}
shouldUseSingleExecution
/>
{otherIntegrationsItems && (
<CollapsibleSection
title={translate('workspace.accounting.other')}
wrapperStyle={[styles.pr3, styles.mt5, styles.pv3]}
titleStyle={[styles.textNormal, styles.colorMuted]}
textStyle={[styles.flex1, styles.userSelectNone, styles.textNormal, styles.colorMuted]}
>
{isConnectionDataFetchNeeded ? (
<View style={styles.mnh20}>
<AccountingListSkeletonView shouldAnimate />
</View>
) : (
<>
<MenuItemList
menuItems={otherIntegrationsItems}
menuItems={connectionsMenuItems}
shouldUseSingleExecution
/>
</CollapsibleSection>
{otherIntegrationsItems && (
<CollapsibleSection
title={translate('workspace.accounting.other')}
wrapperStyle={[styles.pr3, styles.mt5, styles.pv3]}
titleStyle={[styles.textNormal, styles.colorMuted]}
textStyle={[styles.flex1, styles.userSelectNone, styles.textNormal, styles.colorMuted]}
>
<MenuItemList
menuItems={otherIntegrationsItems}
shouldUseSingleExecution
/>
</CollapsibleSection>
)}
</>
)}
</Section>
</View>
Expand Down Expand Up @@ -383,4 +392,5 @@ export default withPolicyConnections(
key: (props) => `${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${props.route.params.policyID}`,
},
})(PolicyAccountingPage),
false,
);
25 changes: 12 additions & 13 deletions src/pages/workspace/withPolicyConnections.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React, {useEffect} from 'react';
import type {ComponentType} from 'react';
import {useOnyx} from 'react-native-onyx';
import FullPageOfflineBlockingView from '@components/BlockingViews/FullPageOfflineBlockingView';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import useNetwork from '@hooks/useNetwork';
import {openPolicyAccountingPage} from '@libs/actions/PolicyConnections';
import ONYXKEYS from '@src/ONYXKEYS';
import withPolicy from './withPolicy';
import type {WithPolicyProps} from './withPolicy';

type WithPolicyConnectionsProps = WithPolicyProps;
type WithPolicyConnectionsProps = WithPolicyProps & {
isConnectionDataFetchNeeded: boolean;
};

/**
* Higher-order component that fetches the connections data and populates
Expand All @@ -21,35 +22,33 @@ type WithPolicyConnectionsProps = WithPolicyProps;
* Only the active policy gets the complete policy data upon app start that includes the connections data.
* For other policies, the connections data needs to be fetched when it's needed.
*/
function withPolicyConnections<TProps extends WithPolicyConnectionsProps>(WrappedComponent: ComponentType<TProps>) {
function withPolicyConnections<TProps extends WithPolicyConnectionsProps>(WrappedComponent: ComponentType<TProps>, shouldBlockView = true) {
function WithPolicyConnections(props: TProps) {
const {isOffline} = useNetwork();
const [hasConnectionsDataBeenFetched, {status}] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${props.policy?.id ?? '0'}`, {
const [hasConnectionsDataBeenFetched] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY_HAS_CONNECTIONS_DATA_BEEN_FETCHED}${props.policy?.id ?? '0'}`, {
initWithStoredValues: false,
});
const isConnectionDataFetchNeeded = !isOffline && props.policy && props.policy.areConnectionsEnabled && !props.policy.connections && !hasConnectionsDataBeenFetched;

useEffect(() => {
// When the accounting feature is not enabled, or if the connections data already exists,
// there is no need to fetch the connections data.
if (!props.policy || !props.policy.areConnectionsEnabled || !!hasConnectionsDataBeenFetched || !!props.policy.connections) {
if (!isConnectionDataFetchNeeded || !props.policy?.id) {
return;
}

openPolicyAccountingPage(props.policy.id);
}, [hasConnectionsDataBeenFetched, props.policy, isOffline]);

if (props.policy?.areConnectionsEnabled && (!props.policy || status === 'loading' || hasConnectionsDataBeenFetched === false)) {
return (
<FullPageOfflineBlockingView>
<FullScreenLoadingIndicator />
</FullPageOfflineBlockingView>
);
}, [props.policy?.id, isConnectionDataFetchNeeded]);

if (isConnectionDataFetchNeeded && shouldBlockView) {
return <FullScreenLoadingIndicator />;
}

return (
<WrappedComponent
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
isConnectionDataFetchNeeded={isConnectionDataFetchNeeded}
/>
);
}
Expand Down
4 changes: 4 additions & 0 deletions src/styles/utils/sizing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export default {
minHeight: '100%',
},

mnh20: {
minHeight: 80,
},

mnw2: {
minWidth: 8,
},
Expand Down

0 comments on commit b928739

Please sign in to comment.