Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7044,6 +7044,7 @@ const CONST = {
HAS_SUBSCRIPTION_INFO: 'hasSubscriptionInfo',
HAS_PHONE_NUMBER_ERROR: 'hasPhoneNumberError',
HAS_CARD_CONNECTION_ERROR: 'hasCardConnectionError',
HAS_UBER_CREDENTIALS_ERROR: 'hasUberCredentialsError',
},

DEBUG: {
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useGetReceiptPartnersIntegrationData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import useIsPolicyConnectedToUberReceiptPartner from './useIsPolicyConnectedToUb
import useLocalize from './useLocalize';
import usePolicy from './usePolicy';

export default function useGetReceiptPartnersIntegrationData({policyID}: {policyID?: string}) {
export default function useGetReceiptPartnersIntegrationData(policyID?: string) {
const policy = usePolicy(policyID);
const {translate} = useLocalize();

const uber = policy?.receiptPartners?.uber;
const isUberConnected = useIsPolicyConnectedToUberReceiptPartner({policyID});
const shouldShowEnterCredentialsError = isUberConnected && !!uber?.error;
const shouldShowEnterCredentialsError = !!uber?.error;

const getReceiptPartnersIntegrationData = useCallback(
(receiptPartnerName: string) => {
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/useWorkspacesTabIndicatorStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {useMemo} from 'react';
import type {ValueOf} from 'type-fest';
import {isConnectionInProgress} from '@libs/actions/connections';
import {shouldShowQBOReimbursableExportDestinationAccountError} from '@libs/actions/connections/QuickbooksOnline';
import {shouldShowCustomUnitsError, shouldShowEmployeeListError, shouldShowPolicyError, shouldShowSyncError} from '@libs/PolicyUtils';
import {getUberConnectionErrorDirectlyFromPolicy, shouldShowCustomUnitsError, shouldShowEmployeeListError, shouldShowPolicyError, shouldShowSyncError} from '@libs/PolicyUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import useOnyx from './useOnyx';
Expand All @@ -23,7 +23,6 @@ function useWorkspacesTabIndicatorStatus(): WorkspacesTabIndicatorStatusResult {
// If a policy was just deleted from Onyx, then Onyx will pass a null value to the props, and
// those should be cleaned out before doing any error checking
const cleanPolicies = useMemo(() => Object.fromEntries(Object.entries(policies ?? {}).filter(([, policy]) => policy?.id)), [policies]);

const policyErrors = {
[CONST.INDICATOR_STATUS.HAS_POLICY_ERRORS]: Object.values(cleanPolicies).find(shouldShowPolicyError),
[CONST.INDICATOR_STATUS.HAS_CUSTOM_UNITS_ERROR]: Object.values(cleanPolicies).find(shouldShowCustomUnitsError),
Expand All @@ -32,6 +31,7 @@ function useWorkspacesTabIndicatorStatus(): WorkspacesTabIndicatorStatusResult {
shouldShowSyncError(cleanPolicy, isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${cleanPolicy?.id}`], cleanPolicy)),
),
[CONST.INDICATOR_STATUS.HAS_QBO_EXPORT_ERROR]: Object.values(cleanPolicies).find(shouldShowQBOReimbursableExportDestinationAccountError),
[CONST.INDICATOR_STATUS.HAS_UBER_CREDENTIALS_ERROR]: Object.values(cleanPolicies).find(getUberConnectionErrorDirectlyFromPolicy),
};

// All of the error & info-checking methods are put into an array. This is so that using _.some() will return
Expand Down
7 changes: 7 additions & 0 deletions src/libs/PolicyUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@

let allPolicies: OnyxCollection<Policy>;

Onyx.connect({

Check warning on line 60 in src/libs/PolicyUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.POLICY,
waitForCollectionCallback: true,
callback: (value) => (allPolicies = value),
Expand Down Expand Up @@ -302,6 +302,12 @@
return false;
}

function getUberConnectionErrorDirectlyFromPolicy(policy: OnyxEntry<Policy>) {
const receiptUber = policy?.receiptPartners?.uber;

return !!receiptUber?.error;
}

function isExpensifyTeam(email: string | undefined): boolean {
const emailDomain = Str.extractEmailDomain(email ?? '');
return emailDomain === CONST.EXPENSIFY_PARTNER_NAME || emailDomain === CONST.EMAIL.GUIDES_DOMAIN;
Expand Down Expand Up @@ -1577,6 +1583,7 @@
isPolicyAuditor,
isPolicyEmployee,
isPolicyFeatureEnabled,
getUberConnectionErrorDirectlyFromPolicy,
isPolicyOwner,
isPolicyMember,
isPolicyPayer,
Expand Down
2 changes: 1 addition & 1 deletion src/pages/workspace/WorkspaceInitialPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ function WorkspaceInitialPage({policyDraft, policy: policyProp, route}: Workspac
.filter((domainID): domainID is number => !!domainID);
const {login, accountID} = useCurrentUserPersonalDetails();
const hasSyncError = shouldShowSyncError(policy, isConnectionInProgress(connectionSyncProgress, policy));
const {shouldShowEnterCredentialsError} = useGetReceiptPartnersIntegrationData({policyID: policy?.id});
const {shouldShowEnterCredentialsError} = useGetReceiptPartnersIntegrationData(policy?.id);
const waitForNavigate = useWaitForNavigation();
const {singleExecution, isExecuting} = useSingleExecution();
const activeRoute = useNavigationState((state) => findFocusedRoute(state)?.name);
Expand Down
7 changes: 5 additions & 2 deletions src/pages/workspace/WorkspacesListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import usePreloadFullScreenNavigators from '@libs/Navigation/AppNavigator/usePre
import Navigation from '@libs/Navigation/Navigation';
import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types';
import type {AuthScreensParamList} from '@libs/Navigation/types';
import {getDefaultApprover, getPolicy, getPolicyBrickRoadIndicatorStatus, isPolicyAdmin, shouldShowPolicy} from '@libs/PolicyUtils';
import {getDefaultApprover, getPolicy, getPolicyBrickRoadIndicatorStatus, getUberConnectionErrorDirectlyFromPolicy, isPolicyAdmin, shouldShowPolicy} from '@libs/PolicyUtils';
import {getDefaultWorkspaceAvatar} from '@libs/ReportUtils';
import shouldRenderTransferOwnerButton from '@libs/shouldRenderTransferOwnerButton';
import {shouldCalculateBillNewDot as shouldCalculateBillNewDotFn} from '@libs/SubscriptionUtils';
Expand Down Expand Up @@ -113,7 +113,7 @@ function WorkspacesListPage() {
const shouldShowLoadingIndicator = isLoadingApp && !isOffline;
const route = useRoute<PlatformStackRouteProp<AuthScreensParamList, typeof SCREENS.WORKSPACES_LIST>>();
const [fundList] = useOnyx(ONYXKEYS.FUND_LIST, {canBeMissing: true});
const [duplicateWorkspace] = useOnyx(ONYXKEYS.DUPLICATE_WORKSPACE, {canBeMissing: false});
const [duplicateWorkspace] = useOnyx(ONYXKEYS.DUPLICATE_WORKSPACE, {canBeMissing: true});
const {isRestrictedToPreferredPolicy} = usePreferredPolicy();

// This hook preloads the screens of adjacent tabs to make changing tabs faster.
Expand Down Expand Up @@ -354,6 +354,8 @@ function WorkspacesListPage() {
return Object.values(policies)
.filter((policy): policy is PolicyType => shouldShowPolicy(policy, isOffline, session?.email))
.map((policy): WorkspaceItem => {
const receiptUberBrickRoadIndicator = getUberConnectionErrorDirectlyFromPolicy(policy) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined;

if (policy?.isJoinRequestPending && policy?.policyDetailsForNonMembers) {
const policyInfo = Object.values(policy.policyDetailsForNonMembers).at(0) as PolicyDetailsForNonMembers;
const id = Object.keys(policy.policyDetailsForNonMembers).at(0);
Expand Down Expand Up @@ -381,6 +383,7 @@ function WorkspacesListPage() {
brickRoadIndicator: !isPolicyAdmin(policy)
? undefined
: (reimbursementAccountBrickRoadIndicator ??
receiptUberBrickRoadIndicator ??
getPolicyBrickRoadIndicatorStatus(
policy,
isConnectionInProgress(allConnectionSyncProgresses?.[`${ONYXKEYS.COLLECTION.POLICY_CONNECTION_SYNC_PROGRESS}${policy.id}`], policy),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function WorkspaceReceiptPartnersPage({route}: WorkspaceReceiptPartnersPageProps
const {isOffline} = useNetwork();
const threeDotsMenuContainerRef = useRef<View>(null);
const policy = usePolicy(policyID);
const {getReceiptPartnersIntegrationData, shouldShowEnterCredentialsError, isUberConnected} = useGetReceiptPartnersIntegrationData({policyID});
const {getReceiptPartnersIntegrationData, shouldShowEnterCredentialsError, isUberConnected} = useGetReceiptPartnersIntegrationData(policyID);
const [selectedPartner, setSelectedPartner] = useState<string | null>(null);
const isLoading = policy?.isLoading;
const [isDisconnectModalOpen, setIsDisconnectModalOpen] = useState(false);
Expand Down
45 changes: 45 additions & 0 deletions tests/unit/PolicyUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
getSubmitToAccountID,
getTagList,
getTagListByOrderWeight,
getUberConnectionErrorDirectlyFromPolicy,
getUnitRateValue,
isCurrentUserMemberOfAnyPolicy,
isPolicyMemberWithoutPendingDelete,
Expand Down Expand Up @@ -318,6 +319,50 @@ describe('PolicyUtils', () => {
});
});

describe('getUberConnectionErrorDirectlyFromPolicy', () => {
it('should return true if Uber connection is enabled and has an error', () => {
const policy: Policy = {
...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
receiptPartners: {
uber: {
enabled: true,
error: 'Some error',
connectFormData: 'Some data',
},
},
};

expect(getUberConnectionErrorDirectlyFromPolicy(policy)).toBe(true);
});

it('should return false if Uber connection is enabled but has no error', () => {
const policy: Policy = {
...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
receiptPartners: {
uber: {
enabled: true,
error: undefined,
connectFormData: 'Some data',
},
},
};

expect(getUberConnectionErrorDirectlyFromPolicy(policy)).toBe(false);
});

it('should return false if Uber connection does not exist', () => {
const policy: Policy = {
...createRandomPolicy(1, CONST.POLICY.TYPE.TEAM),
};

expect(getUberConnectionErrorDirectlyFromPolicy(policy)).toBe(false);
});

it('should return false if policy is undefined', () => {
expect(getUberConnectionErrorDirectlyFromPolicy(undefined)).toBe(false);
});
});

describe('getUnitRateValue', () => {
it('should return an empty string for NaN', () => {
const rate = getUnitRateValue(toLocaleDigitMock, {rate: 'invalid' as unknown as number});
Expand Down
Loading