diff options
| author | Ivan Chen <ivan@tagg.id> | 2021-03-05 16:38:32 -0500 | 
|---|---|---|
| committer | Ivan Chen <ivan@tagg.id> | 2021-03-05 16:38:32 -0500 | 
| commit | 1465df9621fb963ff873485ad927ff79ea547fa0 (patch) | |
| tree | affcb43f37f263f3e0e555dd019dd952b62e1f0a /src/screens/onboarding/OnboardingStepOne.tsx | |
| parent | 2360e774d94e271d1d9db0d5b92b801b9325535e (diff) | |
| parent | b1dee65ee7bb8e120fc38a495f4027905d300650 (diff) | |
Merge branch 'master' into tma-634-badge-selection-screen
# Conflicts:
#	src/components/taggs/SocialMediaInfo.tsx
Diffstat (limited to 'src/screens/onboarding/OnboardingStepOne.tsx')
| -rw-r--r-- | src/screens/onboarding/OnboardingStepOne.tsx | 263 | 
1 files changed, 263 insertions, 0 deletions
| diff --git a/src/screens/onboarding/OnboardingStepOne.tsx b/src/screens/onboarding/OnboardingStepOne.tsx new file mode 100644 index 00000000..0fa7a6a5 --- /dev/null +++ b/src/screens/onboarding/OnboardingStepOne.tsx @@ -0,0 +1,263 @@ +import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useMemo, useRef, useState} from 'react'; +import { +  Alert, +  KeyboardAvoidingView, +  Platform, +  StatusBar, +  StyleSheet, +  Text, +  TouchableOpacity, +  View, +} from 'react-native'; +import { +  ArrowButton, +  Background, +  RegistrationWizard, +  TaggInput, +} 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'; + +type OnboardingStepOneNavigationProp = StackNavigationProp< +  OnboardingStackParams, +  'OnboardingStepOne' +>; +interface OnboardingStepOneProps { +  navigation: OnboardingStepOneNavigationProp; +} + +const OnboardingStepOne: React.FC<OnboardingStepOneProps> = ({navigation}) => { +  const lnameRef = useRef(); +  const emailRef = useRef(); +  const phoneRef = useRef(); + +  const handleFocusChange = (field: string): void => { +    switch (field) { +      case 'lname': +        const lnameField: any = lnameRef.current; +        lnameField.focus(); +        break; +      case 'email': +        const emailField: any = emailRef.current; +        emailField.focus(); +        break; +      case 'phone': +        const phoneField: any = phoneRef.current; +        phoneField.focus(); +        break; +      default: +        return; +    } +  }; + +  const [form, setForm] = useState({ +    fname: '', +    lname: '', +    phone: '', +    isValidFname: false, +    isValidLname: false, +    isValidPhone: false, +    attemptedSubmit: false, +    token: '', +  }); + +  const handleFnameUpdate = (fname: string) => { +    fname = fname.trim(); +    let isValidFname: boolean = nameRegex.test(fname); +    setForm({ +      ...form, +      fname, +      isValidFname, +    }); +  }; + +  const handleLnameUpdate = (lname: string) => { +    lname = lname.trim(); +    let isValidLname: boolean = nameRegex.test(lname); +    setForm({ +      ...form, +      lname, +      isValidLname, +    }); +  }; + +  const handlePhoneUpdate = (phone: string) => { +    phone = phone.trim(); +    let isValidPhone: boolean = phoneRegex.test(phone); +    setForm({ +      ...form, +      phone, +      isValidPhone, +    }); +  }; + +  const goNext = async () => { +    if (!form.attemptedSubmit) { +      setForm({ +        ...form, +        attemptedSubmit: true, +      }); +    } +    try { +      if (form.isValidFname && form.isValidLname && form.isValidPhone) { +        const code = await sendOtpStatusCode(form.phone); +        if (code) { +          switch (code) { +            case 200: +              navigation.navigate('PhoneVerification', { +                firstName: form.fname, +                lastName: form.lname, +                phone: form.phone, +              }); +              break; +            case 409: +              Alert.alert(ERROR_PHONE_IN_USE); +              break; +            default: +              Alert.alert(ERROR_TWILIO_SERVER_ERROR); +          } +        } +      } else { +        setForm({...form, attemptedSubmit: false}); +        setTimeout(() => setForm({...form, attemptedSubmit: true})); +      } +    } catch (error) { +      Alert.alert(ERROR_NEXT_PAGE); +      return { +        name: 'Navigation error', +        description: error, +      }; +    } +  }; + +  const footer = useMemo( +    () => ( +      <View style={styles.footer}> +        <ArrowButton +          direction="backward" +          onPress={() => navigation.navigate('Login')} +        /> +        <TouchableOpacity onPress={goNext}> +          <ArrowButton +            direction="forward" +            disabled={ +              !(form.isValidFname && form.isValidLname && form.isValidPhone) +            } +            onPress={goNext} +          /> +        </TouchableOpacity> +      </View> +    ), +    [form.isValidFname, form.isValidLname, form.isValidPhone], +  ); + +  return ( +    <Background +      style={styles.container} +      gradientType={BackgroundGradientType.Light}> +      <StatusBar barStyle="light-content" /> +      <RegistrationWizard style={styles.wizard} step="one" /> +      <KeyboardAvoidingView +        behavior={Platform.OS === 'ios' ? 'padding' : 'height'} +        style={styles.container}> +        <View> +          <Text style={styles.formHeader}>ENTER NAME</Text> +        </View> +        <TaggInput +          accessibilityHint="Enter your first name." +          accessibilityLabel="First name input field." +          placeholder="First Name" +          autoCompleteType="name" +          textContentType="name" +          returnKeyType="next" +          onChangeText={handleFnameUpdate} +          onSubmitEditing={() => handleFocusChange('lname')} +          blurOnSubmit={false} +          valid={form.isValidFname} +          invalidWarning="Please enter a valid first name." +          attemptedSubmit={form.attemptedSubmit} +          width={280} +        /> +        <TaggInput +          accessibilityHint="Enter your last name." +          accessibilityLabel="Last name input field." +          placeholder="Last Name" +          autoCompleteType="name" +          textContentType="name" +          returnKeyType="next" +          onChangeText={handleLnameUpdate} +          blurOnSubmit={false} +          ref={lnameRef} +          valid={form.isValidLname} +          invalidWarning="Please enter a valid last name." +          attemptedSubmit={form.attemptedSubmit} +          width={280} +        /> +        <TaggInput +          maxLength={10} // 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" +          keyboardType="number-pad" +          onChangeText={handlePhoneUpdate} +          blurOnSubmit={false} +          ref={phoneRef} +          valid={form.isValidPhone} +          invalidWarning={'Please enter a valid 10 digit number.'} +          attemptedSubmit={form.attemptedSubmit} +          width={280} +          onSubmitEditing={goNext} +        /> +      </KeyboardAvoidingView> +      {footer} +    </Background> +  ); +}; + +const styles = StyleSheet.create({ +  container: { +    flex: 1, +    alignItems: 'center', +    justifyContent: 'center', +  }, +  wizard: { +    position: 'absolute', +    top: SCREEN_HEIGHT * 0.1, +  }, +  formHeader: { +    color: '#fff', +    fontSize: 30, +    fontWeight: '600', +    marginBottom: '16%', +  }, +  load: { +    top: '5%', +  }, +  footer: { +    width: '100%', +    flexDirection: 'row', +    justifyContent: 'space-around', +    ...Platform.select({ +      ios: { +        bottom: '20%', +      }, +      android: { +        bottom: '10%', +      }, +    }), +  }, +}); + +export default OnboardingStepOne; | 
