Files
bw-expo-app/app/(auth)/register.tsx
imeepos 7e3f94bae3 Initial commit: Expo app with Better Auth integration
- Complete Expo React Native app setup with TypeScript
- Better Auth authentication system integration
- Secure storage implementation for session tokens
- Authentication flow with login/logout functionality
- API client configuration for backend communication
- Responsive UI components with themed styling
- Expo Router navigation setup
- Development configuration and scripts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-14 10:32:52 +08:00

192 lines
4.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from "react";
import {
View,
TextInput,
StyleSheet,
Alert,
KeyboardAvoidingView,
Platform,
TouchableOpacity,
ActivityIndicator,
ScrollView,
} from "react-native";
import { router } from "expo-router";
import { authClient } from "@/lib/auth/client";
import { ThemedView } from "@/components/themed-view";
import { ThemedText } from "@/components/themed-text";
export default function RegisterScreen() {
const [username, setUsername] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [isLoading, setIsLoading] = useState(false);
const handleRegister = async () => {
if (!username.trim() || !email.trim() || !password.trim()) {
Alert.alert("错误", "请填写所有必填字段");
return;
}
if (password !== confirmPassword) {
Alert.alert("错误", "两次输入的密码不一致");
return;
}
if (password.length < 6) {
Alert.alert("错误", "密码长度至少为 6 位");
return;
}
setIsLoading(true);
try {
await authClient.signUp.email({
email: email.trim(),
password,
name: username.trim(),
});
Alert.alert("注册成功", "请登录您的账号", [
{ text: "确定", onPress: () => router.replace("/(auth)/login") },
]);
} catch (error: any) {
Alert.alert("注册失败", error?.message || "注册失败,请稍后重试");
} finally {
setIsLoading(false);
}
};
return (
<KeyboardAvoidingView
behavior={Platform.OS === "ios" ? "padding" : "height"}
style={styles.container}
>
<ScrollView contentContainerStyle={styles.scrollContent}>
<ThemedView style={styles.content}>
<ThemedText type="title" style={styles.title}>
</ThemedText>
<ThemedText style={styles.subtitle}></ThemedText>
<View style={styles.form}>
<TextInput
style={styles.input}
placeholder="用户名"
value={username}
onChangeText={setUsername}
autoCapitalize="none"
autoCorrect={false}
editable={!isLoading}
/>
<TextInput
style={styles.input}
placeholder="邮箱"
value={email}
onChangeText={setEmail}
autoCapitalize="none"
keyboardType="email-address"
autoCorrect={false}
editable={!isLoading}
/>
<TextInput
style={styles.input}
placeholder="密码(至少 6 位)"
value={password}
onChangeText={setPassword}
secureTextEntry
editable={!isLoading}
/>
<TextInput
style={styles.input}
placeholder="确认密码"
value={confirmPassword}
onChangeText={setConfirmPassword}
secureTextEntry
editable={!isLoading}
/>
<TouchableOpacity
style={[styles.button, isLoading && styles.buttonDisabled]}
onPress={handleRegister}
disabled={isLoading}
>
{isLoading ? (
<ActivityIndicator color="#fff" />
) : (
<ThemedText style={styles.buttonText}></ThemedText>
)}
</TouchableOpacity>
<TouchableOpacity
style={styles.loginLink}
onPress={() => router.back()}
disabled={isLoading}
>
<ThemedText style={styles.loginText}></ThemedText>
</TouchableOpacity>
</View>
</ThemedView>
</ScrollView>
</KeyboardAvoidingView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
scrollContent: {
flexGrow: 1,
},
content: {
flex: 1,
padding: 24,
justifyContent: "center",
},
title: {
marginBottom: 8,
textAlign: "center",
},
subtitle: {
marginBottom: 32,
textAlign: "center",
opacity: 0.7,
},
form: {
gap: 16,
},
input: {
borderWidth: 1,
borderColor: "#ddd",
borderRadius: 8,
padding: 12,
fontSize: 16,
backgroundColor: "#fff",
},
button: {
backgroundColor: "#007AFF",
padding: 16,
borderRadius: 8,
alignItems: "center",
marginTop: 8,
},
buttonDisabled: {
opacity: 0.6,
},
buttonText: {
color: "#fff",
fontSize: 16,
fontWeight: "600",
},
loginLink: {
alignItems: "center",
marginTop: 8,
},
loginText: {
color: "#007AFF",
fontSize: 14,
},
});