Merge pull request 'profile' (#12) from profile into master

Reviewed-on: #12
pull/13/head
Leni BEAULATON 2 months ago
commit 95ad9a6478

@ -50,7 +50,7 @@ android {
}
dependencies {
implementation(libs.bcrypt) // pour hacher les mdp
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
@ -68,4 +68,6 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest)
implementation(libs.coil.compose) //gére les url des image
}

@ -2,6 +2,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"

@ -11,6 +11,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.navigation.NavController
import com.example.what_the_fantasy.ui.screens.AppNavigator
import com.example.what_the_fantasy.ui.theme.What_The_FantasyTheme
import com.example.what_the_fantasy.ui.screens.LoginPage
@ -23,27 +24,13 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
What_The_FantasyTheme {
Column {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Title(
title = "What The Fantasy",
modifier = Modifier.padding(innerPadding)
)
}
}
//AppNavigator() // Accès à la page login et SingUp (pour le moment)
AppNavigator() // Accès à la page login et SingUp (pour le moment)
//ProfilPage() //Accès à la page profil
QuizPage()
//QuizPage()
}
}
}
}
@Composable
fun Title(title: String, modifier: Modifier = Modifier) {
Text(
text = "Welcome to $title!",
modifier = modifier
)
}

@ -8,73 +8,90 @@ object UserStub {
username = "Aragorn123",
email = "aragorn@example.com",
date = "2022-01-15",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-fantaisie_1045-185.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-fantaisie_1045-185.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user2 = User(
id = 2,
username = "Legolas456",
email = "legolas@example.com",
date = "2021-05-23",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-elfe-fantaisie_1045-186.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-elfe-fantaisie_1045-186.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user3 = User(
id = 3,
username = "Gandalf789",
email = "gandalf@example.com",
date = "2020-09-10",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-magicien-fantaisie_1045-187.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-magicien-fantaisie_1045-187.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user4 = User(
id = 4,
username = "FrodoBaggins",
email = "frodo@example.com",
date = "2023-03-18",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-hobbit-fantaisie_1045-188.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-hobbit-fantaisie_1045-188.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user5 = User(
id = 5,
username = "Gimli999",
email = "gimli@example.com",
date = "2022-07-04",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-nain-fantaisie_1045-189.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-nain-fantaisie_1045-189.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user6 = User(
id = 6,
username = "Galadriel321",
email = "galadriel@example.com",
date = "2021-11-30",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-elfe-femme-fantaisie_1045-190.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-elfe-femme-fantaisie_1045-190.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user7 = User(
id = 7,
username = "Boromir654",
email = "boromir@example.com",
date = "2023-06-22",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-191.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-191.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user8 = User(
id = 8,
username = "Eowyn777",
email = "eowyn@example.com",
date = "2022-04-11",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerriere-femme-fantaisie_1045-192.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerriere-femme-fantaisie_1045-192.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user9 = User(
id = 9,
username = "Saruman888",
email = "saruman@example.com",
date = "2021-08-15",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-magicien-malefique-fantaisie_1045-193.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-magicien-malefique-fantaisie_1045-193.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user10 = User(
id = 10,
username = "Faramir222",
email = "faramir@example.com",
date = "2023-02-08",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"
)
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val user11 = User(
id = 10,
username = "testeur",
email = "testeur@example.com",
date = "2023-02-08",
imgUrl = "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg",
password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234
val allUsers: List<User> = listOf(
user1, user2, user3, user4, user5, user6, user7, user8, user9, user10
user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11
)
}

@ -5,5 +5,6 @@ class User(
var username:String,
var email:String,
var date:String,
val imgUrl: String
val imgUrl: String,
val password: String
)

@ -0,0 +1,22 @@
package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun ErrorMessageProfileComponent(titleResId : Int) {
val textError = stringResource(id = titleResId)
Text(
text = textError,
color = Color.Red,
fontSize = 12.sp,
modifier = Modifier.padding(top = 4.dp)
)
}

@ -0,0 +1,15 @@
package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun SpaceHeightComponent(height : Int){
Spacer(
modifier = Modifier
.height(height.dp)) // Ajoute un espacement
}

@ -0,0 +1,21 @@
package com.example.what_the_fantasy.ui.components
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
@Composable
fun TitlePageComponent(titleResId : Int, size : Int, color : Color) {
val title = stringResource(id = titleResId)
Text(
text = title,
fontSize = size.sp,
fontWeight = FontWeight.Bold,
color = color
)
}

@ -2,6 +2,7 @@ package com.example.what_the_fantasy.ui.screens
import android.os.Bundle
import android.text.style.BackgroundColorSpan
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@ -44,14 +45,22 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.ui.theme.What_The_FantasyTheme
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.navigation.compose.rememberNavController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import com.example.what_the_fantasy.R
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 org.mindrot.jbcrypt.BCrypt
import java.security.MessageDigest
@Composable
fun LoginPage(navController : NavController) {
val users = UserStub.allUsers;
val gradient = Brush.linearGradient(
colors = listOf(Color(0xFF7B1FA2), Color(0xFF311B92)), // Violet clair → Violet foncé
start = Offset(0f, 1000f), // Départ en bas à gauche
@ -74,28 +83,22 @@ fun LoginPage(navController : NavController) {
horizontalAlignment = Alignment.CenterHorizontally
) {
TitlePage(R.string.titleLogin, 20,Color.White)
IdentifiantTextField(R.string.IdentifiantLogin)
PassWdTextField(R.string.PasswdLogin)
Space(16)
ConnexionButtonLogin(R.string.ButtonLogin,18, Color.White, Color.Black)
Space(16)
TitlePageComponent(R.string.titleLogin, 20,Color.White)
val identifiant =IdentifiantTextField(R.string.IdentifiantLogin)
val passwd = PassWdTextField(R.string.PasswdLogin)
SpaceHeightComponent(16)
ConnexionButtonLogin(users,identifiant, passwd, R.string.ButtonLogin,18, Color.White, Color.Black,navController)
SpaceHeightComponent(16)
CreateAccountButton(R.string.ButtonCreateLogin,12, Color.White, navController)
}
}
}
@Composable
fun Space(height : Int){
Spacer(
modifier = Modifier
.height(height.dp)) // Ajoute un espacement
}
@Composable
fun IdentifiantTextField(textIdentifiantResId : Int){
fun IdentifiantTextField(textIdentifiantResId : Int) : String{
val textIdentifiant = stringResource(id = textIdentifiantResId)
var identifiant by remember { mutableStateOf("") } // Stocke la valeur du champ
Column(modifier = Modifier.padding(top = 16.dp)) {
@ -110,10 +113,11 @@ fun IdentifiantTextField(textIdentifiantResId : Int){
shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis
)
}
return identifiant;
}
@Composable
fun PassWdTextField(textpasswdResId : Int){
fun PassWdTextField(textpasswdResId : Int) : String{
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
@ -131,27 +135,28 @@ fun PassWdTextField(textpasswdResId : Int){
IconButton(onClick = { passwordVisible = !passwordVisible }) {
}
},
shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis
shape = RoundedCornerShape(16.dp) // Bords arrondis
)
}
return passwd;
}
@Composable
fun TitlePage(titleResId : Int, size : Int, color : Color){
val title = stringResource(id = titleResId)
Text(
text = title,
fontSize = size.sp,
fontWeight = FontWeight.Bold,
color = color
)
}
//@Composable
//fun TitlePage(titleResId : Int, size : Int, color : Color){
// val title = stringResource(id = titleResId)
// Text(
// text = title,
// fontSize = size.sp,
// fontWeight = FontWeight.Bold,
// color = color
// )
//}
@Composable
fun ConnexionButtonLogin(titleResId : Int, size : Int, colorButton : Color, colorText : Color){
fun ConnexionButtonLogin(userStub : List<User>, id : String, passwd : String, titleResId : Int, size : Int, colorButton : Color, colorText : Color, navController: NavController){
val title = stringResource(id = titleResId)
Button(
onClick = { /* Action */ },
onClick = { validLogin(id, passwd, userStub, navController) },
colors = ButtonDefaults.buttonColors(containerColor = colorButton),
modifier = Modifier
.fillMaxWidth(),
@ -160,6 +165,30 @@ fun ConnexionButtonLogin(titleResId : Int, size : Int, colorButton : Color, colo
}
}
fun validLogin(identifiant : String, passwd : String, users : List<User>, navController: NavController){
users.forEach { user ->
val hashPassWd = hashPassword(passwd)
if (user.username == identifiant && user.password == hashPassWd){
navController.navigate("profile")
//navController.navigate(ProfilPage(navController))
}
}
}
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: NavController){
val title = stringResource(id = titleResId)
@ -180,6 +209,7 @@ fun AppNavigator() {
NavHost(navController, startDestination = "login") {
composable("login") { LoginPage(navController) }
composable("signup") { SignUpPage(navController) }
composable("profile") { ProfilPage(navController) }
}
}

@ -1,6 +1,9 @@
package com.example.what_the_fantasy.ui.screens
import android.content.Context
import android.os.Bundle
import android.util.Patterns
import android.widget.ImageView
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@ -54,16 +57,24 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import coil.compose.AsyncImage
import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.local.QuestionStub
import com.example.what_the_fantasy.data.local.UserStub
import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent
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.theme.What_The_FantasyTheme
@Composable
fun ProfilPage() {
fun ProfilPage(navController: NavController) {
val gradient = Brush.linearGradient(
colors = listOf(Color(0xFF7B1FA2), Color(0xFF311B92)), // Violet clair → Violet foncé
start = Offset(0f, 1000f), // Départ en bas à gauche
end = Offset(1000f, 0f) // Fin en haut à droite
)
val user = UserStub.allUsers
val index = 2 // Pour changer l'utilisateur pour le moment
Box(
modifier = Modifier
@ -82,30 +93,27 @@ fun ProfilPage() {
) {
// Titre
TitleProfil(R.string.titleProfile, 20, Color.White)
SpaceProfil(16)
TitlePageComponent(R.string.titleProfile, 20, Color.White)
SpaceHeightComponent(16)
// Image de profil
val id = R.drawable.ic_launcher_foreground
ImageProfil(id, 120, 2, Color.White)
ImageProfil(user[index].imgUrl, 120, 2, Color.White)
SpaceHeightComponent(16)
EditUsername(user[index].username)// Édition du Username
SpaceHeightComponent(16)
SpaceProfil(16)
EditUsername()// Édition du Username
SpaceProfil(16)
EditEmail()// Édition du Email
EditEmail(user[index].email)// Édition du Email
Spacer(modifier = Modifier.height(8.dp))
EditPasswd()
SpaceProfil(16)
SpaceHeightComponent(16)
// Bouton
ButtonProfile(R.string.ButtonAddQuoteprofile,18, Color.Black, Color.White)
SpaceProfil(16)
SpaceHeightComponent(16)
ButtonProfile(R.string.ButtonLanguageprofile,18, Color.Black, Color.White)
SpaceProfil(16)
SpaceHeightComponent(16)
ButtonProfile(R.string.ButtonUnlogprofile, 18, Color.Black, Color.White)
}
@ -113,81 +121,84 @@ fun ProfilPage() {
}
@Composable
fun SpaceProfil(height : Int){
Spacer(
modifier = Modifier
.height(height.dp)) // Ajoute un espacement
}
@Composable
fun TitleProfil(titleResId : Int, size : Int, color : Color){
val title = stringResource(id = titleResId)
Text(
text = title,
fontSize = size.sp,
fontWeight = FontWeight.Bold,
color = color
)
}
@Composable
fun ImageProfil(imgProfil : Int, size :Int, sizeBorber : Int, colorBorder : Color){
Image(
painter = painterResource(imgProfil),
fun ImageProfil(imgProfil : String, size :Int, sizeBorber : Int, colorBorder : Color){
AsyncImage(
model = imgProfil,
contentDescription = "Photo de profil",
modifier = Modifier
.size(size.dp)
.clip(CircleShape)
.border(sizeBorber.dp, colorBorder, CircleShape)
)
}
@Composable
fun EditEmail(){
var email by remember { mutableStateOf("user@example.com") }
var isEditingEmail by remember { mutableStateOf(false) } // État d'édition
fun EditEmail(userEmail: String) {
var email by remember { mutableStateOf(userEmail) }
var isEditingEmail by remember { mutableStateOf(false) }
var emailError by remember { mutableStateOf(false) }
if (isEditingEmail) {
EmailEditingField(
email = email,
onEmailChange = { newEmail ->
email = newEmail
emailError = !Patterns.EMAIL_ADDRESS.matcher(newEmail).matches()
},
onDone = {
if (!emailError) isEditingEmail = false
},
emailError = emailError
)
} else {
DisplayEmail(email = email, onEdit = { isEditingEmail = true })
}
}
@Composable
fun EmailEditingField(
email: String,
onEmailChange: (String) -> Unit,
onDone: () -> Unit,
emailError: Boolean
) {
OutlinedTextField(
value = email,
onValueChange = {
email = it
emailError = !android.util.Patterns.EMAIL_ADDRESS.matcher(it).matches()
},
onValueChange = onEmailChange,
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(color = Color.White, fontSize = 18.sp),
singleLine = true,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Email, // ✅ Clavier spécialisé pour email
keyboardType = KeyboardType.Email,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { if (!emailError) isEditingEmail = false } // ✅ Fermer si l'email est valide
onDone = { onDone() }
),
trailingIcon = {
IconButton(onClick = { if (!emailError) isEditingEmail = false }) {
IconButton(onClick = { if (!emailError) onDone() }) {
Icon(imageVector = Icons.Default.Check, contentDescription = "Valider")
}
},
isError = emailError // ✅ Afficher l'erreur si l'email est invalide
isError = emailError
)
if (emailError) {
val text = stringResource(id = R.string.ErrorEmailprofile)
Text(
text = text,
color = Color.Red,
fontSize = 12.sp,
modifier = Modifier.padding(top = 4.dp)
)
ErrorMessageProfileComponent(R.string.ErrorEmailprofile)
}
} else {
}
@Composable
fun DisplayEmail(email: String, onEdit: () -> Unit) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { isEditingEmail = true }
modifier = Modifier.clickable { onEdit() }
) {
Text(
text = email,
@ -203,18 +214,36 @@ fun EditEmail(){
)
}
}
}
@Composable
fun EditUsername(){
var username by remember { mutableStateOf("Username") }
var isEditingUsername by remember { mutableStateOf(false) } // État d'édition
fun EditUsername(userName: String) {
var username by remember { mutableStateOf(userName) }
var isEditingUsername by remember { mutableStateOf(false) }
if (isEditingUsername) {
UsernameEditingField(
username = username,
onUsernameChange = { username = it },
onDone = { isEditingUsername = false }
)
} else {
DisplayUsername(username = username, onEdit = { isEditingUsername = true })
}
}
@Composable
fun UsernameEditingField(
username: String,
onUsernameChange: (String) -> Unit,
onDone: () -> Unit
) {
OutlinedTextField(
value = username,
onValueChange = { username = it },
onValueChange = onUsernameChange,
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(color = Color.White, fontSize = 18.sp),
singleLine = true,
@ -222,18 +251,21 @@ fun EditUsername(){
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { isEditingUsername = false } // Quand on appuie sur "Done"
onDone = { onDone() } // Quand on appuie sur "Done", on met fin à l'édition
),
trailingIcon = {
IconButton(onClick = { isEditingUsername = false }) {
IconButton(onClick = { onDone() }) {
Icon(imageVector = Icons.Default.Check, contentDescription = "Valider")
}
}
)
} else {
}
@Composable
fun DisplayUsername(username: String, onEdit: () -> Unit) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { isEditingUsername = true }
modifier = Modifier.clickable { onEdit() }
) {
Text(
text = username,
@ -249,7 +281,10 @@ fun EditUsername(){
)
}
}
}
@Composable
@ -260,93 +295,131 @@ fun EditPasswd(){
var confirmPassword by remember { mutableStateOf("") }
var passwordVisible by remember { mutableStateOf(false) }
var passwordError by remember { mutableStateOf(false) }
if (isEditingPassword) {
PasswordEditingFields(
newPassword = newPassword,
confirmPassword = confirmPassword,
onNewPasswordChange = { newPassword = it },
onConfirmPasswordChange = {
confirmPassword = it
passwordError = newPassword != it
},
passwordVisible = passwordVisible,
onPasswordVisibilityChange = { passwordVisible = it },
passwordError = passwordError,
onDone = {
if (!passwordError && newPassword.isNotEmpty()) {
password = newPassword
isEditingPassword = false
}
}
)
} else {
DisplayPassword(onEdit = { isEditingPassword = true })
}
}
@Composable
fun PasswordEditingFields(
newPassword: String,
confirmPassword: String,
onNewPasswordChange: (String) -> Unit,
onConfirmPasswordChange: (String) -> Unit,
passwordVisible: Boolean,
onPasswordVisibilityChange: (Boolean) -> Unit,
passwordError: Boolean,
onDone: () -> Unit
) {
Column {
val text = stringResource(id = R.string.NewPasswdprofile)
OutlinedTextField(
PasswordTextField(
value = newPassword,
onValueChange = { newPassword = it },
label = { Text(text) },
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(color = Color.White, fontSize = 18.sp),
singleLine = true,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Next
),
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
IconButton(onClick = { passwordVisible = !passwordVisible }) {
}
}
onValueChange = onNewPasswordChange,
label = text,
passwordVisible = passwordVisible,
onPasswordVisibilityChange = onPasswordVisibilityChange
)
Spacer(modifier = Modifier.height(8.dp))
val textConfirm = stringResource(id = R.string.ConfirmNewPasswdprofile)
OutlinedTextField(
PasswordTextField(
value = confirmPassword,
onValueChange = {
confirmPassword = it
passwordError = newPassword != it
},
onValueChange = onConfirmPasswordChange,
label = textConfirm,
passwordVisible = passwordVisible,
onPasswordVisibilityChange = onPasswordVisibilityChange,
isError = passwordError,
onDone = onDone
)
if (passwordError) {
ErrorMessageProfileComponent(R.string.Errorpasswdprofile)
}
Spacer(modifier = Modifier.height(8.dp))
SaveButton(onClick = onDone)
}
}
label = { Text(textConfirm) },
@Composable
fun PasswordTextField(
value: String,
onValueChange: (String) -> Unit,
label: String,
passwordVisible: Boolean,
onPasswordVisibilityChange: (Boolean) -> Unit,
isError: Boolean = false,
onDone: (() -> Unit)? = null
) {
OutlinedTextField(
value = value,
onValueChange = onValueChange,
label = { Text(label) },
modifier = Modifier.fillMaxWidth(),
textStyle = TextStyle(color = Color.White, fontSize = 18.sp),
singleLine = true,
keyboardOptions = KeyboardOptions.Default.copy(
keyboardType = KeyboardType.Password,
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { if (!passwordError && newPassword.isNotEmpty()) {
password = newPassword
isEditingPassword = false
}}
imeAction = if (onDone != null) ImeAction.Done else ImeAction.Next
),
keyboardActions = onDone?.let {
KeyboardActions(onDone = { it() })
} ?: KeyboardActions.Default,
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = {
IconButton(onClick = { passwordVisible = !passwordVisible }) {
IconButton(onClick = { onPasswordVisibilityChange(!passwordVisible) }) {
// Ajout d'une icône pour montrer/masquer le mot de passe
}
},
isError = passwordError
)
if (passwordError) {
val text = stringResource(id = R.string.Errorpasswdprofile)
Text(
text = text,
color = Color.Red,
fontSize = 12.sp,
modifier = Modifier.padding(top = 4.dp)
isError = isError
)
}
Spacer(modifier = Modifier.height(8.dp))
@Composable
fun SaveButton(onClick: () -> Unit) {
Button(
onClick = {
if (!passwordError && newPassword.isNotEmpty()) {
password = newPassword
isEditingPassword = false
}
},
onClick = onClick,
colors = ButtonDefaults.buttonColors(containerColor = Color.White),
modifier = Modifier.fillMaxWidth()
) {
val text = stringResource(id = R.string.ButtonSaveprofile)
Text(text, fontSize = 18.sp, color = Color.Black)
Text(text,
fontSize = 18.sp,
color = Color.Black)
}
}
} else {
@Composable
fun DisplayPassword(onEdit: () -> Unit) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.clickable { isEditingPassword = true }
modifier = Modifier.clickable { onEdit() }
) {
Text(
text = password,
text = "*****",
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
color = Color.White
@ -359,7 +432,10 @@ fun EditPasswd(){
)
}
}
}
@Composable

@ -40,7 +40,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.navigation.NavController
import com.example.what_the_fantasy.R
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.theme.What_The_FantasyTheme
import org.mindrot.jbcrypt.BCrypt
@Composable
fun SignUpPage(navController: NavController) {
@ -66,26 +69,21 @@ fun SignUpPage(navController: NavController) {
horizontalAlignment = Alignment.CenterHorizontally
) {
TitlePage(R.string.titleSignUp, 20,Color.White)
TitlePageComponent(R.string.titleSignUp, 20,Color.White)
IdentifiantTextFieldSign(R.string.IdentifiantLogin)
EmailTextFieldSign("Email*")
PassWdTextFieldSign(R.string.PasswdLogin)
PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp)
SpaceSign(16)
SpaceHeightComponent(16)
ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black)
SpaceSign(16)
SpaceHeightComponent(16)
CreateAccountButtonSign(R.string.ButtonLogin,12, Color.White, navController = navController)
}
}
}
@Composable
fun SpaceSign(height : Int){
Spacer(
modifier = Modifier
.height(height.dp)) // Ajoute un espacement
}
@Composable
@ -119,7 +117,7 @@ fun EmailTextFieldSign(textIdentifiant : String){
.fillMaxWidth()
.padding(top = 8.dp),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Email),
shape = RoundedCornerShape(16.dp) // 🔹 Bords arrondis
shape = RoundedCornerShape(16.dp) // Bords arrondis
)
}
}
@ -172,15 +170,7 @@ fun PassWdConfirmTextFieldSign(textpasswdResId : Int){
}
}
//@Composable
//fun TitleSign(title : String, size : Int, color : Color){
// Text(
// text = title,
// fontSize = size.sp,
// fontWeight = FontWeight.Bold,
// color = color
// )
//}
@Composable
fun ConnexionButtonSign(titleResId : Int, size : Int, colorButton : Color, colorText : Color){

@ -1,5 +1,8 @@
[versions]
agp = "8.6.0"
bcrypt = "0.4"
coilCompose = "2.2.1"
kotlin = "1.9.0"
coreKtx = "1.10.1"
junit = "4.13.2"
@ -13,6 +16,9 @@ navigationCommonAndroid = "2.9.0-alpha05"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
bcrypt = { module = "org.mindrot:jbcrypt", version.ref = "bcrypt" }
coil-compose = { module = "io.coil-kt:coil-compose", version.ref = "coilCompose" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }

Loading…
Cancel
Save