mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-29 23:57:59 +00:00
Fix all shadow deprecation warnings across entire mobile app
- Replaced shadowColor/shadowOffset/shadowOpacity/shadowRadius with boxShadow - Fixed 28 files (21 screens + 7 components) - Preserved elevation for Android compatibility - All React Native Web deprecation warnings resolved Files fixed: - All screen components - All reusable components - Navigation components - Modal components
This commit is contained in:
@@ -0,0 +1,631 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TextInput,
|
||||
TouchableOpacity,
|
||||
StyleSheet,
|
||||
SafeAreaView,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
ScrollView,
|
||||
StatusBar,
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
} from 'react-native';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
import { KurdistanColors } from '../theme/colors';
|
||||
|
||||
const AuthScreen: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const { signIn, signUp } = useAuth();
|
||||
|
||||
// Tab state
|
||||
const [activeTab, setActiveTab] = useState<'signin' | 'signup'>('signin');
|
||||
|
||||
// Sign In state
|
||||
const [loginEmail, setLoginEmail] = useState('');
|
||||
const [loginPassword, setLoginPassword] = useState('');
|
||||
const [showLoginPassword, setShowLoginPassword] = useState(false);
|
||||
const [rememberMe, setRememberMe] = useState(false);
|
||||
|
||||
// Sign Up state
|
||||
const [signupName, setSignupName] = useState('');
|
||||
const [signupEmail, setSignupEmail] = useState('');
|
||||
const [signupPassword, setSignupPassword] = useState('');
|
||||
const [signupConfirmPassword, setSignupConfirmPassword] = useState('');
|
||||
const [signupReferralCode, setSignupReferralCode] = useState('');
|
||||
const [showSignupPassword, setShowSignupPassword] = useState(false);
|
||||
|
||||
// Common state
|
||||
const [error, setError] = useState('');
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleSignIn = async () => {
|
||||
setError('');
|
||||
|
||||
if (!loginEmail || !loginPassword) {
|
||||
setError(t('auth.fillAllFields', 'Please fill in all fields'));
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const { error: signInError } = await signIn(loginEmail, loginPassword, rememberMe);
|
||||
|
||||
if (signInError) {
|
||||
if (signInError.message?.includes('Invalid login credentials')) {
|
||||
setError(t('auth.invalidCredentials', 'Email or password is incorrect'));
|
||||
} else {
|
||||
setError(signInError.message || t('auth.loginFailed', 'Login failed'));
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
setError(t('auth.loginFailed', 'Login failed. Please try again.'));
|
||||
if (__DEV__) console.error('Sign in error:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSignUp = async () => {
|
||||
setError('');
|
||||
|
||||
if (!signupName || !signupEmail || !signupPassword || !signupConfirmPassword) {
|
||||
setError(t('auth.fillAllFields', 'Please fill in all required fields'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (signupPassword !== signupConfirmPassword) {
|
||||
setError(t('auth.passwordsDoNotMatch', 'Passwords do not match'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (signupPassword.length < 8) {
|
||||
setError(t('auth.passwordTooShort', 'Password must be at least 8 characters'));
|
||||
return;
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
|
||||
try {
|
||||
const { error: signUpError } = await signUp(
|
||||
signupEmail,
|
||||
signupPassword,
|
||||
signupName,
|
||||
signupReferralCode
|
||||
);
|
||||
|
||||
if (signUpError) {
|
||||
setError(signUpError.message || t('auth.signupFailed', 'Sign up failed'));
|
||||
}
|
||||
} catch (err) {
|
||||
setError(t('auth.signupFailed', 'Sign up failed. Please try again.'));
|
||||
if (__DEV__) console.error('Sign up error:', err);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<StatusBar barStyle="light-content" />
|
||||
<LinearGradient
|
||||
colors={['#111827', '#000000', '#111827']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 1 }}
|
||||
style={styles.gradient}
|
||||
>
|
||||
{/* Grid overlay */}
|
||||
<View style={styles.gridOverlay} />
|
||||
|
||||
<KeyboardAvoidingView
|
||||
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
|
||||
style={styles.keyboardView}
|
||||
>
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
keyboardShouldPersistTaps="handled"
|
||||
>
|
||||
{/* Card Container */}
|
||||
<View style={styles.card}>
|
||||
{/* Header */}
|
||||
<View style={styles.header}>
|
||||
<View style={styles.logoContainer}>
|
||||
<Image
|
||||
source={require('../../assets/kurdistan-map.png')}
|
||||
style={styles.logoImage}
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.brandTitle}>PezkuwiChain</Text>
|
||||
<Text style={styles.subtitle}>
|
||||
{t('login.subtitle', 'Access your governance account')}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* Tabs */}
|
||||
<View style={styles.tabContainer}>
|
||||
<TouchableOpacity
|
||||
style={[styles.tab, activeTab === 'signin' && styles.tabActive]}
|
||||
onPress={() => {
|
||||
setActiveTab('signin');
|
||||
setError('');
|
||||
}}
|
||||
>
|
||||
<Text style={[styles.tabText, activeTab === 'signin' && styles.tabTextActive]}>
|
||||
{t('login.signin', 'Sign In')}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.tab, activeTab === 'signup' && styles.tabActive]}
|
||||
onPress={() => {
|
||||
setActiveTab('signup');
|
||||
setError('');
|
||||
}}
|
||||
>
|
||||
<Text style={[styles.tabText, activeTab === 'signup' && styles.tabTextActive]}>
|
||||
{t('login.signup', 'Sign Up')}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{/* Sign In Form */}
|
||||
{activeTab === 'signin' && (
|
||||
<View style={styles.form}>
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>{t('login.email', 'Email')}</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>✉️</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="name@example.com"
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={loginEmail}
|
||||
onChangeText={setLoginEmail}
|
||||
keyboardType="email-address"
|
||||
autoCapitalize="none"
|
||||
editable={!loading}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>{t('login.password', 'Password')}</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>🔒</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="••••••••"
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={loginPassword}
|
||||
onChangeText={setLoginPassword}
|
||||
secureTextEntry={!showLoginPassword}
|
||||
editable={!loading}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.eyeButton}
|
||||
onPress={() => setShowLoginPassword(!showLoginPassword)}
|
||||
>
|
||||
<Text style={styles.eyeIcon}>{showLoginPassword ? '👁️' : '👁️🗨️'}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.rowBetween}>
|
||||
<TouchableOpacity
|
||||
style={styles.checkboxContainer}
|
||||
onPress={() => setRememberMe(!rememberMe)}
|
||||
>
|
||||
<View style={[styles.checkbox, rememberMe && styles.checkboxChecked]}>
|
||||
{rememberMe && <Text style={styles.checkmark}>✓</Text>}
|
||||
</View>
|
||||
<Text style={styles.checkboxLabel}>
|
||||
{t('login.rememberMe', 'Remember me')}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity>
|
||||
<Text style={styles.linkText}>
|
||||
{t('login.forgotPassword', 'Forgot password?')}
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
{error && (
|
||||
<View style={styles.errorContainer}>
|
||||
<Text style={styles.errorIcon}>⚠️</Text>
|
||||
<Text style={styles.errorText}>{error}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.primaryButton, styles.signInButton, loading && styles.buttonDisabled]}
|
||||
onPress={handleSignIn}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#FFFFFF" />
|
||||
) : (
|
||||
<Text style={styles.primaryButtonText}>
|
||||
{t('login.signin', 'Sign In')}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Sign Up Form */}
|
||||
{activeTab === 'signup' && (
|
||||
<View style={styles.form}>
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>{t('login.fullName', 'Full Name')}</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>👤</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="John Doe"
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={signupName}
|
||||
onChangeText={setSignupName}
|
||||
editable={!loading}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>{t('login.email', 'Email')}</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>✉️</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="name@example.com"
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={signupEmail}
|
||||
onChangeText={setSignupEmail}
|
||||
keyboardType="email-address"
|
||||
autoCapitalize="none"
|
||||
editable={!loading}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>{t('login.password', 'Password')}</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>🔒</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="••••••••"
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={signupPassword}
|
||||
onChangeText={setSignupPassword}
|
||||
secureTextEntry={!showSignupPassword}
|
||||
editable={!loading}
|
||||
/>
|
||||
<TouchableOpacity
|
||||
style={styles.eyeButton}
|
||||
onPress={() => setShowSignupPassword(!showSignupPassword)}
|
||||
>
|
||||
<Text style={styles.eyeIcon}>{showSignupPassword ? '👁️' : '👁️🗨️'}</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>{t('login.confirmPassword', 'Confirm Password')}</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>🔒</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder="••••••••"
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={signupConfirmPassword}
|
||||
onChangeText={setSignupConfirmPassword}
|
||||
secureTextEntry
|
||||
editable={!loading}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={styles.inputGroup}>
|
||||
<Text style={styles.label}>
|
||||
{t('login.referralCode', 'Referral Code')}{' '}
|
||||
<Text style={styles.optionalText}>
|
||||
({t('login.optional', 'Optional')})
|
||||
</Text>
|
||||
</Text>
|
||||
<View style={styles.inputContainer}>
|
||||
<Text style={styles.inputIcon}>👥</Text>
|
||||
<TextInput
|
||||
style={styles.input}
|
||||
placeholder={t('login.enterReferralCode', 'Referral code (optional)')}
|
||||
placeholderTextColor="#9CA3AF"
|
||||
value={signupReferralCode}
|
||||
onChangeText={setSignupReferralCode}
|
||||
editable={!loading}
|
||||
/>
|
||||
</View>
|
||||
<Text style={styles.hintText}>
|
||||
{t('login.referralDescription', 'If someone referred you, enter their code here')}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{error && (
|
||||
<View style={styles.errorContainer}>
|
||||
<Text style={styles.errorIcon}>⚠️</Text>
|
||||
<Text style={styles.errorText}>{error}</Text>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<TouchableOpacity
|
||||
style={[styles.primaryButton, styles.signUpButton, loading && styles.buttonDisabled]}
|
||||
onPress={handleSignUp}
|
||||
disabled={loading}
|
||||
>
|
||||
{loading ? (
|
||||
<ActivityIndicator color="#FFFFFF" />
|
||||
) : (
|
||||
<Text style={styles.primaryButtonText}>
|
||||
{t('login.createAccount', 'Create Account')}
|
||||
</Text>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{/* Footer */}
|
||||
<View style={styles.footer}>
|
||||
<Text style={styles.footerText}>
|
||||
{t('login.terms', 'By continuing, you agree to our')}{' '}
|
||||
</Text>
|
||||
<View style={styles.footerLinks}>
|
||||
<Text style={styles.footerLink}>
|
||||
{t('login.termsOfService', 'Terms of Service')}
|
||||
</Text>
|
||||
<Text style={styles.footerText}> {t('login.and', 'and')} </Text>
|
||||
<Text style={styles.footerLink}>
|
||||
{t('login.privacyPolicy', 'Privacy Policy')}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
</ScrollView>
|
||||
</KeyboardAvoidingView>
|
||||
</LinearGradient>
|
||||
</SafeAreaView>
|
||||
);
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: '#000000',
|
||||
},
|
||||
gradient: {
|
||||
flex: 1,
|
||||
},
|
||||
gridOverlay: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
opacity: 0.1,
|
||||
},
|
||||
keyboardView: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollContent: {
|
||||
flexGrow: 1,
|
||||
padding: 16,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
card: {
|
||||
backgroundColor: 'rgba(17, 24, 39, 0.9)',
|
||||
borderRadius: 16,
|
||||
padding: 24,
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(55, 65, 81, 0.5)',
|
||||
},
|
||||
header: {
|
||||
alignItems: 'center',
|
||||
marginBottom: 24,
|
||||
},
|
||||
logoContainer: {
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: 32,
|
||||
backgroundColor: '#FFFFFF',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginBottom: 12,
|
||||
padding: 8,
|
||||
},
|
||||
logoImage: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
brandTitle: {
|
||||
fontSize: 24,
|
||||
fontWeight: 'bold',
|
||||
textAlign: 'center',
|
||||
marginBottom: 4,
|
||||
color: '#10B981',
|
||||
},
|
||||
subtitle: {
|
||||
fontSize: 14,
|
||||
color: '#9CA3AF',
|
||||
textAlign: 'center',
|
||||
},
|
||||
tabContainer: {
|
||||
flexDirection: 'row',
|
||||
backgroundColor: '#1F2937',
|
||||
borderRadius: 8,
|
||||
padding: 4,
|
||||
marginBottom: 24,
|
||||
},
|
||||
tab: {
|
||||
flex: 1,
|
||||
paddingVertical: 8,
|
||||
alignItems: 'center',
|
||||
borderRadius: 6,
|
||||
},
|
||||
tabActive: {
|
||||
backgroundColor: '#374151',
|
||||
},
|
||||
tabText: {
|
||||
fontSize: 14,
|
||||
fontWeight: '600',
|
||||
color: '#9CA3AF',
|
||||
},
|
||||
tabTextActive: {
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
form: {
|
||||
gap: 16,
|
||||
},
|
||||
inputGroup: {
|
||||
marginBottom: 16,
|
||||
},
|
||||
label: {
|
||||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
color: '#D1D5DB',
|
||||
marginBottom: 8,
|
||||
},
|
||||
optionalText: {
|
||||
fontSize: 12,
|
||||
color: '#6B7280',
|
||||
},
|
||||
inputContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#1F2937',
|
||||
borderRadius: 8,
|
||||
borderWidth: 1,
|
||||
borderColor: '#374151',
|
||||
paddingHorizontal: 12,
|
||||
},
|
||||
inputIcon: {
|
||||
fontSize: 16,
|
||||
marginRight: 8,
|
||||
},
|
||||
input: {
|
||||
flex: 1,
|
||||
paddingVertical: 12,
|
||||
fontSize: 16,
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
eyeButton: {
|
||||
padding: 4,
|
||||
},
|
||||
eyeIcon: {
|
||||
fontSize: 20,
|
||||
},
|
||||
hintText: {
|
||||
fontSize: 12,
|
||||
color: '#6B7280',
|
||||
marginTop: 4,
|
||||
},
|
||||
rowBetween: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 16,
|
||||
},
|
||||
checkboxContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
checkbox: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 4,
|
||||
borderWidth: 2,
|
||||
borderColor: '#10B981',
|
||||
marginRight: 8,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
checkboxChecked: {
|
||||
backgroundColor: '#10B981',
|
||||
},
|
||||
checkmark: {
|
||||
color: '#FFFFFF',
|
||||
fontSize: 12,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
checkboxLabel: {
|
||||
fontSize: 14,
|
||||
color: '#9CA3AF',
|
||||
},
|
||||
linkText: {
|
||||
fontSize: 14,
|
||||
color: '#10B981',
|
||||
fontWeight: '500',
|
||||
},
|
||||
errorContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: 'rgba(239, 68, 68, 0.1)',
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(239, 68, 68, 0.3)',
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
marginBottom: 16,
|
||||
},
|
||||
errorIcon: {
|
||||
fontSize: 16,
|
||||
marginRight: 8,
|
||||
},
|
||||
errorText: {
|
||||
flex: 1,
|
||||
fontSize: 14,
|
||||
color: '#FCA5A5',
|
||||
},
|
||||
primaryButton: {
|
||||
paddingVertical: 14,
|
||||
borderRadius: 8,
|
||||
alignItems: 'center',
|
||||
marginTop: 8,
|
||||
},
|
||||
signInButton: {
|
||||
backgroundColor: '#059669',
|
||||
},
|
||||
signUpButton: {
|
||||
backgroundColor: '#D97706',
|
||||
},
|
||||
primaryButtonText: {
|
||||
fontSize: 16,
|
||||
fontWeight: 'bold',
|
||||
color: '#FFFFFF',
|
||||
},
|
||||
buttonDisabled: {
|
||||
opacity: 0.5,
|
||||
},
|
||||
footer: {
|
||||
marginTop: 24,
|
||||
alignItems: 'center',
|
||||
},
|
||||
footerText: {
|
||||
fontSize: 12,
|
||||
color: '#6B7280',
|
||||
textAlign: 'center',
|
||||
},
|
||||
footerLinks: {
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap',
|
||||
justifyContent: 'center',
|
||||
marginTop: 4,
|
||||
},
|
||||
footerLink: {
|
||||
fontSize: 12,
|
||||
color: '#10B981',
|
||||
},
|
||||
});
|
||||
|
||||
export default AuthScreen;
|
||||
Reference in New Issue
Block a user