From 407dd4f22abf5fcf8270579494ebef671c7eec82 Mon Sep 17 00:00:00 2001 From: tomivt Date: Thu, 20 Feb 2025 15:25:04 +0100 Subject: [PATCH 1/7] Add Navigation into Quiz pages --- .../example/what_the_fantasy/MainActivity.kt | 12 ------- .../ui/navigations/AppNavigator.kt | 27 ++++++++++++++-- .../what_the_fantasy/ui/screens/LoginPage.kt | 7 ---- .../ui/screens/QuizEndPage.kt | 2 +- .../screens/{QuizAccueil.kt => QuizMenu.kt} | 32 +++---------------- .../what_the_fantasy/ui/screens/QuizPage.kt | 14 +++----- 6 files changed, 35 insertions(+), 59 deletions(-) rename What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/{QuizAccueil.kt => QuizMenu.kt} (80%) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt index 2d893b5..2c953cc 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt @@ -4,19 +4,8 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -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.navigations.AppNavigator import com.example.what_the_fantasy.ui.theme.What_The_FantasyTheme -import com.example.what_the_fantasy.ui.screens.LoginPage -import com.example.what_the_fantasy.ui.screens.ProfilPage -import com.example.what_the_fantasy.ui.screens.QuizPage class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -26,7 +15,6 @@ class MainActivity : ComponentActivity() { What_The_FantasyTheme { AppNavigator() - //QuizPage() } } } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt index fc05703..4475a7f 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt @@ -8,6 +8,8 @@ import com.example.what_the_fantasy.ui.screens.AccueilPage import com.example.what_the_fantasy.ui.screens.FavoritePage import com.example.what_the_fantasy.ui.screens.LoginPage import com.example.what_the_fantasy.ui.screens.ProfilPage +import com.example.what_the_fantasy.ui.screens.QuizEndPage +import com.example.what_the_fantasy.ui.screens.QuizMenu import com.example.what_the_fantasy.ui.screens.QuizPage import com.example.what_the_fantasy.ui.screens.QuotePage import com.example.what_the_fantasy.ui.screens.SearchPage @@ -21,7 +23,12 @@ sealed class Destination(val route: String) { data object Accueil : Destination("Accueil") data object Favorite : Destination("Favorite") data object Profil : Destination("Profil") + data object QuizMenu : Destination("QuizMenu") data object Quiz : Destination("Quiz") + data object QuizEnd : Destination("QuizEnd/{idQuiz}/{pts}") { + // Ajout paramètres idQuiz et pts + fun createIdAndPts(idQuiz : Int, pts : Int) = "QuizEnd/$idQuiz/$pts" + } data object Quote : Destination("Quote") data object Search : Destination("Search") data object SignUp : Destination("SignUp") @@ -32,7 +39,7 @@ sealed class Destination(val route: String) { fun AppNavigator() { val navController = rememberNavController() - NavHost(navController, startDestination = Destination.Login.route) { + NavHost(navController, startDestination = Destination.QuizMenu.route) { composable(Destination.Login.route) { LoginPage( navControllerSignUp = { navController.navigate(Destination.SignUp.route) }, @@ -42,7 +49,23 @@ fun AppNavigator() { composable(Destination.Accueil.route) { AccueilPage() } composable(Destination.Favorite.route) { FavoritePage() } composable(Destination.Profil.route) { ProfilPage(navController) } - composable(Destination.Quiz.route) { QuizPage() } + composable(Destination.QuizMenu.route) { + QuizMenu( + navControllerQuiz = { navController.navigate(Destination.Quiz.route) } + ) + } + composable(Destination.Quiz.route) { + QuizPage( + navControllerQuizEnd = { idQuiz, pts -> + navController.navigate(Destination.QuizEnd.createIdAndPts(idQuiz, pts)) + } + ) + } + composable(Destination.QuizEnd.route) { backStackEntry -> + val idQuiz = backStackEntry.arguments?.getString("idQuiz")?.toInt() ?: 0 + val pts = backStackEntry.arguments?.getString("pts")?.toInt() ?: 0 + QuizEndPage(idQuiz, pts) + } composable(Destination.Quote.route) { QuotePage() } composable(Destination.Search.route) { SearchPage() } composable(Destination.SignUp.route) { SignUpPage(navController) } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt index f6e1023..252b217 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt @@ -22,8 +22,6 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType @@ -31,10 +29,6 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -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 @@ -49,7 +43,6 @@ fun LoginPage(navControllerSignUp: () -> Unit, navControllerProfil: () -> Unit) val users = UserStub.allUsers; - Box( modifier = Modifier .fillMaxSize() diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt index 359e7f7..686a127 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt @@ -34,7 +34,7 @@ val gradient = Brush.linearGradient( @Composable -fun QuizEndPage(points: Int, idQuiz: Int) { +fun QuizEndPage(idQuiz: Int, points: Int) { Column( modifier = Modifier.fillMaxSize().background(Color(0xFF100C1B)) ) { diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizAccueil.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizMenu.kt similarity index 80% rename from What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizAccueil.kt rename to What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizMenu.kt index b237afd..08225f0 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizAccueil.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizMenu.kt @@ -19,15 +19,11 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController import com.example.what_the_fantasy.R @Composable -fun QuizAccueil(navController: NavController) { +fun QuizMenu(navControllerQuiz: () -> Unit) { Row( modifier = Modifier .fillMaxSize() @@ -47,7 +43,7 @@ fun QuizAccueil(navController: NavController) { .size(width = 150.dp, height = 100.dp) .padding(8.dp) .clickable { - navController.navigate("quizPage") + navControllerQuiz() } ) { Image( @@ -63,8 +59,7 @@ fun QuizAccueil(navController: NavController) { .size(width = 150.dp, height = 100.dp) .padding(8.dp) .clickable { - - navController.navigate("quizPage") + navControllerQuiz() } ) { Image( @@ -89,7 +84,7 @@ fun QuizAccueil(navController: NavController) { .size(width = 150.dp, height = 100.dp) .padding(8.dp) .clickable { - navController.navigate("quizPage") + navControllerQuiz() } ) { Image( @@ -105,7 +100,7 @@ fun QuizAccueil(navController: NavController) { .size(width = 150.dp, height = 100.dp) .padding(8.dp) .clickable { - navController.navigate("quizPage") + navControllerQuiz() } ) { Image( @@ -119,21 +114,4 @@ fun QuizAccueil(navController: NavController) { Spacer(modifier = Modifier.weight(0.1f)) } -} - -@Composable -fun QuizApp() { - val navController = rememberNavController() - - NavHost(navController = navController, startDestination = "quizEndPage") { - composable("quizAccueil") { - QuizAccueil(navController = navController) - } - composable("quizPage") { - QuizPage(navController = navController) - } - composable("quizEndPage") { - QuizEndPage(5, 1) - } - } } \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt index 4317669..b1d9dc7 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt @@ -4,11 +4,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material.icons.filled.ArrowBack -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment @@ -18,11 +13,10 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.navigation.NavController import com.example.what_the_fantasy.data.local.QuestionStub @Composable -fun QuizPage(navController: NavController) { +fun QuizPage(navControllerQuizEnd: (Int, Int) -> Unit) { val questions = QuestionStub.allQuestions var idCurrentQuestion by remember { mutableIntStateOf(0) } var pts by remember { mutableIntStateOf(0) } @@ -44,7 +38,7 @@ fun QuizPage(navController: NavController) { if (answer == correctAnswer) pts++ if (idCurrentQuestion < questions.size - 1) idCurrentQuestion++ - else navController.popBackStack() // Retour menu + else navControllerQuizEnd(0, pts) // Retour menu } Box( @@ -66,12 +60,12 @@ fun QuizPage(navController: NavController) { Box( modifier = Modifier.fillMaxWidth() ) { - IconButton( + /*IconButton( onClick = { navController.popBackStack() }, modifier = Modifier.align(Alignment.TopStart) ) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Retour", tint = Color.White) - } + }*/ } Text("Question ${question.id}", color = Color.White, fontSize = 18.sp, modifier = Modifier.padding(top = 20.dp)) Text("Points : $pts", color = Color.White, fontSize = 18.sp, modifier = Modifier.padding(top = 40.dp)) From bba419bff0fdd2a37f88ab6dd1845ebebedc70ad Mon Sep 17 00:00:00 2001 From: "leni.beaulaton" Date: Wed, 26 Feb 2025 18:26:35 +0100 Subject: [PATCH 2/7] La page d'inscription fonctionne --- .../data/services/IServices.kt | 2 +- .../data/services/ServicesAPI.kt | 2 +- .../data/services/ServicesStub.kt | 30 +++- .../ui/components/hashPassword.kt | 14 ++ .../what_the_fantasy/ui/screens/LoginPage.kt | 13 +- .../what_the_fantasy/ui/screens/SignUpPage.kt | 131 +++++++++++++----- .../app/src/main/res/values-fr/strings.xml | 5 + .../app/src/main/res/values/strings.xml | 5 + 8 files changed, 152 insertions(+), 50 deletions(-) create mode 100644 What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt index df15ebd..2b8febf 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt @@ -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) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt index 9743f68..fdbcb49 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt @@ -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") } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt index 8c84176..dc4519f 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt @@ -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") } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt new file mode 100644 index 0000000..2f46a9d --- /dev/null +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/components/hashPassword.kt @@ -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) } +} \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt index 47309cc..9aec7bd 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt @@ -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, 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) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt index 3e77782..d344889 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt @@ -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, diff --git a/What_The_Fantasy/app/src/main/res/values-fr/strings.xml b/What_The_Fantasy/app/src/main/res/values-fr/strings.xml index 9d55b61..899a998 100644 --- a/What_The_Fantasy/app/src/main/res/values-fr/strings.xml +++ b/What_The_Fantasy/app/src/main/res/values-fr/strings.xml @@ -16,6 +16,11 @@ Inscription Confirmer mot de passe* S\'inscrire + Email* + Email invalide + Les mots de passe ne correspondent pas + Le nom d\'utilisateur ne peut pas être vide + Le nom d\'utilisateur n\'est pas disponible //Page Profil Profil diff --git a/What_The_Fantasy/app/src/main/res/values/strings.xml b/What_The_Fantasy/app/src/main/res/values/strings.xml index c9ab3e1..4e02f70 100644 --- a/What_The_Fantasy/app/src/main/res/values/strings.xml +++ b/What_The_Fantasy/app/src/main/res/values/strings.xml @@ -15,6 +15,11 @@ Account creation Confirm your password* Create + Your email* + Invalid email + Passwords do not match + Username cannot be empty + Username is not available //Page Profil Profile From b93310671e5335d68a469dddcd09884501b50efb Mon Sep 17 00:00:00 2001 From: tomivt Date: Thu, 27 Feb 2025 03:33:48 +0100 Subject: [PATCH 3/7] UI QuizPage + Add Icons --- .../example/what_the_fantasy/MainActivity.kt | 1 - .../ui/navigations/AppNavigator.kt | 9 +- .../ui/screens/QuizEndPage.kt | 20 +-- .../what_the_fantasy/ui/screens/QuizPage.kt | 147 +++++++++++++----- .../app/src/main/res/drawable/like_icon.png | Bin 0 -> 19932 bytes .../src/main/res/drawable/profile_icon.png | Bin 0 -> 16875 bytes .../app/src/main/res/drawable/quiz_icon.png | Bin 0 -> 10876 bytes .../app/src/main/res/drawable/toggle.png | Bin 0 -> 10431 bytes .../app/src/main/res/drawable/wf_logo.png | Bin 0 -> 8339 bytes 9 files changed, 126 insertions(+), 51 deletions(-) create mode 100644 What_The_Fantasy/app/src/main/res/drawable/like_icon.png create mode 100644 What_The_Fantasy/app/src/main/res/drawable/profile_icon.png create mode 100644 What_The_Fantasy/app/src/main/res/drawable/quiz_icon.png create mode 100644 What_The_Fantasy/app/src/main/res/drawable/toggle.png create mode 100644 What_The_Fantasy/app/src/main/res/drawable/wf_logo.png diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt index 2c953cc..cbed7f2 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/MainActivity.kt @@ -13,7 +13,6 @@ class MainActivity : ComponentActivity() { enableEdgeToEdge() setContent { What_The_FantasyTheme { - AppNavigator() } } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt index 4475a7f..f872ec4 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt @@ -58,13 +58,18 @@ fun AppNavigator() { QuizPage( navControllerQuizEnd = { idQuiz, pts -> navController.navigate(Destination.QuizEnd.createIdAndPts(idQuiz, pts)) - } + }, + navControllerQuizMenu = { navController.navigate(Destination.QuizMenu.route) } ) } composable(Destination.QuizEnd.route) { backStackEntry -> val idQuiz = backStackEntry.arguments?.getString("idQuiz")?.toInt() ?: 0 val pts = backStackEntry.arguments?.getString("pts")?.toInt() ?: 0 - QuizEndPage(idQuiz, pts) + QuizEndPage( + idQuiz, + pts, + navControllerQuizMenu = { navController.navigate(Destination.QuizMenu.route) } + ) } composable(Destination.Quote.route) { QuotePage() } composable(Destination.Search.route) { SearchPage() } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt index 686a127..c66c04c 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt @@ -2,6 +2,7 @@ package com.example.what_the_fantasy.ui.screens import androidx.compose.foundation.Image import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -31,10 +32,8 @@ val gradient = Brush.linearGradient( end = Offset(1000f, 0f) ) - - @Composable -fun QuizEndPage(idQuiz: Int, points: Int) { +fun QuizEndPage(idQuiz: Int, points: Int, navControllerQuizMenu: () -> Unit) { Column( modifier = Modifier.fillMaxSize().background(Color(0xFF100C1B)) ) { @@ -48,9 +47,6 @@ fun QuizEndPage(idQuiz: Int, points: Int) { horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { - IconButton(onClick = { }) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Retour", tint = Color.White) - } Image( painter = painterResource(id = R.drawable.quiz), contentDescription = "Profil", @@ -58,8 +54,7 @@ fun QuizEndPage(idQuiz: Int, points: Int) { ) Image( painter = painterResource(id = R.drawable.quiz), - contentDescription = "Profil", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) + contentDescription = "Profil" ) } @@ -122,8 +117,7 @@ fun QuizEndPage(idQuiz: Int, points: Int) { // Bouton Quiz Suivant Image( painter = painterResource(id = R.drawable.quiz), - contentDescription = "Profil", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) + contentDescription = "Profil" ) } @@ -148,9 +142,9 @@ fun QuizEndPage(idQuiz: Int, points: Int) { ) // Bouton WhatTheFantasy Image( - painter = painterResource(id = R.drawable.quiz), - contentDescription = "Bouton", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) + painter = painterResource(R.drawable.wf_logo), + contentDescription = "Menu Button", + Modifier.clickable { navControllerQuizMenu() } ) // Bouton Quiz Image( diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt index b1d9dc7..721d37d 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizPage.kt @@ -1,8 +1,10 @@ package com.example.what_the_fantasy.ui.screens +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.* @@ -11,12 +13,20 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.example.what_the_fantasy.R import com.example.what_the_fantasy.data.local.QuestionStub @Composable -fun QuizPage(navControllerQuizEnd: (Int, Int) -> Unit) { +fun QuizPage( + navControllerQuizEnd: (Int, Int) -> Unit, + navControllerQuizMenu: () -> Unit + ) { val questions = QuestionStub.allQuestions var idCurrentQuestion by remember { mutableIntStateOf(0) } var pts by remember { mutableIntStateOf(0) } @@ -41,56 +51,123 @@ fun QuizPage(navControllerQuizEnd: (Int, Int) -> Unit) { else navControllerQuizEnd(0, pts) // Retour menu } - Box( - modifier = Modifier - .fillMaxSize() - .background(Color(0xFF100C1B)) - .padding(16.dp) + Column ( + modifier = Modifier.fillMaxSize().background(Color(0xFF100C1B)) ) { + // Bandeau supérieur + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.1f) + //.background(Color(0xFF300052)) + .padding(20.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + Image( + painter = painterResource(id = R.drawable.profile_icon), + contentDescription = "Profil" + ) + Image( + painter = painterResource(id = R.drawable.toggle), + contentDescription = "Profil" + ) + } + + // Contenu princiapl Column( modifier = Modifier - .fillMaxSize(), + .weight(0.8f) + .fillMaxWidth() + .padding(horizontal = 50.dp, vertical = 20.dp), horizontalAlignment = Alignment.CenterHorizontally ) { val question = questions[idCurrentQuestion] - Column ( + Column( horizontalAlignment = Alignment.CenterHorizontally, ) { - Box( - modifier = Modifier.fillMaxWidth() + Text( + text = "▶ Quiz ◀", + color = Color.White, + style = TextStyle(fontSize = 25.sp, fontWeight = FontWeight.Bold, textAlign = TextAlign.Center) + ) + Column ( + modifier = Modifier + .background(brush = gradient, shape = RoundedCornerShape(20.dp)), + horizontalAlignment = Alignment.CenterHorizontally ) { - /*IconButton( - onClick = { navController.popBackStack() }, - modifier = Modifier.align(Alignment.TopStart) - ) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Retour", tint = Color.White) - }*/ - } - Text("Question ${question.id}", color = Color.White, fontSize = 18.sp, modifier = Modifier.padding(top = 20.dp)) - Text("Points : $pts", color = Color.White, fontSize = 18.sp, modifier = Modifier.padding(top = 40.dp)) - Text(question.question, color = Color.White, fontSize = 22.sp, modifier = Modifier.padding(40.dp)) - } - Column ( - modifier = Modifier - .padding(top = 30.dp) - ) { - listOf(question.ansA, question.ansB, question.ansC, question.ansD).forEach { answer -> - Box( + Text( + "Question ${question.id}", + color = Color.White, + fontSize = 18.sp, + modifier = Modifier.padding(top = 20.dp), + style = TextStyle( + fontSize = 25.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center + ) + ) + Text( + question.question, + color = Color.White, + fontSize = 22.sp, + modifier = Modifier.padding(40.dp) + ) + Column( modifier = Modifier - .width(220.dp) - .height(50.dp) - .background(brush = gradient, shape = RoundedCornerShape(16.dp)) - .clickable { onAnswerSelected(answer) } - .padding(horizontal = 8.dp), - contentAlignment = Alignment.Center + .padding(top = 30.dp) ) { - Text(answer, color = Color.White, fontSize = 18.sp) + listOf( + question.ansA, + question.ansB, + question.ansC, + question.ansD + ).forEach { answer -> + Box( + modifier = Modifier + .width(220.dp) + .height(50.dp) + .background(Color.White, shape = RoundedCornerShape(16.dp)) + .clickable { onAnswerSelected(answer) } + .padding(horizontal = 8.dp), + contentAlignment = Alignment.Center + ) { + Text(answer, color = Color.Black, fontSize = 18.sp) + } + Spacer(modifier = Modifier.height(60.dp)) + } } - Spacer(modifier = Modifier.height(60.dp)) } } + } + // Bandeau inférieur + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.1f) + .background(Color(0xFF300052)) + .padding(20.dp), + horizontalArrangement = Arrangement.SpaceAround, + verticalAlignment = Alignment.CenterVertically + ) { + // Bouton Likes + Image( + painter = painterResource(id = R.drawable.like_icon), + contentDescription = "Bouton" + ) + // Bouton WhatTheFantasy + Image( + painter = painterResource(R.drawable.wf_logo), + contentDescription = "Menu Button", + Modifier.clickable { navControllerQuizMenu() } + ) + // Bouton Quiz + Image( + painter = painterResource(id = R.drawable.quiz_icon), + contentDescription = "Bouton" + ) } } } \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/res/drawable/like_icon.png b/What_The_Fantasy/app/src/main/res/drawable/like_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6d62a6cf2999c0d640e96085a9ea5c879bc7e4ec GIT binary patch literal 19932 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 pe<-Mg`#{p$|N4;a=Uu&0_&suium{txdoaO400 literal 0 HcmV?d00001 diff --git a/What_The_Fantasy/app/src/main/res/drawable/wf_logo.png b/What_The_Fantasy/app/src/main/res/drawable/wf_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7388be92954e0d44f6b46f3455a0dbd72b16cb4e GIT binary patch literal 8339 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ξR@^~kE;ogKyh8><(pWPFunVN4g3S7>4?)in-#lWk*3PBP$cWlf8 zbw+3#0XA^kOiDbctd2E~g*UVJ$UQuVF=2ZI{iPiRx}XDOxM78eV)}sENZes0zyuGS zTrATd8VAD`t~xI}+04bZIj{;x4- zCuY7DJiQz!?ojo%N9DsNdij0)IXm()h)}k-|MvJCZn4Z{36^P3aB;{Mk}{)!-Dr~S z&vMdwaUF(KDccX8)1B_@o}C#3ro8lSd0YR8=}ikBrPWflhVLE`V|x9}SWXR|`M(c4 zECjYy{>qG4OOz*Y!{WoQvu`VCf7@mUxo*CZKM>m$N1+_OpWvYh>=w7hzwHoT%F|q+5PYLIw|>zP6@>-OzdC&M<)3<5xh@6B$w%eEH~E#doPYNGj9Jr`?$mTbBmx=H%hk-YaR;sX2d|wjyCKo=_Zsdx!%_%j-z8*V=i3SzaE~Q(wIt00 ziT-d*@Odh#7YLM>dEBofwQ&b+Q1VsMzQ1$z_Kz!dAHIWzx%5pQ{;vt>7fd(o?qGo2 gzq0`UgK8Zbf~be>7^#wE@5BJl6rU?p$eRWKADs=T Date: Thu, 27 Feb 2025 13:36:17 +0100 Subject: [PATCH 4/7] Les pages se partagent les services --- .../what_the_fantasy/data/local/UserStub.kt | 121 +++++------------- .../data/services/IServices.kt | 8 +- .../data/services/ServicesAPI.kt | 12 +- .../data/services/ServicesStub.kt | 28 +++- .../ui/navigations/AppNavigator.kt | 15 ++- .../what_the_fantasy/ui/screens/LoginPage.kt | 8 +- .../what_the_fantasy/ui/screens/ProfilPage.kt | 8 +- .../what_the_fantasy/ui/screens/SignUpPage.kt | 11 +- 8 files changed, 94 insertions(+), 117 deletions(-) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/local/UserStub.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/local/UserStub.kt index 552ad3e..e166cd4 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/local/UserStub.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/local/UserStub.kt @@ -3,95 +3,38 @@ package com.example.what_the_fantasy.data.local import com.example.what_the_fantasy.data.model.User object UserStub { - val user1 = User( - id = 1, - 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", - 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", - 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", - 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", - 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", - 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", - 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", - 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", - 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", - 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", - password = "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4") // 1234 + //LE MOT DE PASSE POUR TOUS LES UTILISATEURS EST : 1234 + val users: MutableList = mutableListOf( + User(1, "Aragorn123", "aragorn@example.com", "2022-01-15", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-fantaisie_1045-185.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"), //1234 + User(2, "Legolas456", "legolas@example.com", "2021-05-23", "https://img.freepik.com/vecteurs-libre/personnage-elfe-fantaisie_1045-186.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(3, "Gandalf789", "gandalf@example.com", "2020-09-10", "https://img.freepik.com/vecteurs-libre/personnage-magicien-fantaisie_1045-187.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(4, "FrodoBaggins", "frodo@example.com", "2023-03-18", "https://img.freepik.com/vecteurs-libre/personnage-hobbit-fantaisie_1045-188.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(5, "Gimli999", "gimli@example.com", "2022-07-04", "https://img.freepik.com/vecteurs-libre/personnage-nain-fantaisie_1045-189.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(6, "Galadriel321", "galadriel@example.com", "2021-11-30", "https://img.freepik.com/vecteurs-libre/personnage-elfe-femme-fantaisie_1045-190.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(7, "Boromir654", "boromir@example.com", "2023-06-22", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-191.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(8, "Eowyn777", "eowyn@example.com", "2022-04-11", "https://img.freepik.com/vecteurs-libre/personnage-guerriere-femme-fantaisie_1045-192.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(9, "Saruman888", "saruman@example.com", "2021-08-15", "https://img.freepik.com/vecteurs-libre/personnage-magicien-malefique-fantaisie_1045-193.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(10, "Faramir222", "faramir@example.com", "2023-02-08", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4"),//1234 + User(11, "dev", "testeur@example.com", "2023-02-08", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4")//1234 + ) - val user11 = User( - id = 10, - username = "dev", - 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 + fun addUser(user: User) { + users.add(user) + } + +// +// // Modifier un utilisateur +// fun updateUser(id: Int, updatedUser: User) { +// val index = users.indexOfFirst { it.id == id } +// if (index != -1) { +// users[index] = updatedUser +// } +// } +// +// // Supprimer un utilisateur +// fun removeUser(id: Int) { +// users.removeAll { it.id == id } +// } +// - val allUsers: List = listOf( - user1, user2, user3, user4, user5, user6, user7, user8, user9, user10, user11 - ) } \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt index 2b8febf..d48fd2f 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt @@ -1,13 +1,19 @@ package com.example.what_the_fantasy.data.services +import com.example.what_the_fantasy.data.local.UserStub.users +import com.example.what_the_fantasy.data.model.User + interface IServices { fun EditUsername(username : String) fun EditEmail(email : String) fun EditPasswd(passwd : String, passwdValid : String) fun EditImage(imageURL : String) - fun CreateUser(username : String, email : String, passwd : String, imageURL: String) : Boolean + fun CreateUser(username : String, email : String, passwd : String, imageURL: String, services : IServices) : Boolean fun getFavorite(username: String) + fun getAllUsers(): List + + fun getUserById(id: Int): User? fun SearchQuote(quote : String) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt index fdbcb49..5ac90ee 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt @@ -1,5 +1,7 @@ package com.example.what_the_fantasy.data.services +import com.example.what_the_fantasy.data.model.User + class ServicesAPI : IServices { override fun EditUsername(username: String) { TODO("Not yet implemented") @@ -17,7 +19,7 @@ class ServicesAPI : IServices { TODO("Not yet implemented") } - override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) : Boolean { + override fun CreateUser(username: String, email: String, passwd: String, imageURL: String, services: IServices) : Boolean { TODO("Not yet implemented") } @@ -28,4 +30,12 @@ class ServicesAPI : IServices { override fun getFavorite(username: String) { TODO("Not yet implemented") } + + override fun getAllUsers(): List { + TODO("Not yet implemented") + } + + override fun getUserById(id: Int): User? { + TODO("Not yet implemented") + } } \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt index dc4519f..d6cbfe3 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt @@ -3,6 +3,7 @@ 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.local.UserStub.users import com.example.what_the_fantasy.data.model.User import com.example.what_the_fantasy.ui.components.hashPassword import java.time.LocalDate @@ -24,22 +25,26 @@ class ServicesStub : IServices { TODO("Not yet implemented") } - override fun CreateUser(username: String, email: String, passwd: String, imageURL: String) : Boolean { + override fun CreateUser(username: String, email: String, passwd: String, imageURL: String, services : IServices) : Boolean { val date =dateDuJour() val passwordhash = hashPassword(passwd) //Check si user existe déjà - val users = UserStub.allUsers - for (user in users) { + val userStub = services.getAllUsers() + val nbUser = userStub.size + for (user in userStub) { 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 + val user = User(nbUser+1,username, email, imageURL, date, passwordhash) + users.add(user)//ajout au stub + //Afficher tous les users + for(user in userStub){ + Log.e("CreateUser", "User created: ${user.username} => ${user.password}") + } + return true } @SuppressLint("NewApi") @@ -47,6 +52,15 @@ class ServicesStub : IServices { val date = LocalDate.now() return date.toString() } + + + // Récupérer tous les utilisateurs + override fun getAllUsers(): List = users + + override fun getUserById(id: Int): User? { + return (users.find { it.id == id+1 }) + } + override fun SearchQuote(quote: String) { TODO("Not yet implemented") } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt index d7c38e5..bda1463 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import com.example.what_the_fantasy.data.services.ServicesStub import com.example.what_the_fantasy.ui.screens.AccueilPage import com.example.what_the_fantasy.ui.screens.FavoritePage import com.example.what_the_fantasy.ui.screens.LoginPage @@ -33,28 +34,28 @@ sealed class Destination(val route: String) { @Composable fun AppNavigator() { val navController = rememberNavController() - + val services = ServicesStub() // A changer si l'on veut passer au service API NavHost(navController, startDestination = Destination.Login.route) { composable(Destination.Login.route) { LoginPage( navControllerSignUp = { navController.navigate(Destination.SignUp.route) }, navControllerProfil = { userIndex -> navController.navigate(Destination.Profil.createRoute(userIndex)) // Passe l'index à Profil - } + }, + services ) } composable(Destination.Accueil.route) { AccueilPage() } composable(Destination.Favorite.route) { FavoritePage() } - composable(Destination.Profil.route) { backStackEntry -> + composable(Destination.Profil.route) { // Récupère l'index passé dans la route - val userIndex = backStackEntry.arguments?.getString("userIndex")?.toInt() ?: -1 - ProfilPage(index = userIndex, navController = navController) + val userIndex = it.arguments?.getString("userIndex")?.toInt() ?: -1 + ProfilPage(index = userIndex, navController = navController, services) } composable(Destination.Quiz.route) { QuizPage(navController) } composable(Destination.Quote.route) { QuotePage() } composable(Destination.Search.route) { SearchPage() } - composable(Destination.SignUp.route) { SignUpPage(navController) } + composable(Destination.SignUp.route) { SignUpPage(navController, services) } composable(Destination.SubmitQuote.route) { SubmitQuotePage() } } } - diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt index 9aec7bd..a824491 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt @@ -39,6 +39,8 @@ 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.data.services.IServices +import com.example.what_the_fantasy.data.services.ServicesStub 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 @@ -47,10 +49,8 @@ import com.example.what_the_fantasy.ui.theme.gradienBox import java.security.MessageDigest @Composable -fun LoginPage(navControllerSignUp: () -> Unit, navControllerProfil: (Int) -> Unit) { - - val users = UserStub.allUsers; - +fun LoginPage(navControllerSignUp: () -> Unit, navControllerProfil: (Int) -> Unit, services : IServices) { + val users = services.getAllUsers() Box( modifier = Modifier diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt index 98e7838..c8ee9aa 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt @@ -61,6 +61,9 @@ 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.data.local.UserStub.users +import com.example.what_the_fantasy.data.services.IServices +import com.example.what_the_fantasy.data.services.ServicesStub 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 @@ -68,10 +71,9 @@ import com.example.what_the_fantasy.ui.theme.What_The_FantasyTheme import com.example.what_the_fantasy.ui.theme.gradienBox @Composable -fun ProfilPage(index: Int, navController: NavController) { +fun ProfilPage(index: Int, navController: NavController, services: IServices) { - val userList = UserStub.allUsers - val user = userList[index] + val user = services.getUserById(index) ?: return Box( modifier = Modifier diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt index d344889..48c21b8 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/SignUpPage.kt @@ -43,6 +43,7 @@ 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.data.services.IServices 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 @@ -52,13 +53,13 @@ import com.example.what_the_fantasy.data.services.ServicesStub import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent @Composable -fun SignUpPage(navController: NavController) { +fun SignUpPage(navController: NavController, services : IServices) { 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() + //val servicesStub = ServicesStub() Box( modifier = Modifier @@ -82,7 +83,7 @@ fun SignUpPage(navController: NavController) { 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, username, email, password, confirmPassword, servicesStub, navController = navController) + ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black, username, email, password, confirmPassword, services, navController = navController) SpaceHeightComponent(16) ReturnLogin(R.string.ButtonLogin,12, Color.White, navController = navController) @@ -196,7 +197,7 @@ fun ConnexionButtonSign( email: String, password: String, confirmPassword: String, - service: ServicesStub, + service: IServices, navController: NavController ) { val title = stringResource(id = titleResId) @@ -215,7 +216,7 @@ fun ConnexionButtonSign( 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") + usernameErrorExist = !service.CreateUser(username, email, password, "https://img.freepik.com/vecteurs-libre/personnage-magicien-malefique-fantaisie_1045-193.jpg?size=338&ext=jpg", service) } }, colors = ButtonDefaults.buttonColors(containerColor = colorButton), From 6a639eb6d38a99598f2d0723068775ce104bfdf5 Mon Sep 17 00:00:00 2001 From: Leni BEAULATON Date: Thu, 27 Feb 2025 15:09:20 +0100 Subject: [PATCH 5/7] =?UTF-8?q?Mise=20=C3=A0=20jour=20de=20'README.md'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6210e70..b0bfd5d 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,42 @@ -# WF-Android +# Projet Android What the Fantasy +# Description +L'application mobile **What the Fantasy** est une application pour android permettant aux utilisateurs de découvrir des citations célèbres du monde de la fantasy. En plus de pouvoir lire et apprécier les citations, les utilisateurs peuvent créer un compte pour interagir avec elles en les likant, en les commentant, et en participant à des quiz à thème ou aléatoires. + +### Fonctionnalités principales + +- **Découverte de citations** : Parcourez une large sélection de citations tirées de l'univers de la fantasy. +- **Interaction avec les citations** : Les utilisateurs connectés peuvent **liker** et **commenter** les citations. +- **Création de compte utilisateur** : Inscription et connexion des utilisateurs pour accéder à des fonctionnalités supplémentaires. +- **Quiz interactifs** : Les utilisateurs peuvent participer à des quiz à thème (par exemple, quiz sur les personnages de la fantasy) ou un quiz aléatoire pour deviner qui a dit une citation parmi une liste d'auteurs célèbres. + +## Prérequis + +Avant d'exécuter l'application sur votre android, vous devez avoir installé les éléments suivants sur votre machine : + +- **Android Studio** : L'IDE officiel des applications Android + - [Installation d'Android Studio](https://developer.android.com/studio?hl=fr) + + +## Installation +### 1. Cloner le dépôt + +Clonez le dépôt Git sur votre machine locale avec la commande suivante : + +```bash +git clone https://codefirst.iut.uca.fr/git/WhatTheFantasy/WF-Android.git +``` +### 2. Lancer l'application à travers Android Studio +Une fois le projet ouvert dans Android Studio, lancer le build du projet, soit sur votre smartphone android physique, soit par un émulateur intégré à Android Studio + + + + +## Auteurs +BRONGNIART Kentin
+BEAULATON Léni
+ROCHER Maxime
+MONDEJAR Kevin
+GUICHARD-MONTGUERS Louis
+NGUYEN Tommy
+ \ No newline at end of file From 65bc43f40e7c2e7d780712c5bac2dc5239f0be1e Mon Sep 17 00:00:00 2001 From: "leni.beaulaton" Date: Thu, 27 Feb 2025 19:45:57 +0100 Subject: [PATCH 6/7] =?UTF-8?q?Lien=20entre=20le=20stub=20est=20la=20maj?= =?UTF-8?q?=20des=20donn=C3=A9es=20des=20utilisateur=20sur=20la=20page=20p?= =?UTF-8?q?rofil=20(seul=20image=20n'a=20pas=20encore=20=C3=A9t=C3=A9=20fa?= =?UTF-8?q?it)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../what_the_fantasy/data/model/User.kt | 2 +- .../data/services/IServices.kt | 8 +-- .../data/services/ServicesAPI.kt | 8 +-- .../data/services/ServicesStub.kt | 56 ++++++++++++------- .../what_the_fantasy/ui/screens/LoginPage.kt | 3 + .../what_the_fantasy/ui/screens/ProfilPage.kt | 53 +++++++++++------- .../app/src/main/res/values-fr/strings.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + 8 files changed, 84 insertions(+), 48 deletions(-) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/model/User.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/model/User.kt index ce4cb2f..febe20d 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/model/User.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/model/User.kt @@ -6,5 +6,5 @@ class User( var email:String, var date:String, val imgUrl: String, - val password: String + var password: String ) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt index d48fd2f..5f8ab42 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/IServices.kt @@ -4,10 +4,10 @@ import com.example.what_the_fantasy.data.local.UserStub.users import com.example.what_the_fantasy.data.model.User interface IServices { - fun EditUsername(username : String) - fun EditEmail(email : String) - fun EditPasswd(passwd : String, passwdValid : String) - fun EditImage(imageURL : String) + fun EditUsername(username : String, index : Int) + fun EditEmail(email : String, index : Int) + fun EditPasswd(passwd : String, index : Int) + fun EditImage(imageURL : String, index : Int) fun CreateUser(username : String, email : String, passwd : String, imageURL: String, services : IServices) : Boolean fun getFavorite(username: String) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt index 5ac90ee..bf6d27e 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesAPI.kt @@ -3,19 +3,19 @@ package com.example.what_the_fantasy.data.services import com.example.what_the_fantasy.data.model.User class ServicesAPI : IServices { - override fun EditUsername(username: String) { + override fun EditUsername(username: String, index : Int) { TODO("Not yet implemented") } - override fun EditEmail(email: String) { + override fun EditEmail(email: String, index : Int) { TODO("Not yet implemented") } - override fun EditPasswd(passwd: String, passwdValid: String) { + override fun EditPasswd(passwd: String, index : Int) { TODO("Not yet implemented") } - override fun EditImage(imageURL: String) { + override fun EditImage(imageURL: String, index : Int) { TODO("Not yet implemented") } diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt index d6cbfe3..c6c3ed1 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/data/services/ServicesStub.kt @@ -9,19 +9,33 @@ 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") + override fun EditUsername(username: String, index : Int) { + val user = getUserById(index) + user?.username = username + + //Afficher tous les users + debugDisplayUser(getAllUsers(), "UsernameUpdate") + } - override fun EditEmail(email: String) { - TODO("Not yet implemented") + override fun EditEmail(email: String,index : Int) { + val user = getUserById(index) + user?.email = email + + //Afficher tous les users + debugDisplayUser(getAllUsers(), "EmailUpdate") } - override fun EditPasswd(passwd: String, passwdValid: String) { - TODO("Not yet implemented") + override fun EditPasswd(passwd: String,index : Int) { + val user = getUserById(index) + val passwordhash = hashPassword(passwd) + user?.password = passwordhash + + //Afficher tous les users en log + debugDisplayUser(getAllUsers(), "PasswordUpdate") } - override fun EditImage(imageURL: String) { + override fun EditImage(imageURL: String,index : Int) { TODO("Not yet implemented") } @@ -29,7 +43,6 @@ class ServicesStub : IServices { val date =dateDuJour() val passwordhash = hashPassword(passwd) - //Check si user existe déjà val userStub = services.getAllUsers() val nbUser = userStub.size for (user in userStub) { @@ -41,20 +54,10 @@ class ServicesStub : IServices { users.add(user)//ajout au stub //Afficher tous les users - for(user in userStub){ - Log.e("CreateUser", "User created: ${user.username} => ${user.password}") - } + debugDisplayUser(users, "CreateUser") return true } - @SuppressLint("NewApi") - fun dateDuJour(): String { - val date = LocalDate.now() - return date.toString() - } - - - // Récupérer tous les utilisateurs override fun getAllUsers(): List = users override fun getUserById(id: Int): User? { @@ -68,4 +71,19 @@ class ServicesStub : IServices { override fun getFavorite(username: String) { TODO("Not yet implemented") } + + +//------------------------------------------------------ + @SuppressLint("NewApi") + fun dateDuJour(): String { + val date = LocalDate.now() + return date.toString() + } + + + private fun debugDisplayUser(users : List, titleLog : String){ + for(user in users){ + Log.e(titleLog, "User created: ${user.username} => ${user.email} => ${user.password}") + } + } } \ No newline at end of file diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt index a824491..f4689c9 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/LoginPage.kt @@ -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.data.services.IServices import com.example.what_the_fantasy.data.services.ServicesStub +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.components.hashPassword @@ -128,6 +129,7 @@ fun PassWdTextField(textpasswdResId : Int) : String{ @Composable fun ConnexionButtonLogin(userStub : List, id : String, passwd : String, titleResId : Int, size : Int, colorButton : Color, colorText : Color, navController: (Int) -> Unit){ val title = stringResource(id = titleResId) + Button( onClick = { validLogin(id, passwd, userStub, navController) }, colors = ButtonDefaults.buttonColors(containerColor = colorButton), @@ -140,6 +142,7 @@ fun ConnexionButtonLogin(userStub : List, id : String, passwd : String, ti fun validLogin(identifiant : String, passwd : String, users : List, navController: (Int) -> Unit){ + users.forEachIndexed { index, user -> val hashPassWd = hashPassword(passwd) if (user.username == identifiant && user.password == hashPassWd) { diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt index c8ee9aa..54b17af 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/ProfilPage.kt @@ -99,13 +99,13 @@ fun ProfilPage(index: Int, navController: NavController, services: IServices) { ImageProfil(user.imgUrl, 120) SpaceHeightComponent(16) - EditUsername(user.username)// Édition du Username + EditUsername(user.username, index, services)// Édition du Username SpaceHeightComponent(16) - EditEmail(user.email)// Édition du Email + EditEmail(user.email,index, services)// Édition du Email Spacer(modifier = Modifier.height(8.dp)) - EditPasswd() + EditPasswd(index, services) SpaceHeightComponent(16) // Bouton @@ -133,20 +133,27 @@ fun ImageProfil(imgProfil : String, size :Int){ } @Composable -fun EditEmail(userEmail: String) { +fun EditEmail(userEmail: String, index: Int, service: IServices) { var email by remember { mutableStateOf(userEmail) } var isEditingEmail by remember { mutableStateOf(false) } var emailError by remember { mutableStateOf(false) } + fun onDoneEditing() { + service.EditEmail(email, index) + isEditingEmail = false + } + if (isEditingEmail) { EmailEditingField( email = email, onEmailChange = { newEmail -> email = newEmail - emailError = !Patterns.EMAIL_ADDRESS.matcher(newEmail).matches() + emailError = !Patterns.EMAIL_ADDRESS.matcher(newEmail).matches() // Validation email }, onDone = { - if (!emailError) isEditingEmail = false + if (!emailError) { + onDoneEditing() + } }, emailError = emailError ) @@ -212,18 +219,21 @@ fun DisplayEmail(email: String, onEdit: () -> Unit) { - - @Composable -fun EditUsername(userName: String) { +fun EditUsername(userName: String, index: Int, service : IServices) { var username by remember { mutableStateOf(userName) } var isEditingUsername by remember { mutableStateOf(false) } + fun onDoneEditing() { + service.EditUsername(username, index) + isEditingUsername = false + } + if (isEditingUsername) { UsernameEditingField( username = username, onUsernameChange = { username = it }, - onDone = { isEditingUsername = false } + onDone = { onDoneEditing() } ) } else { DisplayUsername(username = username, onEdit = { isEditingUsername = true }) @@ -246,7 +256,7 @@ fun UsernameEditingField( imeAction = ImeAction.Done ), keyboardActions = KeyboardActions( - onDone = { onDone() } // Quand on appuie sur "Done", on met fin à l'édition + onDone = { onDone() } ), trailingIcon = { IconButton(onClick = { onDone() }) { @@ -279,18 +289,22 @@ fun DisplayUsername(username: String, onEdit: () -> Unit) { - - - @Composable -fun EditPasswd() { - var password by remember { mutableStateOf("*******") } +fun EditPasswd(index: Int, service: IServices) { + var password by remember { mutableStateOf("*******") } // Mot de passe actuel (affiché comme un masque) var isEditingPassword by remember { mutableStateOf(false) } var newPassword by remember { mutableStateOf("") } var confirmPassword by remember { mutableStateOf("") } var passwordVisible by remember { mutableStateOf(false) } var passwordError by remember { mutableStateOf(false) } + // Fonction pour finaliser l'édition du mot de passe et appeler la méthode EditPasswd2 + fun onDoneEditing() { + // Appeler EditPasswd2 pour mettre à jour le mot de passe de l'utilisateur + service.EditPasswd(newPassword, index) + isEditingPassword = false + } + if (isEditingPassword) { PasswordEditingFields( newPassword = newPassword, @@ -298,20 +312,19 @@ fun EditPasswd() { onNewPasswordChange = { newPassword = it }, onConfirmPasswordChange = { confirmPassword = it - passwordError = newPassword != it + passwordError = newPassword != it // Vérifier si les mots de passe correspondent }, passwordVisible = passwordVisible, onPasswordVisibilityChange = { passwordVisible = it }, passwordError = passwordError, onDone = { if (!passwordError && newPassword.isNotEmpty()) { - password = newPassword - isEditingPassword = false + onDoneEditing() // Appeler la fonction onDoneEditing() pour mettre à jour le mot de passe } } ) } else { - DisplayPassword(onEdit = { isEditingPassword = true }) + DisplayPassword(onEdit = { isEditingPassword = true }) // Afficher l'option pour modifier le mot de passe } } diff --git a/What_The_Fantasy/app/src/main/res/values-fr/strings.xml b/What_The_Fantasy/app/src/main/res/values-fr/strings.xml index 899a998..a9a859b 100644 --- a/What_The_Fantasy/app/src/main/res/values-fr/strings.xml +++ b/What_The_Fantasy/app/src/main/res/values-fr/strings.xml @@ -11,6 +11,7 @@ Votre mot de passe* Se connecter Créer son compte + Identifiant ou mot de passe incorrect //Page Sign Up Inscription diff --git a/What_The_Fantasy/app/src/main/res/values/strings.xml b/What_The_Fantasy/app/src/main/res/values/strings.xml index 4e02f70..b74a681 100644 --- a/What_The_Fantasy/app/src/main/res/values/strings.xml +++ b/What_The_Fantasy/app/src/main/res/values/strings.xml @@ -10,6 +10,7 @@ Your password* Login Create your account + Incorrect username or password //Page Sign Up Account creation From be237dce7a689b7a888b4babc38ecaaac49462c5 Mon Sep 17 00:00:00 2001 From: tomivt Date: Thu, 27 Feb 2025 21:53:33 +0100 Subject: [PATCH 7/7] Fix Merge issues --- .../ui/navigations/AppNavigator.kt | 2 +- .../ui/screens/QuizEndPage.kt | 43 ++++--------------- 2 files changed, 10 insertions(+), 35 deletions(-) diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt index d696041..e68c8d3 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/navigations/AppNavigator.kt @@ -42,7 +42,7 @@ sealed class Destination(val route: String) { fun AppNavigator() { val navController = rememberNavController() val services = ServicesStub() // A changer si l'on veut passer au service API - NavHost(navController, startDestination = Destination.Login.route) { + NavHost(navController, startDestination = Destination.QuizMenu.route) { composable(Destination.Login.route) { LoginPage( navControllerSignUp = { navController.navigate(Destination.SignUp.route) }, diff --git a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt index c66c04c..3c40225 100644 --- a/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt +++ b/What_The_Fantasy/app/src/main/java/com/example/what_the_fantasy/ui/screens/QuizEndPage.kt @@ -42,18 +42,17 @@ fun QuizEndPage(idQuiz: Int, points: Int, navControllerQuizMenu: () -> Unit) { modifier = Modifier .fillMaxWidth() .weight(0.1f) - .background(Color(0xFF300052)) .padding(20.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically ) { Image( - painter = painterResource(id = R.drawable.quiz), + painter = painterResource(id = R.drawable.profile_icon), contentDescription = "Profil", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) + modifier = Modifier.size(50.dp) ) Image( - painter = painterResource(id = R.drawable.quiz), + painter = painterResource(id = R.drawable.toggle), contentDescription = "Profil" ) } @@ -97,30 +96,6 @@ fun QuizEndPage(idQuiz: Int, points: Int, navControllerQuizMenu: () -> Unit) { color = Color.White, style = TextStyle(fontSize = 15.sp, fontWeight = FontWeight.Bold, textAlign = TextAlign.Center) ) - Row ( - modifier = Modifier - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceAround - ) { - // Bouton Quiz Précédent - Image( - painter = painterResource(id = R.drawable.quiz), - contentDescription = "Profil", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) - ) - // Bouton Retour Menu Quiz - Image( - painter = painterResource(id = R.drawable.quiz), - contentDescription = "Profil", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) - ) - // Bouton Quiz Suivant - Image( - painter = painterResource(id = R.drawable.quiz), - contentDescription = "Profil" - ) - } - } } @@ -136,9 +111,9 @@ fun QuizEndPage(idQuiz: Int, points: Int, navControllerQuizMenu: () -> Unit) { ) { // Bouton Likes Image( - painter = painterResource(id = R.drawable.quiz), + painter = painterResource(id = R.drawable.like_icon), contentDescription = "Bouton", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) + modifier = Modifier.size(50.dp) ) // Bouton WhatTheFantasy Image( @@ -148,10 +123,10 @@ fun QuizEndPage(idQuiz: Int, points: Int, navControllerQuizMenu: () -> Unit) { ) // Bouton Quiz Image( - painter = painterResource(id = R.drawable.quiz), - contentDescription = "Bouton", - modifier = Modifier.size(50.dp).background(Color.Yellow, CircleShape) - ) + painter = painterResource(id = R.drawable.quiz_icon), + contentDescription = "Bouton", + modifier = Modifier.size(50.dp) + ) } } }