initial commit
This commit is contained in:
parent
bf20e7e3d7
commit
e32c9d33fa
@ -1,7 +1,7 @@
|
|||||||
const COLORS = {
|
const COLORS = {
|
||||||
background_user: '#FFFFFF',
|
background_user: '#FFFFFF',
|
||||||
text: '#FFFFFF',
|
text: '#FFFFFF',
|
||||||
primary: '#B07B2C',
|
primary: '#B17741',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default COLORS;
|
export default COLORS;
|
||||||
|
@ -1,34 +1,299 @@
|
|||||||
import React from 'react';
|
import { useState } from "react";
|
||||||
import { View, Text, StyleSheet, Button } from 'react-native';
|
import {
|
||||||
import { router } from 'expo-router';
|
View,
|
||||||
|
Text,
|
||||||
|
TextInput,
|
||||||
|
Pressable,
|
||||||
|
StyleSheet,
|
||||||
|
Image,
|
||||||
|
Alert,
|
||||||
|
TouchableOpacity,
|
||||||
|
} from "react-native";
|
||||||
|
import { Eye, EyeOff } 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";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const SignInScreen = () => {
|
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); // Destructure to get user
|
||||||
|
console.log("Connexion réussie :", user.email); // Access the email directly
|
||||||
|
router.replace("/screens/user/UserHomeScreen"); // You can route based on role later
|
||||||
|
} catch (error: any) {
|
||||||
|
Alert.alert("Erreur", error.message); // Display the error message
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.welcomeText}>Sign In Screen</Text>
|
<Pressable onPress={() => router.back()} style={styles.backButton}>
|
||||||
<Button
|
<Text style={styles.backText}>←</Text>
|
||||||
title="Back to Opening Screen"
|
</Pressable>
|
||||||
onPress={() => router.back()}
|
|
||||||
/>
|
<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 ? (
|
||||||
|
<EyeOff size={20} color="#666" />
|
||||||
|
) : (
|
||||||
|
<Eye 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,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<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>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Styles
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
backgroundColor: '#FFFFFF',
|
backgroundColor: "#fff",
|
||||||
alignItems: 'center',
|
padding: 20,
|
||||||
justifyContent: 'center',
|
|
||||||
paddingHorizontal: 20,
|
|
||||||
},
|
},
|
||||||
welcomeText: {
|
backButton: {
|
||||||
fontSize: 24,
|
marginTop: 2,
|
||||||
fontWeight: 'bold',
|
marginBottom: 0,
|
||||||
color: '#000000',
|
},
|
||||||
|
backText: {
|
||||||
|
fontSize: 40,
|
||||||
|
color: "#000",
|
||||||
|
},
|
||||||
|
logo: {
|
||||||
|
width: 100,
|
||||||
|
height: 100,
|
||||||
|
alignSelf: "center",
|
||||||
marginBottom: 20,
|
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,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
eyeIcon: {
|
||||||
|
padding: 16,
|
||||||
|
},
|
||||||
|
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: 30,
|
||||||
|
},
|
||||||
|
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;
|
export default SignInScreen;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Stack } from 'expo-router';
|
import { Stack } from 'expo-router';
|
||||||
|
|
||||||
|
|
||||||
export default function AuthLayout() {
|
export default function AuthLayout() {
|
||||||
return (
|
return (
|
||||||
<Stack screenOptions={{ headerShown: false }}>
|
<Stack screenOptions={{ headerShown: false }}>
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native';
|
import { View, Text, StyleSheet, Button } from 'react-native';
|
||||||
|
import { router } from 'expo-router';
|
||||||
|
|
||||||
|
|
||||||
const UserHomeScreen = () => {
|
const UserHomeScreen = () => {
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
<Text style={styles.welcomeText}>UserHomeScreen</Text>
|
<Text style={styles.welcomeText}>UserHomeScreen</Text>
|
||||||
|
<Button
|
||||||
|
title="Back to Opening Screen"
|
||||||
|
onPress={() => router.back()}
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Styles
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
container: {
|
container: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
49
firebase/auth.ts
Normal file
49
firebase/auth.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// auth.ts
|
||||||
|
import auth from '@react-native-firebase/auth'; // Importing Firebase Authentication from React Native Firebase
|
||||||
|
import { FirebaseAuthTypes } from '@react-native-firebase/auth';
|
||||||
|
|
||||||
|
// Function to handle user sign-in with email and password
|
||||||
|
export const signIn = async (email: string, password: string) => {
|
||||||
|
try {
|
||||||
|
const userCredential = await auth().signInWithEmailAndPassword(email, password);
|
||||||
|
return { user: userCredential.user }; // Return the user on success
|
||||||
|
} catch (error: any) {
|
||||||
|
throw new Error(error.message); // Throw an error if sign-in fails
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to handle user sign-up with email and password
|
||||||
|
export const signUp = async (email: string, password: string) => {
|
||||||
|
try {
|
||||||
|
const userCredential = await auth().createUserWithEmailAndPassword(email, password);
|
||||||
|
const user = userCredential.user;
|
||||||
|
console.log('User signed up:', user);
|
||||||
|
return user;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error signing up:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to handle user sign-out
|
||||||
|
export const signOutUser = async () => {
|
||||||
|
try {
|
||||||
|
await auth().signOut();
|
||||||
|
console.log('User signed out');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error signing out:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Listen for changes in authentication state
|
||||||
|
export const authStateListener = (callback: (user: FirebaseAuthTypes.User | null) => void) => {
|
||||||
|
return auth().onAuthStateChanged(user => {
|
||||||
|
if (user) {
|
||||||
|
console.log('User is authenticated:', user);
|
||||||
|
} else {
|
||||||
|
console.log('No user is signed in.');
|
||||||
|
}
|
||||||
|
callback(user);
|
||||||
|
});
|
||||||
|
};
|
18
firebase/config.ts
Normal file
18
firebase/config.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// config.ts
|
||||||
|
import { FirebaseApp, initializeApp } from 'firebase/app';
|
||||||
|
|
||||||
|
// Your web app's Firebase configuration
|
||||||
|
const firebaseConfig = {
|
||||||
|
apiKey: 'AIzaSyDHoF8Eahk60s3APh7WxohL1bya_44v39k',
|
||||||
|
authDomain: 'brix-cafe-2ddf1.firebaseapp.com',
|
||||||
|
projectId: 'brix-cafe-2ddf1',
|
||||||
|
storageBucket: 'brix-cafe-2ddf1.firebasestorage.app',
|
||||||
|
messagingSenderId: '577471189504',
|
||||||
|
appId: '1:577471189504:web:7bf8819223bf0d4cf03ee5',
|
||||||
|
measurementId: 'G-FSV5ZQBJS3',
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize Firebase
|
||||||
|
const app: FirebaseApp = initializeApp(firebaseConfig);
|
||||||
|
|
||||||
|
export { app };
|
1480
package-lock.json
generated
1480
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,9 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/vector-icons": "^14.0.2",
|
"@expo/vector-icons": "^14.0.2",
|
||||||
|
"@react-native-async-storage/async-storage": "^1.24.0",
|
||||||
|
"@react-native-firebase/app": "^21.14.0",
|
||||||
|
"@react-native-firebase/auth": "^21.14.0",
|
||||||
"@react-navigation/bottom-tabs": "^7.2.0",
|
"@react-navigation/bottom-tabs": "^7.2.0",
|
||||||
"@react-navigation/native": "^7.0.14",
|
"@react-navigation/native": "^7.0.14",
|
||||||
"expo": "~52.0.46",
|
"expo": "~52.0.46",
|
||||||
@ -30,6 +33,8 @@
|
|||||||
"expo-symbols": "~0.2.2",
|
"expo-symbols": "~0.2.2",
|
||||||
"expo-system-ui": "~4.0.9",
|
"expo-system-ui": "~4.0.9",
|
||||||
"expo-web-browser": "~14.0.2",
|
"expo-web-browser": "~14.0.2",
|
||||||
|
"firebase": "^11.6.0",
|
||||||
|
"lucide-react-native": "^0.488.0",
|
||||||
"react": "18.3.1",
|
"react": "18.3.1",
|
||||||
"react-dom": "18.3.1",
|
"react-dom": "18.3.1",
|
||||||
"react-native": "0.76.9",
|
"react-native": "0.76.9",
|
||||||
|
Loading…
Reference in New Issue
Block a user