import React, { useEffect, useState } from "react";
import {
View,
Text,
TextInput,
TouchableOpacity,
ActivityIndicator,
Alert,
} from "react-native";
import {
useCrossmintAuth,
useWallet,
} from "@crossmint/client-sdk-react-native-ui";
import * as Linking from "expo-linking";
export default function Index() {
const {
loginWithOAuth,
createAuthSession,
user,
crossmintAuth,
logout,
status,
} = useCrossmintAuth();
const { wallet } = useWallet();
// Login state
const [email, setEmail] = useState("");
const [emailId, setEmailId] = useState("");
const [otpSent, setOtpSent] = useState(false);
const [otp, setOtp] = useState("");
const [isPending, setIsPending] = useState(false);
// Handle OAuth callback
const url = Linking.useURL();
// Handle OAuth callback
useEffect(() => {
if (url != null) {
createAuthSession(url);
}
}, [url, createAuthSession]);
// Login functions
const sendOtp = async () => {
if (!email.trim()) {
Alert.alert("Error", "Please enter a valid email address");
return;
}
setIsPending(true);
try {
const res = await crossmintAuth?.sendEmailOtp(email);
setEmailId(res.emailId);
setOtpSent(true);
} catch (error) {
console.error("sendOtp error:", error);
const message =
error instanceof Error
? error.message
: "Failed to send OTP.";
Alert.alert("Error", message);
} finally {
setIsPending(false);
}
};
const verifyOtp = async () => {
if (!otp.trim()) {
Alert.alert("Error", "Please enter the OTP code");
return;
}
setIsPending(true);
try {
const oneTimeSecret =
await crossmintAuth?.confirmEmailOtp(
email,
emailId,
otp
);
await createAuthSession(oneTimeSecret);
} catch (error) {
console.error("verifyOtp error:", error);
const message =
error instanceof Error
? error.message
: "Invalid OTP. Try again.";
Alert.alert("Error", message);
} finally {
setIsPending(false);
}
};
const handleLogout = async () => {
try {
logout();
// Reset login state
setEmail("");
setEmailId("");
setOtpSent(false);
setOtp("");
} catch (error) {
Alert.alert("Error", "Failed to logout. Please try again.");
}
};
// Loading state
if (status === "initializing") {
return (
<View style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
}}>
<ActivityIndicator size="large" />
<Text>Initializing...</Text>
</View>
);
}
// Login screen
if (status === "logged-out") {
return (
<View style={{
flex: 1,
padding: 20,
justifyContent: "center",
}}>
<Text style={{
fontSize: 24,
marginBottom: 20,
textAlign: "center",
}}>
Login
</Text>
<TextInput
style={{
borderWidth: 1,
padding: 10,
marginBottom: 10,
}}
placeholder="Enter your email"
value={email}
onChangeText={setEmail}
editable={!otpSent}
/>
{!otpSent ? (
<TouchableOpacity
style={{
backgroundColor: "#05b959",
padding: 15,
alignItems: "center",
}}
onPress={sendOtp}
disabled={isPending}
>
{isPending ? (
<ActivityIndicator
color="#fff"
size="small"
/>
) : (
<Text style={{ color: "#fff" }}>
Send OTP
</Text>
)}
</TouchableOpacity>
) : (
<>
<TextInput
style={{
borderWidth: 1,
padding: 10,
marginBottom: 10,
}}
placeholder="Enter OTP code"
value={otp}
onChangeText={setOtp}
/>
<TouchableOpacity
style={{
backgroundColor: "#05b959",
padding: 15,
alignItems: "center",
marginBottom: 10,
}}
onPress={verifyOtp}
disabled={isPending}
>
{isPending ? (
<ActivityIndicator
color="#fff"
size="small"
/>
) : (
<Text style={{ color: "#fff" }}>
Verify OTP
</Text>
)}
</TouchableOpacity>
<TouchableOpacity
style={{
backgroundColor: "#ccc",
padding: 15,
alignItems: "center",
}}
onPress={() => setOtpSent(false)}
disabled={isPending}
>
<Text>Back</Text>
</TouchableOpacity>
</>
)}
<View style={{ marginVertical: 20 }}>
<Text style={{
textAlign: "center",
marginBottom: 10,
}}>
OR
</Text>
<TouchableOpacity
style={{
backgroundColor: "#4285f4",
padding: 15,
alignItems: "center",
}}
onPress={
() => loginWithOAuth("google")
}
>
<Text style={{ color: "#fff" }}>
Sign in with Google
</Text>
</TouchableOpacity>
</View>
</View>
);
}
// Main app screen (logged in)
return (
<View style={{ flex: 1, padding: 20 }}>
<View
style={{
flexDirection: "row",
justifyContent: "space-between",
marginBottom: 20,
}}
>
<Text style={{ fontSize: 20 }}>
Welcome!
</Text>
<TouchableOpacity onPress={handleLogout}>
<Text style={{ color: "red" }}>
Logout
</Text>
</TouchableOpacity>
</View>
<View style={{ marginBottom: 20 }}>
<Text style={{
fontSize: 16,
marginBottom: 5,
}}>
User Info:
</Text>
<Text>Email: {user?.email}</Text>
<Text>User ID: {user?.id}</Text>
</View>
{wallet && (
<View style={{ marginBottom: 20 }}>
<Text style={{
fontSize: 16,
marginBottom: 5,
}}>
Wallet Info:
</Text>
<Text>
Address: {wallet.address}
</Text>
</View>
)}
<View>
<Text style={{
fontSize: 16,
marginBottom: 10,
}}>
App Content:
</Text>
<Text>
You are now logged in and can
access your wallet!
</Text>
</View>
</View>
);
}