-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/sign in mobile #209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Feat/sign in mobile #209
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
d1391f1
basic structure done
manueltorres0 0fee3a6
basic styling on auth
manueltorres0 fa04c6f
fixed the sign up missing field
manueltorres0 608033a
lint
manueltorres0 77925dc
lint
manueltorres0 ccb0ad2
fixes
manueltorres0 d196fea
lint#
manueltorres0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| import { ClerkStatus } from "@/constants/clerk"; | ||
| import { useClerkErrorHandler } from "@/hooks/useClerkErrorHandler"; | ||
| import { useSignIn } from "@clerk/clerk-expo"; | ||
| import { Link, router } from "expo-router"; | ||
| import { useState } from "react"; | ||
| import { | ||
| Pressable, | ||
| TextInput, | ||
| View, | ||
| Text, | ||
| Keyboard, | ||
| TouchableWithoutFeedback, | ||
| } from "react-native"; | ||
|
|
||
| export default function Login() { | ||
| const { isLoaded, signIn, setActive } = useSignIn(); | ||
| const [email, setEmail] = useState<string>(""); | ||
| const [password, setPassword] = useState<string>(""); | ||
| const [error, setError] = useState(""); | ||
| const handleClerkAction = useClerkErrorHandler(setError); | ||
|
|
||
| const onLogin = () => | ||
| handleClerkAction(async () => { | ||
| if (!isLoaded || !signIn || !setActive) return; | ||
| const result = await signIn.create({ identifier: email, password }); | ||
| if (result.status === ClerkStatus.Complete) { | ||
| await setActive({ session: result.createdSessionId }); | ||
| router.replace("/home"); | ||
| } | ||
| }); | ||
|
|
||
| return ( | ||
| <TouchableWithoutFeedback onPress={Keyboard.dismiss}> | ||
| <View className="flex-1 justify-center px-6 bg-white"> | ||
| <Text className="text-2xl font-bold text-primary mb-2"> | ||
| Welcome back | ||
| </Text> | ||
| <Text className="text-sm text-shadow-strong mb-8"> | ||
| Sign in to your account | ||
| </Text> | ||
|
|
||
| <View className="gap-y-3 mb-4"> | ||
| <TextInput | ||
| value={email} | ||
| onChangeText={setEmail} | ||
| placeholder="Email" | ||
| keyboardType="email-address" | ||
| autoCapitalize="none" | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base" | ||
| /> | ||
| <TextInput | ||
| value={password} | ||
| onChangeText={setPassword} | ||
| placeholder="Password" | ||
| secureTextEntry | ||
| autoCapitalize="none" | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base" | ||
| /> | ||
| </View> | ||
|
|
||
| {error && <Text className="text-danger text-sm mb-4">{error}</Text>} | ||
|
|
||
| <Pressable | ||
| onPress={onLogin} | ||
| className="bg-primary rounded-xl py-4 items-center mb-4 active:opacity-80" | ||
| > | ||
| <Text className="text-white font-semibold text-base">Sign in</Text> | ||
| </Pressable> | ||
|
|
||
| <Link | ||
| href="/sign-up" | ||
| className="text-center text-sm text-shadow-strong" | ||
| > | ||
| Do not have an account?{" "} | ||
| <Text className="text-primary font-medium">Sign up</Text> | ||
| </Link> | ||
| </View> | ||
| </TouchableWithoutFeedback> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import { useClerkErrorHandler } from "@/hooks/useClerkErrorHandler"; | ||
| import { useSignUp } from "@clerk/clerk-expo"; | ||
| import { Link, router } from "expo-router"; | ||
| import { useState } from "react"; | ||
| import { | ||
| Pressable, | ||
| TextInput, | ||
| View, | ||
| Text, | ||
| Keyboard, | ||
| TouchableWithoutFeedback, | ||
| } from "react-native"; | ||
|
|
||
| export default function SignUp() { | ||
| const { isLoaded, signUp } = useSignUp(); | ||
| const [email, setEmail] = useState<string>(""); | ||
| const [password, setPassword] = useState<string>(""); | ||
| const [firstName, setFirstName] = useState(""); | ||
| const [lastName, setLastName] = useState(""); | ||
| const [error, setError] = useState(""); | ||
| const handleClerkAction = useClerkErrorHandler(setError); | ||
|
|
||
| const onSignUp = () => | ||
| handleClerkAction(async () => { | ||
| if (!isLoaded) return; | ||
| await signUp.create({ | ||
| emailAddress: email, | ||
| password, | ||
| firstName, | ||
| lastName, | ||
| }); | ||
| await signUp.prepareEmailAddressVerification({ strategy: "email_code" }); | ||
| router.push(`/verify?email=${email}`); | ||
| }); | ||
|
|
||
| return ( | ||
| <TouchableWithoutFeedback onPress={Keyboard.dismiss}> | ||
| <View className="flex-1 justify-center px-6 bg-white"> | ||
| <Text className="text-2xl font-bold text-primary mb-2"> | ||
| Create account | ||
| </Text> | ||
| <Text className="text-sm text-shadow-strong mb-8"> | ||
| Sign up to get started | ||
| </Text> | ||
|
|
||
| <View className="gap-y-3 mb-4"> | ||
| <TextInput | ||
| value={firstName} | ||
| onChangeText={setFirstName} | ||
| placeholder="First name" | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base" | ||
| /> | ||
| <TextInput | ||
| value={lastName} | ||
| onChangeText={setLastName} | ||
| placeholder="Last name" | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base" | ||
| /> | ||
| <TextInput | ||
| value={email} | ||
| onChangeText={setEmail} | ||
| placeholder="Email" | ||
| keyboardType="email-address" | ||
| autoCapitalize="none" | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base" | ||
| /> | ||
| <TextInput | ||
| value={password} | ||
| onChangeText={setPassword} | ||
| placeholder="Password" | ||
| secureTextEntry | ||
| autoCapitalize="none" | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base" | ||
| /> | ||
| </View> | ||
|
|
||
| {error && <Text className="text-danger text-sm mb-4">{error}</Text>} | ||
|
|
||
| <Pressable | ||
| onPress={onSignUp} | ||
| className="bg-primary rounded-xl py-4 items-center mb-4 active:opacity-80" | ||
| > | ||
| <Text className="text-white font-semibold text-base">Sign Up</Text> | ||
| </Pressable> | ||
|
|
||
| <Link | ||
| href="/sign-in" | ||
| className="text-center text-sm text-shadow-strong" | ||
| > | ||
| Already have an account?{" "} | ||
| <Text className="text-primary font-medium">Sign in</Text> | ||
| </Link> | ||
| </View> | ||
| </TouchableWithoutFeedback> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| import { ClerkStatus } from "@/constants/clerk"; | ||
| import { useClerkErrorHandler } from "@/hooks/useClerkErrorHandler"; | ||
| import { useSignUp } from "@clerk/clerk-expo"; | ||
| import { router, useLocalSearchParams } from "expo-router"; | ||
| import { useState } from "react"; | ||
| import { | ||
| Pressable, | ||
| TextInput, | ||
| Text, | ||
| View, | ||
| Keyboard, | ||
| TouchableWithoutFeedback, | ||
| } from "react-native"; | ||
|
|
||
| export default function VerifyEmail() { | ||
| const { isLoaded, signUp, setActive } = useSignUp(); | ||
| const { email } = useLocalSearchParams(); | ||
| const [code, setCode] = useState(""); | ||
| const [error, setError] = useState(""); | ||
| const handleClerkAction = useClerkErrorHandler(setError); | ||
|
|
||
| const onVerify = () => | ||
| handleClerkAction(async () => { | ||
| if (!isLoaded) return; | ||
| const result = await signUp.attemptEmailAddressVerification({ code }); | ||
| if (result.status === ClerkStatus.Complete) { | ||
| await setActive({ session: result.createdSessionId }); | ||
| router.replace("/home"); | ||
| } | ||
| }); | ||
|
|
||
| const onResend = () => | ||
| handleClerkAction(async () => { | ||
| if (!isLoaded) return; | ||
| await signUp.prepareEmailAddressVerification({ strategy: "email_code" }); | ||
| }); | ||
|
|
||
| return ( | ||
| <TouchableWithoutFeedback onPress={Keyboard.dismiss}> | ||
| <View className="flex-1 justify-center px-6 bg-white"> | ||
| <Text className="text-2xl font-bold text-primary mb-2"> | ||
| Check your email | ||
| </Text> | ||
| <Text className="text-sm text-shadow-strong mb-8"> | ||
| Verification code sent to {email} | ||
| </Text> | ||
|
|
||
| <TextInput | ||
| value={code} | ||
| onChangeText={setCode} | ||
| placeholder="Enter code" | ||
| keyboardType="number-pad" | ||
| autoComplete="one-time-code" | ||
| autoFocus | ||
| className="border border-stroke-subtle rounded-xl px-4 py-3 text-base mb-4" | ||
| /> | ||
|
|
||
| {error && <Text className="text-danger text-sm mb-4">{error}</Text>} | ||
|
|
||
| <Pressable | ||
| onPress={onVerify} | ||
| className="bg-primary rounded-xl py-4 items-center mb-3 active:opacity-80" | ||
| > | ||
| <Text className="text-white font-semibold text-base">Verify</Text> | ||
| </Pressable> | ||
|
|
||
| <Pressable | ||
| onPress={onResend} | ||
| className="py-3 items-center active:opacity-80" | ||
| > | ||
| <Text className="text-primary text-sm font-medium">Resend code</Text> | ||
| </Pressable> | ||
| </View> | ||
| </TouchableWithoutFeedback> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import LogoutButton from "@/components/Logout"; | ||
| import { router } from "expo-router"; | ||
| import { View } from "react-native"; | ||
|
|
||
| export default function Profile() { | ||
| const onSignOut = () => { | ||
| router.replace("/sign-in"); | ||
| }; | ||
|
|
||
| return ( | ||
| <View className="flex-1 justify-center px-6"> | ||
| <LogoutButton onSignOut={onSignOut} /> | ||
| </View> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| import { Text, View, Pressable } from "react-native"; | ||
| import { router } from "expo-router"; | ||
|
|
||
| export default function Page() { | ||
| return ( | ||
| <View className="flex-1 items-center p-6"> | ||
| <View className="flex-1 justify-center max-w-4xl mx-auto"> | ||
| <Text className="text-6xl font-bold">Hello</Text> | ||
| <Text className="text-4xl text-gray-700">World</Text> | ||
| <Pressable | ||
| onPress={() => router.push("/(tabs)/explore")} | ||
| className="bg-primary rounded-xl py-4 items-center mt-8 active:opacity-80" | ||
| > | ||
| <Text>Go to tabs</Text> | ||
| </Pressable> | ||
| </View> | ||
| </View> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,19 @@ | ||
| import { StyleSheet, Text, View } from "react-native"; | ||
| import { useAuth } from "@clerk/clerk-expo"; | ||
| import { useRouter } from "expo-router"; | ||
| import { useEffect } from "react"; | ||
|
|
||
| export default function Page() { | ||
| return ( | ||
| <View className="flex-1 items-center p-6"> | ||
| <View className="flex-1 justify-center max-w-4xl mx-auto"> | ||
| <Text className="text-6xl font-bold">Hello</Text> | ||
| <Text className="text-4xl text-gray-700">World</Text> | ||
| </View> | ||
| </View> | ||
| ); | ||
| export default function Index() { | ||
| const { isLoaded, isSignedIn } = useAuth(); | ||
| const router = useRouter(); | ||
|
|
||
| useEffect(() => { | ||
| if (!isLoaded) return; | ||
| if (isSignedIn) { | ||
| router.replace("/home"); | ||
| } else { | ||
| router.replace("/sign-in"); | ||
| } | ||
| }, [router, isLoaded, isSignedIn]); | ||
|
|
||
| return null; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| import { useClerk } from "@clerk/clerk-expo"; | ||
| import { Pressable, Text } from "react-native"; | ||
|
|
||
| export default function LogoutButton({ onSignOut }: { onSignOut: () => void }) { | ||
| const { signOut } = useClerk(); | ||
|
|
||
| const onPress = async () => { | ||
| await signOut(); | ||
| onSignOut(); | ||
| }; | ||
|
|
||
| return ( | ||
| <Pressable | ||
| onPress={onPress} | ||
| className="border border-danger rounded-xl py-4 items-center active:opacity-80" | ||
| > | ||
| <Text className="text-danger font-semibold text-base">Sign Out</Text> | ||
| </Pressable> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| export enum ClerkStatus { | ||
| Complete = "complete", | ||
| MissingRequirements = "missing_requirements", | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| export const useClerkErrorHandler = (setError: (msg: string) => void) => { | ||
| const run = async (action: () => Promise<void>) => { | ||
| setError(""); | ||
| try { | ||
| await action(); | ||
| } catch (err: any) { | ||
| setError(err.errors?.[0]?.message); | ||
| } | ||
| }; | ||
|
|
||
| return run; | ||
| }; | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good but just wanna double check that this is standard error format for all errors returned by clerk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, just double checked