Skip to content

Commit

Permalink
Merge pull request #51675 from callstack-internal/pac-guerreiro/fix/5…
Browse files Browse the repository at this point in the history
…1488-reports-with-report-not-found-error-cause-inbox-tab-rbr

Reports with "report not found" error cause Inbox tab RBR
  • Loading branch information
puneetlath authored Nov 6, 2024
2 parents 1679540 + acba675 commit 0a8f897
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 131 deletions.
44 changes: 2 additions & 42 deletions src/hooks/useReportIDs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ import React, {createContext, useCallback, useContext, useMemo} from 'react';
import type {OnyxEntry} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import {getPolicyEmployeeListByIdWithoutCurrentUser} from '@libs/PolicyUtils';
import * as ReportActionsUtils from '@libs/ReportActionsUtils';
import SidebarUtils from '@libs/SidebarUtils';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type * as OnyxTypes from '@src/types/onyx';
import type {Message} from '@src/types/onyx/ReportAction';
import mapOnyxCollectionItems from '@src/utils/mapOnyxCollectionItems';
import useActiveWorkspace from './useActiveWorkspace';
import useCurrentReportID from './useCurrentReportID';
Expand All @@ -34,33 +32,6 @@ const ReportIDsContext = createContext<ReportIDsContextValue>({
policyMemberAccountIDs: [],
});

/**
* This function (and the few below it), narrow down the data from Onyx to just the properties that we want to trigger a re-render of the component. This helps minimize re-rendering
* and makes the entire component more performant because it's not re-rendering when a bunch of properties change which aren't ever used in the UI.
*/
const reportActionsSelector = (reportActions: OnyxEntry<OnyxTypes.ReportActions>): ReportActionsSelector =>
(reportActions &&
Object.values(reportActions)
.filter(Boolean)
.map((reportAction) => {
const {reportActionID, actionName, errors = []} = reportAction;
const originalMessage = ReportActionsUtils.getOriginalMessage(reportAction);
const message = ReportActionsUtils.getReportActionMessage(reportAction);
const decision = message?.moderationDecision?.decision;

return {
reportActionID,
actionName,
errors,
message: [
{
moderationDecision: {decision},
},
] as Message[],
originalMessage,
};
})) as ReportActionsSelector;

const policySelector = (policy: OnyxEntry<OnyxTypes.Policy>): PolicySelector =>
(policy && {
type: policy.type,
Expand All @@ -84,7 +55,6 @@ function ReportIDsContextProvider({
const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE, {initialValue: CONST.PRIORITY_MODE.DEFAULT});
const [chatReports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY, {selector: (c) => mapOnyxCollectionItems(c, policySelector)});
const [allReportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS, {selector: (c) => mapOnyxCollectionItems(c, reportActionsSelector)});
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [reportsDrafts] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT);
const [betas] = useOnyx(ONYXKEYS.BETAS);
Expand All @@ -99,20 +69,10 @@ function ReportIDsContextProvider({

const getOrderedReportIDs = useCallback(
(currentReportID?: string) =>
SidebarUtils.getOrderedReportIDs(
currentReportID ?? null,
chatReports,
betas,
policies,
priorityMode,
allReportActions,
transactionViolations,
activeWorkspaceID,
policyMemberAccountIDs,
),
SidebarUtils.getOrderedReportIDs(currentReportID ?? null, chatReports, betas, policies, priorityMode, transactionViolations, activeWorkspaceID, policyMemberAccountIDs),
// we need reports draft in deps array for reloading of list when reportsDrafts will change
// eslint-disable-next-line react-compiler/react-compiler, react-hooks/exhaustive-deps
[chatReports, betas, policies, priorityMode, allReportActions, transactionViolations, activeWorkspaceID, policyMemberAccountIDs, reportsDrafts],
[chatReports, betas, policies, priorityMode, transactionViolations, activeWorkspaceID, policyMemberAccountIDs, reportsDrafts],
);

const orderedReportIDs = useMemo(() => getOrderedReportIDs(), [getOrderedReportIDs]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {PressableWithFeedback} from '@components/Pressable';
import type {SearchQueryString} from '@components/Search/types';
import Text from '@components/Text';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useCurrentReportID from '@hooks/useCurrentReportID';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
Expand Down Expand Up @@ -65,15 +66,23 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const {activeWorkspaceID} = useActiveWorkspace();
const {currentReportID} = useCurrentReportID() ?? {currentReportID: null};
const [user] = useOnyx(ONYXKEYS.USER);
const [betas] = useOnyx(ONYXKEYS.BETAS);
const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS);
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [chatTabBrickRoad, setChatTabBrickRoad] = useState<BrickRoad>(getChatTabBrickRoad(activeWorkspaceID));
const [chatTabBrickRoad, setChatTabBrickRoad] = useState<BrickRoad>(
getChatTabBrickRoad(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations),
);

useEffect(() => {
setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID));
}, [activeWorkspaceID, transactionViolations, reports, reportActions]);
setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations));
// We need to get a new brick road state when report actions are updated, otherwise we'll be showing an outdated brick road.
// That's why reportActions is added as a dependency here
}, [activeWorkspaceID, transactionViolations, reports, reportActions, betas, policies, priorityMode, currentReportID]);

const navigateToChats = useCallback(() => {
if (selectedTab === SCREENS.HOME) {
Expand Down Expand Up @@ -118,6 +127,12 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
selectedTab={selectedTab}
chatTabBrickRoad={chatTabBrickRoad}
activeWorkspaceID={activeWorkspaceID}
reports={reports}
currentReportID={currentReportID}
betas={betas}
policies={policies}
transactionViolations={transactionViolations}
priorityMode={priorityMode}
/>
)}
<View style={styles.bottomTabBarContainer}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, {useCallback, useMemo} from 'react';
import {View} from 'react-native';
import type {OnyxEntry} from 'react-native-onyx';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import {useOnyx} from 'react-native-onyx';
import Button from '@components/Button';
import Icon from '@components/Icon';
Expand All @@ -21,12 +21,18 @@ import ONYXKEYS from '@src/ONYXKEYS';
import type {Route} from '@src/ROUTES';
import ROUTES from '@src/ROUTES';
import SCREENS from '@src/SCREENS';
import type {ReimbursementAccount} from '@src/types/onyx';
import type {Beta, Policy, PriorityMode, ReimbursementAccount, Report, TransactionViolations} from '@src/types/onyx';

type DebugTabViewProps = {
selectedTab?: string;
chatTabBrickRoad: BrickRoad;
activeWorkspaceID?: string;
currentReportID: string | null;
reports: OnyxCollection<Report>;
betas: OnyxEntry<Beta[]>;
policies: OnyxCollection<Policy>;
transactionViolations: OnyxCollection<TransactionViolations>;
priorityMode: OnyxEntry<PriorityMode>;
};

function getSettingsMessage(status: IndicatorStatus | undefined): TranslationPaths | undefined {
Expand Down Expand Up @@ -91,7 +97,7 @@ function getSettingsRoute(status: IndicatorStatus | undefined, reimbursementAcco
}
}

function DebugTabView({selectedTab = '', chatTabBrickRoad, activeWorkspaceID}: DebugTabViewProps) {
function DebugTabView({selectedTab = '', chatTabBrickRoad, activeWorkspaceID, currentReportID, reports, betas, policies, transactionViolations, priorityMode}: DebugTabViewProps) {
const StyleUtils = useStyleUtils();
const theme = useTheme();
const styles = useThemeStyles();
Expand Down Expand Up @@ -131,7 +137,7 @@ function DebugTabView({selectedTab = '', chatTabBrickRoad, activeWorkspaceID}: D

const navigateTo = useCallback(() => {
if (selectedTab === SCREENS.HOME && !!chatTabBrickRoad) {
const report = getChatTabBrickRoadReport(activeWorkspaceID);
const report = getChatTabBrickRoadReport(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations);

if (report) {
Navigation.navigate(ROUTES.DEBUG_REPORT.getRoute(report.reportID));
Expand All @@ -144,7 +150,7 @@ function DebugTabView({selectedTab = '', chatTabBrickRoad, activeWorkspaceID}: D
Navigation.navigate(route);
}
}
}, [selectedTab, chatTabBrickRoad, activeWorkspaceID, status, reimbursementAccount, policyIDWithErrors]);
}, [selectedTab, chatTabBrickRoad, activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations, status, reimbursementAccount, policyIDWithErrors]);

if (!([SCREENS.HOME, SCREENS.SETTINGS.ROOT] as string[]).includes(selectedTab) || !indicator) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {PressableWithFeedback} from '@components/Pressable';
import type {SearchQueryString} from '@components/Search/types';
import Tooltip from '@components/Tooltip';
import useActiveWorkspace from '@hooks/useActiveWorkspace';
import useCurrentReportID from '@hooks/useCurrentReportID';
import useLocalize from '@hooks/useLocalize';
import useTheme from '@hooks/useTheme';
import useThemeStyles from '@hooks/useThemeStyles';
import * as Session from '@libs/actions/Session';
import interceptAnonymousUser from '@libs/interceptAnonymousUser';
import DebugTabView from '@libs/Navigation/AppNavigator/createCustomBottomTabNavigator/DebugTabView';
import Navigation from '@libs/Navigation/Navigation';
import type {AuthScreensParamList} from '@libs/Navigation/types';
import {isCentralPaneName} from '@libs/NavigationUtils';
Expand Down Expand Up @@ -72,12 +74,23 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
const navigation = useNavigation();
const {activeWorkspaceID} = useActiveWorkspace();
const [isLoadingApp] = useOnyx(ONYXKEYS.IS_LOADING_APP);
const transactionViolations = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [chatTabBrickRoad, setChatTabBrickRoad] = useState<BrickRoad>(getChatTabBrickRoad(activeWorkspaceID));
const {currentReportID} = useCurrentReportID() ?? {currentReportID: null};
const [user] = useOnyx(ONYXKEYS.USER);
const [betas] = useOnyx(ONYXKEYS.BETAS);
const [priorityMode] = useOnyx(ONYXKEYS.NVP_PRIORITY_MODE);
const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [policies] = useOnyx(ONYXKEYS.COLLECTION.POLICY);
const [reportActions] = useOnyx(ONYXKEYS.COLLECTION.REPORT_ACTIONS);
const [transactionViolations] = useOnyx(ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS);
const [chatTabBrickRoad, setChatTabBrickRoad] = useState<BrickRoad>(
getChatTabBrickRoad(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations),
);

useEffect(() => {
setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID));
}, [activeWorkspaceID, transactionViolations]);
setChatTabBrickRoad(getChatTabBrickRoad(activeWorkspaceID, currentReportID, reports, betas, policies, priorityMode, transactionViolations));
// We need to get a new brick road state when report actions are updated, otherwise we'll be showing an outdated brick road.
// That's why reportActions is added as a dependency here
}, [activeWorkspaceID, transactionViolations, reports, reportActions, betas, policies, priorityMode, currentReportID]);

useEffect(() => {
const navigationState = navigation.getState();
Expand Down Expand Up @@ -138,51 +151,66 @@ function BottomTabBar({selectedTab}: BottomTabBarProps) {
}, [activeWorkspaceID, selectedTab]);

return (
<View style={styles.bottomTabBarContainer}>
<Tooltip text={translate('common.inbox')}>
<PressableWithFeedback
onPress={navigateToChats}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.inbox')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.Inbox}
fill={selectedTab === SCREENS.HOME ? theme.iconMenu : theme.icon}
width={variables.iconBottomBar}
height={variables.iconBottomBar}
/>
{!!chatTabBrickRoad && (
<View style={styles.bottomTabStatusIndicator(chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO ? theme.iconSuccessFill : theme.danger)} />
)}
</View>
</PressableWithFeedback>
</Tooltip>
<Tooltip text={translate('common.search')}>
<PressableWithFeedback
onPress={navigateToSearch}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.search')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.MoneySearch}
fill={selectedTab === SCREENS.SEARCH.BOTTOM_TAB ? theme.iconMenu : theme.icon}
width={variables.iconBottomBar}
height={variables.iconBottomBar}
/>
</View>
</PressableWithFeedback>
</Tooltip>
<BottomTabAvatar isSelected={selectedTab === SCREENS.SETTINGS.ROOT} />
<View style={[styles.flex1, styles.bottomTabBarItem]}>
<BottomTabBarFloatingActionButton />
<>
{!!user?.isDebugModeEnabled && (
<DebugTabView
selectedTab={selectedTab}
chatTabBrickRoad={chatTabBrickRoad}
activeWorkspaceID={activeWorkspaceID}
reports={reports}
currentReportID={currentReportID}
betas={betas}
policies={policies}
transactionViolations={transactionViolations}
priorityMode={priorityMode}
/>
)}
<View style={styles.bottomTabBarContainer}>
<Tooltip text={translate('common.inbox')}>
<PressableWithFeedback
onPress={navigateToChats}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.inbox')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.Inbox}
fill={selectedTab === SCREENS.HOME ? theme.iconMenu : theme.icon}
width={variables.iconBottomBar}
height={variables.iconBottomBar}
/>
{!!chatTabBrickRoad && (
<View style={styles.bottomTabStatusIndicator(chatTabBrickRoad === CONST.BRICK_ROAD_INDICATOR_STATUS.INFO ? theme.iconSuccessFill : theme.danger)} />
)}
</View>
</PressableWithFeedback>
</Tooltip>
<Tooltip text={translate('common.search')}>
<PressableWithFeedback
onPress={navigateToSearch}
role={CONST.ROLE.BUTTON}
accessibilityLabel={translate('common.search')}
wrapperStyle={styles.flex1}
style={styles.bottomTabBarItem}
>
<View>
<Icon
src={Expensicons.MoneySearch}
fill={selectedTab === SCREENS.SEARCH.BOTTOM_TAB ? theme.iconMenu : theme.icon}
width={variables.iconBottomBar}
height={variables.iconBottomBar}
/>
</View>
</PressableWithFeedback>
</Tooltip>
<BottomTabAvatar isSelected={selectedTab === SCREENS.SETTINGS.ROOT} />
<View style={[styles.flex1, styles.bottomTabBarItem]}>
<BottomTabBarFloatingActionButton />
</View>
</View>
</View>
</>
);
}

Expand Down
3 changes: 1 addition & 2 deletions src/libs/SidebarUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Str} from 'expensify-common';
import type {OnyxCollection, OnyxEntry} from 'react-native-onyx';
import Onyx from 'react-native-onyx';
import type {ValueOf} from 'type-fest';
import type {PolicySelector, ReportActionsSelector} from '@hooks/useReportIDs';
import type {PolicySelector} from '@hooks/useReportIDs';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type {PersonalDetails, PersonalDetailsList, ReportActions, TransactionViolation} from '@src/types/onyx';
Expand Down Expand Up @@ -92,7 +92,6 @@ function getOrderedReportIDs(
betas: OnyxEntry<Beta[]>,
policies: OnyxCollection<PolicySelector>,
priorityMode: OnyxEntry<PriorityMode>,
allReportActions: OnyxCollection<ReportActionsSelector>,
transactionViolations: OnyxCollection<TransactionViolation[]>,
currentPolicyID = '',
policyMemberAccountIDs: number[] = [],
Expand Down
Loading

0 comments on commit 0a8f897

Please sign in to comment.