337 lines
8.4 KiB
TypeScript
337 lines
8.4 KiB
TypeScript
import { useState } from "react";
|
|
import {View,Text,TextInput,Pressable,StyleSheet,Image,Alert,TouchableOpacity,} from "react-native";
|
|
import { Eye, EyeOff,ArrowLeft,Check } from "lucide-react-native";
|
|
import { router } from "expo-router";
|
|
import { signIn } from "../../../firebase/auth"; // Assure-toi que le chemin est correct
|
|
import { Link } from "expo-router";
|
|
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view"; // Import the library
|
|
import COLORS from "@/constants/colors";
|
|
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
|
|
|
|
const SignInScreen = () => {
|
|
const [form, setForm] = useState({
|
|
email: "",
|
|
password: "",
|
|
rememberMe: false,
|
|
});
|
|
|
|
const [errors, setErrors] = useState({
|
|
email: "",
|
|
password: "",
|
|
});
|
|
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
|
|
const validateForm = () => {
|
|
let valid = true;
|
|
const newErrors = { email: "", password: "" };
|
|
|
|
if (!form.email) {
|
|
newErrors.email = "L'e-mail est requis.";
|
|
valid = false;
|
|
}
|
|
|
|
if (!form.password) {
|
|
newErrors.password = "Le mot de passe est requis.";
|
|
valid = false;
|
|
}
|
|
|
|
setErrors(newErrors);
|
|
return valid;
|
|
};
|
|
|
|
const handleLogin = async () => {
|
|
if (!validateForm()) return;
|
|
|
|
try {
|
|
const { user } = await signIn(form.email, form.password);
|
|
|
|
console.log("Connexion réussie :", user.email);
|
|
|
|
if (form.rememberMe) {
|
|
await AsyncStorage.setItem("rememberMe", "true");
|
|
} else {
|
|
await AsyncStorage.removeItem("rememberMe");
|
|
}
|
|
|
|
router.replace("/screens/user/UserHomeScreen");
|
|
} catch (error: any) {
|
|
Alert.alert("Erreur", error.message);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<KeyboardAwareScrollView
|
|
contentContainerStyle={styles.scrollkeyboard} // Ensures that the content is scrollable
|
|
enableOnAndroid={true} // Makes sure it's enabled on Android
|
|
extraScrollHeight={20} // Adds a little bit more space when the keyboard shows up
|
|
keyboardShouldPersistTaps="handled" // Ensures that taps on the inputs won't dismiss the keyboard
|
|
>
|
|
<View style={styles.container}>
|
|
<TouchableOpacity
|
|
style={styles.backButton}
|
|
onPress={() => router.back()}
|
|
>
|
|
<ArrowLeft size={24} color="#666" />
|
|
</TouchableOpacity>
|
|
<Image source={require('@/assets/images/logo.png')} style={styles.logo}/>
|
|
|
|
<Text style={styles.title}>Se connecter</Text>
|
|
|
|
<Text style={styles.welcome}>Bienvenue! 👋</Text>
|
|
|
|
<View style={styles.form}>
|
|
<View style={styles.inputGroup}>
|
|
<Text style={styles.label}>E-mail</Text>
|
|
<TextInput
|
|
placeholder="Entrez votre adresse e-mail"
|
|
placeholderTextColor="#666"
|
|
style={[styles.input, errors.email && styles.inputError]}
|
|
keyboardType="email-address"
|
|
autoCapitalize="none"
|
|
value={form.email}
|
|
onChangeText={(text) => {
|
|
setForm({ ...form, email: text });
|
|
if (errors.email) setErrors({ ...errors, email: "" });
|
|
}}
|
|
/>
|
|
{errors.email ? (
|
|
<Text style={styles.errorText}>{errors.email}</Text>
|
|
) : null}
|
|
</View>
|
|
|
|
<View style={styles.inputGroup}>
|
|
<Text style={styles.label}>Mot de passe</Text>
|
|
<View
|
|
style={[
|
|
styles.passwordContainer,
|
|
errors.password && styles.inputError,
|
|
]}
|
|
>
|
|
<TextInput
|
|
placeholder="Entrez votre mot de passe"
|
|
placeholderTextColor="#666"
|
|
style={styles.passwordInput}
|
|
secureTextEntry={!showPassword}
|
|
value={form.password}
|
|
onChangeText={(text) => {
|
|
setForm({ ...form, password: text });
|
|
if (errors.password) setErrors({ ...errors, password: "" });
|
|
}}
|
|
/>
|
|
<Pressable
|
|
onPress={() => setShowPassword(!showPassword)}
|
|
style={styles.eyeIcon}
|
|
>
|
|
{showPassword ? (
|
|
<Eye size={20} color="#666" />
|
|
) : (
|
|
<EyeOff size={20} color="#666" />
|
|
)}
|
|
</Pressable>
|
|
</View>
|
|
{errors.password ? (
|
|
<Text style={styles.errorText}>{errors.password}</Text>
|
|
) : null}
|
|
</View>
|
|
|
|
<View style={styles.optionsContainer}>
|
|
<Pressable
|
|
style={styles.rememberMe}
|
|
onPress={() => setForm({ ...form, rememberMe: !form.rememberMe })}
|
|
>
|
|
<View
|
|
style={[
|
|
styles.checkbox,
|
|
form.rememberMe && styles.checkboxChecked,
|
|
]}
|
|
>
|
|
{form.rememberMe && <Check size={16} color="white" />}
|
|
</View>
|
|
|
|
<Text style={styles.rememberText}>Rester Connecté</Text>
|
|
</Pressable>
|
|
|
|
<TouchableOpacity>
|
|
<Text style={styles.forgotText}>Mot de passe oublié?</Text>
|
|
</TouchableOpacity>
|
|
</View>
|
|
</View>
|
|
|
|
<Pressable style={styles.loginButton} onPress={handleLogin}>
|
|
<Text style={styles.loginButtonText}>Connexion</Text>
|
|
</Pressable>
|
|
|
|
<View style={styles.signupContainer}>
|
|
<Text style={styles.signupText}>Nouveau ici? </Text>
|
|
<Link href="/screens/auth/SignUpScreen" style={styles.signupLink}>
|
|
<Text style={styles.signupLinkText}>Créer un compte</Text>
|
|
</Link>
|
|
</View>
|
|
</View>
|
|
</KeyboardAwareScrollView>
|
|
|
|
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: "#fff",
|
|
padding: 20,
|
|
},
|
|
scrollkeyboard:{
|
|
flexGrow: 1,
|
|
backgroundColor:"#fff",
|
|
|
|
},
|
|
backButton: {
|
|
marginTop: 20,
|
|
marginLeft: 2,
|
|
},
|
|
backText: {
|
|
fontSize: 40,
|
|
color: "#000",
|
|
},
|
|
logo: {
|
|
width: 100,
|
|
height: 100,
|
|
alignSelf: "center",
|
|
marginBottom: 20,
|
|
},
|
|
title: {
|
|
fontSize: 24,
|
|
fontWeight: "bold",
|
|
textAlign: "center",
|
|
marginBottom: 30,
|
|
},
|
|
|
|
welcome: {
|
|
fontSize: 28,
|
|
fontWeight: "bold",
|
|
marginBottom: 30,
|
|
},
|
|
form: {
|
|
gap: 20,
|
|
},
|
|
inputGroup: {
|
|
gap: 8,
|
|
},
|
|
label: {
|
|
fontSize: 16,
|
|
fontWeight: "500",
|
|
color: "#333",
|
|
},
|
|
input: {
|
|
backgroundColor: "#f5f5f5",
|
|
padding: 16,
|
|
borderRadius: 8,
|
|
borderWidth:0.5,
|
|
borderColor: COLORS.primary,
|
|
fontSize: 16,
|
|
},
|
|
inputError: {
|
|
borderWidth: 1,
|
|
borderColor: "#ff4444",
|
|
},
|
|
errorText: {
|
|
color: "#ff4444",
|
|
fontSize: 14,
|
|
marginTop: 4,
|
|
},
|
|
passwordContainer: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
backgroundColor: "#f5f5f5",
|
|
borderRadius: 8,
|
|
},
|
|
passwordInput: {
|
|
flex: 1,
|
|
padding: 16,
|
|
fontSize: 16,
|
|
borderTopLeftRadius: 8,
|
|
borderBottomLeftRadius: 8,
|
|
borderTopWidth: 0.5,
|
|
borderLeftWidth: 0.5,
|
|
borderBottomWidth: 0.5,
|
|
borderColor: COLORS.primary,
|
|
},
|
|
eyeIcon: {
|
|
padding: 17,
|
|
borderTopRightRadius: 8,
|
|
borderBottomRightRadius: 8,
|
|
borderTopWidth: 0.5,
|
|
borderRightWidth: 0.5,
|
|
borderBottomWidth: 0.5,
|
|
borderColor: COLORS.primary,
|
|
|
|
},
|
|
optionsContainer: {
|
|
flexDirection: "row",
|
|
justifyContent: "space-between",
|
|
alignItems: "center",
|
|
marginTop: 8,
|
|
},
|
|
rememberMe: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
gap: 8,
|
|
},
|
|
checkbox: {
|
|
width: 20,
|
|
height: 20,
|
|
borderRadius: 4,
|
|
borderWidth: 2,
|
|
borderColor: "#B17741",
|
|
},
|
|
checkboxChecked: {
|
|
backgroundColor: "#B17741",
|
|
},
|
|
rememberText: {
|
|
color: "#333",
|
|
fontSize: 14,
|
|
},
|
|
forgotPassword: {
|
|
padding: 4,
|
|
},
|
|
forgotText: {
|
|
color: "#B17741",
|
|
fontSize: 14,
|
|
fontWeight: "500",
|
|
},
|
|
loginButton: {
|
|
backgroundColor: "#B17741",
|
|
padding: 16,
|
|
borderRadius: 8,
|
|
marginTop: 50,
|
|
},
|
|
loginButtonText: {
|
|
color: "#fff",
|
|
textAlign: "center",
|
|
fontSize: 16,
|
|
fontWeight: "600",
|
|
},
|
|
signupContainer: {
|
|
flexDirection: "row",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
marginTop: 20,
|
|
},
|
|
signupText: {
|
|
color: "#666",
|
|
fontSize: 14,
|
|
},
|
|
signupLink: {
|
|
padding: 4,
|
|
},
|
|
signupLinkText: {
|
|
color: "#B17741",
|
|
fontSize: 14,
|
|
fontWeight: "500",
|
|
},
|
|
});
|
|
|
|
export default SignInScreen;
|