diff options
author | Ashm Walia <40498934+ashmgarv@users.noreply.github.com> | 2020-10-13 10:24:59 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-13 13:24:59 -0400 |
commit | 854a7d8f8526e8142c416ec41682468e87bcbbd2 (patch) | |
tree | 80493f0e697cc1b6d93e960fa2a0a6d5a4a91e95 | |
parent | 6e3fe33e5e1d3818ef8bb942c1544581ab8c0688 (diff) |
[TMA - 238] Added invitation code verification screen as the first onboarding screen (#46)
* Added invitation code verification screen as the first onboarding screen
* Changed screen order on some screens and a quick check on back navigation
-rw-r--r-- | src/components/common/LoadingIndicator.tsx | 24 | ||||
-rw-r--r-- | src/components/common/index.ts | 1 | ||||
-rw-r--r-- | src/components/onboarding/RegistrationWizard.tsx | 8 | ||||
-rw-r--r-- | src/constants/api.ts | 3 | ||||
-rw-r--r-- | src/routes/onboarding/Onboarding.tsx | 5 | ||||
-rw-r--r-- | src/routes/onboarding/OnboardingStack.tsx | 1 | ||||
-rw-r--r-- | src/screens/onboarding/Checkpoint.tsx | 2 | ||||
-rw-r--r-- | src/screens/onboarding/InvitationCodeVerification.tsx | 210 | ||||
-rw-r--r-- | src/screens/onboarding/Login.tsx | 2 | ||||
-rw-r--r-- | src/screens/onboarding/RegistrationOne.tsx | 18 | ||||
-rw-r--r-- | src/screens/onboarding/RegistrationThree.tsx | 18 | ||||
-rw-r--r-- | src/screens/onboarding/RegistrationTwo.tsx | 4 | ||||
-rw-r--r-- | src/screens/onboarding/Verification.tsx | 24 | ||||
-rw-r--r-- | src/screens/onboarding/index.ts | 1 |
14 files changed, 265 insertions, 56 deletions
diff --git a/src/components/common/LoadingIndicator.tsx b/src/components/common/LoadingIndicator.tsx new file mode 100644 index 00000000..f6679556 --- /dev/null +++ b/src/components/common/LoadingIndicator.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import {ActivityIndicator, StyleSheet} from 'react-native'; +import {usePromiseTracker} from 'react-promise-tracker'; + +const LoadingIndicator: React.FC = () => { + const {promiseInProgress} = usePromiseTracker(); + return promiseInProgress ? ( + <ActivityIndicator + style={styles.loadingIndicator} + size="large" + color="#fff" + /> + ) : ( + <></> + ); +}; + +const styles = StyleSheet.create({ + loadingIndicator: { + marginVertical: '5%', + }, +}); + +export default LoadingIndicator; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 4a226c8f..cb9d641b 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -7,4 +7,5 @@ export {default as GradientBackground} from './GradientBackground'; export {default as SocialIcon} from './SocialIcon'; export {default as TabsGradient} from './TabsGradient'; export {default as RecentSearches} from '../search/RecentSearches'; +export {default as LoadingIndicator} from './LoadingIndicator'; export * from './post'; diff --git a/src/components/onboarding/RegistrationWizard.tsx b/src/components/onboarding/RegistrationWizard.tsx index 0094c8af..8d747b01 100644 --- a/src/components/onboarding/RegistrationWizard.tsx +++ b/src/components/onboarding/RegistrationWizard.tsx @@ -3,7 +3,7 @@ import {View, StyleSheet, ViewProps, Keyboard} from 'react-native'; import * as Animatable from 'react-native-animatable'; interface RegistrationWizardProps extends ViewProps { - step: 'one' | 'two' | 'three' | 'four' | 'five'; + step: 'one' | 'two' | 'three' | 'four' | 'five' | 'six'; } const RegistrationWizard = (props: RegistrationWizardProps) => { @@ -41,6 +41,8 @@ const RegistrationWizard = (props: RegistrationWizardProps) => { <View style={props.step === 'four' ? stepActiveStyle : stepStyle} /> <View style={styles.progress} /> <View style={props.step === 'five' ? stepActiveStyle : stepStyle} /> + <View style={styles.progress} /> + <View style={props.step === 'six' ? stepActiveStyle : stepStyle} /> </View> </Animatable.View> )} @@ -58,6 +60,8 @@ const RegistrationWizard = (props: RegistrationWizardProps) => { <View style={props.step === 'four' ? stepActiveStyle : stepStyle} /> <View style={styles.progress} /> <View style={props.step === 'five' ? stepActiveStyle : stepStyle} /> + <View style={styles.progress} /> + <View style={props.step === 'six' ? stepActiveStyle : stepStyle} /> </View> </Animatable.View> )} @@ -82,7 +86,7 @@ const styles = StyleSheet.create({ backgroundColor: '#e1f0ff', }, progress: { - width: '16%', + width: '13%', height: 2, backgroundColor: '#e1f0ff', }, diff --git a/src/constants/api.ts b/src/constants/api.ts index e4fed13e..86b941d0 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -12,3 +12,6 @@ export const COVER_PHOTO_ENDPOINT: string = API_URL + 'large-profile-pic/'; export const AVATAR_PHOTO_ENDPOINT: string = API_URL + 'small-profile-pic/'; export const GET_IG_POSTS_ENDPOINT: string = API_URL + 'posts-ig/'; export const SEARCH_ENDPOINT: string = API_URL + 'search/'; + +//TODO add an endpoint to verify the invitation code, such as below +//export const VERIFY_INVITATION_CODE_ENDPOUNT: string = API_URL + 'verify_invitation_code/'; diff --git a/src/routes/onboarding/Onboarding.tsx b/src/routes/onboarding/Onboarding.tsx index 7b2eb85d..148dbefb 100644 --- a/src/routes/onboarding/Onboarding.tsx +++ b/src/routes/onboarding/Onboarding.tsx @@ -2,6 +2,7 @@ import React from 'react'; import {OnboardingStack} from './OnboardingStack'; import { Login, + InvitationCodeVerification, RegistrationOne, RegistrationTwo, RegistrationThree, @@ -33,6 +34,10 @@ const Onboarding: React.FC = () => { }} /> <OnboardingStack.Screen + name="InvitationCodeVerification" + component={InvitationCodeVerification} + /> + <OnboardingStack.Screen name="RegistrationOne" component={RegistrationOne} /> diff --git a/src/routes/onboarding/OnboardingStack.tsx b/src/routes/onboarding/OnboardingStack.tsx index 1f6214fd..f1cfda39 100644 --- a/src/routes/onboarding/OnboardingStack.tsx +++ b/src/routes/onboarding/OnboardingStack.tsx @@ -3,6 +3,7 @@ import {createStackNavigator} from '@react-navigation/stack'; export type OnboardingStackParams = { Splash: undefined; Login: undefined; + InvitationCodeVerification: undefined; RegistrationOne: undefined; RegistrationTwo: {email: string}; RegistrationThree: {firstName: string; lastName: string; email: string}; diff --git a/src/screens/onboarding/Checkpoint.tsx b/src/screens/onboarding/Checkpoint.tsx index 83f330f1..8ef7f307 100644 --- a/src/screens/onboarding/Checkpoint.tsx +++ b/src/screens/onboarding/Checkpoint.tsx @@ -50,7 +50,7 @@ const Checkpoint: React.FC<CheckpointProps> = ({route, navigation}) => { return ( <Background style={styles.container}> <StatusBar barStyle="light-content" /> - <RegistrationWizard style={styles.wizard} step="five" /> + <RegistrationWizard style={styles.wizard} step="six" /> <View style={styles.textContainer}> <Text style={styles.header}>You are registered!</Text> diff --git a/src/screens/onboarding/InvitationCodeVerification.tsx b/src/screens/onboarding/InvitationCodeVerification.tsx new file mode 100644 index 00000000..ae1c282f --- /dev/null +++ b/src/screens/onboarding/InvitationCodeVerification.tsx @@ -0,0 +1,210 @@ +import React from 'react'; +import {OnboardingStackParams} from '../../routes'; +import {StackNavigationProp} from '@react-navigation/stack'; + +import { + Background, + RegistrationWizard, + SubmitButton, + ArrowButton, + LoadingIndicator, +} from '../../components'; + +//TODO : +//import {VERIFY_INVITATION_CODE_ENDPOUNT} from "../../constants" + +import {Text} from 'react-native-animatable'; +import { + CodeField, + Cursor, + useBlurOnFulfill, + useClearByFocusCell, +} from 'react-native-confirmation-code-field'; +import { + StyleSheet, + View, + KeyboardAvoidingView, + Alert, + Platform, +} from 'react-native'; +import {trackPromise} from 'react-promise-tracker'; + +type InvitationCodeVerificationScreenNavigationProp = StackNavigationProp< + OnboardingStackParams, + 'InvitationCodeVerification' +>; + +interface InvitationCodeVerificationProps { + navigation: InvitationCodeVerificationScreenNavigationProp; +} + +/** + * InvitationCodeVerification screen to verify that the new user has been Invited + * @param navigation react-navigation navigation object + */ + +const InvitationCodeVerification: React.FC<InvitationCodeVerificationProps> = ({ + navigation, +}) => { + const [value, setValue] = React.useState(''); + const ref = useBlurOnFulfill({value, cellCount: 6}); + const [valueProps, getCellOnLayoutHandler] = useClearByFocusCell({ + value, + setValue, + }); + + const handleInvitationCodeVerification = async () => { + //TODO : Verify the code + //The code would look somewhat like below + // try { + // let verifyInviteCodeResponse = await fetch(VERIFY_INVITATION_CODE_ENDPOUNT, { + // method: 'POST', + // body: JSON.stringify({ + // otp: value, + // }), + // }); + + // if (verifyInviteCodeResponse.status == 200) { + // navigation.navigate('RegistrationOne'); + // } else { + // Alert.alert( + // 'Invalid invitation code 🤔', + // ); + // } + // } catch (error) { + // Alert.alert( + // 'Verifiation failed 😓', + // 'Please double-check your network connection and retry.', + // ); + // return { + // name: 'Verification error', + // description: error, + // }; + // } + + navigation.navigate('RegistrationOne'); + }; + + const Footer = () => ( + <View style={styles.footer}> + <ArrowButton + direction="backward" + onPress={() => navigation.navigate('Login')} + /> + </View> + ); + + return ( + <Background centered style={styles.container}> + <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}> + Please enter the invitation code provided to you by us / your friend. + </Text> + <CodeField + ref={ref} + {...valueProps} + value={value} + onChangeText={setValue} + cellCount={6} + rootStyle={styles.codeFieldRoot} + keyboardType="number-pad" + textContentType="oneTimeCode" + renderCell={({index, symbol, isFocused}) => ( + <View + onLayout={getCellOnLayoutHandler(index)} + key={index} + style={[styles.cellRoot, isFocused && styles.focusCell]}> + <Text style={styles.cellText}> + {symbol || (isFocused ? <Cursor /> : null)} + </Text> + </View> + )} + /> + <SubmitButton + text="Verify" + color="#fff" + style={styles.button} + accessibilityLabel="Verify" + accessibilityHint="Select this after entering your invitation code" + onPress={handleInvitationCodeVerification} + /> + <LoadingIndicator /> + </KeyboardAvoidingView> + <Footer /> + </Background> + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + wizard: { + marginTop: '3.5%', + flex: 1, + justifyContent: 'center', + }, + form: { + alignItems: 'center', + justifyContent: 'flex-start', + flex: 3, + }, + formHeader: { + color: '#fff', + fontSize: 20, + fontWeight: 'bold', + alignSelf: 'flex-start', + marginBottom: '6%', + marginHorizontal: '10%', + }, + description: { + color: '#fff', + fontWeight: '600', + fontSize: 17, + marginHorizontal: '10%', + }, + codeFieldRoot: { + width: 280, + marginHorizontal: 'auto', + marginVertical: '15%', + }, + cellRoot: { + width: 40, + height: 60, + justifyContent: 'center', + alignItems: 'center', + borderBottomColor: '#fff', + borderBottomWidth: 1, + }, + cellText: { + color: '#fff', + fontSize: 48, + textAlign: 'center', + }, + focusCell: { + borderBottomColor: '#78a0ef', + borderBottomWidth: 2, + }, + button: { + marginVertical: '5%', + }, + footer: { + width: '100%', + flexDirection: 'row', + justifyContent: 'space-around', + ...Platform.select({ + ios: { + bottom: '20%', + }, + android: { + bottom: '10%', + }, + }), + }, +}); + +export default InvitationCodeVerification; diff --git a/src/screens/onboarding/Login.tsx b/src/screens/onboarding/Login.tsx index c0dc14b7..c9dcba41 100644 --- a/src/screens/onboarding/Login.tsx +++ b/src/screens/onboarding/Login.tsx @@ -173,7 +173,7 @@ const Login: React.FC<LoginProps> = ({navigation}: LoginProps) => { * Handles tap on "Get Started" text by resetting fields & navigating to the registration page. */ const goToRegistration = () => { - navigation.navigate('RegistrationOne'); + navigation.navigate('InvitationCodeVerification'); setForm({...form, attemptedSubmit: false}); }; diff --git a/src/screens/onboarding/RegistrationOne.tsx b/src/screens/onboarding/RegistrationOne.tsx index 9e9cabf5..12643d69 100644 --- a/src/screens/onboarding/RegistrationOne.tsx +++ b/src/screens/onboarding/RegistrationOne.tsx @@ -10,7 +10,6 @@ import { Platform, TouchableOpacity, KeyboardAvoidingView, - ActivityIndicator, } from 'react-native'; import {OnboardingStackParams} from '../../routes'; @@ -20,9 +19,10 @@ import { RegistrationWizard, TaggInput, Background, + LoadingIndicator, } from '../../components'; -import {usePromiseTracker, trackPromise} from 'react-promise-tracker'; +import {trackPromise} from 'react-promise-tracker'; import {SEND_OTP_ENDPOINT} from '../../constants'; @@ -134,22 +134,10 @@ const RegistrationOne: React.FC<RegistrationOneProps> = ({navigation}) => { </View> ); - /** - * An activity indicator to indicate that the app is working during the send_otp request. - */ - const LoadingIndicator = () => { - const {promiseInProgress} = usePromiseTracker(); - return promiseInProgress ? ( - <ActivityIndicator style={styles.load} size="large" color="#fff" /> - ) : ( - <></> - ); - }; - return ( <Background style={styles.container}> <StatusBar barStyle="light-content" /> - <RegistrationWizard style={styles.wizard} step="one" /> + <RegistrationWizard style={styles.wizard} step="two" /> <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.container}> diff --git a/src/screens/onboarding/RegistrationThree.tsx b/src/screens/onboarding/RegistrationThree.tsx index 5b8f52b3..babb0334 100644 --- a/src/screens/onboarding/RegistrationThree.tsx +++ b/src/screens/onboarding/RegistrationThree.tsx @@ -17,7 +17,6 @@ import { KeyboardAvoidingView, ActivityIndicator, } from 'react-native'; -import {usePromiseTracker} from 'react-promise-tracker'; import {OnboardingStackParams} from '../../routes'; import { @@ -26,6 +25,7 @@ import { TaggInput, TermsConditions, Background, + LoadingIndicator, } from '../../components'; import {passwordRegex, usernameRegex, REGISTER_ENDPOINT} from '../../constants'; import AsyncStorage from '@react-native-community/async-storage'; @@ -214,7 +214,7 @@ const RegistrationThree: React.FC<RegistrationThreeProps> = ({ <View style={styles.footer}> <ArrowButton direction="backward" - onPress={() => navigation.navigate('RegistrationOne')} + onPress={() => navigation.navigate('RegistrationTwo', {email: email})} /> <TouchableOpacity onPress={handleRegister}> <ArrowButton @@ -233,22 +233,10 @@ const RegistrationThree: React.FC<RegistrationThreeProps> = ({ </View> ); - /** - * An activity indicator to indicate that the app is working during the send_otp request. - */ - const LoadingIndicator = () => { - const {promiseInProgress} = usePromiseTracker(); - return promiseInProgress ? ( - <ActivityIndicator style={styles.load} size="large" color="#fff" /> - ) : ( - <></> - ); - }; - return ( <Background style={styles.container}> <StatusBar barStyle="light-content" /> - <RegistrationWizard style={styles.wizard} step="four" /> + <RegistrationWizard style={styles.wizard} step="five" /> <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.container}> diff --git a/src/screens/onboarding/RegistrationTwo.tsx b/src/screens/onboarding/RegistrationTwo.tsx index d28fb197..515059f9 100644 --- a/src/screens/onboarding/RegistrationTwo.tsx +++ b/src/screens/onboarding/RegistrationTwo.tsx @@ -134,7 +134,7 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({ <View style={styles.footer}> <ArrowButton direction="backward" - onPress={() => navigation.navigate('Login')} + onPress={() => navigation.navigate('RegistrationOne')} /> <TouchableOpacity onPress={goToRegisterThree}> <ArrowButton @@ -149,7 +149,7 @@ const RegistrationTwo: React.FC<RegistrationTwoProps> = ({ return ( <Background style={styles.container}> <StatusBar barStyle="light-content" /> - <RegistrationWizard style={styles.wizard} step="three" /> + <RegistrationWizard style={styles.wizard} step="four" /> <KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'} style={styles.container}> diff --git a/src/screens/onboarding/Verification.tsx b/src/screens/onboarding/Verification.tsx index 89f79ac8..91e6b181 100644 --- a/src/screens/onboarding/Verification.tsx +++ b/src/screens/onboarding/Verification.tsx @@ -8,6 +8,7 @@ import { RegistrationWizard, SubmitButton, ArrowButton, + LoadingIndicator, } from '../../components'; import {VERIFY_OTP_ENDPOINT, SEND_OTP_ENDPOINT} from '../../constants'; import {Text} from 'react-native-animatable'; @@ -23,10 +24,9 @@ import { TouchableOpacity, KeyboardAvoidingView, Alert, - ActivityIndicator, Platform, } from 'react-native'; -import {usePromiseTracker, trackPromise} from 'react-promise-tracker'; +import {trackPromise} from 'react-promise-tracker'; type VerificationScreenRouteProp = RouteProp< OnboardingStackParams, @@ -64,7 +64,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => { }), }); let statusCode = verifyOtpResponse.status; - if (statusCode == 200) { + if (statusCode === 200) { navigation.navigate('RegistrationTwo', { email: email, }); @@ -114,22 +114,6 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => { } }; - /** - * An activity indicator to indicate that the app is working during the verify_otp request. - */ - const LoadingIndicator = () => { - const {promiseInProgress} = usePromiseTracker(); - return promiseInProgress ? ( - <ActivityIndicator - style={styles.loadingIndicator} - size="large" - color="#fff" - /> - ) : ( - <></> - ); - }; - const Footer = () => ( <View style={styles.footer}> <ArrowButton @@ -141,7 +125,7 @@ const Verification: React.FC<VerificationProps> = ({route, navigation}) => { return ( <Background centered style={styles.container}> - <RegistrationWizard style={styles.wizard} step="two" /> + <RegistrationWizard style={styles.wizard} step="three" /> <KeyboardAvoidingView behavior="padding" style={styles.form}> <Text style={styles.formHeader}>Enter 6 digit code</Text> <Text style={styles.description}> diff --git a/src/screens/onboarding/index.ts b/src/screens/onboarding/index.ts index 041864b7..27a33d32 100644 --- a/src/screens/onboarding/index.ts +++ b/src/screens/onboarding/index.ts @@ -6,3 +6,4 @@ export {default as Verification} from './Verification'; export {default as Checkpoint} from './Checkpoint'; export {default as ProfileOnboarding} from './ProfileOnboarding'; export {default as Splash} from './Splash'; +export {default as InvitationCodeVerification} from './InvitationCodeVerification'; |