Skip to content

Commit

Permalink
Set password after registering in-store, phone number input formatting (
Browse files Browse the repository at this point in the history
#163)

* Set password + phone number input formatting

* Update set password copy

* Add error message on reCaptcha fail

* Update settings styling and logout

* Clarifying 'Set a Password' pages copy + alerts

* Hamburger drawer design updates

* Navigation fixes + alerts
  • Loading branch information
wangannie authored Jun 8, 2020
1 parent 0630588 commit 5eef95e
Show file tree
Hide file tree
Showing 21 changed files with 573 additions and 174 deletions.
4 changes: 2 additions & 2 deletions components/AuthTextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ function AuthTextField({
keyboardType={
fieldType.includes('Phone Number') ||
fieldType === 'Verification Code'
? 'numeric'
? 'number-pad'
: undefined
}
maxLength={
// eslint-disable-next-line no-nested-ternary
fieldType.includes('Phone Number')
? 10
? 14
: fieldType === 'Verification Code'
? 6
: null
Expand Down
20 changes: 13 additions & 7 deletions components/resources/CategoryBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,27 @@ import CircleIcon from '../CircleIcon';
function CategoryBar({ icon, title }) {
return (
<CategoryCard>
<CircleIcon
icon={icon}
iconColor={Colors.lightText}
circleColor={Colors.lighterGreen}
/>
<CategoryHeadingContainer>
{icon !== '' && (
<CircleIcon
icon={icon}
iconColor={Colors.lightText}
circleColor={Colors.lighterGreen}
/>
)}
<CategoryHeadingContainer style={icon !== '' && { marginLeft: 12 }}>
<Title>{title}</Title>
</CategoryHeadingContainer>
</CategoryCard>
);
}

CategoryBar.propTypes = {
icon: PropTypes.string.isRequired,
icon: PropTypes.string,
title: PropTypes.string.isRequired,
};

CategoryBar.defaultProps = {
icon: '',
};

export default CategoryBar;
2 changes: 1 addition & 1 deletion components/rewards/RewardsFooter.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export default class RewardsFooter extends React.Component {
? `${this.state.rewards} rewards`
: this.state.customer.points === 1
? `${this.state.customer.points} point`
: `${this.state.customer.points} points`}
: `${this.state.customer.points || 0} points`}
</Subtitle>
</View>
)}
Expand Down
2 changes: 1 addition & 1 deletion components/rewards/RewardsHome.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function RewardsHome({ customer, participating }) {
Reward Progress
</Overline>
<Title style={{ marginBottom: 2 }}>
{`${pointsToNext} / ${rewardPointValue}`}
{`${pointsToNext || 0} / ${rewardPointValue}`}
</Title>
<ProgressBar
style={{
Expand Down
26 changes: 24 additions & 2 deletions components/settings/SettingsCard.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { FontAwesome5 } from '@expo/vector-icons';
import PropTypes from 'prop-types';
import React from 'react';
import Colors from '../../constants/Colors';
import { ContentContainer, ResourceItemCard } from '../../styled/resources';
import {
ContentContainer,
IconContainer,
ResourceItemCard,
} from '../../styled/resources';
import { Body, ButtonContainer, Subtitle } from '../BaseComponents';

function SettingsCard({ title, description, navigation, titleColor }) {
function SettingsCard({
title,
description,
navigation,
titleColor,
rightIcon,
}) {
return (
<ButtonContainer onPress={() => navigation()}>
<ResourceItemCard>
Expand All @@ -14,6 +25,15 @@ function SettingsCard({ title, description, navigation, titleColor }) {
<Body color={Colors.secondaryText}>{description}</Body>
)}
</ContentContainer>
{rightIcon !== '' && (
<IconContainer>
<FontAwesome5
name={rightIcon}
size={24}
color={Colors.primaryGray}
/>
</IconContainer>
)}
</ResourceItemCard>
</ButtonContainer>
);
Expand All @@ -24,11 +44,13 @@ SettingsCard.propTypes = {
titleColor: PropTypes.string,
description: PropTypes.string,
navigation: PropTypes.func.isRequired,
rightIcon: PropTypes.string,
};

SettingsCard.defaultProps = {
titleColor: Colors.activeText,
description: '',
rightIcon: '',
};

export default SettingsCard;
1 change: 1 addition & 0 deletions constants/Rewards.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export const rewardDollarValue = 5;
export const rewardPointValue = 500;
export const signUpBonus = 500;
24 changes: 19 additions & 5 deletions lib/authUtils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import * as Crypto from 'expo-crypto';
import {
formatIncompletePhoneNumber,
parsePhoneNumberFromString,
} from 'libphonenumber-js';
import { createPushTokens, updateCustomers } from './airtable/request';
import { logErrorToSentry } from './logUtils';
// Fields
Expand Down Expand Up @@ -54,11 +58,21 @@ export async function updateCustomerPushTokens(customer, newToken) {
}
}

// Formats full phone numbers by (...) ...-.... or returns null if the number is not 10 digits
export function formatPhoneNumber(phoneNumber) {
const onlyNumeric = phoneNumber.replace('[^0-9]', '');
const formatted = `(${onlyNumeric.slice(0, 3)}) ${onlyNumeric.slice(
3,
6
)}-${onlyNumeric.slice(6, 10)}`;
const parsedPhoneNumber = parsePhoneNumberFromString(`+1${phoneNumber}`);
if (parsedPhoneNumber && parsedPhoneNumber.isPossible()) {
return parsedPhoneNumber.formatNational();
}
return null;
}

// Automatically formats phone number input to (...) ...-.... as the user types
export function formatPhoneNumberInput(text) {
let formatted = formatIncompletePhoneNumber(text, 'US');
// Workaround for a bug that doesn't allow backspacing the closing parenthesis
if (formatted.slice(-1) === ')') {
formatted = formatted.slice(0, -1);
}
return formatted;
}
18 changes: 14 additions & 4 deletions navigation/AppNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ function DrawerNavigator() {
<Drawer.Navigator
// eslint-disable-next-line react/jsx-props-no-spreading
drawerContent={(props) => <DrawerContent {...props} />}
drawerStyle={{ width: 189 }}
drawerContentOptions={{
labelStyle: {
fontFamily: 'poppins-medium',
Expand All @@ -38,7 +37,12 @@ function DrawerNavigator() {
color: Colors.activeText,
},
activeTintColor: Colors.primaryGreen,
itemStyle: { marginVertical: 0, marginHorizontal: 0, borderRadius: 0 },
itemStyle: {
marginVertical: 4,
marginHorizontal: 0,
paddingLeft: 16,
borderRadius: 0,
},
}}>
<Drawer.Screen
name="Stores"
Expand All @@ -48,12 +52,18 @@ function DrawerNavigator() {
<Drawer.Screen
name="Resources"
component={ResourcesStackNavigator}
options={{ title: 'Resources', swipeEnabled: false }}
options={{
title: 'Resources',
unmountOnBlur: true,
}}
/>
<Drawer.Screen
name="Settings"
component={SettingsStackNavigator}
options={{ title: 'Settings', swipeEnabled: false }}
options={{
title: 'Settings',
unmountOnBlur: true,
}}
/>
</Drawer.Navigator>
);
Expand Down
84 changes: 59 additions & 25 deletions navigation/DrawerContent.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import { DrawerItemList } from '@react-navigation/drawer';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
import { Updates } from 'expo';
import { useFocusEffect } from '@react-navigation/native';
import * as Analytics from 'expo-firebase-analytics';
import PropTypes from 'prop-types';
import React from 'react';
import { Alert, AsyncStorage, Linking, View } from 'react-native';
import * as Sentry from 'sentry-expo';
import { ButtonContainer, Title } from '../components/BaseComponents';
import {
BigTitle,
ButtonContainer,
ButtonLabel,
FilledButtonContainer,
Subtitle,
Title,
} from '../components/BaseComponents';
import Colors from '../constants/Colors';
import { getCustomersById } from '../lib/airtable/request';
import { logErrorToSentry } from '../lib/logUtils';
import { ColumnContainer, SpaceBetweenRowContainer } from '../styled/shared';

function DrawerContent(props) {
const [customer, setCustomer] = React.useState(null);
const [link, _] = React.useState('http://tiny.cc/RewardsFeedback');
const [isLoading, setIsLoading] = React.useState(true);
const navigation = useNavigation();

const logout = async () => {
props.navigation.navigate('Stores');
await AsyncStorage.clear();
Sentry.configureScope((scope) => scope.clear());
setTimeout(() => {
navigation.navigate('Auth');
}, 500);
props.navigation.closeDrawer();
Updates.reload();
props.navigation.navigate('Auth', { screen: 'LogIn' });
};

useFocusEffect(
Expand Down Expand Up @@ -96,6 +99,8 @@ function DrawerContent(props) {
return null;
}

const isGuest = customer.name === 'Guest';

return (
<View
style={{
Expand All @@ -105,40 +110,69 @@ function DrawerContent(props) {
}}>
<View
style={{
backgroundColor: Colors.bgDark,
height: 114,
backgroundColor: isGuest ? Colors.bgDark : Colors.primaryGreen,
display: 'flex',
flexDirection: 'row',
alignItems: 'flex-end',
padding: 8,
padding: 24,
marginBottom: 24,
}}>
<Title style={{ color: Colors.lightText }}>{customer.name}</Title>
<ColumnContainer style={{ marginTop: 32, width: '100%' }}>
<SpaceBetweenRowContainer
style={{ alignItems: 'center', marginBottom: 4, width: '100%' }}>
<BigTitle style={{ color: Colors.lightText }}>
{customer.name}
</BigTitle>
{isGuest && (
<FilledButtonContainer
style={{
borderColor: Colors.lightText,
borderWidth: 1,
height: 30,
width: 80,
marginVertical: 8,
marginRight: 8,
}}
color={Colors.bgLight}
onPress={() => {
logout();
}}>
<ButtonLabel noCaps>Log In</ButtonLabel>
</FilledButtonContainer>
)}
</SpaceBetweenRowContainer>
{isGuest && (
<Subtitle style={{ color: Colors.lightText }}>
Log in to start saving with Healthy Rewards
</Subtitle>
)}
</ColumnContainer>
</View>
<DrawerItemList {...props} />
<ButtonContainer
style={{ paddingHorizontal: 8, paddingVertical: 13 }}
style={{ paddingLeft: 24, paddingVertical: 13 }}
onPress={() => {
props.navigation.goBack();
props.navigation.navigate('RewardsOverlay');
setTimeout(
() =>
props.navigation.navigate('Stores', { screen: 'RewardsOverlay' }),
700
);
}}>
<Title style={{ height: 30 }}>Rewards</Title>
</ButtonContainer>
<ButtonContainer
style={{ paddingHorizontal: 8, paddingVertical: 13 }}
onPress={() => Linking.openURL(link)}>
<Title style={{ height: 30 }}>Feedback</Title>
<Title style={{ height: 30 }}>Healthy Rewards</Title>
</ButtonContainer>
<DrawerItemList {...props} />
<View
style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-end',
verticalAlign: 'bottom',
paddingBottom: 20,
}}>
<ButtonContainer
style={{ paddingLeft: 16, paddingBottom: 21 }}
onPress={() => logout()}>
<Title>Log Out</Title>
style={{ paddingLeft: 24, paddingVertical: 13 }}
onPress={() => Linking.openURL(link)}>
<Subtitle style={{ height: 30 }}>Submit feedback</Subtitle>
</ButtonContainer>
</View>
</View>
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,15 @@
"geolib": "^3.1.0",
"global": "^4.4.0",
"install": "^0.13.0",
"libphonenumber-js": "^1.7.52",
"npm": "^6.13.4",
"prop-types": "^15.0",
"react": "16.9.0",
"react-dom": "16.9.0",
"react-geocode": "^0.2.0",
"react-is": "^16.12.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-37.0.0.tar.gz",
"react-native-alert-async": "^1.0.5",
"react-native-elements": "^1.2.6",
"react-native-firebase": "^5.6.0",
"react-native-gesture-handler": "~1.6.0",
Expand Down
Loading

0 comments on commit 5eef95e

Please sign in to comment.