mirror of
https://github.com/mudabbir-ahmad/Media-Aggregation-and-Sorting-System.git
synced 2026-10-07 19:40:20 +00:00
143 lines
6.7 KiB
JavaScript
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;
|