Merge pull request 'La page d'inscription fonctionne' (#21) from SignUp into master

Reviewed-on: #21
pull/22/head
Leni BEAULATON 2 months ago
commit d3cc0bc1d3

@ -6,7 +6,7 @@ interface IServices {
fun EditPasswd(passwd : String, passwdValid : String)
fun EditImage(imageURL : String)
fun CreateUser(username : String, email : String, passwd : String, imageURL: String)
fun CreateUser(username : String, email : String, passwd : String, imageURL: String) : Boolean
fun getFavorite(username: String)
fun SearchQuote(quote : String)

@ -17,7 +17,7 @@ class ServicesAPI : IServices {
TODO("Not yet implemented")
}
override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) {
override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) : Boolean {
TODO("Not yet implemented")
}

@ -1,5 +1,12 @@
package com.example.what_the_fantasy.data.services
import android.annotation.SuppressLint
import android.util.Log
import com.example.what_the_fantasy.data.local.UserStub
import com.example.what_the_fantasy.data.model.User
import com.example.what_the_fantasy.ui.components.hashPassword
import java.time.LocalDate
class ServicesStub : IServices {
override fun EditUsername(username: String) {
TODO("Not yet implemented")
@ -17,10 +24,29 @@ class ServicesStub : IServices {
TODO("Not yet implemented")
}
override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) {
TODO("Not yet implemented")
override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) : Boolean {
val date =dateDuJour()
val passwordhash = hashPassword(passwd)
//Check si user existe déjà
val users = UserStub.allUsers
for (user in users) {
if (user.username == username) {
return false
}
}
val user = User(100,username, email, imageURL, date, passwordhash)
//A ajouter au stub
Log.e("CreateUser", "User created: ${user.username} => ${user.password}")
return true
}
@SuppressLint("NewApi")
fun dateDuJour(): String {
val date = LocalDate.now()
return date.toString()
}
override fun SearchQuote(quote: String) {
TODO("Not yet implemented")
}

@ -0,0 +1,14 @@
package com.example.what_the_fantasy.ui.components
import java.security.MessageDigest
fun hashPassword(password: String): String {
// SHA-256
val digest = MessageDigest.getInstance("SHA-256")
// Convertir mdp en bytes et appliquer le hash
val hashedBytes = digest.digest(password.toByteArray())
// Convertir le tableau de bytes en une chaîne hexadécimale
return hashedBytes.joinToString("") { "%02x".format(it) }
}

@ -41,6 +41,7 @@ import com.example.what_the_fantasy.data.local.UserStub
import com.example.what_the_fantasy.data.model.User
import com.example.what_the_fantasy.ui.components.SpaceHeightComponent
import com.example.what_the_fantasy.ui.components.TitlePageComponent
import com.example.what_the_fantasy.ui.components.hashPassword
import com.example.what_the_fantasy.ui.theme.colorBackground
import com.example.what_the_fantasy.ui.theme.gradienBox
import java.security.MessageDigest
@ -148,18 +149,6 @@ fun validLogin(identifiant : String, passwd : String, users : List<User>, navCon
}
}
fun hashPassword(password: String): String {
// SHA-256
val digest = MessageDigest.getInstance("SHA-256")
// Convertir mdp en bytes et appliquer le hash
val hashedBytes = digest.digest(password.toByteArray())
// Convertir le tableau de bytes en une chaîne hexadécimale
return hashedBytes.joinToString("") { "%02x".format(it) }
}
@Composable
fun CreateAccountButton(titleResId : Int, size : Int, color : Color, navController: () -> Unit){
val title = stringResource(id = titleResId)

@ -15,8 +15,11 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
@ -45,10 +48,17 @@ import com.example.what_the_fantasy.ui.components.TitlePageComponent
import com.example.what_the_fantasy.ui.theme.What_The_FantasyTheme
import com.example.what_the_fantasy.ui.theme.colorBackground
import com.example.what_the_fantasy.ui.theme.gradienBox
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent
@Composable
fun SignUpPage(navController: NavController) {
var username by remember { mutableStateOf("") }
var email by remember { mutableStateOf("") }
var password by remember { mutableStateOf("") }
var confirmPassword by remember { mutableStateOf("") }
var passwordVisible by remember { mutableStateOf(false) }
val servicesStub = ServicesStub()
Box(
modifier = Modifier
@ -67,14 +77,14 @@ fun SignUpPage(navController: NavController) {
) {
TitlePageComponent(R.string.titleSignUp, 20,Color.White)
IdentifiantTextFieldSign(R.string.IdentifiantLogin)
EmailTextFieldSign("Email*")
PassWdTextFieldSign(R.string.PasswdLogin)
PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp)
IdentifiantTextFieldSign(R.string.IdentifiantLogin,identifiant = username,onValueChange = { username = it })
EmailTextFieldSign(R.string.EmailSignUp, email, onValueChange = { email = it })
PassWdTextFieldSign(R.string.PasswdLogin,password, onValueChange = { password = it },passwordVisible,onPasswordVisibilityChange = { passwordVisible = !passwordVisible })
PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp,confirmPassword,onValueChange = { confirmPassword = it },passwordVisible,onPasswordVisibilityChange = { passwordVisible = !passwordVisible })
SpaceHeightComponent(16)
ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black)
ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black, username, email, password, confirmPassword, servicesStub, navController = navController)
SpaceHeightComponent(16)
CreateAccountButtonSign(R.string.ButtonLogin,12, Color.White, navController = navController)
ReturnLogin(R.string.ButtonLogin,12, Color.White, navController = navController)
}
}
@ -84,50 +94,47 @@ fun SignUpPage(navController: NavController) {
@Composable
fun IdentifiantTextFieldSign(textIdentifiantResId : Int){
fun IdentifiantTextFieldSign(textIdentifiantResId : Int, identifiant: String, onValueChange: (String) -> Unit){
val textIdentifiant = stringResource(id = textIdentifiantResId)
var identifiant by remember { mutableStateOf("") } // Stocke la valeur du champ
Column(modifier = Modifier.padding(top = 16.dp)) {
OutlinedTextField(
value = identifiant,
onValueChange = { identifiant = it },
onValueChange = onValueChange,
label = { Text(textIdentifiant) },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis
shape = RoundedCornerShape(16.dp)
)
}
}
@Composable
fun EmailTextFieldSign(textIdentifiant : String){
var identifiant by remember { mutableStateOf("") } // Stocke la valeur du champ
fun EmailTextFieldSign(textIdentifiantResId: Int, email: String, onValueChange: (String) -> Unit){
val textIdentifiant = stringResource(id = textIdentifiantResId)
Column(modifier = Modifier.padding(top = 16.dp)) {
OutlinedTextField(
value = identifiant,
onValueChange = { identifiant = it },
value = email,
onValueChange = onValueChange,
label = { Text(textIdentifiant) },
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
shape = RoundedCornerShape(16.dp) // Bords arrondis
shape = RoundedCornerShape(16.dp)
)
}
}
@Composable
fun PassWdTextFieldSign(textpasswdResId : Int){
fun PassWdTextFieldSign(textpasswdResId : Int, passwd: String, onValueChange: (String) -> Unit, passwordVisible: Boolean, onPasswordVisibilityChange: () -> Unit){
val textpasswd = stringResource(id = textpasswdResId)
var passwd by remember { mutableStateOf("") } // Stocke la valeur du champ
var passwordVisible by remember { mutableStateOf(false) } // État pour afficher/masquer
Column(modifier = Modifier.padding(top = 10.dp)) {
OutlinedTextField(
value = passwd,
onValueChange = { passwd = it },
onValueChange = onValueChange,
label = { Text(textpasswd) },
modifier = Modifier
.fillMaxWidth()
@ -135,23 +142,22 @@ fun PassWdTextFieldSign(textpasswdResId : Int){
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
IconButton(onClick = { passwordVisible = !passwordVisible }) {
IconButton(onClick = onPasswordVisibilityChange) {
Icon(imageVector = Icons.Default.Check, contentDescription = "Valider")
}
},
shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis
shape = RoundedCornerShape(16.dp)
)
}
}
@Composable
fun PassWdConfirmTextFieldSign(textpasswdResId : Int){
fun PassWdConfirmTextFieldSign(textpasswdResId : Int,confirmPassword: String, onValueChange: (String) -> Unit, passwordVisible: Boolean, onPasswordVisibilityChange: () -> Unit){
val textpasswd = stringResource(id = textpasswdResId)
var passwd by remember { mutableStateOf("") } // Stocke la valeur du champ
var passwordVisible by remember { mutableStateOf(false) } // État pour afficher/masquer
Column(modifier = Modifier.padding(top = 10.dp)) {
OutlinedTextField(
value = passwd,
onValueChange = { passwd = it },
value = confirmPassword,
onValueChange = onValueChange,
label = { Text(textpasswd) },
modifier = Modifier
.fillMaxWidth()
@ -159,31 +165,88 @@ fun PassWdConfirmTextFieldSign(textpasswdResId : Int){
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
IconButton(onClick = { passwordVisible = !passwordVisible }) {
IconButton(onClick = onPasswordVisibilityChange) {
Icon(imageVector = Icons.Default.Check, contentDescription = "Valider")
}
},
shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis
shape = RoundedCornerShape(16.dp)
)
}
}
// Validation de email
fun isValidEmail(email: String): Boolean {
val emailRegex = "[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}"
return email.matches(emailRegex.toRegex())
}
// Vérification mots de passe
fun arePasswordsMatching(password: String, confirmPassword: String): Boolean {
return password == confirmPassword
}
@Composable
fun ConnexionButtonSign(titleResId : Int, size : Int, colorButton : Color, colorText : Color){
fun ConnexionButtonSign(
titleResId: Int,
size: Int,
colorButton: Color,
colorText: Color,
username: String,
email: String,
password: String,
confirmPassword: String,
service: ServicesStub,
navController: NavController
) {
val title = stringResource(id = titleResId)
var emailError by remember { mutableStateOf(false) }
var passwordError by remember { mutableStateOf(false) }
var usernameErrorEmpty by remember { mutableStateOf(false) }
var usernameErrorExist by remember { mutableStateOf(false) }
Button(
onClick = { /* Action */ },
onClick = {
emailError = !isValidEmail(email)
passwordError = !arePasswordsMatching(password, confirmPassword)
usernameErrorEmpty = username.isBlank()
if (!emailError && !passwordError && !usernameErrorEmpty) {
usernameErrorExist = !service.CreateUser(username, email, password, "https://img.freepik.com/vecteurs-libre/personnage-magicien-malefique-fantaisie_1045-193.jpg?size=338&ext=jpg")
}
},
colors = ButtonDefaults.buttonColors(containerColor = colorButton),
modifier = Modifier
.fillMaxWidth(),
modifier = Modifier.fillMaxWidth(),
) {
Text(title, fontSize = size.sp, color = colorText)
}
// Afficher erreurs
if (usernameErrorEmpty) {
ErrorMessageProfileComponent(R.string.ErrorUserEmptySignUp)
}
if (usernameErrorExist) {
ErrorMessageProfileComponent(R.string.ErrorUserExistSignUp)
}
if (emailError) {
ErrorMessageProfileComponent(R.string.ErrorEmailSignUp)
}
if (passwordError) {
ErrorMessageProfileComponent(R.string.ErrorPasswordSignUp)
}
}
@Composable
fun CreateAccountButtonSign(titleResId: Int, size: Int, color: Color, navController: NavController) {
fun ReturnLogin(titleResId: Int, size: Int, color: Color, navController: NavController) {
val title = stringResource(id = titleResId)
Text(
text = title,

@ -16,6 +16,11 @@
<string name="titleSignUp">Inscription</string>
<string name="ConfirmPassWdSignUp">Confirmer mot de passe*</string>
<string name="ButtonSignUp">S\'inscrire</string>
<string name="EmailSignUp">Email*</string>
<string name="ErrorEmailSignUp">Email invalide</string>
<string name="ErrorPasswordSignUp">Les mots de passe ne correspondent pas</string>
<string name="ErrorUserEmptySignUp">Le nom d\'utilisateur ne peut pas être vide</string>
<string name="ErrorUserExistSignUp">Le nom d\'utilisateur n\'est pas disponible</string>
//Page Profil
<string name="titleProfile">Profil</string>

@ -15,6 +15,11 @@
<string name="titleSignUp">Account creation</string>
<string name="ConfirmPassWdSignUp">Confirm your password*</string>
<string name="ButtonSignUp">Create</string>
<string name="EmailSignUp">Your email*</string>
<string name="ErrorEmailSignUp">Invalid email</string>
<string name="ErrorPasswordSignUp">Passwords do not match</string>
<string name="ErrorUserEmptySignUp">Username cannot be empty</string>
<string name="ErrorUserExistSignUp">Username is not available</string>
//Page Profil
<string name="titleProfile">Profile</string>

Loading…
Cancel
Save