-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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 UI to show fraud states #29680
Changes from all commits
156a966
06a9d0d
5fec082
ce7204a
6045346
e9c5514
77c0194
2fcb4f6
01557b8
e3218aa
cac1753
3516f67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ import _ from 'underscore'; | |
import PropTypes from 'prop-types'; | ||
import {View} from 'react-native'; | ||
import styles from '../styles/styles'; | ||
import stylePropTypes from '../styles/stylePropTypes'; | ||
import Icon from './Icon'; | ||
import * as Expensicons from './Icon/Expensicons'; | ||
import themeColors from '../styles/themes/default'; | ||
|
@@ -25,11 +26,15 @@ const propTypes = { | |
// Additional styles to apply to the container */ | ||
// eslint-disable-next-line react/forbid-prop-types | ||
style: PropTypes.arrayOf(PropTypes.object), | ||
|
||
// Additional styles to apply to the text | ||
textStyles: stylePropTypes, | ||
}; | ||
|
||
const defaultProps = { | ||
messages: {}, | ||
style: [], | ||
textStyles: [], | ||
}; | ||
|
||
function DotIndicatorMessage(props) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related to this PR, but since we're adding changes to this component, let's use prop destructuring, it's documented as a best practice now // Bad
function UserInfo(props) {
return (
<View>
<Text>Name: {props.name}</Text>
<Text>Email: {props.email}</Text>
</View>
}
UserInfo.defaultProps = {
name: 'anonymous';
}
// Good
function UserInfo({ name = 'anonymous', email }) {
return (
<View>
<Text>Name: {name}</Text>
<Text>Email: {email}</Text>
</View>
);
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that we need to update this in the scope of the current task I believe that the best way is to apply it with typescript migration |
||
|
@@ -64,7 +69,7 @@ function DotIndicatorMessage(props) { | |
{_.map(sortedMessages, (message, i) => ( | ||
<Text | ||
key={i} | ||
style={styles.offlineFeedback.text} | ||
style={[styles.offlineFeedback.text, ...props.textStyles]} | ||
> | ||
{message} | ||
</Text> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import {View} from 'react-native'; | ||
import styles from '../../../styles/styles'; | ||
import * as Illustrations from '../../../components/Icon/Illustrations'; | ||
import Text from '../../../components/Text'; | ||
|
||
const propTypes = { | ||
title: PropTypes.string.isRequired, | ||
description: PropTypes.string.isRequired, | ||
}; | ||
|
||
function DangerCardSection({title, description}) { | ||
return ( | ||
<View style={[styles.pageWrapper, styles.walletDangerSection]}> | ||
<View style={[styles.flexRow, styles.alignItemsCenter, styles.w100]}> | ||
<View style={[styles.flexShrink1]}> | ||
<Text style={[styles.walletDangerSectionTitle, styles.mb1]}>{title}</Text> | ||
<Text styles={[styles.walletDangerSectionText]}>{description}</Text> | ||
</View> | ||
<View> | ||
<Illustrations.SmartScan /> | ||
</View> | ||
</View> | ||
</View> | ||
); | ||
} | ||
|
||
DangerCardSection.propTypes = propTypes; | ||
DangerCardSection.displayName = 'DangerCardSection'; | ||
|
||
export default DangerCardSection; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,10 @@ import CardDetails from './WalletPage/CardDetails'; | |
import MenuItem from '../../../components/MenuItem'; | ||
import CONST from '../../../CONST'; | ||
import assignedCardPropTypes from './assignedCardPropTypes'; | ||
import theme from '../../../styles/themes/default'; | ||
import DotIndicatorMessage from '../../../components/DotIndicatorMessage'; | ||
import * as Link from '../../../libs/actions/Link'; | ||
import DangerCardSection from './DangerCardSection'; | ||
|
||
const propTypes = { | ||
/* Onyx Props */ | ||
|
@@ -63,6 +67,9 @@ function ExpensifyCardPage({ | |
setShouldShowCardDetails(true); | ||
}; | ||
|
||
const hasDetectedDomainFraud = _.some(domainCards, (card) => card.fraud === CONST.EXPENSIFY_CARD.FRAUD_TYPES.DOMAIN); | ||
const hasDetectedIndividualFraud = _.some(domainCards, (card) => card.fraud === CONST.EXPENSIFY_CARD.FRAUD_TYPES.INDIVIDUAL); | ||
|
||
return ( | ||
<ScreenWrapper | ||
includeSafeAreaPaddingBottom={false} | ||
|
@@ -75,67 +82,98 @@ function ExpensifyCardPage({ | |
onBackButtonPress={() => Navigation.goBack(ROUTES.SETTINGS_WALLET)} | ||
/> | ||
<ScrollView contentContainerStyle={safeAreaPaddingBottomStyle}> | ||
<View style={[styles.flex1, styles.mb4, styles.mt4]}> | ||
<View style={[styles.flex1, styles.mb9, styles.mt9]}> | ||
<CardPreview /> | ||
</View> | ||
|
||
<MenuItemWithTopDescription | ||
description={translate('cardPage.availableSpend')} | ||
title={formattedAvailableSpendAmount} | ||
interactive={false} | ||
titleStyle={styles.newKansasLarge} | ||
/> | ||
{!_.isEmpty(virtualCard) && ( | ||
{hasDetectedDomainFraud ? ( | ||
<DotIndicatorMessage | ||
style={[styles.pageWrapper]} | ||
textStyle={[styles.walletLockedMessage]} | ||
messages={{0: translate('cardPage.cardLocked')}} | ||
type="error" | ||
/> | ||
) : null} | ||
|
||
{hasDetectedIndividualFraud && !hasDetectedDomainFraud ? ( | ||
<> | ||
{shouldShowCardDetails ? ( | ||
<CardDetails | ||
// This is just a temporary mock, it will be replaced in this issue https://github.com/orgs/Expensify/projects/58?pane=issue&itemId=33286617 | ||
pan="1234123412341234" | ||
expiration="11/02/2024" | ||
cvv="321" | ||
domain={domain} | ||
/> | ||
) : ( | ||
<MenuItemWithTopDescription | ||
description={translate('cardPage.virtualCardNumber')} | ||
title={CardUtils.maskCard(virtualCard.lastFourPAN)} | ||
interactive={false} | ||
titleStyle={styles.walletCardNumber} | ||
shouldShowRightComponent | ||
rightComponent={ | ||
<Button | ||
medium | ||
text={translate('cardPage.cardDetails.revealDetails')} | ||
onPress={handleRevealDetails} | ||
/> | ||
} | ||
/> | ||
)} | ||
<DangerCardSection | ||
title={translate('cardPage.suspiciousBannerTitle')} | ||
description={translate('cardPage.suspiciousBannerDescription')} | ||
/> | ||
<MenuItemWithTopDescription | ||
title={translate('cardPage.reportFraud')} | ||
title={translate('cardPage.reviewTransaction')} | ||
titleStyle={styles.walletCardMenuItem} | ||
icon={Expensicons.Flag} | ||
icon={Expensicons.MagnifyingGlass} | ||
iconFill={theme.icon} | ||
shouldShowRightIcon | ||
onPress={() => Navigation.navigate(ROUTES.SETTINGS_REPORT_FRAUD.getRoute(domain))} | ||
brickRoadIndicator="error" | ||
onPress={() => Link.openOldDotLink('inbox')} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should leave a note that this won't work in DEV and staging too, only in production (I wonder if buildOldDotURL is supposed to add environment to URL, since there is no dev/staging version of oldDot) Screen.Recording.2023-10-19.at.17.06.52.movThere was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@0xmiroslav Internal employees do have a DEV/staging Old Dot There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah you were tagging @eVoloshchak There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess I'll have to change the profile pic, this isn't the first time this happens 😅 |
||
/> | ||
</> | ||
)} | ||
{!_.isEmpty(physicalCard) && ( | ||
) : null} | ||
|
||
{!hasDetectedDomainFraud ? ( | ||
<> | ||
<MenuItemWithTopDescription | ||
description={translate('cardPage.physicalCardNumber')} | ||
title={CardUtils.maskCard(physicalCard.lastFourPAN)} | ||
description={translate('cardPage.availableSpend')} | ||
title={formattedAvailableSpendAmount} | ||
interactive={false} | ||
titleStyle={styles.walletCardMenuItem} | ||
/> | ||
<MenuItem | ||
title={translate('reportCardLostOrDamaged.report')} | ||
icon={Expensicons.Flag} | ||
shouldShowRightIcon | ||
onPress={() => Navigation.navigate(ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.getRoute(domain))} | ||
titleStyle={styles.newKansasLarge} | ||
/> | ||
{!_.isEmpty(virtualCard) && ( | ||
<> | ||
{shouldShowCardDetails ? ( | ||
<CardDetails | ||
// This is just a temporary mock, it will be replaced in this issue https://github.com/orgs/Expensify/projects/58?pane=issue&itemId=33286617 | ||
pan="1234123412341234" | ||
expiration="11/02/2024" | ||
cvv="321" | ||
domain={domain} | ||
/> | ||
) : ( | ||
<MenuItemWithTopDescription | ||
description={translate('cardPage.virtualCardNumber')} | ||
title={CardUtils.maskCard(virtualCard.lastFourPAN)} | ||
interactive={false} | ||
titleStyle={styles.walletCardNumber} | ||
shouldShowRightComponent | ||
rightComponent={ | ||
<Button | ||
medium | ||
text={translate('cardPage.cardDetails.revealDetails')} | ||
onPress={handleRevealDetails} | ||
/> | ||
} | ||
/> | ||
)} | ||
<MenuItemWithTopDescription | ||
title={translate('cardPage.reportFraud')} | ||
titleStyle={styles.walletCardMenuItem} | ||
icon={Expensicons.Flag} | ||
shouldShowRightIcon | ||
onPress={() => Navigation.navigate(ROUTES.SETTINGS_REPORT_FRAUD.getRoute(domain))} | ||
/> | ||
</> | ||
)} | ||
{!_.isEmpty(physicalCard) && ( | ||
<> | ||
<MenuItemWithTopDescription | ||
description={translate('cardPage.physicalCardNumber')} | ||
title={CardUtils.maskCard(physicalCard.lastFourPAN)} | ||
interactive={false} | ||
titleStyle={styles.walletCardMenuItem} | ||
/> | ||
<MenuItem | ||
title={translate('reportCardLostOrDamaged.report')} | ||
icon={Expensicons.Flag} | ||
shouldShowRightIcon | ||
onPress={() => Navigation.navigate(ROUTES.SETTINGS_WALLET_REPORT_CARD_LOST_OR_DAMAGED.getRoute(domain))} | ||
/> | ||
</> | ||
)} | ||
</> | ||
)} | ||
) : null} | ||
</ScrollView> | ||
{physicalCard.state === CONST.EXPENSIFY_CARD.STATE.NOT_ACTIVATED && ( | ||
<Button | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙌