Files
tattletires/app/(auth)/sign-up.tsx

202 lines
6.8 KiB
TypeScript

import { isClerkAPIResponseError, useSignUp } from '@clerk/clerk-expo'
import { ClerkAPIError } from '@clerk/types'
import { router } from 'expo-router'
import { useState } from 'react'
import { StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native'
export default function SignUpScreen() {
const { signUp, setActive, isLoaded } = useSignUp()
const [pendingVerification, setPendingVerification] = useState(false)
const [code, setCode] = useState('')
const [errors, setErrors] = useState<ClerkAPIError[]>([])
const [fname, setFname] = useState('')
const [lname, setLname] = useState('')
const [email, setUsername] = useState('')
const [password, setPassword] = useState('')
async function onSignUpPress() {
if (!isLoaded) return
setErrors([])
try {
// Start Auth
await signUp.create({
firstName: fname,
lastName: lname,
emailAddress: email,
password
})
// Set confirmation
await signUp.prepareEmailAddressVerification()
setPendingVerification(true)
} catch (e) {
if (isClerkAPIResponseError(e)) setErrors(e.errors)
console.log(JSON.stringify(e))
}
}
async function onVerifyPress() {
if (!isLoaded) return
setErrors([])
try {
// Use the code the user provided to attempt verification
const signUpAttempt = await signUp.attemptEmailAddressVerification({
code
})
// If verification was completed, set the session to active
// and redirect the user
if (signUpAttempt.status === 'complete') {
await createUser(signUpAttempt.createdUserId)
await setActive({ session: signUpAttempt.createdSessionId })
} else {
// If the status is not complete, check why. User may need to
// complete further steps.
console.error(JSON.stringify(signUpAttempt, null, 2))
}
} catch (e: any) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
console.error(JSON.stringify(e, null, 2))
setErrors(e.errors)
}
}
async function createUser(clerkUserID: string | null) {
fetch('http://localhost:3000/api/v1/users', {
method: 'POST',
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: `${fname} ${lname}`,
email,
clerkUserID
})
})
}
if (pendingVerification) {
return (
<View style={styles.container}>
<Text style={styles.textCenter}>Enter the verification code we sent to {email}</Text>
<TextInput
style={styles.input}
value={code}
placeholder='Enter your verification code'
onChangeText={(code) => setCode(code)}
/>
<TouchableOpacity onPress={onVerifyPress} style={styles.button}>
<Text>Verify</Text>
</TouchableOpacity>
{errors.map((error) => (
<Text key={error.longMessage} style={{ color: 'red' }}>
{error.longMessage}
</Text>
))}
</View>
)
}
return (
<View style={styles.container}>
<>
<Text style={styles.text}>Create an account</Text>
<View style={{ width: '80%', marginTop: 20 }}>
<Text style={styles.textlabel}>First name</Text>
<TextInput
style={styles.input}
value={fname}
placeholder='Enter first name'
onChangeText={setFname}
/>
<Text style={styles.textlabel}>Last name</Text>
<TextInput
style={styles.input}
value={lname}
placeholder='Enter last name'
onChangeText={setLname}
/>
<Text style={styles.textlabel}>Email</Text>
<TextInput
style={styles.input}
value={email}
placeholder='Enter email'
onChangeText={setUsername}
/>
<Text style={styles.textlabel}>Password</Text>
<TextInput
style={styles.input}
value={password}
placeholder='Enter password'
secureTextEntry
onChangeText={setPassword}
/>
<TouchableOpacity
style={styles.button}
onPress={() => {
onSignUpPress()
}}
>
<Text style={{ color: '#fff', fontWeight: 'bold' }}>Sign Up</Text>
</TouchableOpacity>
<Text style={styles.textCenter}>Already have an account?</Text>
<TouchableOpacity
style={styles.signIn}
onPress={() => {
router.navigate('/sign-in')
}}
>
<Text style={{ color: '#fff' }}>Sign In</Text>
</TouchableOpacity>{' '}
</View>
{errors.map((error) => (
<Text key={error.longMessage} style={{ color: 'red' }}>
{error.longMessage}
</Text>
))}
</>
</View>
)
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#25292e',
justifyContent: 'center',
alignItems: 'center'
},
text: {
color: '#fff'
},
textCenter: {
color: '#ffffff',
alignSelf: 'center',
marginBottom: 12
},
textlabel: {
color: '#fff',
marginBottom: 3
},
input: {
backgroundColor: '#fff',
borderRadius: 5,
padding: 10,
marginBottom: 15
},
button: {
backgroundColor: '#1e90ff',
padding: 12,
borderRadius: 5,
alignItems: 'center',
marginBottom: 15
},
signIn: {
alignItems: 'center'
}
})