Skip to content

Commit

Permalink
Add backTo param handling when opening Report from Search
Browse files Browse the repository at this point in the history
  • Loading branch information
Kicu committed Sep 24, 2024
1 parent a7a408f commit 13d29fc
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 27 deletions.
14 changes: 9 additions & 5 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,9 @@ const ROUTES = {
SEARCH_ADVANCED_FILTERS_IN: 'search/filters/in',
SEARCH_REPORT: {
route: 'search/view/:reportID/:reportActionID?',
getRoute: (reportID: string, reportActionID?: string) => {
if (reportActionID) {
return `search/view/${reportID}/${reportActionID}` as const;
}
return `search/view/${reportID}` as const;
getRoute: ({reportID, reportActionID, backTo}: {reportID: string; reportActionID?: string; backTo?: string}) => {
const baseRoute = reportActionID ? (`search/view/${reportID}/${reportActionID}` as const) : (`search/view/${reportID}` as const);
return getUrlWithBackToParam(baseRoute, backTo);
},
},
TRANSACTION_HOLD_REASON_RHP: 'search/hold',
Expand Down Expand Up @@ -1552,6 +1550,12 @@ type Route = {

type RoutesValidationError = 'Error: One or more routes defined within `ROUTES` have not correctly used `as const` in their `getRoute` function return value.';

/**
* Represents all routes in the app as a union of literal strings.
*
* If TS throws on this line, it implies that one or more routes defined within `ROUTES` have not correctly used
* `as const` in their `getRoute` function return value.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type RouteIsPlainString = AssertTypesNotEqual<string, Route, RoutesValidationError>;

Expand Down
2 changes: 1 addition & 1 deletion src/components/PromotedActionsBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const PromotedActions = {
return;
}

ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute(targetedReportID));
ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute({reportID: targetedReportID}));
},
}),
} satisfies PromotedActionsType;
Expand Down
8 changes: 5 additions & 3 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ function Search({queryJSON}: SearchProps) {
}

const ListItem = SearchUtils.getListItem(type, status);
const data = SearchUtils.getSections(type, status, searchResults.data, searchResults.search);
const data = SearchUtils.getSections(type, status, searchResults.data, searchResults.search, queryJSON.inputQuery);
const sortedData = SearchUtils.getSortedSections(type, status, data, sortBy, sortOrder);
const sortedSelectedData = sortedData.map((item) => mapToItemWithSelectionInfo(item, selectedTransactions, canSelectMultiple));

Expand Down Expand Up @@ -294,13 +294,15 @@ function Search({queryJSON}: SearchProps) {
SearchActions.createTransactionThread(hash, item.transactionID, reportID, item.moneyRequestReportActionID);
}

const backTo = ROUTES.SEARCH_CENTRAL_PANE.getRoute({query: queryJSON.inputQuery});

if (SearchUtils.isReportActionListItemType(item)) {
const reportActionID = item.reportActionID;
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(reportID, reportActionID));
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, reportActionID, backTo}));
return;
}

Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(reportID));
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID, backTo}));
};

const fetchMoreResults = () => {
Expand Down
4 changes: 3 additions & 1 deletion src/components/SelectionList/Search/ReportListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ function ReportListItem<TItem extends ListItem>({
};

const openReportInRHP = (transactionItem: TransactionListItemType) => {
Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute(transactionItem.transactionThreadReportID));
const backTo = ROUTES.SEARCH_CENTRAL_PANE.getRoute({query: reportItem.currentSearchQuery});

Navigation.navigate(ROUTES.SEARCH_REPORT.getRoute({reportID: transactionItem.transactionThreadReportID, backTo}));
};

if (!reportItem?.reportName && reportItem.transactions.length > 1) {
Expand Down
5 changes: 5 additions & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {MutableRefObject, ReactElement, ReactNode} from 'react';
import type {GestureResponderEvent, InputModeOptions, LayoutChangeEvent, SectionListData, StyleProp, TextInput, TextStyle, ViewStyle} from 'react-native';
import type {SearchQueryString} from '@components/Search/types';
import type {BrickRoad} from '@libs/WorkspacesSettingsUtils';
// eslint-disable-next-line no-restricted-imports
import type CursorStyles from '@styles/utils/cursor/types';
Expand Down Expand Up @@ -233,7 +234,11 @@ type ReportListItemType = ListItem &
/** The personal details of the user paying the request */
to: SearchPersonalDetails;

/** List of transactions that belong to this report */
transactions: TransactionListItemType[];

/** The current search query that was used to display these report items */
currentSearchQuery: SearchQueryString;
};

type ListItemProps<TItem extends ListItem> = CommonListItemProps<TItem> & {
Expand Down
24 changes: 12 additions & 12 deletions src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,22 @@ function getMatchingRootRouteForRHPRoute(route: NavigationPartialRoute): Navigat
if (route.params && 'backTo' in route.params && typeof route.params.backTo === 'string') {
const stateForBackTo = getStateFromPath(route.params.backTo, config);
if (stateForBackTo) {
// eslint-disable-next-line @typescript-eslint/no-shadow
const rhpNavigator = stateForBackTo.routes.find((route) => route.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR);

const centralPaneOrFullScreenNavigator = stateForBackTo.routes.find(
// eslint-disable-next-line @typescript-eslint/no-shadow
(route) => isCentralPaneName(route.name) || route.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR,
);

// If there is rhpNavigator in the state generated for backTo url, we want to get root route matching to this rhp screen.
const rhpNavigator = stateForBackTo.routes.find((rt) => rt.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR);
if (rhpNavigator && rhpNavigator.state) {
return getMatchingRootRouteForRHPRoute(findFocusedRoute(stateForBackTo) as NavigationPartialRoute);
}

// If we know that backTo targets the root route (central pane or full screen) we want to use it.
if (centralPaneOrFullScreenNavigator && centralPaneOrFullScreenNavigator.state) {
return centralPaneOrFullScreenNavigator as NavigationPartialRoute<CentralPaneName | typeof NAVIGATORS.FULL_SCREEN_NAVIGATOR>;
// If we know that backTo targets the root route (full screen) we want to use it.
const fullScreenNavigator = stateForBackTo.routes.find((rt) => rt.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR);
if (fullScreenNavigator && fullScreenNavigator.state) {
return fullScreenNavigator as NavigationPartialRoute<CentralPaneName | typeof NAVIGATORS.FULL_SCREEN_NAVIGATOR>;
}

// If we know that backTo targets a central pane screen we want to use it.
const centralPaneScreen = stateForBackTo.routes.find((rt) => isCentralPaneName(rt.name));
if (centralPaneScreen) {
return centralPaneScreen as NavigationPartialRoute<CentralPaneName | typeof NAVIGATORS.FULL_SCREEN_NAVIGATOR>;
}
}
}
Expand Down Expand Up @@ -191,7 +191,7 @@ function getAdaptedState(state: PartialState<NavigationState<RootStackParamList>
if (focusedRHPRoute) {
let matchingRootRoute = getMatchingRootRouteForRHPRoute(focusedRHPRoute);
const isRHPScreenOpenedFromLHN = focusedRHPRoute?.name && RHP_SCREENS_OPENED_FROM_LHN.includes(focusedRHPRoute?.name as RHPScreenOpenedFromLHN);
// This may happen if this RHP doens't have a route that should be under the overlay defined.
// This may happen if this RHP doesn't have a route that should be under the overlay defined.
if (!matchingRootRoute || isRHPScreenOpenedFromLHN) {
metainfo.isCentralPaneAndBottomTabMandatory = false;
metainfo.isFullScreenNavigatorMandatory = false;
Expand Down
20 changes: 15 additions & 5 deletions src/libs/SearchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ function getIOUReportName(data: OnyxTypes.SearchResults['data'], reportItem: Sea
return reportItem.reportName;
}

function getReportSections(data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search']): ReportListItemType[] {
function getReportSections(data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], currentSearchQuery: SearchQueryString): ReportListItemType[] {
const shouldShowMerchant = getShouldShowMerchant(data);

const doesDataContainAPastYearTransaction = shouldShowYear(data);
Expand All @@ -271,6 +271,7 @@ function getReportSections(data: OnyxTypes.SearchResults['data'], metadata: Onyx
from: data.personalDetailsList?.[reportItem.accountID ?? -1],
to: reportItem.managerID ? data.personalDetailsList?.[reportItem.managerID] : emptyPersonalDetails,
transactions,
currentSearchQuery,
reportName: isIOUReport ? getIOUReportName(data, reportItem) : reportItem.reportName,
};
} else if (isTransactionEntry(key)) {
Expand Down Expand Up @@ -313,21 +314,30 @@ function getListItem(type: SearchDataTypes, status: SearchStatus): ListItemType<
if (type === CONST.SEARCH.DATA_TYPES.CHAT) {
return ChatListItem;
}
return status === CONST.SEARCH.STATUS.EXPENSE.ALL ? TransactionListItem : ReportListItem;
if (status === CONST.SEARCH.STATUS.EXPENSE.ALL) {
return TransactionListItem;
}
return ReportListItem;
}

function getSections(type: SearchDataTypes, status: SearchStatus, data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search']) {
function getSections(type: SearchDataTypes, status: SearchStatus, data: OnyxTypes.SearchResults['data'], metadata: OnyxTypes.SearchResults['search'], currentSearchQuery: SearchQueryString) {
if (type === CONST.SEARCH.DATA_TYPES.CHAT) {
return getReportActionsSections(data);
}
return status === CONST.SEARCH.STATUS.EXPENSE.ALL ? getTransactionsSections(data, metadata) : getReportSections(data, metadata);
if (status === CONST.SEARCH.STATUS.EXPENSE.ALL) {
return getTransactionsSections(data, metadata);
}
return getReportSections(data, metadata, currentSearchQuery);
}

function getSortedSections(type: SearchDataTypes, status: SearchStatus, data: ListItemDataType<typeof type, typeof status>, sortBy?: SearchColumnType, sortOrder?: SortOrder) {
if (type === CONST.SEARCH.DATA_TYPES.CHAT) {
return getSortedReportActionData(data as ReportActionListItemType[]);
}
return status === CONST.SEARCH.STATUS.EXPENSE.ALL ? getSortedTransactionData(data as TransactionListItemType[], sortBy, sortOrder) : getSortedReportData(data as ReportListItemType[]);
if (status === CONST.SEARCH.STATUS.EXPENSE.ALL) {
return getSortedTransactionData(data as TransactionListItemType[], sortBy, sortOrder);
}
return getSortedReportData(data as ReportListItemType[]);
}

function getSortedTransactionData(data: TransactionListItemType[], sortBy?: SearchColumnType, sortOrder?: SortOrder) {
Expand Down

0 comments on commit 13d29fc

Please sign in to comment.