Skip to content

Commit

Permalink
register page and email verfication
Browse files Browse the repository at this point in the history
  • Loading branch information
Satora1 committed Sep 23, 2024
1 parent 23245f9 commit d6c9396
Show file tree
Hide file tree
Showing 9 changed files with 968 additions and 38 deletions.
1 change: 1 addition & 0 deletions .env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_cHJvbXB0LW1hZ2dvdC02MC5jbGVyay5hY2NvdW50cy5kZXYk
65 changes: 57 additions & 8 deletions app/(auth)/sign-in.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,62 @@
import { View, Text } from "react-native"
import { SafeAreaView } from "react-native-safe-area-context"
import { Link, router } from "expo-router";
import { useState } from "react";
import { Alert, Image, ScrollView, Text, View } from "react-native";

import CustomButton from "@/components/CustomButton";
import InputField from "@/components/InputField";
import { icons, images } from "@/constants";
import OAuth from "@/components/OAuth";

const SignIn = () => {
return(
<SafeAreaView>
<Text>
SignIn
</Text>
</SafeAreaView>
const [form, setForm] = useState({
email: '',
password: '',
})
const onSignInPress = async () => {

}
return (
<ScrollView className="flex-1 bg-white">
<View className="flex-1 bg-white">
<View className="relative w-full h-[250px]">
<Image source={images.signUpCar} className="z-0 w-full h-[250px]" />
<Text className="text-2xl text-black font-JakartaSemiBold absolute bottom-5 left-5">
Welcome
</Text>
</View>
<View className="p-5">
<InputField
label="Email"
placeholder="Enter email"
icon={icons.email}
textContentType="emailAddress"
value={form.email}
onChangeText={(value) => setForm({ ...form, email: value })}
/>
<InputField
label="Password"
placeholder="Enter password"
icon={icons.lock}
secureTextEntry={true}
textContentType="password"
value={form.password}
onChangeText={(value) => setForm({ ...form, password: value })}
/>
<CustomButton title="Sign In" onPress={onSignInPress} className="mt-6" />

<OAuth />

<Link href="/sign-up" className="text-lg text-center-general-200 mt-10">
<Text>
Dont have an account
<Text className="text-primary-500">
Sign up
</Text>
</Text>
</Link>
</View>
</View>
</ScrollView>
)
}

Expand Down
98 changes: 94 additions & 4 deletions app/(auth)/sign-up.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,71 @@
import { useSignUp } from "@clerk/clerk-expo";
import { Link, router } from "expo-router";
import { useState } from "react";
import { Alert, Image, ScrollView, Text, View } from "react-native";

import { ReactNativeModal } from "react-native-modal";
import CustomButton from "@/components/CustomButton";
import InputField from "@/components/InputField";
import { icons, images } from "@/constants";
import OAuth from "@/components/OAuth";

import { icons, images } from "@/constants";
const SignUp = () => {
const { isLoaded, signUp, setActive } = useSignUp()

const [form, setForm] = useState({
name: "",
email: '',
password: '',
})

const [verification, setVerification] = useState({
state: "default",
error: "",
code: ""
})
const onSignUpPress = async () => {
if (!isLoaded) {
return
}

try {
await signUp.create({
emailAddress: form.email,
password: form.password,
})

await signUp.prepareEmailAddressVerification({ strategy: 'email_code' })

setVerification({
...verification,
state: "pending"
})
} catch (err: any) {
// See https://clerk.com/docs/custom-flows/error-handling
// for more info on error handling
Alert.alert("Error", err.errors[0].longMessage)
}
}

const onPressVerify = async () => {
if (!isLoaded) return



try {
const completeSignUp = await signUp.attemptEmailAddressVerification({
code: verification.code,
})

if (completeSignUp.status === 'complete') {

await setActive({ session: completeSignUp.createdSessionId })
setVerification({ ...verification, state: "sucess" })
} else {
setVerification({ ...verification, error: "verification failed", state: "failed" })

}
} catch (err: any) {
setVerification({ ...verification, error: err.errors[0].longMessage, state: "failed" })
}
}
return (
<ScrollView className="flex-1 bg-white">
Expand Down Expand Up @@ -51,7 +102,7 @@ const SignUp = () => {
onChangeText={(value) => setForm({ ...form, password: value })}
/>
<CustomButton title="Sign Up" onPress={onSignUpPress} className="mt-6" />

<OAuth />

<Link href="/sign-in" className="text-lg text-center-general-200 mt-10">
Expand All @@ -63,6 +114,45 @@ const SignUp = () => {
</Text>
</Link>
</View>
<ReactNativeModal isVisible={verification.state === "pending"}
onModalHide={() => setVerification({ ...verification, state: "success" })}>
<View className="bg-white px-7 py-9 rounded-2xl min-h-[300px]">
<Text className="text-2xl font-JakartaExtraBold mb-2 ">
Verification
</Text>
<Text className="font-Jakarta mb-5">
We sent a verification code to {form.email}
</Text>
<InputField
label="Code"
icon={icons.lock}
placeholder="12345"
value={verification.code}
keyboardType="numeric"
onChangeText={(code) => setVerification({ ...verification, code })}
/>
{verification.error && (
<Text className="text-red-500 text-sm mt-1">
{verification.error}
</Text>
)}
<CustomButton title="Verify Email" onPress={onPressVerify} className="mt-5 bg-success-500" />
</View>
</ReactNativeModal>
<ReactNativeModal isVisible={verification.state === "success"}>

<View className="bg-white px-7 py-9 rounded-2xl min-h-[300px]">
<Image source={images.check} className="w-[110px] h-[110px] mx-auto my-5" />
<Text className="text-3xl font-JakartaBold text-center">
Verified

</Text>
<Text className="text-base text-gray-400 font-Jakarta text-center mt-2">
You have succesfully veryfied your account
</Text>
<CustomButton title="Broswer Home" onPress={() => router.replace("/(root)/(tabs)/home")} className="mt-5" />
</View>
</ReactNativeModal>
</View>
</ScrollView>
)
Expand Down
33 changes: 21 additions & 12 deletions app/(root)/(tabs)/home.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { View, Text } from "react-native"
import { SafeAreaView } from "react-native-safe-area-context"
import { SignedIn, SignedOut, useUser } from '@clerk/clerk-expo'
import { Link } from 'expo-router'
import { Text, View } from 'react-native'

const Home = () => {
return(
<SafeAreaView>
<Text>
Home
</Text>
</SafeAreaView>
)
}
export default function Page() {
const { user } = useUser()

export default Home;
return (
<View>
<SignedIn>
<Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
</SignedIn>
<SignedOut>
<Link href="/sign-in">
<Text>Sign In</Text>
</Link>
<Link href="/sign-up">
<Text>Sign Up</Text>
</Link>
</SignedOut>
</View>
)
}
29 changes: 23 additions & 6 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,19 @@ import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
import 'react-native-reanimated';

import { ClerkProvider, ClerkLoaded } from '@clerk/clerk-expo'
import { Slot } from 'expo-router'

const publishableKey = process.env.EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY!



if (!publishableKey) {
throw new Error(
'Missing Publishable Key. Please set EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY in your .env',
)
}


// Prevent the splash screen from auto-hiding before asset loading is complete.
SplashScreen.preventAutoHideAsync();
Expand All @@ -30,11 +43,15 @@ export default function RootLayout() {
}

return (
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="(root)" options={{ headerShown: false }} />
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
<ClerkProvider publishableKey={publishableKey}>
<ClerkLoaded>
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="(root)" options={{ headerShown: false }} />
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
</ClerkLoaded>
</ClerkProvider>
);
}
8 changes: 7 additions & 1 deletion app/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { useAuth } from "@clerk/clerk-expo"
import { Redirect } from "expo-router"


const Home = () => {
const { isSignedIn } = useAuth()

if (isSignedIn) {
return <Redirect href={'/(root)/(tabs)/home'} />
}
return <Redirect href="/(auth)/welcome/"></Redirect>


}

export default Home;
33 changes: 33 additions & 0 deletions lib/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

import * as SecureStore from 'expo-secure-store'

export interface TokenCache {
getToken: (key: string) => Promise<string | undefined | null>
saveToken: (key: string, token: string) => Promise<void>
clearToken?: (key: string) => void
}

export const tokenCache = {
async getToken(key: string) {
try {
const item = await SecureStore.getItemAsync(key)
if (item) {
console.log(`${key} was used 🔐 \n`)
} else {
console.log('No values stored under key: ' + key)
}
return item
} catch (error) {
console.error('SecureStore get item error: ', error)
await SecureStore.deleteItemAsync(key)
return null
}
},
async saveToken(key: string, value: string) {
try {
return SecureStore.setItemAsync(key, value)
} catch (err) {
return
}
},
}
Loading

0 comments on commit d6c9396

Please sign in to comment.