Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Expense Request Headers / Empty State #22562

Merged
merged 14 commits into from
Jul 19, 2023
3 changes: 3 additions & 0 deletions src/CONST.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,9 @@ const CONST = {
CONTAINER_MINHEIGHT: 500,
VIEW_HEIGHT: 275,
},
MONEY_REPORT: {
MIN_HEIGHT: 280,
},
},

RIGHT_MODAL_BACKGROUND_OVERLAY_OPACITY: 0.4,
Expand Down
19 changes: 7 additions & 12 deletions src/components/MoneyRequestHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,6 @@ const propTypes = {
/** Personal details so we can get the ones for the report participants */
personalDetails: PropTypes.objectOf(participantPropTypes).isRequired,

/** Whether we're viewing a report with a single transaction in it */
isSingleTransactionView: PropTypes.bool,

/** Session info for the currently logged in user. */
session: PropTypes.shape({
/** Currently logged in user email */
Expand All @@ -46,30 +43,27 @@ const propTypes = {
};

const defaultProps = {
isSingleTransactionView: false,
session: {
email: null,
},
parentReport: {},
};

function MoneyRequestHeader(props) {
const moneyRequestReport = props.isSingleTransactionView ? props.parentReport : props.report;
const moneyRequestReport = props.parentReport;
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);
const policy = props.policies[`${ONYXKEYS.COLLECTION.POLICY}${props.report.policyID}`];
const isPayer =
Policy.isAdminOfFreePolicy([policy]) || (ReportUtils.isMoneyRequestReport(moneyRequestReport) && lodashGet(props.session, 'accountID', null) === moneyRequestReport.managerID);
const report = props.report;
if (props.isSingleTransactionView) {
report.ownerAccountID = lodashGet(props, ['parentReport', 'ownerAccountID'], null);
report.ownerEmail = lodashGet(props, ['parentReport', 'ownerEmail'], '');
}
report.ownerAccountID = lodashGet(props, ['parentReport', 'ownerAccountID'], null);
report.ownerEmail = lodashGet(props, ['parentReport', 'ownerEmail'], '');
return (
<View style={[styles.highlightBG, styles.pl0]}>
<View style={[styles.pl0]}>
<HeaderWithBackButton
shouldShowAvatarWithDisplay
shouldShowPinButton={props.isSingleTransactionView}
shouldShowThreeDotsButton={!isPayer && !isSettled && props.isSingleTransactionView}
shouldShowPinButton={false}
shouldShowThreeDotsButton={!isPayer && !isSettled}
threeDotsMenuItems={[
{
icon: Expensicons.Trashcan,
Expand All @@ -84,6 +78,7 @@ function MoneyRequestHeader(props) {
personalDetails={props.personalDetails}
shouldShowBackButton={props.isSmallScreenWidth}
onBackButtonPress={() => Navigation.goBack(ROUTES.HOME, false, true)}
shouldShowBorderBottom
/>
</View>
);
Expand Down
104 changes: 104 additions & 0 deletions src/components/ReportActionItem/MoneyRequestView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react';
import {View, Image} from 'react-native';
import {withOnyx} from 'react-native-onyx';
import lodashGet from 'lodash/get';
import PropTypes from 'prop-types';
import reportPropTypes from '../../pages/reportPropTypes';
import ONYXKEYS from '../../ONYXKEYS';
import withLocalize, {withLocalizePropTypes} from '../withLocalize';
import withWindowDimensions from '../withWindowDimensions';
import withCurrentUserPersonalDetails, {withCurrentUserPersonalDetailsPropTypes} from '../withCurrentUserPersonalDetails';
import compose from '../../libs/compose';
import MenuItemWithTopDescription from '../MenuItemWithTopDescription';
import styles from '../../styles/styles';
import * as ReportUtils from '../../libs/ReportUtils';
import * as ReportActionsUtils from '../../libs/ReportActionsUtils';
import * as StyleUtils from '../../styles/StyleUtils';
import CONST from '../../CONST';
import * as Expensicons from '../Icon/Expensicons';
import iouReportPropTypes from '../../pages/iouReportPropTypes';
import DateUtils from '../../libs/DateUtils';
import * as CurrencyUtils from '../../libs/CurrencyUtils';
import EmptyStateBackgroundImage from '../../../assets/images/empty-state_background-fade.png';

const propTypes = {
/** The report currently being looked at */
report: reportPropTypes.isRequired,

/** The expense report or iou report (only will have a value if this is a transaction thread) */
parentReport: iouReportPropTypes,

/** Whether we should display the horizontal rule below the component */
shouldShowHorizontalRule: PropTypes.bool.isRequired,

...withLocalizePropTypes,
grgia marked this conversation as resolved.
Show resolved Hide resolved

...withCurrentUserPersonalDetailsPropTypes,
};

const defaultProps = {
parentReport: {},
};

function MoneyRequestView(props) {
const parentReportAction = ReportActionsUtils.getParentReportAction(props.report);
const {amount: transactionAmount, currency: transactionCurrency, comment: transactionDescription} = ReportUtils.getMoneyRequestAction(parentReportAction);
const formattedTransactionAmount = transactionAmount && transactionCurrency && CurrencyUtils.convertToDisplayString(transactionAmount, transactionCurrency);
const transactionDate = lodashGet(parentReportAction, ['created']);
const formattedTransactionDate = DateUtils.getDateStringFromISOTimestamp(transactionDate);

const moneyRequestReport = props.parentReport;
const isSettled = ReportUtils.isSettled(moneyRequestReport.reportID);

return (
<View>
<View style={[StyleUtils.getReportWelcomeContainerStyle(props.isSmallScreenWidth), StyleUtils.getMinimumHeight(CONST.EMPTY_STATE_BACKGROUND.MONEY_REPORT.MIN_HEIGHT)]}>
<Image
pointerEvents="none"
source={EmptyStateBackgroundImage}
style={[StyleUtils.getReportWelcomeBackgroundImageStyle(true)]}
/>
</View>
<MenuItemWithTopDescription
title={formattedTransactionAmount}
shouldShowTitleIcon={isSettled}
titleIcon={Expensicons.Checkmark}
description={`${props.translate('iou.amount')} • ${props.translate('iou.cash')}${isSettled ? ` • ${props.translate('iou.settledExpensify')}` : ''}`}
titleStyle={styles.newKansasLarge}
disabled={isSettled}
// Note: These options are temporarily disabled while we figure out the required API changes
// shouldShowRightIcon={!isSettled}
// onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.AMOUNT))}
/>
<MenuItemWithTopDescription
description={props.translate('common.description')}
title={transactionDescription}
disabled={isSettled}
// shouldShowRightIcon={!isSettled}
// onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DESCRIPTION))}
/>
<MenuItemWithTopDescription
description={props.translate('common.date')}
title={formattedTransactionDate}
// shouldShowRightIcon={!isSettled}
// onPress={() => Navigation.navigate(ROUTES.getEditRequestRoute(props.report.reportID, CONST.EDIT_REQUEST_FIELD.DATE))}
/>
{props.shouldShowHorizontalRule && <View style={styles.taskHorizontalRule} />}
</View>
);
}

MoneyRequestView.propTypes = propTypes;
MoneyRequestView.defaultProps = defaultProps;
MoneyRequestView.displayName = 'MoneyRequestView';

export default compose(
withWindowDimensions,
withLocalize,
withCurrentUserPersonalDetails,
withOnyx({
parentReport: {
key: (props) => `${ONYXKEYS.COLLECTION.REPORT}${props.report.parentReportID}`,
},
}),
)(MoneyRequestView);
39 changes: 22 additions & 17 deletions src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,27 @@ class ReportScreen extends React.Component {

const policy = this.props.policies[`${ONYXKEYS.COLLECTION.POLICY}${this.props.report.policyID}`];

let headerView = (
<HeaderView
reportID={reportID}
onNavigationMenuButtonClicked={() => Navigation.goBack(ROUTES.HOME, false, true)}
personalDetails={this.props.personalDetails}
report={this.props.report}
/>
);

if (isSingleTransactionView) {
headerView = (
<MoneyRequestHeader
report={this.props.report}
policies={this.props.policies}
personalDetails={this.props.personalDetails}
isSingleTransactionView={isSingleTransactionView}
parentReportAction={parentReportAction}
/>
);
}

return (
<ReportScreenContext.Provider
value={{
Expand All @@ -275,23 +296,7 @@ class ReportScreen extends React.Component {
errors={addWorkspaceRoomOrChatErrors}
shouldShowErrorMessages={false}
>
{ReportUtils.isMoneyRequestReport(this.props.report) || isSingleTransactionView ? (
<MoneyRequestHeader
report={this.props.report}
policies={this.props.policies}
personalDetails={this.props.personalDetails}
isSingleTransactionView={isSingleTransactionView}
parentReportAction={parentReportAction}
/>
) : (
<HeaderView
reportID={reportID}
onNavigationMenuButtonClicked={() => Navigation.goBack(ROUTES.HOME, false, true)}
personalDetails={this.props.personalDetails}
report={this.props.report}
/>
)}

{headerView}
{ReportUtils.isTaskReport(this.props.report) && this.props.isSmallScreenWidth && ReportUtils.isOpenTaskReport(this.props.report) && (
<View style={[styles.borderBottom]}>
<View style={[styles.appBG, styles.pl0]}>
Expand Down
12 changes: 11 additions & 1 deletion src/pages/home/report/ReportActionItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ import SelectionScraper from '../../../libs/SelectionScraper';
import focusTextInputAfterAnimation from '../../../libs/focusTextInputAfterAnimation';
import * as User from '../../../libs/actions/User';
import * as ReportUtils from '../../../libs/ReportUtils';
import * as ReportActionsUtils from '../../../libs/ReportActionsUtils';
import OfflineWithFeedback from '../../../components/OfflineWithFeedback';
import * as ReportActions from '../../../libs/actions/ReportActions';
import * as ReportActionsUtils from '../../../libs/ReportActionsUtils';
import reportPropTypes from '../../reportPropTypes';
import {ShowContextMenuContext} from '../../../components/ShowContextMenuContext';
import ChronosOOOListActions from '../../../components/ReportActionItem/ChronosOOOListActions';
Expand All @@ -56,6 +56,7 @@ import TaskPreview from '../../../components/ReportActionItem/TaskPreview';
import TaskAction from '../../../components/ReportActionItem/TaskAction';
import TaskView from '../../../components/ReportActionItem/TaskView';
import * as Session from '../../../libs/actions/Session';
import MoneyRequestView from '../../../components/ReportActionItem/MoneyRequestView';
import {hideContextMenu} from './ContextMenu/ReportActionContextMenu';

const propTypes = {
Expand Down Expand Up @@ -414,6 +415,15 @@ function ReportActionItem(props) {
};

if (props.action.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED) {
const parentReport = ReportActionsUtils.getParentReportAction(props.report);
if (ReportActionsUtils.isTransactionThread(parentReport)) {
return (
<MoneyRequestView
report={props.report}
shouldShowHorizontalRule={!props.isOnlyReportAction}
/>
);
}
if (ReportUtils.isTaskReport(props.report)) {
return (
<TaskView
Expand Down
23 changes: 5 additions & 18 deletions src/pages/home/report/ReportActionsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import reportPropTypes from '../../reportPropTypes';
import networkPropTypes from '../../../components/networkPropTypes';
import withLocalize from '../../../components/withLocalize';
import useReportScrollManager from '../../../hooks/useReportScrollManager';
import MoneyRequestDetails from '../../../components/MoneyRequestDetails';

const propTypes = {
/** Position of the "New" line marker */
Expand Down Expand Up @@ -126,7 +125,10 @@ function ReportActionsList(props) {
({item: reportAction, index}) => {
// When the new indicator should not be displayed we explicitly set it to null
const shouldDisplayNewMarker = reportAction.reportActionID === newMarkerReportActionID;
const shouldDisplayParentAction = reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED && ReportUtils.isChatThread(report);
const shouldDisplayParentAction =
reportAction.actionName === CONST.REPORT.ACTIONS.TYPE.CREATED &&
ReportUtils.isChatThread(report) &&
!ReportActionsUtils.isTransactionThread(ReportActionsUtils.getParentReportAction(report));
const shouldHideThreadDividerLine =
shouldDisplayParentAction && sortedReportActions.length > 1 && sortedReportActions[sortedReportActions.length - 2].reportActionID === newMarkerReportActionID;
return shouldDisplayParentAction ? (
Expand Down Expand Up @@ -161,23 +163,19 @@ function ReportActionsList(props) {
const extraData = [props.isSmallScreenWidth ? props.newMarkerReportActionID : undefined, ReportUtils.isArchivedRoom(props.report)];
const shouldShowReportRecipientLocalTime = ReportUtils.canShowReportRecipientLocalTime(props.personalDetailsList, props.report, props.currentUserPersonalDetails.accountID);

const parentReportAction = ReportActionsUtils.getParentReportAction(props.report);
const isSingleTransactionView = ReportActionsUtils.isTransactionThread(parentReportAction);
const showMoneyRequestDetails = ReportUtils.isMoneyRequestReport(props.report) || isSingleTransactionView;
return (
<Animated.View style={[animatedStyles, styles.flex1]}>
<InvertedFlatList
accessibilityLabel={props.translate('sidebarScreen.listOfChatMessages')}
ref={reportScrollManager.ref}
data={props.sortedReportActions}
renderItem={renderItem}
contentContainerStyle={[styles.chatContentScrollView, shouldShowReportRecipientLocalTime && styles.pt0, showMoneyRequestDetails && styles.pb0]}
contentContainerStyle={[styles.chatContentScrollView, shouldShowReportRecipientLocalTime]}
keyExtractor={keyExtractor}
initialRowHeight={32}
initialNumToRender={calculateInitialNumToRender()}
onEndReached={props.loadMoreChats}
onEndReachedThreshold={0.75}
ListFooterComponentStyle={showMoneyRequestDetails ? styles.chatFooterAtTheTop : {}}
ListFooterComponent={() => {
if (props.report.isLoadingMoreReportActions) {
return <ReportActionsSkeletonView containerHeight={CONST.CHAT_SKELETON_VIEW.AVERAGE_ROW_HEIGHT * 3} />;
Expand All @@ -195,17 +193,6 @@ function ReportActionsList(props) {
/>
);
}
if (showMoneyRequestDetails) {
return (
<MoneyRequestDetails
report={props.report}
policy={props.policy}
personalDetails={props.personalDetailsList}
isSingleTransactionView={isSingleTransactionView}
parentReportAction={parentReportAction}
/>
);
}
return null;
}}
keyboardShouldPersistTaps="handled"
Expand Down
Loading