aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/assets/images/onboarding-backarrow.pngbin0 -> 2036 bytes
-rw-r--r--src/components/onboarding/ArrowButton.tsx48
-rw-r--r--src/components/onboarding/TaggInput.tsx14
-rw-r--r--src/components/onboarding/TermsConditions.tsx4
-rw-r--r--src/constants/strings.ts5
-rw-r--r--src/routes/onboarding/OnboardingStackNavigator.tsx5
-rw-r--r--src/routes/onboarding/OnboardingStackScreen.tsx22
-rw-r--r--src/screens/onboarding/BasicInfoOnboarding.tsx588
-rw-r--r--src/screens/onboarding/Login.tsx2
-rw-r--r--src/screens/onboarding/PhoneVerification.tsx46
-rw-r--r--src/screens/onboarding/ProfileInfoOnboarding.tsx (renamed from src/screens/onboarding/OnboardingStepThree.tsx)19
-rw-r--r--src/screens/onboarding/WelcomeScreen.tsx2
-rw-r--r--src/screens/onboarding/index.ts5
-rw-r--r--src/screens/onboarding/legacy/OnboardingStepOne.tsx (renamed from src/screens/onboarding/OnboardingStepOne.tsx)16
-rw-r--r--src/screens/onboarding/legacy/OnboardingStepTwo.tsx (renamed from src/screens/onboarding/OnboardingStepTwo.tsx)18
15 files changed, 699 insertions, 95 deletions
diff --git a/src/assets/images/onboarding-backarrow.png b/src/assets/images/onboarding-backarrow.png
new file mode 100644
index 00000000..9aaa66cb
--- /dev/null
+++ b/src/assets/images/onboarding-backarrow.png
Binary files differ
diff --git a/src/components/onboarding/ArrowButton.tsx b/src/components/onboarding/ArrowButton.tsx
index bf07c6ac..67fd0f62 100644
--- a/src/components/onboarding/ArrowButton.tsx
+++ b/src/components/onboarding/ArrowButton.tsx
@@ -1,23 +1,51 @@
import React from 'react';
-import {Image, TouchableOpacity, TouchableOpacityProps} from 'react-native';
+import {
+ Image,
+ StyleSheet,
+ TouchableOpacity,
+ TouchableOpacityProps,
+} from 'react-native';
+import {normalize} from '../../utils';
interface ArrowButtonProps extends TouchableOpacityProps {
direction: 'forward' | 'backward';
disabled?: boolean;
+ onboarding?: boolean;
}
-const ArrowButton: React.FC<ArrowButtonProps> = (props: ArrowButtonProps) => {
- const arrow =
- props.direction === 'forward'
- ? props.disabled
- ? require('../../assets/images/arrow-forward-disabled.png')
- : require('../../assets/images/arrow-forward-enabled.png')
- : require('../../assets/images/arrow-backward.png');
+const ArrowButton: React.FC<ArrowButtonProps> = (props) => {
+ const {direction, disabled, onboarding} = props;
+ let uri;
+
+ if (direction === 'forward') {
+ if (disabled) {
+ uri = require('../../assets/images/arrow-forward-disabled.png');
+ } else {
+ uri = require('../../assets/images/arrow-forward-enabled.png');
+ }
+ } else {
+ if (onboarding) {
+ uri = require('../../assets/images/onboarding-backarrow.png');
+ } else {
+ uri = require('../../assets/images/arrow-backward.png');
+ }
+ }
return (
- <TouchableOpacity {...props}>
- <Image source={arrow} />
+ <TouchableOpacity style={[styles.defautSize, props.style]} {...props}>
+ <Image style={styles.image} source={uri} />
</TouchableOpacity>
);
};
+const styles = StyleSheet.create({
+ image: {
+ width: '100%',
+ height: '100%',
+ },
+ defautSize: {
+ width: normalize(29),
+ height: normalize(25),
+ },
+});
+
export default ArrowButton;
diff --git a/src/components/onboarding/TaggInput.tsx b/src/components/onboarding/TaggInput.tsx
index 405564ab..297392e5 100644
--- a/src/components/onboarding/TaggInput.tsx
+++ b/src/components/onboarding/TaggInput.tsx
@@ -1,5 +1,12 @@
import React from 'react';
-import {View, TextInput, StyleSheet, TextInputProps} from 'react-native';
+import {
+ View,
+ TextInput,
+ StyleSheet,
+ TextInputProps,
+ ViewStyle,
+ StyleProp,
+} from 'react-native';
import * as Animatable from 'react-native-animatable';
import {TAGG_LIGHT_PURPLE} from '../../constants';
@@ -7,6 +14,7 @@ interface TaggInputProps extends TextInputProps {
valid?: boolean;
invalidWarning?: string;
attemptedSubmit?: boolean;
+ externalStyles?: Record<string, StyleProp<ViewStyle>>;
}
/**
* An input component that receives all props a normal TextInput component does. TaggInput components grow to 60% of their parent's width by default, but this can be set using the `width` prop.
@@ -15,7 +23,7 @@ const TaggInput = React.forwardRef((props: TaggInputProps, ref: any) => {
return (
<View style={styles.container}>
<TextInput
- style={styles.input}
+ style={[styles.input, props.externalStyles?.inputWarning]}
placeholderTextColor="#ddd"
clearButtonMode="while-editing"
ref={ref}
@@ -25,7 +33,7 @@ const TaggInput = React.forwardRef((props: TaggInputProps, ref: any) => {
<Animatable.Text
animation="shake"
duration={500}
- style={styles.warning}>
+ style={[styles.warning, props.externalStyles?.warning]}>
{props.invalidWarning}
</Animatable.Text>
)}
diff --git a/src/components/onboarding/TermsConditions.tsx b/src/components/onboarding/TermsConditions.tsx
index 08cd8228..9bd0ee3b 100644
--- a/src/components/onboarding/TermsConditions.tsx
+++ b/src/components/onboarding/TermsConditions.tsx
@@ -49,11 +49,11 @@ const TermsConditions: React.FC<TermsConditionsProps> = (props) => {
<View style={styles.body}>
<RadioCheckbox checked={accepted} onPress={toggleAccepted} />
<View style={styles.bodyPrompt}>
- <Text style={styles.bodyPromptText}>I accept the </Text>
+ <Text style={styles.bodyPromptText}>Accept </Text>
<TouchableOpacity onPress={() => setModalVisible(true)}>
<Text
style={[styles.bodyPromptText, styles.bodyPromptTextUnderline]}>
- EULA & Terms of Service
+ Terms and Conditions
</Text>
</TouchableOpacity>
</View>
diff --git a/src/constants/strings.ts b/src/constants/strings.ts
index e8f2725d..56d54d39 100644
--- a/src/constants/strings.ts
+++ b/src/constants/strings.ts
@@ -45,6 +45,7 @@ export const ERROR_SERVER_DOWN = 'mhm, looks like our servers are down, please r
export const ERROR_SOMETHING_WENT_WRONG = 'Oh dear, don’t worry someone will be held responsible for this error, In the meantime refresh the app';
export const ERROR_SOMETHING_WENT_WRONG_REFRESH = "Ha, looks like this one's on us, please refresh and try again";
export const ERROR_SOMETHING_WENT_WRONG_RELOAD = "You broke it, Just kidding! we don't know what happened... Please reload the app and try again";
+export const ERROR_T_AND_C_NOT_ACCEPTED = 'You must first agree to the terms and conditions.';
export const ERROR_TWILIO_SERVER_ERROR = 'mhm, looks like that is an invalid phone number or our servers are down, please try again in a few mins';
export const ERROR_UNABLE_CONNECT_CHAT = 'Unable to connect chat';
export const ERROR_UNABLE_TO_FIND_PROFILE = 'We were unable to find this profile. Please check username and try again';
@@ -57,17 +58,17 @@ export const ERROR_UPLOAD_SMALL_PROFILE_PIC = "Can't have a profile without a pi
export const ERROR_UPLOAD_SP_PHOTO = 'Unable to update suggested people photo. Please retry!';
export const ERROR_VERIFICATION_FAILED_SHORT = 'Verification failed 😓';
export const FIRST_MESSAGE = 'How about sending your first message to your friend';
-export const START_CHATTING = 'Let’s Start Chatting!';
export const MARKED_AS_MSG = (str: string) => `Marked as ${str}`;
export const MOMENT_DELETED_MSG = 'Moment deleted....Some moments have to go, to create space for greater ones';
export const NO_NEW_NOTIFICATIONS = 'You have no new notifications';
export const NO_RESULTS_FOUND = 'No Results Found!';
export const PRIVATE_ACCOUNT = 'This account is private';
+export const START_CHATTING = 'Let’s Start Chatting!';
export const SUCCESS_BADGES_UPDATE = 'Badges updated successfully!'
export const SUCCESS_CATEGORY_DELETE = 'Category successfully deleted, but its memory will live on';
-export const SUCCESS_LAST_CONTACT_INVITE = 'Done! That was your last invite, hope you used it wisely!';
export const SUCCESS_INVITATION_CODE = 'Welcome to Tagg!';
export const SUCCESS_INVITE_CONTACT = (str: string) => `Success! You now have ${str} invites left!`;
+export const SUCCESS_LAST_CONTACT_INVITE = 'Done! That was your last invite, hope you used it wisely!';
export const SUCCESS_LINK = (str: string) => `Successfully linked ${str} 🎉`;
export const SUCCESS_PIC_UPLOAD = 'Beautiful, the picture was uploaded successfully!';
export const SUCCESS_PWD_RESET = 'Your password was reset successfully!';
diff --git a/src/routes/onboarding/OnboardingStackNavigator.tsx b/src/routes/onboarding/OnboardingStackNavigator.tsx
index 4726a47d..7a74988b 100644
--- a/src/routes/onboarding/OnboardingStackNavigator.tsx
+++ b/src/routes/onboarding/OnboardingStackNavigator.tsx
@@ -3,9 +3,8 @@ import {createStackNavigator} from '@react-navigation/stack';
export type OnboardingStackParams = {
InvitationCodeVerification: {userId: string; username: string};
Login: undefined;
- OnboardingStepOne: undefined;
- OnboardingStepThree: {userId: string; username: string};
- OnboardingStepTwo: {firstName: string; lastName: string; phone: string};
+ BasicInfoOnboarding: {isPhoneVerified: boolean};
+ ProfileInfoOnboarding: {userId: string; username: string};
PasswordReset: {value: string};
PasswordResetRequest: undefined;
PasswordVerification: {id: string};
diff --git a/src/routes/onboarding/OnboardingStackScreen.tsx b/src/routes/onboarding/OnboardingStackScreen.tsx
index 339c3d0d..50fd52d6 100644
--- a/src/routes/onboarding/OnboardingStackScreen.tsx
+++ b/src/routes/onboarding/OnboardingStackScreen.tsx
@@ -1,17 +1,16 @@
import {StackCardInterpolationProps} from '@react-navigation/stack';
import React from 'react';
import {
+ BasicInfoOnboarding,
InvitationCodeVerification,
Login,
- OnboardingStepThree,
- OnboardingStepTwo,
PasswordReset,
PasswordResetRequest,
PasswordVerification,
PhoneVerification,
+ ProfileInfoOnboarding,
WelcomeScreen,
} from '../../screens';
-import OnboardingStepOne from '../../screens/onboarding/OnboardingStepOne';
import {modalStyle} from '../main';
import {OnboardingStack} from './OnboardingStackNavigator';
@@ -44,6 +43,10 @@ const Onboarding: React.FC = () => {
/>
<OnboardingStack.Screen name="WelcomeScreen" component={WelcomeScreen} />
<OnboardingStack.Screen
+ name="BasicInfoOnboarding"
+ component={BasicInfoOnboarding}
+ />
+ <OnboardingStack.Screen
name="PasswordReset"
component={PasswordReset}
options={{
@@ -59,22 +62,13 @@ const Onboarding: React.FC = () => {
}}
/>
<OnboardingStack.Screen
- name="OnboardingStepOne"
- component={OnboardingStepOne}
- />
- <OnboardingStack.Screen
name="PhoneVerification"
component={PhoneVerification}
options={{...modalStyle}}
/>
<OnboardingStack.Screen
- name="OnboardingStepTwo"
- component={OnboardingStepTwo}
- options={{...modalStyle}}
- />
- <OnboardingStack.Screen
- name="OnboardingStepThree"
- component={OnboardingStepThree}
+ name="ProfileInfoOnboarding"
+ component={ProfileInfoOnboarding}
options={{...modalStyle}}
/>
<OnboardingStack.Screen
diff --git a/src/screens/onboarding/BasicInfoOnboarding.tsx b/src/screens/onboarding/BasicInfoOnboarding.tsx
new file mode 100644
index 00000000..3fa33f63
--- /dev/null
+++ b/src/screens/onboarding/BasicInfoOnboarding.tsx
@@ -0,0 +1,588 @@
+import AsyncStorage from '@react-native-community/async-storage';
+import {useNavigation} from '@react-navigation/core';
+import {RouteProp} from '@react-navigation/native';
+import {StackNavigationProp} from '@react-navigation/stack';
+import React, {useEffect, useState} from 'react';
+import {
+ Alert,
+ KeyboardAvoidingView,
+ Platform,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+} from 'react-native';
+import {normalize} from 'react-native-elements';
+import Animated, {Easing, useValue} from 'react-native-reanimated';
+import {
+ ArrowButton,
+ Background,
+ LoadingIndicator,
+ TaggInput,
+ TaggSquareButton,
+ TermsConditions,
+} from '../../components';
+import {
+ emailRegex,
+ nameRegex,
+ passwordRegex,
+ phoneRegex,
+ usernameRegex,
+} from '../../constants';
+import {
+ ERROR_NEXT_PAGE,
+ ERROR_PHONE_IN_USE,
+ ERROR_REGISTRATION,
+ ERROR_SOMETHING_WENT_WRONG_REFRESH,
+ ERROR_TWILIO_SERVER_ERROR,
+ ERROR_T_AND_C_NOT_ACCEPTED,
+} from '../../constants/strings';
+import {OnboardingStackParams} from '../../routes';
+import {sendOtpStatusCode, sendRegister} from '../../services';
+import {BackgroundGradientType} from '../../types';
+import {HeaderHeight, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
+
+type BasicInfoOnboardingRouteProp = RouteProp<
+ OnboardingStackParams,
+ 'BasicInfoOnboarding'
+>;
+type BasicInfoOnboardingNavigationProp = StackNavigationProp<
+ OnboardingStackParams,
+ 'BasicInfoOnboarding'
+>;
+interface BasicInfoOnboardingProps {
+ route: BasicInfoOnboardingRouteProp;
+ navigation: BasicInfoOnboardingNavigationProp;
+}
+
+const BasicInfoOnboarding: React.FC<BasicInfoOnboardingProps> = ({route}) => {
+ const {isPhoneVerified} = route.params;
+ const navigation = useNavigation();
+ const [attemptedSubmit, setAttemptedSubmit] = useState(false);
+ const [valid, setValid] = useState(false);
+ const [currentStep, setCurrentStep] = useState(0);
+ const [tcAccepted, setTCAccepted] = useState(false);
+ const [passVisibility, setPassVisibility] = useState(false);
+ const [autoCapitalize, setAutoCap] = useState<
+ 'none' | 'sentences' | 'words' | 'characters' | undefined
+ >('none');
+ const [fadeValue, setFadeValue] = useState<Animated.Value<number>>(
+ new Animated.Value(0),
+ );
+ const fadeButtonValue = useValue<number>(0);
+ const [form, setForm] = useState({
+ fname: '',
+ lname: '',
+ username: '',
+ phone: '',
+ email: '',
+ password: '',
+ });
+
+ const fadeFormIn = () => {
+ setFadeValue(new Animated.Value(0));
+ };
+
+ const fadeButtonTo = (target: number) => {
+ Animated.timing(fadeButtonValue, {
+ toValue: target,
+ duration: 100,
+ easing: Easing.linear,
+ }).start();
+ };
+
+ useEffect(() => {
+ const fade = async () => {
+ Animated.timing(fadeValue, {
+ toValue: 1,
+ duration: 1000,
+ easing: Easing.linear,
+ }).start();
+ };
+ fade();
+ }, [fadeValue]);
+
+ useEffect(() => {
+ if (valid) {
+ fadeButtonTo(1);
+ } else {
+ fadeButtonTo(0);
+ }
+ }, [valid]);
+
+ const goToPhoneVerification = async () => {
+ if (!attemptedSubmit) {
+ setAttemptedSubmit(true);
+ }
+ try {
+ if (valid) {
+ const {phone} = form;
+ const code = await sendOtpStatusCode(phone);
+ if (code) {
+ switch (code) {
+ case 200:
+ const {fname, lname} = form;
+ navigation.navigate('PhoneVerification', {
+ firstName: fname,
+ lastName: lname,
+ phone,
+ });
+ break;
+ case 409:
+ Alert.alert(ERROR_PHONE_IN_USE);
+ break;
+ default:
+ Alert.alert(ERROR_TWILIO_SERVER_ERROR);
+ }
+ } else {
+ setAttemptedSubmit(false);
+ setTimeout(() => {
+ setAttemptedSubmit(true);
+ });
+ }
+ }
+ } catch (error) {
+ Alert.alert(ERROR_NEXT_PAGE);
+ return {
+ name: 'Navigation error',
+ description: error,
+ };
+ }
+ };
+ // 0 = first name, 1 = last name, 2 = username, 3 = phone #
+ const handleNameUpdate = (name: string, nameType: number) => {
+ name = name.trim();
+ let isValidName: boolean = nameRegex.test(name);
+ switch (nameType) {
+ case 0:
+ setForm({
+ ...form,
+ fname: name,
+ });
+ setAutoCap('words');
+ setValid(isValidName);
+ break;
+ case 1:
+ setForm({
+ ...form,
+ lname: name,
+ });
+ setAutoCap('words');
+ setValid(isValidName);
+ break;
+ case 2:
+ setForm({
+ ...form,
+ username: name,
+ });
+ setValid(usernameRegex.test(name));
+ setAutoCap('none');
+ break;
+ }
+ };
+ const handlePhoneUpdate = (phone: string) => {
+ phone = phone.trim();
+ setForm({
+ ...form,
+ phone,
+ });
+ setAutoCap('none');
+ setValid(phoneRegex.test(phone));
+ };
+ const handleEmailUpdate = (email: string) => {
+ email = email.trim();
+ setForm({
+ ...form,
+ email,
+ });
+ setAutoCap('none');
+ setValid(emailRegex.test(email));
+ };
+ const handlePasswordUpdate = (password: string) => {
+ setForm({
+ ...form,
+ password,
+ });
+ setAutoCap('none');
+ setValid(passwordRegex.test(password));
+ };
+ const formSteps: {
+ placeholder: string;
+ onChangeText: (text: string) => void;
+ }[] = [
+ {
+ placeholder: 'First Name',
+ onChangeText: (text) => handleNameUpdate(text, 0),
+ },
+ {
+ placeholder: 'Last Name',
+ onChangeText: (text) => handleNameUpdate(text, 1),
+ },
+ {
+ placeholder: 'Phone',
+ onChangeText: handlePhoneUpdate,
+ },
+ {
+ placeholder: 'School Email',
+ onChangeText: handleEmailUpdate,
+ },
+ {
+ placeholder: 'Username',
+ onChangeText: (text) => handleNameUpdate(text, 2),
+ },
+ {
+ placeholder: 'Password',
+ onChangeText: handlePasswordUpdate,
+ },
+ ];
+ const resetForm = (formStep: String) => {
+ setValid(false);
+ switch (formStep) {
+ case 'First Name':
+ setForm({
+ ...form,
+ fname: '',
+ });
+ break;
+ case 'Last Name':
+ setForm({
+ ...form,
+ lname: '',
+ });
+ break;
+ case 'Email':
+ setForm({
+ ...form,
+ email: '',
+ });
+ break;
+ case 'Password':
+ setForm({
+ ...form,
+ password: '',
+ });
+ break;
+ case 'School Email':
+ setForm({
+ ...form,
+ email: '',
+ });
+ break;
+ case 'Username':
+ setForm({
+ ...form,
+ username: '',
+ });
+ break;
+ }
+ };
+ const step = formSteps[currentStep];
+ const advance = () => {
+ setAttemptedSubmit(true);
+ if (valid) {
+ setCurrentStep(currentStep + 1);
+ setAttemptedSubmit(false);
+ setValid(false);
+ fadeFormIn();
+ }
+ };
+ const advanceRegistration = async () => {
+ setAttemptedSubmit(true);
+ if (!valid) {
+ return;
+ }
+ if (!tcAccepted) {
+ Alert.alert('Terms and conditions', ERROR_T_AND_C_NOT_ACCEPTED);
+ return;
+ }
+ const {fname, lname, phone, email, username, password} = form;
+ const response = await sendRegister(
+ fname,
+ lname,
+ phone,
+ email,
+ username,
+ password,
+ );
+ if (response) {
+ const data = await response.json();
+ const {token, UserID} = data;
+ switch (response.status) {
+ case 201:
+ await AsyncStorage.setItem('token', token);
+ navigation.navigate('ProfileInfoOnboarding', {
+ userId: UserID,
+ username: username,
+ });
+ break;
+ case 400:
+ Alert.alert(ERROR_REGISTRATION(data.toLowerCase()));
+ break;
+ default:
+ Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH);
+ break;
+ }
+ } else {
+ Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH);
+ }
+ };
+
+ useEffect(() => {
+ if (isPhoneVerified) {
+ advance();
+ }
+ }, [isPhoneVerified]);
+
+ return (
+ <Background
+ style={styles.container}
+ gradientType={BackgroundGradientType.Light}>
+ <StatusBar barStyle="light-content" />
+ <KeyboardAvoidingView
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ keyboardVerticalOffset={-(SCREEN_HEIGHT * 0.2)}
+ style={styles.container}>
+ {currentStep !== 0 && currentStep !== 3 && (
+ <ArrowButton
+ style={styles.backArrow}
+ direction="backward"
+ onboarding={true}
+ onPress={() => {
+ // if I go back do I want to reset the previous form?
+ setCurrentStep(currentStep - 1);
+ resetForm(step.placeholder);
+ setAttemptedSubmit(false);
+ setFadeValue(new Animated.Value(0));
+ }}
+ />
+ )}
+ {step.placeholder === 'Phone' && !isPhoneVerified ? (
+ <>
+ <Animated.Text style={[styles.formHeader, {opacity: fadeValue}]}>
+ PHONE NUMBER
+ </Animated.Text>
+ <Animated.View style={[styles.formContainer, {opacity: fadeValue}]}>
+ <TaggInput
+ style={
+ attemptedSubmit && !valid
+ ? [styles.input, styles.invalidColor]
+ : styles.input
+ }
+ maxLength={10} // currently only support US phone numbers
+ accessibilityHint="Enter your phone number."
+ accessibilityLabel="Phone number input field."
+ placeholder="Phone Number"
+ autoCompleteType="tel"
+ selectionColor="white"
+ textContentType="telephoneNumber"
+ externalStyles={{
+ warning: styles.passWarning,
+ }}
+ keyboardType="number-pad"
+ onChangeText={handlePhoneUpdate}
+ autoFocus={true}
+ blurOnSubmit={false}
+ valid={valid}
+ invalidWarning={'Please enter a valid 10 digit number.'}
+ attemptedSubmit={attemptedSubmit}
+ onSubmitEditing={goToPhoneVerification}
+ />
+ <Animated.View style={{opacity: fadeButtonValue}}>
+ <TaggSquareButton
+ onPress={goToPhoneVerification}
+ title={'Verify'}
+ buttonStyle={'normal'}
+ buttonColor={'white'}
+ labelColor={'blue'}
+ />
+ </Animated.View>
+ </Animated.View>
+ </>
+ ) : (
+ <>
+ {step.placeholder !== 'Password' ? (
+ <>
+ <Text style={styles.formHeader}>SIGN UP</Text>
+ <Animated.View
+ style={[styles.formContainer, {opacity: fadeValue}]}>
+ <TaggInput
+ key={step.placeholder}
+ style={
+ attemptedSubmit && !valid
+ ? [styles.input, styles.invalidColor]
+ : styles.input
+ }
+ accessibilityHint={`Enter your ${step.placeholder.toLowerCase()}`}
+ accessibilityLabel={`${step.placeholder} input field.`}
+ placeholder={step.placeholder}
+ autoCompleteType="name"
+ autoCapitalize={autoCapitalize}
+ textContentType="name"
+ returnKeyType="done"
+ selectionColor="white"
+ onChangeText={step.onChangeText}
+ onSubmitEditing={advance}
+ autoFocus={true}
+ blurOnSubmit={false}
+ externalStyles={{
+ warning: styles.passWarning,
+ }}
+ valid={valid}
+ invalidWarning={`Please enter a valid ${step.placeholder.toLowerCase()}`}
+ attemptedSubmit={attemptedSubmit}
+ />
+ <Animated.View style={{opacity: fadeButtonValue}}>
+ <TaggSquareButton
+ onPress={advance}
+ title={'Next'}
+ buttonStyle={'normal'}
+ buttonColor={'white'}
+ labelColor={'blue'}
+ />
+ </Animated.View>
+ </Animated.View>
+ </>
+ ) : (
+ <Animated.View
+ style={[styles.formContainer, {opacity: fadeValue}]}>
+ <TaggInput
+ accessibilityHint="Enter a password."
+ accessibilityLabel="Password input field."
+ placeholder="Password"
+ autoCompleteType="password"
+ textContentType="oneTimeCode"
+ returnKeyType="done"
+ selectionColor="white"
+ onChangeText={handlePasswordUpdate}
+ onSubmitEditing={advanceRegistration}
+ blurOnSubmit={false}
+ autoFocus={true}
+ secureTextEntry={!passVisibility}
+ valid={valid}
+ externalStyles={{
+ warning: styles.passWarning,
+ }}
+ invalidWarning={
+ 'Password must be at least 8 characters & contain at least one of a-z, A-Z, 0-9, and a special character.'
+ }
+ attemptedSubmit={attemptedSubmit}
+ style={
+ attemptedSubmit && !valid
+ ? [styles.input, styles.invalidColor]
+ : styles.input
+ }
+ />
+ <TouchableOpacity
+ accessibilityLabel="Show password button"
+ accessibilityHint="Select this if you want to display your tagg password"
+ style={styles.showPassContainer}
+ onPress={() => setPassVisibility(!passVisibility)}>
+ <Text style={styles.showPass}>Show Password</Text>
+ </TouchableOpacity>
+ <LoadingIndicator />
+ <TermsConditions
+ style={styles.tc}
+ accepted={tcAccepted}
+ onChange={setTCAccepted}
+ />
+ <Animated.View style={{opacity: fadeButtonValue}}>
+ <TaggSquareButton
+ onPress={advanceRegistration}
+ title={'Next'}
+ buttonStyle={'normal'}
+ buttonColor={'white'}
+ labelColor={'blue'}
+ />
+ </Animated.View>
+ </Animated.View>
+ )}
+ </>
+ )}
+ </KeyboardAvoidingView>
+ </Background>
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ height: SCREEN_HEIGHT,
+ width: SCREEN_WIDTH,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ formContainer: {
+ marginTop: '20%',
+ height: SCREEN_HEIGHT * 0.2,
+ width: '80%',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ },
+ arrow: {
+ color: '#6EE7E7',
+ },
+ showPassContainer: {
+ marginVertical: '1%',
+ borderBottomWidth: 1,
+ paddingBottom: '1%',
+ alignSelf: 'flex-start',
+ borderBottomColor: 'white',
+ marginBottom: '8%',
+ },
+ showPass: {
+ color: 'white',
+ },
+ passWarning: {
+ fontSize: 14,
+ marginTop: 5,
+ color: '#FF8989',
+ maxWidth: 350,
+ alignSelf: 'flex-start',
+ },
+ input: {
+ minWidth: '100%',
+ height: 40,
+ fontSize: 16,
+ fontWeight: '600',
+ color: '#fff',
+ borderBottomWidth: 1,
+ borderBottomColor: '#fff',
+ },
+ invalidColor: {
+ color: '#FF8989',
+ },
+ errorInput: {
+ minWidth: '60%',
+ height: 40,
+ fontSize: 16,
+ fontWeight: '600',
+ color: '#FF8989',
+ borderBottomWidth: 1,
+ borderBottomColor: '#fff',
+ },
+ button: {
+ alignItems: 'center',
+ width: 40,
+ aspectRatio: 10,
+ },
+ formHeader: {
+ color: '#fff',
+ fontSize: 30,
+ fontWeight: '600',
+ position: 'absolute',
+ top: SCREEN_HEIGHT * 0.15,
+ },
+ load: {
+ top: '5%',
+ },
+ tc: {
+ marginVertical: '5%',
+ },
+ backArrow: {
+ width: normalize(29),
+ height: normalize(25),
+ position: 'absolute',
+ top: HeaderHeight * 1.5,
+ left: 20,
+ },
+});
+export default BasicInfoOnboarding;
diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx
index 3b970864..6922bbc7 100644
--- a/src/screens/onboarding/Login.tsx
+++ b/src/screens/onboarding/Login.tsx
@@ -182,7 +182,7 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => {
* finish step 3, thus does not have a universtiy.
* Redirecting user back to onboarding to finish the process
*/
- navigation.navigate('OnboardingStepThree', {
+ navigation.navigate('ProfileInfoOnboarding', {
userId: data.UserID,
username: username,
});
diff --git a/src/screens/onboarding/PhoneVerification.tsx b/src/screens/onboarding/PhoneVerification.tsx
index 6ec511b3..7d9a04d8 100644
--- a/src/screens/onboarding/PhoneVerification.tsx
+++ b/src/screens/onboarding/PhoneVerification.tsx
@@ -4,7 +4,6 @@ import React, {useMemo} from 'react';
import {
Alert,
KeyboardAvoidingView,
- Platform,
StyleSheet,
TouchableOpacity,
View,
@@ -16,12 +15,12 @@ import {
useBlurOnFulfill,
useClearByFocusCell,
} from 'react-native-confirmation-code-field';
+import {normalize} from 'react-native-elements';
import {trackPromise} from 'react-promise-tracker';
import {
ArrowButton,
Background,
LoadingIndicator,
- RegistrationWizard,
SubmitButton,
} from '../../components';
import {codeRegex} from '../../constants';
@@ -32,7 +31,7 @@ import {
import {OnboardingStackParams} from '../../routes';
import {sendOtp, verifyOtp} from '../../services';
import {BackgroundGradientType} from '../../types';
-import {SCREEN_HEIGHT} from '../../utils';
+import {HeaderHeight} from '../../utils';
type PhoneVerificationRouteProp = RouteProp<
OnboardingStackParams,
@@ -67,9 +66,7 @@ const PhoneVerification: React.FC<PhoneVerificationProps> = ({
try {
const success = await trackPromise(verifyOtp(phone, value));
if (success) {
- navigation.navigate('OnboardingStepTwo', {
- ...route.params,
- });
+ navigation.navigate('BasicInfoOnboarding', {isPhoneVerified: true});
}
} catch (error) {
console.log(error);
@@ -79,12 +76,14 @@ const PhoneVerification: React.FC<PhoneVerificationProps> = ({
const footer = useMemo(
() => (
- <View style={styles.footer}>
- <ArrowButton
- direction="backward"
- onPress={() => navigation.navigate('OnboardingStepOne')}
- />
- </View>
+ <ArrowButton
+ style={styles.backArrow}
+ direction="backward"
+ onboarding={true}
+ onPress={() =>
+ navigation.navigate('BasicInfoOnboarding', {isPhoneVerified: false})
+ }
+ />
),
[],
);
@@ -94,7 +93,6 @@ const PhoneVerification: React.FC<PhoneVerificationProps> = ({
centered
style={styles.container}
gradientType={BackgroundGradientType.Light}>
- <RegistrationWizard style={styles.wizard} step="one" />
<KeyboardAvoidingView behavior="padding" style={styles.form}>
<Text style={styles.formHeader}>Enter 6 digit code</Text>
<Text style={styles.description}>
@@ -144,10 +142,6 @@ const styles = StyleSheet.create({
alignItems: 'center',
justifyContent: 'center',
},
- wizard: {
- position: 'absolute',
- top: SCREEN_HEIGHT * 0.1,
- },
form: {
top: '20%',
alignItems: 'center',
@@ -208,18 +202,12 @@ const styles = StyleSheet.create({
loadingIndicator: {
marginVertical: '5%',
},
- footer: {
- width: '100%',
- flexDirection: 'row',
- justifyContent: 'space-around',
- ...Platform.select({
- ios: {
- bottom: '20%',
- },
- android: {
- bottom: '10%',
- },
- }),
+ backArrow: {
+ width: normalize(29),
+ height: normalize(25),
+ position: 'absolute',
+ top: HeaderHeight * 1.5,
+ left: 20,
},
});
export default PhoneVerification;
diff --git a/src/screens/onboarding/OnboardingStepThree.tsx b/src/screens/onboarding/ProfileInfoOnboarding.tsx
index 34173b39..a481b0c0 100644
--- a/src/screens/onboarding/OnboardingStepThree.tsx
+++ b/src/screens/onboarding/ProfileInfoOnboarding.tsx
@@ -33,17 +33,17 @@ import {patchEditProfile} from '../../services';
import {BackgroundGradientType, UniversityType} from '../../types';
import {normalize, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils';
-type OnboardingStepThreeRouteProp = RouteProp<
+type ProfileInfoOnboardingRouteProp = RouteProp<
OnboardingStackParams,
- 'OnboardingStepThree'
+ 'ProfileInfoOnboarding'
>;
-type OnboardingStepThreeNavigationProp = StackNavigationProp<
+type ProfileInfoOnboardingNavigationProp = StackNavigationProp<
OnboardingStackParams,
- 'OnboardingStepThree'
+ 'ProfileInfoOnboarding'
>;
-interface OnboardingStepThreeProps {
- route: OnboardingStepThreeRouteProp;
- navigation: OnboardingStepThreeNavigationProp;
+interface ProfileInfoOnboardingProps {
+ route: ProfileInfoOnboardingRouteProp;
+ navigation: ProfileInfoOnboardingNavigationProp;
}
type FormType = {
@@ -56,7 +56,7 @@ type FormType = {
attemptedSubmit: boolean;
};
-const OnboardingStepThree: React.FC<OnboardingStepThreeProps> = ({
+const ProfileInfoOnboarding: React.FC<ProfileInfoOnboardingProps> = ({
route,
navigation,
}) => {
@@ -224,7 +224,6 @@ const OnboardingStepThree: React.FC<OnboardingStepThreeProps> = ({
gradientType={BackgroundGradientType.Light}
style={styles.container}>
<StatusBar barStyle="light-content" />
- <RegistrationWizard style={styles.wizard} step="three" />
<View style={styles.profile}>
<SmallProfilePic />
<Image
@@ -378,4 +377,4 @@ const styles = StyleSheet.create({
},
});
-export default OnboardingStepThree;
+export default ProfileInfoOnboarding;
diff --git a/src/screens/onboarding/WelcomeScreen.tsx b/src/screens/onboarding/WelcomeScreen.tsx
index c36a6e05..f0089206 100644
--- a/src/screens/onboarding/WelcomeScreen.tsx
+++ b/src/screens/onboarding/WelcomeScreen.tsx
@@ -35,7 +35,7 @@ const WelcomeScreen: React.FC<WelcomeScreenProps> = ({navigation}) => {
</View>
<TaggSquareButton
onPress={() => {
- navigation.navigate('OnboardingStepOne');
+ navigation.navigate('BasicInfoOnboarding', {isPhoneVerified: false});
}}
title={'Next'}
buttonStyle={'large'}
diff --git a/src/screens/onboarding/index.ts b/src/screens/onboarding/index.ts
index 7eb0587f..5423c46e 100644
--- a/src/screens/onboarding/index.ts
+++ b/src/screens/onboarding/index.ts
@@ -1,8 +1,7 @@
export {default as InvitationCodeVerification} from './InvitationCodeVerification';
export {default as Login} from './Login';
-export {default as OnboardingStepOne} from './OnboardingStepOne';
-export {default as OnboardingStepThree} from './OnboardingStepThree';
-export {default as OnboardingStepTwo} from './OnboardingStepTwo';
+export {default as ProfileInfoOnboarding} from './ProfileInfoOnboarding';
+export {default as BasicInfoOnboarding} from './BasicInfoOnboarding';
export {default as PasswordReset} from './PasswordReset';
export {default as PasswordResetRequest} from './PasswordResetRequest';
export {default as PhoneVerification} from './PhoneVerification';
diff --git a/src/screens/onboarding/OnboardingStepOne.tsx b/src/screens/onboarding/legacy/OnboardingStepOne.tsx
index 618bc39b..b25d41fd 100644
--- a/src/screens/onboarding/OnboardingStepOne.tsx
+++ b/src/screens/onboarding/legacy/OnboardingStepOne.tsx
@@ -15,17 +15,17 @@ import {
Background,
RegistrationWizard,
TaggInput,
-} from '../../components';
-import {nameRegex, phoneRegex} from '../../constants';
+} from '../../../components';
+import {nameRegex, phoneRegex} from '../../../constants';
import {
ERROR_NEXT_PAGE,
ERROR_PHONE_IN_USE,
ERROR_TWILIO_SERVER_ERROR,
-} from '../../constants/strings';
-import {OnboardingStackParams} from '../../routes';
-import {sendOtpStatusCode} from '../../services';
-import {BackgroundGradientType} from '../../types';
-import {SCREEN_HEIGHT} from '../../utils';
+} from '../../../constants/strings';
+import {OnboardingStackParams} from '../../../routes';
+import {sendOtpStatusCode} from '../../../services';
+import {BackgroundGradientType} from '../../../types';
+import {SCREEN_HEIGHT} from '../../../utils';
type OnboardingStepOneNavigationProp = StackNavigationProp<
OnboardingStackParams,
@@ -270,4 +270,4 @@ const styles = StyleSheet.create({
},
});
-export default OnboardingStepOne;
+export default OnboardingStepOne; \ No newline at end of file
diff --git a/src/screens/onboarding/OnboardingStepTwo.tsx b/src/screens/onboarding/legacy/OnboardingStepTwo.tsx
index fc89b887..40130263 100644
--- a/src/screens/onboarding/OnboardingStepTwo.tsx
+++ b/src/screens/onboarding/legacy/OnboardingStepTwo.tsx
@@ -19,17 +19,17 @@ import {
RegistrationWizard,
TaggInput,
TermsConditions,
-} from '../../components';
-import {emailRegex, passwordRegex, usernameRegex} from '../../constants';
+} from '../../../components';
+import {emailRegex, passwordRegex, usernameRegex} from '../../../constants';
import {
ERROR_DOUBLE_CHECK_CONNECTION,
ERROR_REGISTRATION,
ERROR_SOMETHING_WENT_WRONG_REFRESH,
-} from '../../constants/strings';
-import {OnboardingStackParams} from '../../routes';
-import {sendRegister} from '../../services';
-import {BackgroundGradientType} from '../../types';
-import {SCREEN_HEIGHT} from '../../utils';
+} from '../../../constants/strings';
+import {OnboardingStackParams} from '../../../routes';
+import {sendRegister} from '../../../services';
+import {BackgroundGradientType} from '../../../types';
+import {SCREEN_HEIGHT} from '../../../utils';
type OnboardingStepTwoRouteProp = RouteProp<
OnboardingStackParams,
@@ -272,7 +272,7 @@ const OnboardingStepTwo: React.FC<OnboardingStepTwoProps> = ({
ref={usernameRef}
valid={form.isValidUsername}
invalidWarning={
- 'Username must be at least 6 characters and contain only alphanumerics.'
+ 'Username must be at least 6 characters and contain only alphanumerics.'
}
attemptedSubmit={form.attemptedSubmit}
width={280}
@@ -378,4 +378,4 @@ const styles = StyleSheet.create({
},
});
-export default OnboardingStepTwo;
+export default OnboardingStepTwo; \ No newline at end of file