Skip to content

Commit

Permalink
Merge pull request Expensify#11363 from Expensify/cmartins-addBanner
Browse files Browse the repository at this point in the history
Render banner in Concierge chat
  • Loading branch information
yuwenmemon authored Sep 29, 2022
2 parents 9198db3 + 07fa556 commit b299503
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 17 deletions.
3 changes: 3 additions & 0 deletions src/ONYXKEYS.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ export default {
// Holds information about the users account that is logging in
ACCOUNT: 'account',

// Holds the reportID for the report between the user and their account manager
ACCOUNT_MANAGER_REPORT_ID: 'accountManagerReportID',

// Boolean flag only true when first set
NVP_IS_FIRST_TIME_NEW_EXPENSIFY_USER: 'isFirstTimeNewExpensifyUser',

Expand Down
1 change: 1 addition & 0 deletions src/components/ArchivedReportFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ const ArchivedReportFooter = (props) => {
policyName: `<strong>${ReportUtils.getPolicyName(props.report, props.policies)}</strong>`,
})}
shouldRenderHTML={archiveReason !== CONST.REPORT.ARCHIVE_REASON.DEFAULT}
shouldShowIcon
/>
);
};
Expand Down
72 changes: 60 additions & 12 deletions src/components/Banner.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, {memo} from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import {View, Pressable} from 'react-native';
import compose from '../libs/compose';
import Hoverable from './Hoverable';
import Icon from './Icon';
import * as Expensicons from './Icon/Expensicons';
Expand All @@ -9,17 +10,45 @@ import Text from './Text';
import styles from '../styles/styles';
import * as StyleUtils from '../styles/StyleUtils';
import getButtonState from '../libs/getButtonState';
import Tooltip from './Tooltip';
import withLocalize, {withLocalizePropTypes} from './withLocalize';

const propTypes = {
/** Text to display in the banner. */
text: PropTypes.string.isRequired,

/** Should this component render the left-aligned exclamation icon? */
shouldShowIcon: PropTypes.bool,

/** Should this component render a close button? */
shouldShowCloseButton: PropTypes.bool,

/** Should this component render the text as HTML? */
shouldRenderHTML: PropTypes.bool,

/** Callback called when the close button is pressed */
onClose: PropTypes.func,

/** Callback called when the message is pressed */
onPress: PropTypes.func,

// eslint-disable-next-line react/forbid-prop-types
containerStyles: PropTypes.arrayOf(PropTypes.object),

// eslint-disable-next-line react/forbid-prop-types
textStyles: PropTypes.arrayOf(PropTypes.object),

...withLocalizePropTypes,
};

const defaultProps = {
shouldRenderHTML: false,
shouldShowIcon: false,
shouldShowCloseButton: false,
onClose: () => {},
onPress: () => {},
containerStyles: [],
textStyles: [],
};

const Banner = props => (
Expand All @@ -32,19 +61,35 @@ const Banner = props => (
styles.borderRadiusNormal,
isHovered ? styles.activeComponentBG : styles.hoveredComponentBG,
styles.breakAll,
...props.containerStyles,
]}
>
<View style={[styles.mr3]}>
<Icon
src={Expensicons.Exclamation}
fill={StyleUtils.getIconFillColor(getButtonState(isHovered))}
/>
<View style={[styles.flexRow, styles.flexGrow1, styles.mw100, styles.alignItemsCenter]}>
{props.shouldShowIcon && (
<View style={[styles.mr3]}>
<Icon
src={Expensicons.Exclamation}
fill={StyleUtils.getIconFillColor(getButtonState(isHovered))}
/>
</View>
)}
{
props.shouldRenderHTML
? <RenderHTML html={props.text} />
: <Text style={[...props.textStyles]} onPress={props.onPress}>{props.text}</Text>
}
</View>
{
props.shouldRenderHTML
? <RenderHTML html={props.text} />
: <Text>{props.text}</Text>
}
{props.shouldShowCloseButton && (
<Tooltip text={props.translate('common.close')}>
<Pressable
onPress={props.onClose}
accessibilityRole="button"
accessibilityLabel={props.translate('common.close')}
>
<Icon src={Expensicons.Close} />
</Pressable>
</Tooltip>
)}
</View>
)}
</Hoverable>
Expand All @@ -54,4 +99,7 @@ Banner.propTypes = propTypes;
Banner.defaultProps = defaultProps;
Banner.displayName = 'Banner';

export default memo(Banner);
export default compose(
withLocalize,
memo,
)(Banner);
1 change: 1 addition & 0 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export default {
beginningOfChatHistoryPolicyExpenseChatPartOne: 'Collaboration between ',
beginningOfChatHistoryPolicyExpenseChatPartTwo: ' and ',
beginningOfChatHistoryPolicyExpenseChatPartThree: ' starts here! 🎉 This is the place to chat, request money and settle up.',
chatWithAccountManager: 'Chat with your account manager here',
},
newMessages: 'New messages',
reportTypingIndicator: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ export default {
beginningOfChatHistoryPolicyExpenseChatPartOne: '¡La colaboración entre ',
beginningOfChatHistoryPolicyExpenseChatPartTwo: ' y ',
beginningOfChatHistoryPolicyExpenseChatPartThree: ' empieza aquí! :tada: Este es el lugar donde chatear, pedir dinero y pagar.',
chatWithAccountManager: 'Chatea con tu gestor de cuenta aquí',
},
newMessages: 'Mensajes nuevos',
reportTypingIndicator: {
Expand Down
17 changes: 12 additions & 5 deletions src/libs/Navigation/DeprecatedCustomActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,16 +102,23 @@ function pushDrawerRoute(route) {
const screenRoute = {type: 'route', name: newScreenName};
const history = _.map(state.history ? [...state.history] : [screenRoute], () => screenRoute);

// Force drawer to close
// https://github.com/react-navigation/react-navigation/blob/94ab791cae5061455f036cd3f6bc7fa63167e7c7/packages/routers/src/DrawerRouter.tsx#L142
const hasDrawerhistory = _.find(state.history || [], h => h.type === 'drawer');
if (!hasDrawerhistory || currentState.type !== 'drawer') {
const drawerHistoryItem = _.find(state.history || [], h => h.type === 'drawer');
const isDrawerClosed = drawerHistoryItem && drawerHistoryItem.status === 'closed';
if (!drawerHistoryItem || currentState.type !== 'drawer') {
// Add the drawer item to the navigation history to control if the drawer should be in open or closed state
history.push({
type: 'drawer',

// If current state is not from drawer navigator then always use closed status to close the drawer
// If current state is not from drawer navigator then always force the drawer to close by using closed status
// https://github.com/react-navigation/react-navigation/blob/94ab791cae5061455f036cd3f6bc7fa63167e7c7/packages/routers/src/DrawerRouter.tsx#L142
status: currentState.type !== 'drawer' || currentState.default === 'open' ? 'closed' : 'open',
});
} else if (isDrawerClosed) {
// Keep the drawer closed if it's already closed
history.push({
type: 'drawer',
status: 'closed',
});
}

return CommonActions.reset({
Expand Down
27 changes: 27 additions & 0 deletions src/pages/home/ReportScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import withWindowDimensions, {windowDimensionsPropTypes} from '../../components/
import OfflineIndicator from '../../components/OfflineIndicator';
import OfflineWithFeedback from '../../components/OfflineWithFeedback';
import withDrawerState, {withDrawerPropTypes} from '../../components/withDrawerState';
import Banner from '../../components/Banner';
import withLocalize from '../../components/withLocalize';
import reportPropTypes from '../reportPropTypes';

const propTypes = {
Expand Down Expand Up @@ -112,11 +114,14 @@ class ReportScreen extends React.Component {

this.onSubmitComment = this.onSubmitComment.bind(this);
this.updateViewportOffsetTop = this.updateViewportOffsetTop.bind(this);
this.chatWithAccountManager = this.chatWithAccountManager.bind(this);
this.dismissBanner = this.dismissBanner.bind(this);
this.removeViewportResizeListener = () => {};

this.state = {
skeletonViewContainerHeight: 0,
viewportOffsetTop: 0,
isBannerVisible: true,
};
}

Expand Down Expand Up @@ -191,6 +196,14 @@ class ReportScreen extends React.Component {
this.setState({viewportOffsetTop});
}

dismissBanner() {
this.setState({isBannerVisible: false});
}

chatWithAccountManager() {
Navigation.navigate(ROUTES.getReportRoute(this.props.accountManagerReportID));
}

render() {
if (!this.props.isSidebarLoaded) {
return null;
Expand Down Expand Up @@ -236,6 +249,16 @@ class ReportScreen extends React.Component {
onNavigationMenuButtonClicked={() => Navigation.navigate(ROUTES.HOME)}
/>
</OfflineWithFeedback>
{this.props.accountManagerReportID && ReportUtils.isConciergeChatReport(this.props.report) && this.state.isBannerVisible && (
<Banner
containerStyles={[styles.mh4, styles.mt4, styles.p4, styles.bgDark]}
textStyles={[styles.colorReversed]}
text={this.props.translate('reportActionsView.chatWithAccountManager')}
onClose={this.dismissBanner}
onPress={this.chatWithAccountManager}
shouldShowCloseButton
/>
)}
<View
nativeID={CONST.REPORT.DROP_NATIVE_ID}
style={[styles.flex1, styles.justifyContentEnd, styles.overflowHidden]}
Expand Down Expand Up @@ -300,6 +323,7 @@ ReportScreen.propTypes = propTypes;
ReportScreen.defaultProps = defaultProps;

export default compose(
withLocalize,
withWindowDimensions,
withDrawerState,
withNetwork(),
Expand All @@ -326,5 +350,8 @@ export default compose(
policies: {
key: ONYXKEYS.COLLECTION.POLICY,
},
accountManagerReportID: {
key: ONYXKEYS.ACCOUNT_MANAGER_REPORT_ID,
},
}),
)(ReportScreen);
4 changes: 4 additions & 0 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ const styles = {
backgroundColor: 'transparent',
},

bgDark: {
backgroundColor: colors.dark,
},

opacity0: {
opacity: 0,
},
Expand Down

0 comments on commit b299503

Please sign in to comment.