Skip to content

Commit

Permalink
Merge pull request #22484 from Expensify/georgia-expenseReportView
Browse files Browse the repository at this point in the history
Update Expense Report View / Headers
  • Loading branch information
srikarparsi authored Jul 14, 2023
2 parents 2c36599 + e117a32 commit 0b00e1c
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 30 deletions.
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 @@ -95,7 +95,7 @@ function MenuItem(props) {
const descriptionTextStyle = StyleUtils.combineStyles([
styles.textLabelSupporting,
props.icon && !_.isArray(props.icon) ? styles.ml3 : undefined,
styles.lineHeightNormal,
styles.lhNormal,
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,

/** 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}
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',
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

0 comments on commit 0b00e1c

Please sign in to comment.