mirror of
https://github.com/mudabbir-ahmad/Media-Aggregation-and-Sorting-System.git
synced 2026-10-07 19:40:20 +00:00
refactored code into components (major cleanup for reused code) added email for local acccount creation and changes to how nas and google photo connections work and added themes
This commit is contained in:
1 parent
c1d7139055
commit
6f4ec66e2e
17 files changed
+1761
-1018
No files matched your search
+69
-175
@@ -1,19 +1,16 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
View,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
Alert,
|
||||
ActivityIndicator,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StyleSheet, View, Text, TextInput, TouchableOpacity, Alert,
|
||||
ActivityIndicator, KeyboardAvoidingView, Platform, ScrollView, Image,
|
||||
} from 'react-native';
|
||||
import { useTheme } from '../services/ThemeContext';
|
||||
import DatabaseService from '../services/DatabaseService';
|
||||
|
||||
// Same icon constant as LoginScreen – edit in one place
|
||||
const APP_ICON = require('../../assets/icon.png');
|
||||
|
||||
const RegisterScreen = ({ navigation }) => {
|
||||
const { theme } = useTheme();
|
||||
const [username, setUsername] = useState('');
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
@@ -21,51 +18,23 @@ const RegisterScreen = ({ navigation }) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleRegister = async () => {
|
||||
if (!username.trim()) {
|
||||
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 (!email.trim()) {
|
||||
Alert.alert('Error', 'Please enter an email');
|
||||
return;
|
||||
}
|
||||
if (!email.includes('@') || !email.includes('.')) {
|
||||
Alert.alert('Error', 'Please enter a valid email address');
|
||||
return;
|
||||
}
|
||||
if (!password.trim()) {
|
||||
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;
|
||||
}
|
||||
if (!username.trim()) { 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 (!email.trim()) { Alert.alert('Error', 'Please enter an email'); return; }
|
||||
if (!email.includes('@') || !email.includes('.')) { Alert.alert('Error', 'Please enter a valid email address'); return; }
|
||||
if (!password.trim()) { 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;
|
||||
}
|
||||
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 }),
|
||||
},
|
||||
{ text: 'OK', onPress: () => navigation.replace('Onboarding', { userId }) },
|
||||
]);
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
@@ -78,85 +47,69 @@ const RegisterScreen = ({ navigation }) => {
|
||||
return (
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
style={styles.container}
|
||||
style={[styles.container, { backgroundColor: theme.background }]}
|
||||
>
|
||||
<ScrollView contentContainerStyle={styles.scrollContent} showsVerticalScrollIndicator={false}>
|
||||
<View style={styles.content}>
|
||||
<View style={styles.headerContainer}>
|
||||
<Text style={styles.appIcon}>📸</Text>
|
||||
<Text style={styles.title}>Create Account</Text>
|
||||
<Text style={styles.subtitle}>Set up your local photo library account</Text>
|
||||
<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}>Username</Text>
|
||||
<Text style={[styles.label, { color: theme.textSecondary }]}>Username</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Choose a username"
|
||||
placeholderTextColor="#9aa0a6"
|
||||
value={username}
|
||||
onChangeText={setUsername}
|
||||
editable={!loading}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
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}>Email</Text>
|
||||
<Text style={[styles.label, { color: theme.textSecondary }]}>Email</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Enter your email"
|
||||
placeholderTextColor="#9aa0a6"
|
||||
value={email}
|
||||
onChangeText={setEmail}
|
||||
editable={!loading}
|
||||
autoCapitalize="none"
|
||||
autoCorrect={false}
|
||||
keyboardType="email-address"
|
||||
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}>Password</Text>
|
||||
<Text style={[styles.label, { color: theme.textSecondary }]}>Password</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Create a password (min 6 characters)"
|
||||
placeholderTextColor="#9aa0a6"
|
||||
value={password}
|
||||
onChangeText={setPassword}
|
||||
editable={!loading}
|
||||
secureTextEntry
|
||||
autoCapitalize="none"
|
||||
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}>Confirm Password</Text>
|
||||
<Text style={[styles.label, { color: theme.textSecondary }]}>Confirm Password</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="Confirm your password"
|
||||
placeholderTextColor="#9aa0a6"
|
||||
value={confirmPassword}
|
||||
onChangeText={setConfirmPassword}
|
||||
editable={!loading}
|
||||
secureTextEntry
|
||||
autoCapitalize="none"
|
||||
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>
|
||||
|
||||
{/* Create Account button – blue */}
|
||||
<TouchableOpacity
|
||||
style={[styles.registerButton, loading && styles.buttonDisabled]}
|
||||
style={[styles.primaryButton, { backgroundColor: theme.primary, borderColor: theme.border }, loading && styles.buttonDisabled]}
|
||||
onPress={handleRegister}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#fff" />
|
||||
) : (
|
||||
<Text style={styles.buttonText}>Create Account</Text>
|
||||
{loading ? <ActivityIndicator color="#fff" /> : (
|
||||
<Text style={styles.primaryButtonText}>Create Account</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
|
||||
<View style={styles.loginContainer}>
|
||||
<Text style={styles.loginText}>Already have an account? </Text>
|
||||
<TouchableOpacity onPress={() => navigation.navigate('Login')} disabled={loading}>
|
||||
<Text style={styles.loginLink}>Sign in</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{/* Back to Login button – white/outlined */}
|
||||
<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>
|
||||
@@ -164,86 +117,27 @@ const RegisterScreen = ({ navigation }) => {
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
scrollContent: {
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
content: {
|
||||
paddingHorizontal: 24,
|
||||
paddingVertical: 40,
|
||||
},
|
||||
headerContainer: {
|
||||
marginBottom: 36,
|
||||
alignItems: 'center',
|
||||
},
|
||||
appIcon: {
|
||||
fontSize: 56,
|
||||
marginBottom: 16,
|
||||
},
|
||||
title: {
|
||||
fontSize: 28,
|
||||
fontWeight: '700',
|
||||
color: '#202124',
|
||||
marginBottom: 8,
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 15,
|
||||
color: '#5f6368',
|
||||
textAlign: 'center',
|
||||
},
|
||||
inputContainer: {
|
||||
marginBottom: 24,
|
||||
},
|
||||
label: {
|
||||
fontSize: 13,
|
||||
fontWeight: '600',
|
||||
color: '#3c4043',
|
||||
marginBottom: 6,
|
||||
marginTop: 16,
|
||||
},
|
||||
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,
|
||||
borderColor: '#dadce0',
|
||||
borderRadius: 8,
|
||||
paddingHorizontal: 14,
|
||||
paddingVertical: 12,
|
||||
fontSize: 15,
|
||||
backgroundColor: '#fff',
|
||||
color: '#202124',
|
||||
borderWidth: 1, borderRadius: 8, paddingHorizontal: 14, paddingVertical: 12, fontSize: 15,
|
||||
},
|
||||
registerButton: {
|
||||
backgroundColor: '#1a73e8',
|
||||
borderRadius: 8,
|
||||
paddingVertical: 14,
|
||||
alignItems: 'center',
|
||||
marginBottom: 20,
|
||||
primaryButton: {
|
||||
borderRadius: 8, paddingVertical: 14, alignItems: 'center', marginBottom: 10, borderWidth: 1,
|
||||
},
|
||||
buttonDisabled: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
buttonText: {
|
||||
color: '#fff',
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
},
|
||||
loginContainer: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
loginText: {
|
||||
color: '#5f6368',
|
||||
fontSize: 14,
|
||||
},
|
||||
loginLink: {
|
||||
color: '#1a73e8',
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
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;
|
||||
Reference in new issue
Block a user