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, View, } from 'react-native'; 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 {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 = ({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 [form, setForm] = useState({ fname: '', lname: '', username: '', phone: '', email: '', password: '', }); const goNext = 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, }); setValid(isValidName); break; case 1: setForm({ ...form, lname: name, }); setValid(isValidName); break; case 2: setForm({ ...form, username: name, }); setValid(usernameRegex.test(name)); break; } }; const handlePhoneUpdate = (phone: string) => { phone = phone.trim(); setForm({ ...form, phone, }); setValid(phoneRegex.test(phone)); }; const handleEmailUpdate = (email: string) => { email = email.trim(); setForm({ ...form, email, }); setValid(emailRegex.test(email)); }; const handlePasswordUpdate = (password: string) => { setForm({ ...form, password, }); 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); } }; 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 ( {/* getting rid of registration progress in onboarding*/} {/* */} {currentStep !== 0 && currentStep !== 3 && ( { // if I go back do I want to reset the previous form? setCurrentStep(currentStep - 1); resetForm(step.placeholder); setAttemptedSubmit(false); }} /> )} {step.placeholder === 'Phone' && !isPhoneVerified ? ( <> ) : ( <> {step.placeholder !== 'Password' ? ( <> SIGN UP ) : ( <> setPassVisibility(!passVisibility)}> Show Password )} )} ); }; const styles = StyleSheet.create({ container: { height: SCREEN_HEIGHT, width: SCREEN_WIDTH, alignItems: 'center', justifyContent: 'center', }, input: { minWidth: '60%', height: 40, fontSize: 16, fontWeight: '600', color: '#fff', paddingLeft: 13, borderBottomWidth: 1, borderBottomColor: '#fff', }, button: { width: 40, aspectRatio: 10, }, formHeader: { color: '#fff', fontSize: 30, fontWeight: '600', position: 'absolute', top: '20%', }, load: { top: '5%', }, tc: { marginVertical: '5%', }, footer: { width: '100%', flexDirection: 'row', justifyContent: 'space-around', ...Platform.select({ ios: { bottom: '20%', }, android: { bottom: '10%', }, }), }, }); export default BasicInfoOnboarding;