aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGeorge Rusu <56009869+grusu6928@users.noreply.github.com>2020-10-27 12:13:13 -0700
committerGitHub <noreply@github.com>2020-10-27 15:13:13 -0400
commit9c7a867c1851914322a4b60f20223ae06a31c661 (patch)
tree7e8a70b2c5e5654240362146d76727991fd1ca97 /src
parente7a712038a17a759d09bf80c6945c89e060f7310 (diff)
[TMA263] Added Phone Verification UI (#74)
* [TMA263] Added Phone Verification UI * include email field Co-authored-by: george <grus6928@gmail.com> Co-authored-by: hsalhab <husam_salhab@brown.edu>
Diffstat (limited to 'src')
-rw-r--r--src/constants/regex.ts8
-rw-r--r--src/routes/onboarding/OnboardingStack.tsx6
-rw-r--r--src/screens/onboarding/RegistrationOne.tsx53
-rw-r--r--src/screens/onboarding/RegistrationThree.tsx9
-rw-r--r--src/screens/onboarding/RegistrationTwo.tsx48
-rw-r--r--src/screens/onboarding/Verification.tsx14
6 files changed, 94 insertions, 44 deletions
diff --git a/src/constants/regex.ts b/src/constants/regex.ts
index 38ed03ce..4d60d78c 100644
--- a/src/constants/regex.ts
+++ b/src/constants/regex.ts
@@ -48,3 +48,11 @@ export const bioRegex: RegExp = /^$|^[A-Za-z'\-,.!@#$%^&*()_:?/ ]{1,150}$/;
* - match alphanumerics, hyphens, and whitespaces
*/
export const genderRegex: RegExp = /^$|^[A-Za-z\- ]{2,20}$/;
+
+/**
+ * The phone regex has the following constraints
+ * - must be 10 digits
+ * - accepts 012-345-6789
+ *
+ */
+export const phoneRegex: RegExp = /(\+[1][0-9]{10})/;
diff --git a/src/routes/onboarding/OnboardingStack.tsx b/src/routes/onboarding/OnboardingStack.tsx
index ab9816b4..6bc1ed9d 100644
--- a/src/routes/onboarding/OnboardingStack.tsx
+++ b/src/routes/onboarding/OnboardingStack.tsx
@@ -5,10 +5,10 @@ export type OnboardingStackParams = {
Login: undefined;
InvitationCodeVerification: undefined;
RegistrationOne: undefined;
- RegistrationTwo: {email: string};
- RegistrationThree: {firstName: string; lastName: string; email: string};
+ RegistrationTwo: {phone: string};
+ RegistrationThree: {firstName: string; lastName: string; phone: string; email: string};
Checkpoint: {username: string; userId: string};
- Verification: {email: string};
+ Verification: {phone: string};
ProfileOnboarding: {username: string; userId: string};
SocialMedia: {username: string; userId: string};
};
diff --git a/src/screens/onboarding/RegistrationOne.tsx b/src/screens/onboarding/RegistrationOne.tsx
index 12643d69..e0db0755 100644
--- a/src/screens/onboarding/RegistrationOne.tsx
+++ b/src/screens/onboarding/RegistrationOne.tsx
@@ -26,7 +26,7 @@ import {trackPromise} from 'react-promise-tracker';
import {SEND_OTP_ENDPOINT} from '../../constants';
-import {emailRegex} from '../../constants';
+import {phoneRegex} from '../../constants';
type RegistrationScreenOneRouteProp = RouteProp<
OnboardingStackParams,
@@ -46,24 +46,24 @@ interface RegistrationOneProps {
*/
const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => {
// // refs for changing focus
- const emailRef = useRef();
+ const phoneRef = useRef();
// registration form state
const [form, setForm] = useState({
- email: '',
- isValidEmail: false,
+ phone_number: '',
+ isValidPhone: false,
attemptedSubmit: false,
});
/*
* Handles changes to the email field value and verifies the input by updating state and running a validation function.
*/
- const handleEmailUpdate = (email: string) => {
- let isValidEmail: boolean = emailRegex.test(email);
+ const handlePhoneUpdate = (phone_number: string) => {
+ let isValidPhone: boolean = phoneRegex.test(phone_number);
setForm({
...form,
- email,
- isValidEmail,
+ phone_number,
+ isValidPhone,
});
};
@@ -78,27 +78,27 @@ const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => {
});
}
try {
- if (form.isValidEmail) {
+ if (form.isValidPhone) {
let sendOtpResponse = await trackPromise(
fetch(SEND_OTP_ENDPOINT, {
method: 'POST',
body: JSON.stringify({
- email: form.email,
+ phone_number: form.phone_number,
}),
}),
);
let otpStatusCode = sendOtpResponse.status;
if (otpStatusCode === 200) {
navigation.navigate('Verification', {
- email: form.email,
+ phone: form.phone_number,
});
} else if (otpStatusCode === 409) {
Alert.alert(
- 'This email is already registered with us, please use another email.',
+ 'This phone number is already registered with us, please use another email.',
);
} else {
Alert.alert(
- "Looks like Our email servers might be down 😓'",
+ "Looks like Our phone servers might be down 😓'",
"Try again in a couple minutes. We're sorry for the inconvenience.",
);
}
@@ -127,7 +127,7 @@ const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => {
<TouchableOpacity onPress={goToVerification}>
<ArrowButton
direction="forward"
- disabled={!form.isValidEmail}
+ disabled={!form.isValidPhone}
onPress={goToVerification}
/>
</TouchableOpacity>
@@ -142,22 +142,23 @@ const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => {
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={styles.container}>
<View>
- <Text style={styles.formHeader}>ENTER EMAIL</Text>
+ <Text style={styles.formHeader}>ENTER PHONE NUMBER</Text>
</View>
<TaggInput
- accessibilityHint="Enter your email."
- accessibilityLabel="Email input field."
- placeholder="Email"
- autoCompleteType="email"
- textContentType="emailAddress"
+ maxLength = {12} // currently only support US phone numbers
+ accessibilityHint="Enter your phone number."
+ accessibilityLabel="Phone number input field."
+ placeholder="Phone Number"
+ autoCompleteType="tel"
+ textContentType="telephoneNumber"
autoCapitalize="none"
returnKeyType="next"
- keyboardType="email-address"
- onChangeText={handleEmailUpdate}
+ keyboardType="phone-pad"
+ onChangeText={handlePhoneUpdate}
blurOnSubmit={false}
- ref={emailRef}
- valid={form.isValidEmail}
- invalidWarning={'Please enter a valid email address.'}
+ ref={phoneRef}
+ valid={form.isValidPhone}
+ invalidWarning={'Please enter a valid US phone number.'}
attemptedSubmit={form.attemptedSubmit}
width={280}
onSubmitEditing={goToVerification}
@@ -209,4 +210,4 @@ const styles = StyleSheet.create({
},
});
-export default RegistrationOne;
+export default RegistrationOne; \ No newline at end of file
diff --git a/src/screens/onboarding/RegistrationThree.tsx b/src/screens/onboarding/RegistrationThree.tsx
index fd742728..1e1b48d4 100644
--- a/src/screens/onboarding/RegistrationThree.tsx
+++ b/src/screens/onboarding/RegistrationThree.tsx
@@ -58,7 +58,9 @@ const RegistrationThree: React.FC<RegistrationThreeProps> = ({
const registrationName = route.params;
const fname: string = registrationName!.firstName;
const lname: string = registrationName!.lastName;
+ const phone: string = registrationName!.phone;
const email: string = registrationName!.email;
+
/**
* Handles focus change to the next input field.
* @param field key for field to move focus onto
@@ -84,11 +86,11 @@ const RegistrationThree: React.FC<RegistrationThreeProps> = ({
// registration form state
const [form, setForm] = useState({
- email: '',
+ phone: '',
username: '',
password: '',
confirm: '',
- isValidEmail: false,
+ isValidPhone: false,
isValidUsername: false,
isValidPassword: false,
passwordsMatch: false,
@@ -163,6 +165,7 @@ const RegistrationThree: React.FC<RegistrationThreeProps> = ({
first_name: fname,
last_name: lname,
email: email,
+ phone_number: phone,
username: form.username,
password: form.password,
}),
@@ -218,7 +221,7 @@ const RegistrationThree: React.FC<RegistrationThreeProps> = ({
<View style={styles.footer}>
<ArrowButton
direction="backward"
- onPress={() => navigation.navigate('RegistrationTwo', {email: email})}
+ onPress={() => navigation.navigate('RegistrationTwo', {phone: phone})}
/>
<TouchableOpacity onPress={handleRegister}>
<ArrowButton
diff --git a/src/screens/onboarding/RegistrationTwo.tsx b/src/screens/onboarding/RegistrationTwo.tsx
index 515059f9..c0fde48d 100644
--- a/src/screens/onboarding/RegistrationTwo.tsx
+++ b/src/screens/onboarding/RegistrationTwo.tsx
@@ -21,7 +21,7 @@ import {
Background,
} from '../../components';
-import {nameRegex} from '../../constants';
+import {nameRegex, emailRegex} from '../../constants';
type RegistrationScreenTwoRouteProp = RouteProp<
OnboardingStackParams,
@@ -45,9 +45,10 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({
}) => {
// refs for changing focus
const lnameRef = useRef();
+ const emailRef = useRef();
const params = route.params;
- const email: string = params!.email;
+ const phone: string = params!.phone;
/**
* Handles focus change to the next input field.
* @param field key for field to move focus onto
@@ -58,6 +59,10 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({
const lnameField: any = lnameRef.current;
lnameField.focus();
break;
+ case 'email':
+ const emailField: any = emailRef.current;
+ emailField.focus();
+ break;
default:
return;
}
@@ -66,9 +71,11 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({
// registration form state
const [form, setForm] = useState({
fname: '',
- lname: '',
+ lname: '',
+ email: '',
isValidFname: false,
isValidLname: false,
+ isValidEmail: false,
attemptedSubmit: false,
token: '',
});
@@ -97,6 +104,18 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({
});
};
+ /*
+ * Handles changes to the email field value and verifies the input by updating state and running a validation function.
+ */
+ const handleEmailUpdate = (email: string) => {
+ let isValidEmail: boolean = emailRegex.test(email);
+ setForm({
+ ...form,
+ email,
+ isValidEmail,
+ });
+ };
+
/**
* Handles a click on the "next" arrow button by navigating to RegistrationThree if First Name and Last Name are filled
*/
@@ -108,11 +127,12 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({
});
}
try {
- if (form.isValidFname && form.isValidLname) {
+ if (form.isValidFname && form.isValidLname && form.isValidEmail) {
navigation.navigate('RegistrationThree', {
firstName: form.fname,
lastName: form.lname,
- email: email,
+ email: form.email,
+ phone: phone,
});
} else {
setForm({...form, attemptedSubmit: false});
@@ -187,6 +207,24 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({
width={280}
onSubmitEditing={goToRegisterThree}
/>
+ <TaggInput
+ accessibilityHint="Enter your email."
+ accessibilityLabel="Email input field."
+ placeholder="Email"
+ autoCompleteType="email"
+ textContentType="emailAddress"
+ autoCapitalize="none"
+ returnKeyType="next"
+ keyboardType="email-address"
+ onChangeText={handleEmailUpdate}
+ blurOnSubmit={false}
+ ref={emailRef}
+ valid={form.isValidEmail}
+ invalidWarning={'Please enter a valid email address.'}
+ attemptedSubmit={form.attemptedSubmit}
+ width={280}
+ onSubmitEditing={goToRegisterThree}
+ />
</KeyboardAvoidingView>
<Footer />
</Background>
diff --git a/src/screens/onboarding/Verification.tsx b/src/screens/onboarding/Verification.tsx
index 91e6b181..228cb778 100644
--- a/src/screens/onboarding/Verification.tsx
+++ b/src/screens/onboarding/Verification.tsx
@@ -48,7 +48,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
value,
setValue,
});
- const {email} = route.params;
+ const {phone} = route.params;
/**
* Sends the verify_otp request upon tapping the Verify button.
@@ -59,14 +59,14 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
let verifyOtpResponse = await fetch(VERIFY_OTP_ENDPOINT, {
method: 'POST',
body: JSON.stringify({
- email: email,
+ phone_number: phone,
otp: value,
}),
});
let statusCode = verifyOtpResponse.status;
if (statusCode === 200) {
navigation.navigate('RegistrationTwo', {
- email: email,
+ phone: phone,
});
} else {
Alert.alert(
@@ -95,7 +95,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
fetch(SEND_OTP_ENDPOINT, {
method: 'POST',
body: JSON.stringify({
- email: email,
+ phone: phone,
}),
}),
);
@@ -104,7 +104,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
setValue('');
Alert.alert(
'New verification code sent!',
- 'Check your email for your code.',
+ 'Check your phone messages for your code.',
);
} else {
Alert.alert('Something went wrong!');
@@ -129,7 +129,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
<KeyboardAvoidingView behavior="padding" style={styles.form}>
<Text style={styles.formHeader}>Enter 6 digit code</Text>
<Text style={styles.description}>
- We sent a 6 digit verification code to the email you provided.
+ We sent a 6 digit verification code to the phone number you provided.
</Text>
<CodeField
ref={ref}
@@ -156,7 +156,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => {
color="#fff"
style={styles.button}
accessibilityLabel="Verify"
- accessibilityHint="Select this after entering your email verification code"
+ accessibilityHint="Select this after entering your phone number verification code"
onPress={handleVerification}
/>
<TouchableOpacity onPress={handleResend}>