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/PhoneVerification.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/PhoneVerification.tsx')
-rw-r--r-- | src/screens/onboarding/PhoneVerification.tsx | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/src/screens/onboarding/PhoneVerification.tsx b/src/screens/onboarding/PhoneVerification.tsx new file mode 100644 index 00000000..6ec511b3 --- /dev/null +++ b/src/screens/onboarding/PhoneVerification.tsx @@ -0,0 +1,225 @@ +import {RouteProp} from '@react-navigation/native'; +import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useMemo} from 'react'; +import { + Alert, + KeyboardAvoidingView, + Platform, + StyleSheet, + TouchableOpacity, + View, +} from 'react-native'; +import {Text} from 'react-native-animatable'; +import { + CodeField, + Cursor, + useBlurOnFulfill, + useClearByFocusCell, +} from 'react-native-confirmation-code-field'; +import {trackPromise} from 'react-promise-tracker'; +import { + ArrowButton, + Background, + LoadingIndicator, + RegistrationWizard, + SubmitButton, +} from '../../components'; +import {codeRegex} from '../../constants'; +import { + ERROR_INVALID_VERIFICATION_CODE_FORMAT, + ERROR_SOMETHING_WENT_WRONG, +} from '../../constants/strings'; +import {OnboardingStackParams} from '../../routes'; +import {sendOtp, verifyOtp} from '../../services'; +import {BackgroundGradientType} from '../../types'; +import {SCREEN_HEIGHT} from '../../utils'; + +type PhoneVerificationRouteProp = RouteProp< + OnboardingStackParams, + 'PhoneVerification' +>; +type PhoneVerificationNavigationProp = StackNavigationProp< + OnboardingStackParams, + 'PhoneVerification' +>; +interface PhoneVerificationProps { + route: PhoneVerificationRouteProp; + navigation: PhoneVerificationNavigationProp; +} + +const PhoneVerification: React.FC<PhoneVerificationProps> = ({ + route, + navigation, +}) => { + const [value, setValue] = React.useState(''); + const ref = useBlurOnFulfill({value, cellCount: 6}); + const [valueProps, getCellOnLayoutHandler] = useClearByFocusCell({ + value, + setValue, + }); + const {phone} = route.params; + + const handleVerification = async () => { + if (!codeRegex.test(value)) { + Alert.alert(ERROR_INVALID_VERIFICATION_CODE_FORMAT); + return; + } + try { + const success = await trackPromise(verifyOtp(phone, value)); + if (success) { + navigation.navigate('OnboardingStepTwo', { + ...route.params, + }); + } + } catch (error) { + console.log(error); + Alert.alert(ERROR_SOMETHING_WENT_WRONG); + } + }; + + const footer = useMemo( + () => ( + <View style={styles.footer}> + <ArrowButton + direction="backward" + onPress={() => navigation.navigate('OnboardingStepOne')} + /> + </View> + ), + [], + ); + + return ( + <Background + 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}> + We sent a 6 digit verification code to the phone number you provided. + </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 phone number verification code" + onPress={handleVerification} + /> + <TouchableOpacity onPress={() => sendOtp(phone)}> + <Text style={styles.resend}>Resend Code</Text> + </TouchableOpacity> + <LoadingIndicator /> + </KeyboardAvoidingView> + {footer} + </Background> + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + alignItems: 'center', + justifyContent: 'center', + }, + wizard: { + position: 'absolute', + top: SCREEN_HEIGHT * 0.1, + }, + form: { + top: '20%', + alignItems: 'center', + justifyContent: 'flex-start', + flex: 3, + }, + formPasswordVerification: { + alignItems: 'center', + justifyContent: 'flex-start', + flex: 3, + top: '35%', + }, + formHeader: { + color: '#fff', + fontSize: 20, + fontWeight: 'bold', + alignSelf: 'flex-start', + marginBottom: '6%', + marginHorizontal: '10%', + }, + description: { + color: '#fff', + fontWeight: '600', + fontSize: 17, + marginHorizontal: '10%', + }, + resend: { + textDecorationLine: 'underline', + color: '#fff', + fontSize: 15, + fontWeight: '600', + }, + 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%', + }, + loadingIndicator: { + marginVertical: '5%', + }, + footer: { + width: '100%', + flexDirection: 'row', + justifyContent: 'space-around', + ...Platform.select({ + ios: { + bottom: '20%', + }, + android: { + bottom: '10%', + }, + }), + }, +}); +export default PhoneVerification; |