Skip to content

Commit

Permalink
Merge pull request Expensify#49641 from software-mansion-labs/kicu/48…
Browse files Browse the repository at this point in the history
…817-search-backto

Add backTo param handling when opening Report from Search
  • Loading branch information
luacmartins authored Sep 27, 2024
2 parents 4c76858 + 43c4676 commit 70ed492
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 24 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 @@ -1579,6 +1577,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 @@ -100,7 +100,7 @@ const PromotedActions = {
return;
}

ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute(targetedReportID), currentSearchHash);
ReportUtils.changeMoneyRequestHoldStatus(reportAction, ROUTES.SEARCH_REPORT.getRoute({reportID: targetedReportID}), currentSearchHash);
},
}),
} satisfies PromotedActionsType;
Expand Down
6 changes: 4 additions & 2 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,15 @@ function Search({queryJSON}: SearchProps) {
SearchActions.createTransactionThread(hash, item.transactionID, reportID, item.moneyRequestReportActionID);
}

const backTo = Navigation.getActiveRoute();

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 = Navigation.getActiveRoute();

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

if (!reportItem?.reportName && reportItem.transactions.length > 1) {
Expand Down
1 change: 1 addition & 0 deletions src/components/SelectionList/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ type ReportListItemType = ListItem &
/** The personal details of the user paying the request */
to: SearchPersonalDetails;

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

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
15 changes: 12 additions & 3 deletions src/libs/SearchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,21 +311,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']) {
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);
}

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 70ed492

Please sign in to comment.