Skip to content

Commit 83fd154

Browse files
committed
feat(Wallet): add empty state and redesign wallet page
# Conflicts: # src/components/LottieAnimations.js # src/pages/settings/Wallet/WalletPage/BaseWalletPage.js fix(wallet): item styles not matching designs fix(wallet): PropTypes console errors fix(wallet): popover menu positioning issues fix(wallet): flags used to determine if the empty state should be shown refactor(wallet): code style # Conflicts: # src/pages/settings/Wallet/PaymentMethodList.js fix(wallet): accessing wrong onyx key to look for assigned cards fix(wallet): spanish translations refactor(wallet): apply code style guidelines refactor(wallet): differentiate old wallet from new version using URL # Conflicts: # src/ROUTES.ts # src/libs/Navigation/AppNavigator/ModalStackNavigators.js # src/libs/Navigation/linkingConfig.js add padding top prop to IlustratedHeaderPageLayout # Conflicts: # src/components/IllustratedHeaderPageLayout.js remove header top padding replace hardcoded values with references to SCREENS # Conflicts: # src/SCREENS.ts add scroll to WalletPage, disable scroll in PaymentMethodList lint code # Conflicts: # src/pages/settings/Wallet/PaymentMethodList.js chore: reduce FastMoney animation filesize chore: add wallet backgriound color to light theme refactor: wallet route refactor: remove unused prop refactor(wallet): remove unnecessary wrapper component fix(wallet): linter issue refactor(wallet): remove underscore dependency chore(wallet): use old wallet instead of new one # Conflicts: # src/libs/Navigation/AppNavigator/ModalStackNavigators.js chore: apply prettier # Conflicts: # src/SCREENS.ts chore(wallet): remove card item left padding fix(section): missing subtitle refactor(wallet): use constant screen name for wallet domain cards # Conflicts: # src/libs/Navigation/linkingConfig.js refactor(wallet): use constant screen name for wallet fix(wallet): screen wrapper adding unnecessary vertical padding # Conflicts: # src/pages/settings/Wallet/WalletPage/WalletPage.js fix(wallet): wrong display name type fix(wallet): missing testID for screen wrapper and unnecessary fragment fix(wallet): unused import fix(wallet): status bar background color fix(wallet): revert scrollview removal fix(wallet): wrong section border radius fix(wallet): wrong payment item height fix(wallet): console error with nested Flatlist inside a ScrollView # Conflicts: # src/pages/settings/Wallet/PaymentMethodList.js fix(wallet): section card item styles refactor(wallet): replace direct import from colors with themeColors fix(wallet): popover menu positioning fix(wallet): transfer balance button styles refactor(wallet): remove paypal references fix(wallet): adjust spacings inside wallet section fix(wallet): bank accounts section spacing chore(wallet): fix linter issues refactor: remove unused paypal route # Conflicts: # src/ROUTES.ts chore(wallet): remove old wallet page # Conflicts: # src/pages/settings/Wallet/WalletPage/BaseWalletPage.js chore: rebase with main branch fix(wallet): wrong lineHeight type
1 parent 9699988 commit 83fd154

22 files changed

+539
-227
lines changed

assets/animations/FastMoney.json

+1
Large diffs are not rendered by default.
Loading

src/SCREENS.ts

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export default {
1717
WORKSPACES: 'Settings_Workspaces',
1818
SECURITY: 'Settings_Security',
1919
STATUS: 'Settings_Status',
20+
WALLET: 'Settings_Wallet',
21+
WALLET_DOMAIN_CARDS: 'Settings_Wallet_DomainCards',
2022
},
2123
SAVE_THE_WORLD: {
2224
ROOT: 'SaveTheWorld_Root',

src/components/Icon/Illustrations.js

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import MoneyBadge from '../../../assets/images/simple-illustrations/simple-illus
4545
import TreasureChest from '../../../assets/images/simple-illustrations/simple-illustration__treasurechest.svg';
4646
import ThumbsUpStars from '../../../assets/images/simple-illustrations/simple-illustration__thumbsupstars.svg';
4747
import Hands from '../../../assets/images/product-illustrations/home-illustration-hands.svg';
48+
import HandEarth from '../../../assets/images/simple-illustrations/simple-illustration__handearth.svg';
4849

4950
export {
5051
Abracadabra,
@@ -94,4 +95,5 @@ export {
9495
TreasureChest,
9596
ThumbsUpStars,
9697
Hands,
98+
HandEarth,
9799
};

src/components/IllustratedHeaderPageLayout.js

+50-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
1+
import _ from 'underscore';
12
import React from 'react';
23
import PropTypes from 'prop-types';
3-
import Lottie from './Lottie';
4+
import {ScrollView, View} from 'react-native';
5+
import Lottie from 'lottie-react-native';
46
import headerWithBackButtonPropTypes from './HeaderWithBackButton/headerWithBackButtonPropTypes';
7+
import HeaderWithBackButton from './HeaderWithBackButton';
8+
import ScreenWrapper from './ScreenWrapper';
59
import styles from '../styles/styles';
610
import themeColors from '../styles/themes/default';
7-
import HeaderPageLayout from './HeaderPageLayout';
11+
import * as StyleUtils from '../styles/StyleUtils';
12+
import useWindowDimensions from '../hooks/useWindowDimensions';
13+
import FixedFooter from './FixedFooter';
14+
import useNetwork from '../hooks/useNetwork';
815

916
const propTypes = {
1017
...headerWithBackButtonPropTypes,
@@ -23,37 +30,59 @@ const propTypes = {
2330

2431
/** Overlay content to display on top of animation */
2532
overlayContent: PropTypes.func,
33+
34+
/** Whether to include padding top */
35+
includePaddingTop: PropTypes.bool,
2636
};
2737

2838
const defaultProps = {
2939
backgroundColor: themeColors.appBG,
3040
footer: null,
3141
overlayContent: null,
42+
includePaddingTop: true,
3243
};
3344

34-
function IllustratedHeaderPageLayout({backgroundColor, children, illustration, footer, overlayContent, ...propsToPassToHeader}) {
45+
function IllustratedHeaderPageLayout({backgroundColor, children, illustration, footer, overlayContent, includePaddingTop, ...propsToPassToHeader}) {
46+
const {windowHeight} = useWindowDimensions();
47+
const {isOffline} = useNetwork();
3548
return (
36-
<HeaderPageLayout
37-
backgroundColor={backgroundColor}
38-
title={propsToPassToHeader.title}
39-
headerContent={
49+
<ScreenWrapper
50+
style={[StyleUtils.getBackgroundColorStyle(backgroundColor)]}
51+
shouldEnablePickerAvoiding={false}
52+
includeSafeAreaPaddingBottom={false}
53+
includePaddingTop={includePaddingTop}
54+
offlineIndicatorStyle={[StyleUtils.getBackgroundColorStyle(themeColors.appBG)]}
55+
>
56+
{({safeAreaPaddingBottomStyle}) => (
4057
<>
41-
<Lottie
42-
source={illustration}
43-
style={styles.w100}
44-
autoPlay
45-
loop
58+
<HeaderWithBackButton
59+
// eslint-disable-next-line react/jsx-props-no-spreading
60+
{...propsToPassToHeader}
61+
titleColor={backgroundColor === themeColors.appBG ? undefined : themeColors.textColorfulBackground}
62+
iconFill={backgroundColor === themeColors.appBG ? undefined : themeColors.iconColorfulBackground}
4663
/>
47-
{overlayContent && overlayContent()}
64+
<View style={[styles.flex1, StyleUtils.getBackgroundColorStyle(themeColors.appBG), !isOffline ? safeAreaPaddingBottomStyle : {}]}>
65+
<ScrollView
66+
contentContainerStyle={safeAreaPaddingBottomStyle}
67+
showsVerticalScrollIndicator={false}
68+
>
69+
<View style={styles.overscrollSpacer(backgroundColor, windowHeight)} />
70+
<View style={[styles.alignItemsCenter, styles.justifyContentEnd, StyleUtils.getBackgroundColorStyle(backgroundColor)]}>
71+
<Lottie
72+
source={illustration}
73+
style={styles.w100}
74+
autoPlay
75+
loop
76+
/>
77+
{overlayContent && overlayContent()}
78+
</View>
79+
<View style={[styles.pt5]}>{children}</View>
80+
</ScrollView>
81+
{!_.isNull(footer) && <FixedFooter>{footer}</FixedFooter>}
82+
</View>
4883
</>
49-
}
50-
headerContainerStyles={[styles.justifyContentCenter, styles.w100]}
51-
footer={footer}
52-
// eslint-disable-next-line react/jsx-props-no-spreading
53-
{...propsToPassToHeader}
54-
>
55-
{children}
56-
</HeaderPageLayout>
84+
)}
85+
</ScreenWrapper>
5786
);
5887
}
5988

src/components/LottieAnimations.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
const ExpensifyLounge = require('../../assets/animations/ExpensifyLounge.json');
2+
const FastMoney = require('../../assets/animations/FastMoney.json');
23
const Fireworks = require('../../assets/animations/Fireworks.json');
34
const Hands = require('../../assets/animations/Hands.json');
45
const PreferencesDJ = require('../../assets/animations/PreferencesDJ.json');
56
const ReviewingBankInfo = require('../../assets/animations/ReviewingBankInfo.json');
67
const WorkspacePlanet = require('../../assets/animations/WorkspacePlanet.json');
78
const SaveTheWorld = require('../../assets/animations/SaveTheWorld.json');
89
const Safe = require('../../assets/animations/Safe.json');
9-
const Magician = require('../../assets/animations/Magician.json');
1010

11-
export {ExpensifyLounge, Fireworks, Hands, PreferencesDJ, ReviewingBankInfo, SaveTheWorld, WorkspacePlanet, Safe, Magician};
11+
export {ExpensifyLounge, FastMoney, Fireworks, Hands, PreferencesDJ, ReviewingBankInfo, SaveTheWorld, WorkspacePlanet, Safe};

src/components/Section.js

+34-10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const propTypes = {
1414
/** The text to display in the title of the section */
1515
title: PropTypes.string.isRequired,
1616

17+
/** The text to display in the subtitle of the section */
18+
subtitle: PropTypes.string,
19+
1720
/** The icon to display along with the title */
1821
icon: PropTypes.func,
1922

@@ -27,6 +30,18 @@ const propTypes = {
2730
// eslint-disable-next-line react/forbid-prop-types
2831
containerStyles: PropTypes.arrayOf(PropTypes.object),
2932

33+
/** Customize the Section container */
34+
// eslint-disable-next-line react/forbid-prop-types
35+
titleStyles: PropTypes.arrayOf(PropTypes.object),
36+
37+
/** Customize the Section container */
38+
// eslint-disable-next-line react/forbid-prop-types
39+
subtitleStyles: PropTypes.arrayOf(PropTypes.object),
40+
41+
/** Customize the Section container */
42+
// eslint-disable-next-line react/forbid-prop-types
43+
childrenStyles: PropTypes.arrayOf(PropTypes.object),
44+
3045
/** Customize the Icon container */
3146
// eslint-disable-next-line react/forbid-prop-types
3247
iconContainerStyles: PropTypes.arrayOf(PropTypes.object),
@@ -39,21 +54,24 @@ const defaultProps = {
3954
IconComponent: null,
4055
containerStyles: [],
4156
iconContainerStyles: [],
57+
titleStyles: [],
58+
subtitleStyles: [],
59+
childrenStyles: [],
60+
subtitle: null,
4261
};
4362

44-
function Section(props) {
45-
const IconComponent = props.IconComponent;
63+
function Section({children, childrenStyles, containerStyles, icon, IconComponent, iconContainerStyles, menuItems, subtitle, subtitleStyles, title, titleStyles}) {
4664
return (
4765
<>
48-
<View style={[styles.pageWrapper, styles.cardSection, ...props.containerStyles]}>
49-
<View style={[styles.flexRow, styles.alignItemsCenter, styles.w100]}>
66+
<View style={[styles.pageWrapper, styles.cardSection, ...containerStyles]}>
67+
<View style={[styles.flexRow, styles.alignItemsCenter, styles.w100, ...titleStyles]}>
5068
<View style={[styles.flexShrink1]}>
51-
<Text style={[styles.textHeadline, styles.cardSectionTitle]}>{props.title}</Text>
69+
<Text style={[styles.textHeadline, styles.cardSectionTitle]}>{title}</Text>
5270
</View>
53-
<View style={[styles.flexGrow1, styles.flexRow, styles.justifyContentEnd, ...props.iconContainerStyles]}>
54-
{Boolean(props.icon) && (
71+
<View style={[styles.flexGrow1, styles.flexRow, styles.justifyContentEnd, ...iconContainerStyles]}>
72+
{Boolean(icon) && (
5573
<Icon
56-
src={props.icon}
74+
src={icon}
5775
height={68}
5876
width={68}
5977
/>
@@ -62,9 +80,15 @@ function Section(props) {
6280
</View>
6381
</View>
6482

65-
<View style={[styles.w100]}>{props.children}</View>
83+
{Boolean(subtitle) && (
84+
<View style={[styles.flexRow, styles.alignItemsCenter, styles.w100, styles.mt4, ...subtitleStyles]}>
85+
<Text style={styles.textNormal}>{subtitle}</Text>
86+
</View>
87+
)}
88+
89+
<View style={[styles.w100, ...childrenStyles]}>{children}</View>
6690

67-
<View style={[styles.w100]}>{Boolean(props.menuItems) && <MenuItemList menuItems={props.menuItems} />}</View>
91+
<View style={[styles.w100]}>{Boolean(menuItems) && <MenuItemList menuItems={menuItems} />}</View>
6892
</View>
6993
</>
7094
);

src/components/WalletSection.js

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import PropTypes from 'prop-types';
2+
import React from 'react';
3+
import Section from './Section';
4+
import styles from '../styles/styles';
5+
6+
const propTypes = {
7+
/** Contents to display inside the section */
8+
children: PropTypes.node,
9+
10+
/** The icon to display along with the title */
11+
icon: PropTypes.func,
12+
13+
/** The text to display in the subtitle of the section */
14+
subtitle: PropTypes.string,
15+
16+
/** The text to display in the title of the section */
17+
title: PropTypes.string.isRequired,
18+
};
19+
20+
const defaultProps = {
21+
children: null,
22+
icon: null,
23+
subtitle: null,
24+
};
25+
26+
function WalletSection({children, icon, subtitle, title}) {
27+
return (
28+
<Section
29+
icon={icon}
30+
subtitle={subtitle}
31+
title={title}
32+
containerStyles={[styles.p0, styles.pv5]}
33+
titleStyles={[styles.ph5]}
34+
subtitleStyles={[styles.ph5]}
35+
>
36+
{children}
37+
</Section>
38+
);
39+
}
40+
41+
WalletSection.defaultProps = defaultProps;
42+
WalletSection.displayName = 'WalletSection';
43+
WalletSection.propTypes = propTypes;
44+
45+
export default WalletSection;

src/languages/en.ts

+10
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,16 @@ export default {
834834
setDefaultFailure: 'Something went wrong. Please chat with Concierge for further assistance.',
835835
},
836836
addBankAccountFailure: 'An unexpected error occurred while trying to add your bank account. Please try again.',
837+
getPaidFaster: 'Get paid faster',
838+
addPaymentMethod: 'Add a payment method to send and receive payments directly in the app.',
839+
getPaidBackFaster: 'Get paid back faster',
840+
secureAccessToYourMoney: 'Secure access to your money',
841+
receiveMoney: 'Receive money in your local currency',
842+
expensifyWallet: 'Expensify Wallet',
843+
sendAndReceiveMoney: 'Send and receive money from your Expensify Wallet.',
844+
bankAccounts: 'Bank accounts',
845+
addBankAccountToSendAndReceive: 'Add a bank account to send and receive payments directly in the app.',
846+
addBankAccount: 'Add bank account',
837847
},
838848
cardPage: {
839849
expensifyCard: 'Expensify Card',

src/languages/es.ts

+10
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,16 @@ export default {
830830
setDefaultFailure: 'No se ha podido configurar el método de pago.',
831831
},
832832
addBankAccountFailure: 'Ocurrió un error inesperado al intentar añadir la cuenta bancaria. Inténtalo de nuevo.',
833+
getPaidFaster: 'Cobra más rápido',
834+
addPaymentMethod: 'Añade un método de pago para enviar y recibir pagos directamente en la aplicación.',
835+
getPaidBackFaster: 'Recibe tus pagos más rápido',
836+
secureAccessToYourMoney: 'Acceso seguro a tu dinero',
837+
receiveMoney: 'Recibe dinero en tu moneda local',
838+
expensifyWallet: 'Billetera Expensify',
839+
sendAndReceiveMoney: 'Envía y recibe dinero desde tu Billetera Expensify.',
840+
bankAccounts: 'Cuentas bancarias',
841+
addBankAccountToSendAndReceive: 'Añade una cuenta bancaria para enviar y recibir pagos directamente en la aplicación.',
842+
addBankAccount: 'Agregar cuenta bancaria',
833843
},
834844
cardPage: {
835845
expensifyCard: 'Tarjeta Expensify',

src/libs/Navigation/NavigationRoot.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ function NavigationRoot(props) {
101101

102102
const animateStatusBarBackgroundColor = () => {
103103
const currentRoute = navigationRef.getCurrentRoute();
104-
const currentScreenBackgroundColor = themeColors.PAGE_BACKGROUND_COLORS[currentRoute.name] || themeColors.appBG;
104+
const currentScreenBackgroundColor = (currentRoute.params && currentRoute.params.backgroundColor) || themeColors.PAGE_BACKGROUND_COLORS[currentRoute.name] || themeColors.appBG;
105105

106106
prevStatusBarBackgroundColor.current = statusBarBackgroundColor.current;
107107
statusBarBackgroundColor.current = currentScreenBackgroundColor;

0 commit comments

Comments
 (0)