Skip to content

Commit

Permalink
Merge pull request #40570 from software-mansion-labs/search-v1/rhp-re…
Browse files Browse the repository at this point in the history
…port

[Search v1] Add ReportScreen to RHP
  • Loading branch information
luacmartins authored Apr 25, 2024
2 parents 0c723cc + 5575b53 commit 6060e6f
Show file tree
Hide file tree
Showing 23 changed files with 185 additions and 40 deletions.
5 changes: 5 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const ROUTES = {
getRoute: (query: string) => `search/${query}` as const,
},

SEARCH_REPORT: {
route: '/search/:query/view/:reportID',
getRoute: (query: string, reportID: string) => `search/${query}/view/${reportID}` as const,
},

// This is a utility route used to go to the user's concierge chat, or the sign-in page if the user's not authenticated
CONCIERGE: 'concierge',
FLAG_COMMENT: {
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const SCREENS = {
WORKSPACES_CENTRAL_PANE: 'WorkspacesCentralPane',
SEARCH: {
CENTRAL_PANE: 'Search_Central_Pane',
REPORT_RHP: 'Search_Report_RHP',
BOTTOM_TAB: 'Search_Bottom_Tab',
},
SETTINGS: {
Expand Down Expand Up @@ -130,6 +131,7 @@ const SCREENS = {
ROOM_INVITE: 'RoomInvite',
REFERRAL: 'Referral',
PROCESS_MONEY_REQUEST_HOLD: 'ProcessMoneyRequestHold',
SEARCH_REPORT: 'SearchReport',
},
ONBOARDING_MODAL: {
ONBOARDING: 'Onboarding',
Expand Down
32 changes: 22 additions & 10 deletions src/components/MoneyReportHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,25 @@ type MoneyReportHeaderProps = MoneyReportHeaderOnyxProps & {
/** The reportID of the transaction thread report associated with this current report, if any */
// eslint-disable-next-line react/no-unused-prop-types
transactionThreadReportID?: string | null;

/** Whether we should display the header as in narrow layout */
shouldUseNarrowLayout?: boolean;
};

function MoneyReportHeader({session, policy, chatReport, nextStep, report: moneyRequestReport, transactionThreadReport, reportActions}: MoneyReportHeaderProps) {
function MoneyReportHeader({
session,
policy,
chatReport,
nextStep,
report: moneyRequestReport,
transactionThreadReport,
reportActions,
shouldUseNarrowLayout = false,
}: MoneyReportHeaderProps) {
const styles = useThemeStyles();
const [isDeleteRequestModalVisible, setIsDeleteRequestModalVisible] = useState(false);
const {translate} = useLocalize();
const {windowWidth, isSmallScreenWidth} = useWindowDimensions();
const {windowWidth} = useWindowDimensions();
const {reimbursableSpend} = ReportUtils.getMoneyRequestSpendBreakdown(moneyRequestReport);
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const requestParentReportAction = useMemo(() => {
Expand Down Expand Up @@ -108,7 +120,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
const formattedAmount = CurrencyUtils.convertToDisplayString(reimbursableSpend, moneyRequestReport.currency);
const [nonHeldAmount, fullAmount] = ReportUtils.getNonHeldAndFullAmount(moneyRequestReport, policy);
const displayedAmount = ReportUtils.hasHeldExpenses(moneyRequestReport.reportID) && canAllowSettlement ? nonHeldAmount : formattedAmount;
const isMoreContentShown = shouldShowNextStep || (shouldShowAnyButton && isSmallScreenWidth);
const isMoreContentShown = shouldShowNextStep || (shouldShowAnyButton && shouldUseNarrowLayout);

const confirmPayment = (type?: PaymentMethodType | undefined) => {
if (!type) {
Expand Down Expand Up @@ -185,15 +197,15 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
shouldShowPinButton={false}
report={moneyRequestReport}
policy={policy}
shouldShowBackButton={isSmallScreenWidth}
shouldShowBackButton={shouldUseNarrowLayout}
onBackButtonPress={() => Navigation.goBack(undefined, false, true)}
// Shows border if no buttons or next steps are showing below the header
shouldShowBorderBottom={!(shouldShowAnyButton && isSmallScreenWidth) && !(shouldShowNextStep && !isSmallScreenWidth)}
shouldShowBorderBottom={!(shouldShowAnyButton && shouldUseNarrowLayout) && !(shouldShowNextStep && !shouldUseNarrowLayout)}
shouldShowThreeDotsButton
threeDotsMenuItems={threeDotsMenuItems}
threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(windowWidth)}
>
{shouldShowSettlementButton && !isSmallScreenWidth && (
{shouldShowSettlementButton && !shouldUseNarrowLayout && (
<View style={styles.pv2}>
<SettlementButton
currency={moneyRequestReport.currency}
Expand All @@ -213,7 +225,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
/>
</View>
)}
{shouldShowSubmitButton && !isSmallScreenWidth && (
{shouldShowSubmitButton && !shouldUseNarrowLayout && (
<View style={styles.pv2}>
<Button
medium
Expand All @@ -227,7 +239,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
)}
</HeaderWithBackButton>
<View style={isMoreContentShown ? [styles.dFlex, styles.flexColumn, styles.borderBottom] : []}>
{shouldShowSettlementButton && isSmallScreenWidth && (
{shouldShowSettlementButton && shouldUseNarrowLayout && (
<View style={[styles.ph5, styles.pb2]}>
<SettlementButton
currency={moneyRequestReport.currency}
Expand All @@ -246,7 +258,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
/>
</View>
)}
{shouldShowSubmitButton && isSmallScreenWidth && (
{shouldShowSubmitButton && shouldUseNarrowLayout && (
<View style={[styles.ph5, styles.pb2]}>
<Button
medium
Expand All @@ -269,7 +281,7 @@ function MoneyReportHeader({session, policy, chatReport, nextStep, report: money
nonHeldAmount={!ReportUtils.hasOnlyHeldExpenses(moneyRequestReport.reportID) ? nonHeldAmount : undefined}
requestType={requestType}
fullAmount={fullAmount}
isSmallScreenWidth={isSmallScreenWidth}
isSmallScreenWidth={shouldUseNarrowLayout}
onClose={() => setIsHoldMenuVisible(false)}
isVisible={isHoldMenuVisible}
paymentType={paymentType}
Expand Down
24 changes: 18 additions & 6 deletions src/components/MoneyRequestHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,21 @@ type MoneyRequestHeaderProps = MoneyRequestHeaderOnyxProps & {

/** The report action the transaction is tied to from the parent report */
parentReportAction: OnyxEntry<ReportAction>;

/** Whether we should display the header as in narrow layout */
shouldUseNarrowLayout?: boolean;
};

function MoneyRequestHeader({session, parentReport, report, parentReportAction, transaction, shownHoldUseExplanation = false, policy}: MoneyRequestHeaderProps) {
function MoneyRequestHeader({
session,
parentReport,
report,
parentReportAction,
transaction,
shownHoldUseExplanation = false,
policy,
shouldUseNarrowLayout = false,
}: MoneyRequestHeaderProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const [isDeleteModalVisible, setIsDeleteModalVisible] = useState(false);
Expand All @@ -61,7 +73,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
const isSettled = ReportUtils.isSettled(moneyRequestReport?.reportID);
const isApproved = ReportUtils.isReportApproved(moneyRequestReport);
const isOnHold = TransactionUtils.isOnHold(transaction);
const {isSmallScreenWidth, windowWidth} = useWindowDimensions();
const {windowWidth} = useWindowDimensions();

// Only the requestor can take delete the expense, admins can only edit it.
const isActionOwner = typeof parentReportAction?.actorAccountID === 'number' && typeof session?.accountID === 'number' && parentReportAction.actorAccountID === session?.accountID;
Expand Down Expand Up @@ -144,14 +156,14 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
return;
}

if (isSmallScreenWidth) {
if (shouldUseNarrowLayout) {
if (Navigation.getActiveRoute().slice(1) === ROUTES.PROCESS_MONEY_REQUEST_HOLD) {
Navigation.goBack();
}
} else {
Navigation.navigate(ROUTES.PROCESS_MONEY_REQUEST_HOLD);
}
}, [isSmallScreenWidth, shouldShowHoldMenu]);
}, [shouldUseNarrowLayout, shouldShowHoldMenu]);

const handleHoldRequestClose = () => {
IOU.setShownHoldUseExplanation();
Expand Down Expand Up @@ -180,7 +192,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
ownerAccountID: parentReport?.ownerAccountID,
}}
policy={policy}
shouldShowBackButton={isSmallScreenWidth}
shouldShowBackButton={shouldUseNarrowLayout}
onBackButtonPress={() => Navigation.goBack(undefined, false, true)}
/>
{isPending && (
Expand Down Expand Up @@ -209,7 +221,7 @@ function MoneyRequestHeader({session, parentReport, report, parentReportAction,
cancelText={translate('common.cancel')}
danger
/>
{isSmallScreenWidth && shouldShowHoldMenu && (
{shouldUseNarrowLayout && shouldShowHoldMenu && (
<ProcessMoneyRequestHoldMenu
onClose={handleHoldRequestClose}
onConfirm={handleHoldRequestClose}
Expand Down
9 changes: 9 additions & 0 deletions src/hooks/useIsReportOpenInRHP.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {useNavigationState} from '@react-navigation/native';
import getTopmostRouteName from '@libs/Navigation/getTopmostRouteName';
import SCREENS from '@src/SCREENS';

// This hook checks if the currently open route is ReportScreen in RHP.
export default function useIsReportOpenInRHP() {
const activeRoute = useNavigationState(getTopmostRouteName);
return activeRoute === SCREENS.SEARCH.REPORT_RHP;
}
5 changes: 4 additions & 1 deletion src/hooks/useThumbnailDimensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {useMemo} from 'react';
import type {StyleProp, ViewStyle} from 'react-native';
import type {DimensionValue} from 'react-native/Libraries/StyleSheet/StyleSheetTypes';
import CONST from '@src/CONST';
import useIsReportOpenInRHP from './useIsReportOpenInRHP';
import useWindowDimensions from './useWindowDimensions';

type ThumbnailDimensions = {
Expand All @@ -13,8 +14,10 @@ type ThumbnailDimensions = {
};

export default function useThumbnailDimensions(width: number, height: number): ThumbnailDimensions {
const isReportOpenInRHP = useIsReportOpenInRHP();
const {isSmallScreenWidth} = useWindowDimensions();
const fixedDimension = isSmallScreenWidth ? CONST.THUMBNAIL_IMAGE.SMALL_SCREEN.SIZE : CONST.THUMBNAIL_IMAGE.WIDE_SCREEN.SIZE;
const shouldUseNarrowLayout = isSmallScreenWidth || isReportOpenInRHP;
const fixedDimension = shouldUseNarrowLayout ? CONST.THUMBNAIL_IMAGE.SMALL_SCREEN.SIZE : CONST.THUMBNAIL_IMAGE.WIDE_SCREEN.SIZE;
const thumbnailDimensionsStyles = useMemo(() => {
if (!width || !height) {
return {width: fixedDimension, aspectRatio: CONST.THUMBNAIL_IMAGE.NAN_ASPECT_RATIO};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
ReportSettingsNavigatorParamList,
RoomInviteNavigatorParamList,
RoomMembersNavigatorParamList,
SearchReportParamList,
SettingsNavigatorParamList,
SignInNavigatorParamList,
SplitDetailsNavigatorParamList,
Expand Down Expand Up @@ -329,7 +330,6 @@ const PrivateNotesModalStackNavigator = createModalStackNavigator<PrivateNotesNa
const SignInModalStackNavigator = createModalStackNavigator<SignInNavigatorParamList>({
[SCREENS.SIGN_IN_ROOT]: () => require('../../../../pages/signin/SignInModal').default as React.ComponentType,
});

const ReferralModalStackNavigator = createModalStackNavigator<ReferralDetailsNavigatorParamList>({
[SCREENS.REFERRAL_DETAILS]: () => require('../../../../pages/ReferralDetailsPage').default as React.ComponentType,
});
Expand All @@ -338,6 +338,10 @@ const ProcessMoneyRequestHoldStackNavigator = createModalStackNavigator({
[SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: () => require('../../../../pages/ProcessMoneyRequestHoldPage').default as React.ComponentType,
});

const SearchReportModalStackNavigator = createModalStackNavigator<SearchReportParamList>({
[SCREENS.SEARCH.REPORT_RHP]: () => require('../../../../pages/home/ReportScreen').default as React.ComponentType,
});

export {
AddPersonalBankAccountModalStackNavigator,
DetailsModalStackNavigator,
Expand Down Expand Up @@ -367,4 +371,5 @@ export {
WalletStatementStackNavigator,
ProcessMoneyRequestHoldStackNavigator,
WorkspaceSettingsModalStackNavigator,
SearchReportModalStackNavigator,
};
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ function RightModalNavigator({navigation}: RightModalNavigatorProps) {
name="ProcessMoneyRequestHold"
component={ModalStackNavigators.ProcessMoneyRequestHoldStackNavigator}
/>
<Stack.Screen
name={SCREENS.RIGHT_MODAL.SEARCH_REPORT}
component={ModalStackNavigators.SearchReportModalStackNavigator}
/>
</Stack.Navigator>
</View>
</NoDropZone>
Expand Down
4 changes: 4 additions & 0 deletions src/libs/Navigation/Navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ROUTES, {HYBRID_APP_ROUTES} from '@src/ROUTES';
import {PROTECTED_SCREENS} from '@src/SCREENS';
import type {Report} from '@src/types/onyx';
import type {EmptyObject} from '@src/types/utils/EmptyObject';
import originalCloseRHPFlow from './closeRHPFlow';
import originalDismissModal from './dismissModal';
import originalDismissModalWithReport from './dismissModalWithReport';
import originalGetTopmostReportActionId from './getTopmostReportActionID';
Expand Down Expand Up @@ -60,6 +61,8 @@ const dismissModal = (reportID?: string, ref = navigationRef) => {
const report = getReport(reportID);
originalDismissModalWithReport({reportID, ...report}, ref);
};
// Re-exporting the closeRHPFlow here to fill in default value for navigationRef. The closeRHPFlow isn't defined in this file to avoid cyclic dependencies.
const closeRHPFlow = (ref = navigationRef) => originalCloseRHPFlow(ref);

// Re-exporting the dismissModalWithReport here to fill in default value for navigationRef. The dismissModalWithReport isn't defined in this file to avoid cyclic dependencies.
// This method is needed because it allows to dismiss the modal and then open the report. Within this method is checked whether the report belongs to a specific workspace. Sometimes the report we want to check, hasn't been added to the Onyx yet.
Expand Down Expand Up @@ -380,6 +383,7 @@ export default {
navigateWithSwitchPolicyID,
resetToHome,
isDisplayedInModal,
closeRHPFlow,
};

export {navigationRef};
30 changes: 30 additions & 0 deletions src/libs/Navigation/closeRHPFlow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import type {NavigationContainerRef} from '@react-navigation/native';
import {StackActions} from '@react-navigation/native';
import Log from '@libs/Log';
import NAVIGATORS from '@src/NAVIGATORS';
import type {RootStackParamList} from './types';

/**
* Closes the last RHP flow, if there is only one, closes the entire RHP.
*/
export default function closeRHPFlow(navigationRef: NavigationContainerRef<RootStackParamList>) {
if (!navigationRef.isReady()) {
return;
}
const state = navigationRef.getState();
const lastRoute = state.routes.at(-1);
const isLastRouteRHP = lastRoute?.name === NAVIGATORS.RIGHT_MODAL_NAVIGATOR;

if (!isLastRouteRHP) {
Log.warn('RHP Navigator has not been found when calling closeRHPFlow function');
return;
}

let target = state.key;

const hasMoreThanOneRoute = lastRoute?.state?.routes?.length && lastRoute.state.routes.length > 1;
if (lastRoute?.state?.key && hasMoreThanOneRoute) {
target = lastRoute.state.key;
}
navigationRef.dispatch({...StackActions.pop(), target});
}
12 changes: 12 additions & 0 deletions src/libs/Navigation/getTopmostRouteName.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type {NavigationState, PartialState} from '@react-navigation/native';

// Get the name of topmost route in the navigation stack.
function getTopmostRouteName(state: NavigationState | PartialState<NavigationState>): string | undefined {
if (!state) {
return;
}

return state.routes.at(-1)?.name;
}

export default getTopmostRouteName;
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const CENTRAL_PANE_TO_RHP_MAPPING: Partial<Record<CentralPaneName, string[]>> =
[SCREENS.SETTINGS.ABOUT]: [SCREENS.SETTINGS.APP_DOWNLOAD_LINKS],
[SCREENS.SETTINGS.SAVE_THE_WORLD]: [SCREENS.I_KNOW_A_TEACHER, SCREENS.INTRO_SCHOOL_PRINCIPAL, SCREENS.I_AM_A_TEACHER],
[SCREENS.SETTINGS.TROUBLESHOOT]: [SCREENS.SETTINGS.CONSOLE],
[SCREENS.SEARCH.CENTRAL_PANE]: [SCREENS.SEARCH.REPORT_RHP],
};

export default CENTRAL_PANE_TO_RHP_MAPPING;
5 changes: 5 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,11 @@ const config: LinkingOptions<RootStackParamList>['config'] = {
[SCREENS.PROCESS_MONEY_REQUEST_HOLD_ROOT]: ROUTES.PROCESS_MONEY_REQUEST_HOLD,
},
},
[SCREENS.RIGHT_MODAL.SEARCH_REPORT]: {
screens: {
[SCREENS.SEARCH.REPORT_RHP]: ROUTES.SEARCH_REPORT.route,
},
},
},
},

Expand Down
7 changes: 6 additions & 1 deletion src/libs/Navigation/linkingConfig/getAdaptedStateFromPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ function getMatchingRootRouteForRHPRoute(
// Check for CentralPaneNavigator
for (const [centralPaneName, RHPNames] of Object.entries(CENTRAL_PANE_TO_RHP_MAPPING)) {
if (RHPNames.includes(route.name)) {
return createCentralPaneNavigator({name: centralPaneName as CentralPaneName, params: route.params});
const params = {...route.params};
if (centralPaneName === SCREENS.SEARCH.CENTRAL_PANE) {
delete (params as Record<string, string | undefined>)?.reportID;
}
return createCentralPaneNavigator({name: centralPaneName as CentralPaneName, params});
}
}

Expand Down Expand Up @@ -195,6 +199,7 @@ function getAdaptedState(state: PartialState<NavigationState<RootStackParamList>
if (matchingRootRoute?.name === NAVIGATORS.FULL_SCREEN_NAVIGATOR) {
routes.push(createCentralPaneNavigator({name: SCREENS.SETTINGS.WORKSPACES}));
}

if (matchingRootRoute && (!isNarrowLayout || !isRHPScreenOpenedFromLHN)) {
routes.push(matchingRootRoute);
}
Expand Down
9 changes: 9 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,7 @@ type RightModalNavigatorParamList = {
[SCREENS.RIGHT_MODAL.PROCESS_MONEY_REQUEST_HOLD]: NavigatorScreenParams<ProcessMoneyRequestHoldNavigatorParamList>;
[SCREENS.RIGHT_MODAL.REFERRAL]: NavigatorScreenParams<ReferralDetailsNavigatorParamList>;
[SCREENS.RIGHT_MODAL.PRIVATE_NOTES]: NavigatorScreenParams<PrivateNotesNavigatorParamList>;
[SCREENS.RIGHT_MODAL.SEARCH_REPORT]: NavigatorScreenParams<SearchReportParamList>;
};

type WorkspacesCentralPaneNavigatorParamList = {
Expand Down Expand Up @@ -818,6 +819,13 @@ type AuthScreensParamList = SharedScreensParamList & {
};
};

type SearchReportParamList = {
[SCREENS.SEARCH.REPORT_RHP]: {
query: string;
reportID: string;
};
};

type RootStackParamList = PublicScreensParamList & AuthScreensParamList & ChatFinderNavigatorParamList;

type BottomTabName = keyof BottomTabNavigatorParamList;
Expand Down Expand Up @@ -882,4 +890,5 @@ export type {
WelcomeVideoModalNavigatorParamList,
WorkspaceSwitcherNavigatorParamList,
WorkspacesCentralPaneNavigatorParamList,
SearchReportParamList,
};
Loading

0 comments on commit 6060e6f

Please sign in to comment.