Files
Media-Aggregation-and-Sorti…/src/screens/RegisterScreen.js
T

143 lines
6.7 KiB
JavaScript

import React, { useState } from 'react';
import {
StyleSheet, View, Text, TextInput, TouchableOpacity, Alert,
ActivityIndicator, KeyboardAvoidingView, Platform, ScrollView, Image,
} from 'react-native';
import { useTheme } from '../services/ThemeContext';
import DatabaseService from '../services/DatabaseService';
const APP_ICON = require('../../assets/icon.png');
const isBlank = (value) => !value?.trim();
const isEmailValid = (value) => value.includes('@') && value.includes('.');
const RegisterScreen = ({ navigation }) => {
const { theme } = useTheme();
const [username, setUsername] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [loading, setLoading] = useState(false);
const handleRegister = async () => {
if (isBlank(username)) { Alert.alert('Error', 'Please enter a username'); return; }
if (username.trim().length < 3) { Alert.alert('Error', 'Username must be at least 3 characters'); return; }
if (isBlank(email)) { Alert.alert('Error', 'Please enter an email'); return; }
if (!isEmailValid(email)) { Alert.alert('Error', 'Please enter a valid email address'); return; }
if (isBlank(password)) { Alert.alert('Error', 'Please enter a password'); return; }
if (password.length < 6) { Alert.alert('Error', 'Password must be at least 6 characters'); return; }
if (password !== confirmPassword) { Alert.alert('Error', 'Passwords do not match'); return; }
setLoading(true);
try {
const exists = await DatabaseService.userExists(username.trim(), email.trim().toLowerCase());
if (exists) { Alert.alert('Error', 'Username or email already taken'); setLoading(false); return; }
const userId = await DatabaseService.createUser(username.trim(), email.trim().toLowerCase(), password);
Alert.alert('Success', 'Account created!', [
{ text: 'OK', onPress: () => navigation.replace('Onboarding', { userId }) },
]);
} catch (error) {
console.error('Registration error:', error);
Alert.alert('Error', 'Failed to register: ' + error.message);
} finally {
setLoading(false);
}
};
return (
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={[styles.container, { backgroundColor: theme.background }]}
>
<ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
<View style={styles.content}>
<View style={styles.headerContainer}>
<Image source={APP_ICON} style={styles.appIcon} resizeMode="contain" />
<Text style={[styles.title, { color: theme.text }]}>Create Account</Text>
<Text style={[styles.subtitle, { color: theme.textSecondary }]}>Set up your local photo library account</Text>
</View>
<View style={styles.inputContainer}>
<Text style={[styles.label, { color: theme.textSecondary }]}>Username</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, borderColor: theme.border, color: theme.text }]}
placeholder="Choose a username" placeholderTextColor={theme.textTertiary}
value={username} onChangeText={setUsername} editable={!loading}
autoCapitalize="none" autoCorrect={false}
/>
<Text style={[styles.label, { color: theme.textSecondary }]}>Email</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, borderColor: theme.border, color: theme.text }]}
placeholder="Enter your email" placeholderTextColor={theme.textTertiary}
value={email} onChangeText={setEmail} editable={!loading}
autoCapitalize="none" autoCorrect={false} keyboardType="email-address"
/>
<Text style={[styles.label, { color: theme.textSecondary }]}>Password</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, borderColor: theme.border, color: theme.text }]}
placeholder="Create a password (min 6 characters)" placeholderTextColor={theme.textTertiary}
value={password} onChangeText={setPassword} editable={!loading}
secureTextEntry autoCapitalize="none"
/>
<Text style={[styles.label, { color: theme.textSecondary }]}>Confirm Password</Text>
<TextInput
style={[styles.input, { backgroundColor: theme.inputBg, borderColor: theme.border, color: theme.text }]}
placeholder="Confirm your password" placeholderTextColor={theme.textTertiary}
value={confirmPassword} onChangeText={setConfirmPassword} editable={!loading}
secureTextEntry autoCapitalize="none"
/>
</View>
<TouchableOpacity
style={[styles.primaryButton, { backgroundColor: theme.primary, borderColor: theme.border }, loading && styles.buttonDisabled]}
onPress={handleRegister}
disabled={loading}
>
{loading ? <ActivityIndicator color="#fff" /> : (
<Text style={styles.primaryButtonText}>Create Account</Text>
)}
</TouchableOpacity>
<TouchableOpacity
style={[styles.secondaryButton, { backgroundColor: theme.background, borderColor: theme.border }]}
onPress={() => navigation.navigate('Login')}
disabled={loading}
>
<Text style={[styles.secondaryButtonText, { color: theme.text }]}>Back to Login</Text>
</TouchableOpacity>
</View>
</ScrollView>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
container: { flex: 1 },
scrollContent: { flexGrow: 1, justifyContent: 'center' },
content: { paddingHorizontal: 24, paddingVertical: 40 },
headerContainer: { marginBottom: 36, alignItems: 'center' },
appIcon: { width: 80, height: 80, marginBottom: 16, borderRadius: 16 },
title: { fontSize: 28, fontWeight: '700', marginBottom: 8 },
subtitle: { fontSize: 15, textAlign: 'center' },
inputContainer: { marginBottom: 24 },
label: { fontSize: 13, fontWeight: '600', marginBottom: 6, marginTop: 16 },
input: {
borderWidth: 1, borderRadius: 8, paddingHorizontal: 14, paddingVertical: 12, fontSize: 15,
},
primaryButton: {
borderRadius: 8, paddingVertical: 14, alignItems: 'center', marginBottom: 10, borderWidth: 1,
},
primaryButtonText: { color: '#fff', fontSize: 15, fontWeight: '600' },
secondaryButton: {
borderRadius: 8, paddingVertical: 14, alignItems: 'center', borderWidth: 1,
},
secondaryButtonText: { fontSize: 15, fontWeight: '600' },
buttonDisabled: { opacity: 0.6 },
});
export default RegisterScreen;