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 Report View / Headers #22484

Merged
merged 26 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
4 changes: 2 additions & 2 deletions src/components/HeaderWithBackButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ class HeaderWithBackButton extends Component {
subtitle={this.props.stepCounter && this.props.shouldShowStepCounter ? this.props.translate('stepCounter', this.props.stepCounter) : this.props.subtitle}
/>
)}
<View style={[styles.reportOptions, styles.flexRow, styles.pr5]}>
<View style={[styles.reportOptions, styles.flexRow, styles.pr5, styles.alignItemsCenter]}>
{this.props.children}
{this.props.shouldShowDownloadButton && (
<Tooltip text={this.props.translate('common.download')}>
<PressableWithoutFeedback
Expand All @@ -220,7 +221,6 @@ class HeaderWithBackButton extends Component {
</PressableWithoutFeedback>
</Tooltip>
)}

{this.props.shouldShowGetAssistanceButton && (
<Tooltip text={this.props.translate('getAssistancePage.questionMarkButtonTooltip')}>
<PressableWithoutFeedback
Expand Down
2 changes: 1 addition & 1 deletion src/components/MenuItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function MenuItem(props) {
const descriptionTextStyle = StyleUtils.combineStyles([
styles.textLabelSupporting,
props.icon && !_.isArray(props.icon) ? styles.ml3 : undefined,
styles.lineHeightNormal,
styles.lhNormal,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was overlooked.
There was no lineHeightNormal property in styles.
Making this valid caused minor regression - Test Assignee is cut of from the bottom

props.title ? descriptionVerticalMargin : StyleUtils.getFontSizeStyle(variables.fontSizeNormal),
props.descriptionTextStyle,
isDeleted ? styles.offlineFeedback.deleted : undefined,
Expand Down
141 changes: 141 additions & 0 deletions src/components/MoneyReportHeader.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import React from 'react';
import {withOnyx} from 'react-native-onyx';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import lodashGet from 'lodash/get';
import HeaderWithBackButton from './HeaderWithBackButton';
import iouReportPropTypes from '../pages/iouReportPropTypes';
import * as ReportUtils from '../libs/ReportUtils';
import * as Expensicons from './Icon/Expensicons';
import participantPropTypes from './participantPropTypes';
import styles from '../styles/styles';
import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions';
import compose from '../libs/compose';
import Navigation from '../libs/Navigation/Navigation';
import ROUTES from '../ROUTES';
import SettlementButton from './SettlementButton';
import * as Policy from '../libs/actions/Policy';
import ONYXKEYS from '../ONYXKEYS';
import * as IOU from '../libs/actions/IOU';
import * as CurrencyUtils from '../libs/CurrencyUtils';
import reportPropTypes from '../pages/reportPropTypes';
import useLocalize from '../hooks/useLocalize';

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

/** The policies which the user has access to and which the report could be tied to */
policies: PropTypes.shape({
/** Name of the policy */
name: PropTypes.string,
}).isRequired,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

policy is marked as required here but for some cases like deleted workspaces, it's value is undefined.

Issue: #26991


/** The chat report this report is linked to */
chatReport: reportPropTypes,

/** Personal details so we can get the ones for the report participants */
personalDetails: PropTypes.objectOf(participantPropTypes).isRequired,

/** Session info for the currently logged in user. */
session: PropTypes.shape({
/** Currently logged in user email */
email: PropTypes.string,
}),

...windowDimensionsPropTypes,
};

const defaultProps = {
chatReport: {},
session: {
email: null,
},
};

function MoneyReportHeader(props) {
const moneyRequestReport = props.report;
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 shouldShowSettlementButton = !isSettled && isPayer;
const bankAccountRoute = ReportUtils.getBankAccountRoute(props.chatReport);
const shouldShowPaypal = Boolean(lodashGet(props.personalDetails, [moneyRequestReport.managerID, 'payPalMeAddress']));
const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(props.report), props.report.currency);
const {translate} = useLocalize();

return (
<View style={[styles.pt0]}>
<HeaderWithBackButton
shouldShowAvatarWithDisplay
shouldShowPinButton={false}
shouldShowThreeDotsButton={false}
threeDotsMenuItems={[
{
icon: Expensicons.Trashcan,
text: translate('common.delete'),
onSelected: () => {},
},
]}
threeDotsAnchorPosition={styles.threeDotsPopoverOffsetNoCloseButton(props.windowWidth)}
report={props.report}
policies={props.policies}
personalDetails={props.personalDetails}
shouldShowBackButton
onBackButtonPress={() => Navigation.goBack(ROUTES.HOME, false, true)}
shouldShowBorderBottom={!shouldShowSettlementButton || !props.isSmallScreenWidth}
>
{shouldShowSettlementButton && !props.isSmallScreenWidth && (
<View style={[styles.pv2]}>
<SettlementButton
currency={props.report.currency}
policyID={props.report.policyID}
shouldShowPaypal={shouldShowPaypal}
chatReportID={props.chatReport.reportID}
iouReport={props.report}
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, props.chatReport, props.report)}
enablePaymentsRoute={ROUTES.BANK_ACCOUNT_NEW}
addBankAccountRoute={bankAccountRoute}
shouldShowPaymentOptions
style={[styles.pv2]}
formattedAmount={formattedAmount}
/>
</View>
)}
</HeaderWithBackButton>
{shouldShowSettlementButton && props.isSmallScreenWidth && (
<View style={[styles.ph5, styles.pb2, props.isSmallScreenWidth && styles.borderBottom]}>
<SettlementButton
currency={props.report.currency}
policyID={props.report.policyID}
shouldShowPaypal={shouldShowPaypal}
chatReportID={props.report.chatReportID}
iouReport={props.report}
onPress={(paymentType) => IOU.payMoneyRequest(paymentType, props.chatReport, props.report)}
enablePaymentsRoute={ROUTES.BANK_ACCOUNT_NEW}
addBankAccountRoute={bankAccountRoute}
Comment on lines +99 to +117
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We missed to pass addDebitCardRoute={ROUTES.IOU_SEND_ADD_DEBIT_CARD} which caused #38641

shouldShowPaymentOptions
formattedAmount={formattedAmount}
/>
</View>
)}
</View>
);
}

MoneyReportHeader.displayName = 'MoneyReportHeader';
MoneyReportHeader.propTypes = propTypes;
MoneyReportHeader.defaultProps = defaultProps;

export default compose(
withWindowDimensions,
withOnyx({
chatReport: {
key: ({report}) => `${ONYXKEYS.COLLECTION.REPORT}${report.chatReportID}`,
},
session: {
key: ONYXKEYS.SESSION,
},
}),
)(MoneyReportHeader);
76 changes: 76 additions & 0 deletions src/components/ReportActionItem/MoneyReportView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React from 'react';
import {View, Image} from 'react-native';
import PropTypes from 'prop-types';
import reportPropTypes from '../../pages/reportPropTypes';
import withWindowDimensions, {windowDimensionsPropTypes} from '../withWindowDimensions';
import styles from '../../styles/styles';
import * as ReportUtils from '../../libs/ReportUtils';
import * as StyleUtils from '../../styles/StyleUtils';
import CONST from '../../CONST';
import Text from '../Text';
import Icon from '../Icon';
import * as Expensicons from '../Icon/Expensicons';
import variables from '../../styles/variables';
import * as CurrencyUtils from '../../libs/CurrencyUtils';
import EmptyStateBackgroundImage from '../../../assets/images/empty-state_background-fade.png';
import useLocalize from '../../hooks/useLocalize';

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

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

...windowDimensionsPropTypes,
};

function MoneyReportView(props) {
const formattedAmount = CurrencyUtils.convertToDisplayString(ReportUtils.getMoneyRequestTotal(props.report), props.report.currency);
const isSettled = ReportUtils.isSettled(props.report.reportID);
const {translate} = useLocalize();

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>
<View style={[styles.flexRow, styles.menuItemTextContainer, styles.pointerEventsNone, styles.containerWithSpaceBetween, styles.ph5, styles.pv2]}>
<View style={[styles.flex1, styles.justifyContentCenter]}>
<Text
style={[styles.textLabelSupporting, styles.lhNormal, StyleUtils.getFontSizeStyle(variables.fontSizeNormal)]}
numberOfLines={1}
>
{translate('common.total')}
</Text>
</View>
<View style={[styles.flexRow, styles.justifyContentCenter]}>
{isSettled && (
<View style={[styles.defaultCheckmarkWrapper, styles.mh1]}>
<Icon
src={Expensicons.Checkmark}
fill={styles.success}
/>
</View>
)}
<Text
numberOfLines={1}
style={[styles.taskTitleMenuItem, styles.alignSelfCenter]}
>
{formattedAmount}
</Text>
</View>
</View>
{props.shouldShowHorizontalRule && <View style={styles.reportHorizontalRule} />}
</View>
);
}

MoneyReportView.propTypes = propTypes;
MoneyReportView.displayName = 'MoneyReportView';

export default withWindowDimensions(MoneyReportView);
2 changes: 1 addition & 1 deletion src/components/ReportActionItem/TaskView.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function TaskView(props) {
/>
)}

{props.shouldShowHorizontalRule && <View style={styles.taskHorizontalRule} />}
{props.shouldShowHorizontalRule && <View style={styles.reportHorizontalRule} />}
</View>
);
}
Expand Down
10 changes: 7 additions & 3 deletions src/components/SettlementButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const propTypes = {
/** Additional styles to add to the component */
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]),

/** Total money amount in form <currency><amount> */
formattedAmount: PropTypes.string,

...withLocalizePropTypes,
};

Expand All @@ -67,6 +70,7 @@ const defaultProps = {
style: [],
iouReport: {},
policyID: '',
formattedAmount: '',
};

class SettlementButton extends React.Component {
Expand All @@ -79,17 +83,17 @@ class SettlementButton extends React.Component {
const isExpenseReport = ReportUtils.isExpenseReport(this.props.iouReport);
const paymentMethods = {
[CONST.IOU.PAYMENT_TYPE.EXPENSIFY]: {
text: this.props.translate('iou.settleExpensify'),
text: this.props.translate('iou.settleExpensify', {formattedAmount: this.props.formattedAmount || ''}),
icon: Expensicons.Wallet,
value: CONST.IOU.PAYMENT_TYPE.EXPENSIFY,
},
[CONST.IOU.PAYMENT_TYPE.VBBA]: {
text: this.props.translate('iou.settleExpensify'),
text: this.props.translate('iou.settleExpensify', {formattedAmount: this.props.formattedAmount || ''}),
icon: Expensicons.Wallet,
value: CONST.IOU.PAYMENT_TYPE.VBBA,
},
[CONST.IOU.PAYMENT_TYPE.PAYPAL_ME]: {
text: this.props.translate('iou.settlePaypalMe'),
text: this.props.translate('iou.settlePaypalMe', {formattedAmount: this.props.formattedAmount || ''}),
icon: Expensicons.PayPal,
value: CONST.IOU.PAYMENT_TYPE.PAYPAL_ME,
},
Expand Down
5 changes: 3 additions & 2 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export default {
km: 'kilometer',
copied: 'Copied!',
someone: 'Someone',
total: 'Total',
edit: 'Edit',
},
anonymousReportFooter: {
Expand Down Expand Up @@ -353,9 +354,9 @@ export default {
settledExpensify: 'Paid',
settledElsewhere: 'Paid elsewhere',
settledPaypalMe: 'Paid using Paypal.me',
settleExpensify: 'Pay with Expensify',
settleExpensify: ({formattedAmount}) => `Pay ${formattedAmount} with Expensify`,
payElsewhere: 'Pay elsewhere',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, the formattedAmount was not added to payElsewhere which was fixed in #34620

settlePaypalMe: 'Pay with PayPal.me',
settlePaypalMe: ({formattedAmount}) => `Pay ${formattedAmount} with PayPal.me`,
requestAmount: ({amount}) => `request ${amount}`,
splitAmount: ({amount}) => `split ${amount}`,
amountEach: ({amount}) => `${amount} each`,
Expand Down
5 changes: 3 additions & 2 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export default {
km: 'kilómetro',
copied: '¡Copiado!',
someone: 'Alguien',
total: 'Total',
edit: 'Editar',
},
anonymousReportFooter: {
Expand Down Expand Up @@ -352,9 +353,9 @@ export default {
settledExpensify: 'Pagado',
settledElsewhere: 'Pagado de otra forma',
settledPaypalMe: 'Pagado con PayPal.me',
settleExpensify: 'Pagar con Expensify',
settleExpensify: ({formattedAmount}) => `Pagar ${formattedAmount} con Expensify`,
payElsewhere: 'Pagar de otra forma',
settlePaypalMe: 'Pagar con PayPal.me',
settlePaypalMe: ({formattedAmount}) => `Pagar ${formattedAmount} con PayPal.me`,
requestAmount: ({amount}) => `solicitar ${amount}`,
splitAmount: ({amount}) => `dividir ${amount}`,
amountEach: ({amount}) => `${amount} cada uno`,
Expand Down
Loading
Loading