Compare commits

..

36 Commits

Author SHA1 Message Date
Leni BEAULATON ec33ebbea4 Merge pull request 'Tests en plus pour les services citation et utilisateur' (#56) from TestUnit into master
2 weeks ago
Leni BEAULATON fba1f2b595 merge
2 weeks ago
Leni BEAULATON fa6921bd72 Tests en plus pour les services citation et utilisateur
2 weeks ago
Leni BEAULATON ad5ae952ac Quote ViewModel
2 weeks ago
Leni BEAULATON beecdb1640 Merge branch 'master' of https://codefirst.iut.uca.fr/git/WhatTheFantasy/WF-Android
3 weeks ago
Leni BEAULATON 442ef2ed42 Pb résolue pour sortie du mode édition username et email
3 weeks ago
Leni BEAULATON c892315428 Merge pull request 'TestUnit' (#55) from TestUnit into master
3 weeks ago
Leni BEAULATON 20180a1e81 Tests commentaires
3 weeks ago
Leni BEAULATON 3a2ac655fe Test search
3 weeks ago
Leni BEAULATON 11b2010997 Merge pull request 'Tests unitaires des user' (#54) from TestUnit into master
3 weeks ago
Leni BEAULATON 2ac42caf6f Tests unitaires des user
3 weeks ago
Leni BEAULATON aa498b8ccc Merge pull request 'Changement de l'image de profil' (#53) from ViewModelSearch into master
3 weeks ago
Leni BEAULATON 4c3e146303 Changement de l'image de profil
3 weeks ago
Leni BEAULATON e392ad5aea Merge pull request 'Quelques changement de design' (#52) from ameliorationApp into master
3 weeks ago
Leni BEAULATON 0b78773f6a Quelques changement de design
3 weeks ago
Leni BEAULATON 6a85bdc936 Merge pull request 'viewModelAgain' (#51) from viewModelAgain into master
3 weeks ago
Maxime ROCHER e097290152 nettoyage code mort et imports
3 weeks ago
Maxime ROCHER a68ffab341 nettoyage code mort et imports
3 weeks ago
Maxime ROCHER f976c7c162 fix
3 weeks ago
brongniart 0d2a4b06ef fin de merge
3 weeks ago
Leni BEAULATON daf45f2fd2 Merge avec master
3 weeks ago
Leni BEAULATON 60ec8300f4 Nettoyage
3 weeks ago
Leni BEAULATON c813196555 ViewModel pour NavBar
3 weeks ago
Leni BEAULATON 9d54fce591 random image lors de la création de compte
3 weeks ago
Leni BEAULATON 2e98af2450 Lien avec le profil
3 weeks ago
Leni BEAULATON 210d8c575f ViewModel AppNavigation pour SignUp et Login
3 weeks ago
Leni BEAULATON 6045bfdfe6 Lien avec profil
3 weeks ago
Leni BEAULATON 5ed3f5f1ec init en cours
3 weeks ago
Leni BEAULATON 1830ededb9 View Model pour le current en cours
3 weeks ago
Leni BEAULATON 1d9d3edc69 Ajout icon visible password
4 weeks ago
Leni BEAULATON 311d876e1c ViewModel Inscription
4 weeks ago
Leni BEAULATON 4489ca930e Archi pour viewmodel de profil
1 month ago
Leni BEAULATON 197ea96cd2 suppression des services passés en paramètre à login
1 month ago
Leni BEAULATON 619526be17 Déplacement de la fonction login dans service
1 month ago
Leni BEAULATON 819ef8d739 viewModel password fonctionne aussi
1 month ago
Leni BEAULATON 673fd8ea5d viewModel pour username authentification marche
1 month ago

@ -71,7 +71,10 @@ dependencies {
androidTestImplementation(libs.androidx.ui.test.junit4) androidTestImplementation(libs.androidx.ui.test.junit4)
debugImplementation(libs.androidx.ui.tooling) debugImplementation(libs.androidx.ui.tooling)
debugImplementation(libs.androidx.ui.test.manifest) debugImplementation(libs.androidx.ui.test.manifest)
implementation(libs.coil.compose) //gére les url des image implementation(libs.coil.compose) //gére les url des images
implementation(kotlin("script-runtime")) implementation(kotlin("script-runtime"))
//ViewModel
implementation(libs.android.lifecycle.viewmodel)
implementation(libs.android.lifecycle.viewmodel.runtime.ktx)
} }

@ -1,28 +0,0 @@
package com.example.what_the_fantasy.Logs
import android.util.Log
import com.example.what_the_fantasy.data.model.User
class LogsUsers{
fun logDebugAllUsers(users : List<User>, titleLog : String){
for(user in users){
Log.e(titleLog, "User created: ${user.username} => ${user.email} => ${user.imgUrl} => ${user.langage}")
}
}
fun logDebugUserEmail(user : User?, titleLog : String){
Log.e(titleLog, "User created: ${user?.username} => ${user?.email}")
}
fun logDebugUserLangage(user : User?, titleLog : String){
Log.e(titleLog, "User Change: ${user?.username} => ${user?.langage}")
}
fun logInformationUserConnect(user : User?, titleLog : String){
Log.e(titleLog, "${user?.username} logged in")
}
fun unlogInformationUserConnect(titleLog : String){
Log.e(titleLog, "Logged out")
}
}

@ -1,39 +1,34 @@
package com.example.what_the_fantasy.data.local package com.example.what_the_fantasy.data.local
import com.example.what_the_fantasy.data.local.UserStub.users
import com.example.what_the_fantasy.data.model.Comment import com.example.what_the_fantasy.data.model.Comment
import com.example.what_the_fantasy.data.model.User import com.example.what_the_fantasy.data.model.User
object CommentStub { object CommentStub {
val comments: MutableList<Comment> = mutableListOf( val comments: MutableList<Comment> = mutableListOf(
Comment("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Franchement, si la Force était avec moi, je n'aurais jamais perdu mes clés ce matin !", users[0].username, "21-12-2005", users[0].imgUrl),
Comment("Trop bien","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Je pourrais vraiment utiliser un peu de Force pour mes révisions !", users[10].username, "22-12-2005", users[10].imgUrl),
Comment("encore un Test","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Si la Force était vraiment avec moi, je serais déjà en vacances !", users[2].username, "23-12-2005", users[2].imgUrl),
Comment("Je suis la ","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Avec toute cette Force, je devrais pouvoir arrêter de procrastiner !", users[3].username, "24-12-2005", users[3].imgUrl),
Comment("J'en ai rien a foutre de la citation","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("Android c'est bien","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("La vie, c'est comme une boîte de chocolats… mais parfois tu tombes sur le chocolat que tu détestes.", users[4].username, "25-12-2005", users[4].imgUrl),
Comment("je sais plus quoi mettre donc ca va être le bordel","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Ce qui est drôle, c'est que moi, je choisis toujours les chocolats que je veux. Pas de surprise !", users[5].username, "26-12-2005", users[5].imgUrl),
Comment("Et un test de plus","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("La vie, c'est comme une boîte de chocolats… mais parfois les petits chocolats ont un goût étrange.", users[6].username, "27-12-2005", users[6].imgUrl),
Comment("La bombe à été activer","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("J'aimerais juste éviter la noix au fond de la boîte, c'est toujours le pire chocolat.", users[7].username, "28-12-2005", users[7].imgUrl),
Comment("J'aime pas les *****","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("Test","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Est-ce que ça veut dire que je suis en train d'exister juste parce que je suis en train de lire ça ? 🤔", users[8].username, "29-12-2005", users[8].imgUrl),
Comment("Trop bien","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Ah, Descartes… c'est fou, mais à chaque fois que je pense trop, je me sens plus perdu !", users[9].username, "30-12-2005", users[9].imgUrl),
Comment("encore un Test","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Ouais, mais parfois j'aimerais bien être juste un peu plus je suis et un peu moins je pense", users[0].username, "31-12-2005", users[0].imgUrl),
Comment("Je suis la ","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Je pense donc je suis… Mais je me demande parfois si je suis vraiment ce que je pense !", users[1].username, "01-01-2006", users[1].imgUrl),
Comment("J'en ai rien a foutre de la citation","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("Android c'est bien","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("La montagne, c'est mon tas de linge à laver… et les petites pierres, ce sont mes excuses pour ne pas m'en occuper.", users[2].username, "02-01-2006", users[2].imgUrl),
Comment("je sais plus quoi mettre donc ca va être le bordel","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("La montagne, c'est mon carnet de tâches… et j'ai perdu ma motivation pour enlever les petites pierres.", users[3].username, "03-01-2006", users[3].imgUrl),
Comment("Et un test de plus","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Ok, mais parfois, les petites pierres deviennent des montagnes en elles-mêmes...", users[4].username, "04-01-2006", users[4].imgUrl),
Comment("La bombe à été activer","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("C'est facile à dire, mais je suis toujours coincé à déplacer la première petite pierre.", users[5].username, "05-01-2006", users[5].imgUrl),
Comment("J'aime pas les *****","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("Test","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Et c'est aussi là qu'on reconnaît ceux qui ne répondent pas aux messages.", users[6].username, "06-01-2006", users[6].imgUrl),
Comment("Trop bien","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("C'est vrai… mais parfois, même les vrais amis se cachent sous un coussin pendant les moments difficiles.", users[7].username, "07-01-2006", users[7].imgUrl),
Comment("encore un Test","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Les vrais amis, c'est ceux qui viennent t'aider à déplacer des meubles quand tu déménages. 😉", users[8].username, "08-01-2006", users[8].imgUrl),
Comment("Je suis la ","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"), Comment("Je préfère qu'un ami vienne avec des pizzas pendant l'adversité. C'est plus mon genre.", users[9].username, "09-01-2006", users[9].imgUrl)
Comment("J'en ai rien a foutre de la citation","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("Android c'est bien","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("je sais plus quoi mettre donc ca va être le bordel","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("Et un test de plus","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("La bombe à été activer","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
Comment("J'aime pas les *****","Dev","21-12-2005", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg"),
) )
} }

@ -6,16 +6,16 @@ import com.example.what_the_fantasy.data.model.User
object UserStub { object UserStub {
//LE MOT DE PASSE POUR TOUS LES UTILISATEURS EST : 1234 //LE MOT DE PASSE POUR TOUS LES UTILISATEURS EST : 1234
val users: MutableList<User> = mutableListOf( val users: MutableList<User> = 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", SrcLanguage.vf), //1234 User(0, "Aragorn123", "aragorn@example.com", "2022-01-15", "https://img.freepik.com/vecteurs-libre/personnage-guerrier-fantaisie_1045-185.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", SrcLanguage.vf), //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", SrcLanguage.vf),//1234 User(1, "Legolas456", "legolas@example.com", "2021-05-23", "https://img.freepik.com/vecteurs-libre/personnage-elfe-fantaisie_1045-186.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", SrcLanguage.vf),//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", SrcLanguage.vf),//1234 User(2, "Gandalf789", "gandalf@example.com", "2020-09-10", "https://img.freepik.com/vecteurs-libre/personnage-magicien-fantaisie_1045-187.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", SrcLanguage.vf),//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", SrcLanguage.vf),//1234 User(3, "FrodoBaggins", "frodo@example.com", "2023-03-18", "https://img.freepik.com/vecteurs-libre/personnage-hobbit-fantaisie_1045-188.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", SrcLanguage.vf),//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", SrcLanguage.vo),//1234 User(4, "Gimli999", "gimli@example.com", "2022-07-04", "https://img.freepik.com/vecteurs-libre/personnage-nain-fantaisie_1045-189.jpg?size=338&ext=jpg", "03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4", SrcLanguage.vo),//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", SrcLanguage.vo),//1234 User(5, "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", SrcLanguage.vo),//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", SrcLanguage.vo),//1234 User(6, "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", SrcLanguage.vo),//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", SrcLanguage.vo),//1234 User(7, "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", SrcLanguage.vo),//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", SrcLanguage.vo),//1234 User(8, "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", SrcLanguage.vo),//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", SrcLanguage.vo),//1234 User(9, "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", SrcLanguage.vo),//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", SrcLanguage.vo)//1234 User(10, "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", SrcLanguage.vo)//1234
) )
} }

@ -5,7 +5,7 @@ import java.util.Date
data class Quote ( data class Quote (
val id: Int, val id: Int,
val content: String, val content: String,
val likes: Int, var likes: Int,
val language: SrcLanguage, val language: SrcLanguage,
val character: String, val character: String,
val source: String, val source: String,

@ -3,29 +3,38 @@ package com.example.what_the_fantasy.data.services
import com.example.what_the_fantasy.data.model.Favorite import com.example.what_the_fantasy.data.model.Favorite
import com.example.what_the_fantasy.data.model.Comment import com.example.what_the_fantasy.data.model.Comment
import com.example.what_the_fantasy.data.model.Quote import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.model.SrcLanguage
import com.example.what_the_fantasy.data.model.User import com.example.what_the_fantasy.data.model.User
import com.example.what_the_fantasy.ui.states.AuthUserState
import kotlinx.coroutines.flow.StateFlow
interface IServices { interface IServices {
fun validLogin(username : String,
passwd : String,
navController: (Int) -> Unit,
initialierCurrentUser : (Int) ->Unit): Boolean
fun EditUsername(username : String, index : Int) : Boolean fun EditUsername(username : String, index : Int) : Boolean
fun EditEmail(email : String, index : Int) : Boolean fun EditEmail(email : String, index : Int) : Boolean
fun EditPasswd(passwd : String, index : Int) fun EditPasswd(passwd : String, index : Int)
fun EditImage(imageURL : String, index : Int) fun EditImage(index : Int) : String
fun ChangeLangage(user: User) fun ChangeLangage(index : Int): SrcLanguage
fun isUsernameExist(username : String) : Boolean
fun isEmailExist(email : String) : Boolean
fun AddFav(userId: Int, QuoteId : Int) fun AddFav(userId: Int, QuoteId : Int)
fun SupFav(userId: Int, QuoteId : Int) fun SupFav(userId: Int, QuoteId : Int)
fun AddComment(content : String) fun AddComment(content : String)
fun CreateUser(username : String, email : String, passwd : String, services : IServices) : Boolean fun CreateUser(username : String, email : String, passwd : String) : Boolean
fun getFavorite(user: User): List<Quote> fun getFavorite(user: User): List<Quote>
fun getAllUsers(): List<User> fun getAllUsers(): List<User>
fun getComment(quoteId : Int) : List<Comment> fun getComment(quoteId : Int) : List<Comment>
fun getUserById(id: Int): User? fun getUserById(id: Int): User?
fun SearchQuote(quote : String)
fun getQuote( id : Int): Quote? fun getQuote( id : Int): Quote?
fun isFavorite(id : Int, user: User): Boolean fun isFavorite(idQuote : Int, iduser: Int): Boolean
fun getAllFavorite(): List<Favorite> fun getAllFavorite(): List<Favorite>
fun getAllQuote(): List<Quote> fun getAllQuote(): List<Quote>
fun getSomeQuotes(nb: Int, page: Int) : MutableList<Quote> fun getSomeQuotes(nb: Int, page: Int) : MutableList<Quote>

@ -1,89 +1,89 @@
package com.example.what_the_fantasy.data.services package com.example.what_the_fantasy.data.services
import com.example.what_the_fantasy.data.model.Comment //import com.example.what_the_fantasy.data.model.Comment
import com.example.what_the_fantasy.data.model.Favorite //import com.example.what_the_fantasy.data.model.Favorite
import com.example.what_the_fantasy.data.model.Quote //import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.model.User //import com.example.what_the_fantasy.data.model.User
//import com.example.what_the_fantasy.ui.navigations.Destination ////import com.example.what_the_fantasy.ui.navigations.Destination
class ServicesAPI : IServices { //class ServicesAPI : IServices {
override fun EditUsername(username: String, index : Int): Boolean { // override fun EditUsername(username: String, index : Int): Boolean {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun EditEmail(email: String, index : Int): Boolean { // override fun EditEmail(email: String, index : Int): Boolean {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun EditPasswd(passwd: String, index : Int) { // override fun EditPasswd(passwd: String, index : Int) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun EditImage(imageURL: String, index : Int) { // override fun EditImage(imageURL: String, index : Int) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun ChangeLangage(user: User) { // override fun ChangeLangage(user: User) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun AddFav(userId: Int, QuoteId: Int) { // override fun AddFav(userId: Int, QuoteId: Int) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun SupFav(userId: Int, QuoteId: Int) { // override fun SupFav(userId: Int, QuoteId: Int) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun AddComment(content: String) { // override fun AddComment(content: String) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun CreateUser(username: String, email: String, passwd: String, services: IServices) : Boolean { // override fun CreateUser(username: String, email: String, passwd: String, services: IServices) : Boolean {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getFavorite(user: User): List<Quote> { // override fun getFavorite(user: User): List<Quote> {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun SearchQuote(quote: String) { // override fun SearchQuote(quote: String) {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getQuote(id: Int): Quote? { // override fun getQuote(id: Int): Quote? {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun isFavorite(id: Int, user: User): Boolean { // override fun isFavorite(id: Int, user: User): Boolean {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getAllFavorite(): List<Favorite> { // override fun getAllFavorite(): List<Favorite> {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getAllQuote(): List<Quote> { // override fun getAllQuote(): List<Quote> {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getSomeQuotes(nb: Int, page: Int): MutableList<Quote> { // override fun getSomeQuotes(nb: Int, page: Int): MutableList<Quote> {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getAllUsers(): List<User> { // override fun getAllUsers(): List<User> {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getComment(quoteId: Int): List<Comment> { // override fun getComment(quoteId: Int): List<Comment> {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun getUserById(id: Int): User? { // override fun getUserById(id: Int): User? {
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
//
override fun search(type : String ,search:String ,indexCount: Int): List<Quote>{ // override fun search(type : String ,search:String ,indexCount: Int): List<Quote>{
TODO("Not yet implemented") // TODO("Not yet implemented")
} // }
} //}

@ -3,20 +3,39 @@ package com.example.what_the_fantasy.data.services
import android.annotation.SuppressLint import android.annotation.SuppressLint
import com.example.what_the_fantasy.data.local.UserStub.users 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.data.model.User
import com.example.what_the_fantasy.Logs.LogsUsers import com.example.what_the_fantasy.logs.LogsUsers
import com.example.what_the_fantasy.data.local.FavoriteStub.favorites import com.example.what_the_fantasy.data.local.FavoriteStub.favorites
import com.example.what_the_fantasy.data.local.ImageStub.allImages
import com.example.what_the_fantasy.data.local.QuoteStub.quotes import com.example.what_the_fantasy.data.local.QuoteStub.quotes
import com.example.what_the_fantasy.data.model.Favorite import com.example.what_the_fantasy.data.model.Favorite
import com.example.what_the_fantasy.data.local.CommentStub.comments import com.example.what_the_fantasy.data.local.CommentStub.comments
import com.example.what_the_fantasy.data.model.Comment import com.example.what_the_fantasy.data.model.Comment
import com.example.what_the_fantasy.data.model.Quote import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.model.SrcLanguage import com.example.what_the_fantasy.data.model.SrcLanguage
import com.example.what_the_fantasy.ui.components.hashPassword
import java.time.LocalDate import java.time.LocalDate
class ServicesStub : IServices { class ServicesStub : IServices {
val logsUser = LogsUsers() //gestion des logs pour les utilisateurs val logsUser = LogsUsers() //gestion des logs pour les utilisateurs
override fun validLogin(username : String,
passwd : String,
navController: (Int) -> Unit,
initialierCurrentUser : (Int) ->Unit): Boolean{
users.forEachIndexed { index, user ->
val hashPassWd = hashPassword(passwd)
if (user.username == username && user.password == hashPassWd) {
initialierCurrentUser(index)
navController(index)
//logsUser.logInformationUserConnect(user, "UserConnect")
return true
}
}
return false
}
override fun EditUsername(username: String, index : Int) : Boolean{ override fun EditUsername(username: String, index : Int) : Boolean{
val user = getUserById(index) val user = getUserById(index)
@ -26,7 +45,7 @@ class ServicesStub : IServices {
} }
//Afficher tous les users //Afficher tous les users
logsUser.logDebugUserEmail(user, "UsernameUpdate") //logsUser.logDebugUserEmail(user, "UsernameUpdate")
return false return false
} }
@ -38,7 +57,7 @@ class ServicesStub : IServices {
return true return true
} }
//Afficher tous les users //Afficher tous les users
logsUser.logDebugAllUsers(getAllUsers(), "EmailUpdate") //logsUser.logDebugAllUsers(getAllUsers(), "EmailUpdate")
return false return false
} }
@ -48,21 +67,23 @@ class ServicesStub : IServices {
user?.password = passwordhash user?.password = passwordhash
//Afficher tous les users en log //Afficher tous les users en log
logsUser.logDebugAllUsers(getAllUsers(), "PasswordUpdate") //logsUser.logDebugAllUsers(getAllUsers(), "PasswordUpdate")
} }
override fun EditImage(imageURL: String,index : Int) { override fun EditImage(index : Int) : String {
TODO("Not yet implemented") return randomImage()
} }
override fun ChangeLangage(user: User) { override fun ChangeLangage(index : Int) : SrcLanguage{
if(user.langage == SrcLanguage.vo){ if(getAllUsers()[index].langage == SrcLanguage.vo){
user.langage = SrcLanguage.vf getAllUsers()[index].langage = SrcLanguage.vf
} }
else{ else{
user.langage = SrcLanguage.vo getAllUsers()[index].langage = SrcLanguage.vo
} }
logsUser.logDebugUserLangage(user, "ChangeLangue")
//logsUser.logDebugUserLangage(getAllUsers()[index], "ChangeLangue")
return getAllUsers()[index].langage
} }
override fun AddFav(userId: Int, QuoteId: Int) { override fun AddFav(userId: Int, QuoteId: Int) {
@ -79,19 +100,23 @@ class ServicesStub : IServices {
//comments.add(Comment(content = content,)) //comments.add(Comment(content = content,))
} }
override fun CreateUser(username: String, email: String, passwd: String, services : IServices) : Boolean {
override fun CreateUser(username: String, email: String, passwd: String) : Boolean {
val date =dateDuJour() val date =dateDuJour()
val passwordhash = hashPassword(passwd) val passwordhash = hashPassword(passwd)
val services = ServicesStub()
val userStub = services.getAllUsers() val userStub = services.getAllUsers()
val nbUser = userStub.size val nbUser = userStub.size
if(username == "" || email == "" || passwd == ""){
return false
}
if(!isUsernameExist(username) && !isEmailExist(email)){ if(!isUsernameExist(username) && !isEmailExist(email)){
val user = User(nbUser+1,username, email, date,randomImage(userStub), passwordhash, SrcLanguage.vo) val user = User(nbUser,username, email, date,randomImage(), passwordhash, SrcLanguage.vo)
users.add(user)//ajout au stub users.add(user)//ajout au stub
//Afficher tous les users //Afficher tous les users
logsUser.logDebugAllUsers(users, "CreateUser") //logsUser.logDebugAllUsers(users, "CreateUser")
return true return true
} }
return false return false
@ -99,8 +124,7 @@ class ServicesStub : IServices {
override fun getFavorite(user: User): List<Quote> { override fun getFavorite(user: User): List<Quote> {
val favorite = favorites val favorite = favorites
return favorite[user.id-1].quote return favorite[0].quote
//return emptyList()
} }
override fun getAllFavorite(): List<Favorite> = favorites override fun getAllFavorite(): List<Favorite> = favorites
@ -110,45 +134,54 @@ class ServicesStub : IServices {
override fun getComment(quoteId: Int): List<Comment> = comments override fun getComment(quoteId: Int): List<Comment> = comments
override fun getUserById(id: Int): User? { override fun getUserById(id: Int): User? {
return (users.find { it.id == id+1 }) return (users.find { it.id == id })
} }
override fun SearchQuote(quote: String) {
TODO("Not yet implemented")
}
override fun getQuote(id: Int): Quote? { override fun getQuote(id: Int): Quote? {
return (quotes.find { it.id == id }) return (quotes.find { it.id == id })
} }
override fun getSomeQuotes(nb: Int, page: Int): MutableList<Quote> { override fun getSomeQuotes(nb: Int, page: Int): MutableList<Quote> {
val fromIndex = (page - 1) * nb var nbQuote = nb
val toIndex = minOf(page * nb, quotes.size) var nbPage = page
if(nb < 0) nbQuote = 1
if(nbPage < 0) nbPage = 1
val fromIndex = (nbPage - 1) * nbQuote
val toIndex = minOf(nbPage * nbQuote, quotes.size)
if (fromIndex >= quotes.size) return mutableListOf() if (fromIndex >= quotes.size) return mutableListOf()
return quotes.subList(fromIndex, toIndex).toMutableList() return quotes.subList(fromIndex, toIndex).toMutableList()
} }
override fun isFavorite(id: Int, user: User): Boolean {
override fun isFavorite(idQuote: Int, idUser: Int): Boolean {
val user = getUserById(idUser) ?: return false
val quote = getFavorite(user) val quote = getFavorite(user)
return quote.find{ it.id == id } != null return quote.find{ it.id == idQuote } != null
} }
override fun search(type : String ,search:String ,indexCount: Int): List<Quote> {
return (getAllQuote().filter {
when (type) {
"personnage" -> {
it.character.uppercase().contains(search.uppercase())
}
"titre" -> {
//------------------------------------------------------ it.source.uppercase().contains(search.uppercase())
@SuppressLint("NewApi")
fun dateDuJour(): String {
val date = LocalDate.now()
return date.toString()
} }
fun randomImage(usersImage : List<User>) : String{ else -> {
return "https://img.freepik.com/vecteurs-libre/personnage-guerrier-homme-fantaisie_1045-194.jpg?size=338&ext=jpg" it.content.uppercase().contains(search.uppercase())
}
}
}.take(indexCount))
} }
fun isUsernameExist(username : String) : Boolean{ override fun isUsernameExist(username : String) : Boolean{
val userStub = getAllUsers() val userStub = getAllUsers()
for (user in userStub) { for (user in userStub) {
if (user.username == username) { if (user.username == username) {
@ -158,7 +191,7 @@ class ServicesStub : IServices {
return false return false
} }
fun isEmailExist(email : String) : Boolean{ override fun isEmailExist(email : String) : Boolean{
val userStub = getAllUsers() val userStub = getAllUsers()
for (user in userStub) { for (user in userStub) {
if (user.email == email) { if (user.email == email) {
@ -167,22 +200,23 @@ class ServicesStub : IServices {
} }
return false return false
} }
//------------------------------------------------------
override fun search(type : String ,search:String ,indexCount: Int): List<Quote> { @SuppressLint("NewApi")
return (getAllQuote().filter { fun dateDuJour(): String {
when (type) { val date = LocalDate.now()
"personnage" -> { return date.toString()
it.character.uppercase().contains(search.uppercase())
} }
"titre" -> { fun randomImage() : String{
it.source.uppercase().contains(search.uppercase()) val sizeList = allImages.size
val randomNb = (0..sizeList).random()
allImages.forEach{image ->
if(image.id == randomNb){
return image.url
} }
else -> {
it.content.uppercase().contains(search.uppercase())
} }
return allImages[0].url
} }
}.take(indexCount))
}
} }

@ -1,4 +1,4 @@
package com.example.what_the_fantasy.ui.components package com.example.what_the_fantasy.data.services
import java.security.MessageDigest import java.security.MessageDigest

@ -0,0 +1,39 @@
package com.example.what_the_fantasy.logs
import android.util.Log
import com.example.what_the_fantasy.data.model.User
class LogsUsers{
fun logDebugAllUsers(users : List<User>, titleLog : String){
for(user in users){
Log.d(titleLog, "User created: ${user.username} => ${user.email} => ${user.imgUrl} => ${user.langage}")
}
}
fun logDebugUserEmail(user : User?, titleLog : String){
Log.d(titleLog, "User created: ${user?.username} => ${user?.email}")
}
fun logDebugUserLangage(user : User?, titleLog : String){
Log.d(titleLog, "User Change: ${user?.username} => ${user?.langage}")
}
fun logInformationUserConnect(user : User?, titleLog : String){
Log.i(titleLog, "${user?.username} logged in")
}
fun unlogInformationUserConnect(titleLog : String){
Log.i(titleLog, "Logged out")
}
fun favoriteInformationUserTrue(titleLog : String, quoteId : Int, userId : Int){
Log.i(titleLog, "User $userId added quote $quoteId to favorites")
}
fun favoriteInformationUserFalse(titleLog : String, quoteId : Int, userId : Int){
Log.i(titleLog, "User $userId removed quote $quoteId from favorites")
}
fun shareInformationUser(titleLog : String, quoteId : Int, userId : Int){
Log.i(titleLog, "User $userId shared quote $quoteId")
}
}

@ -0,0 +1,6 @@
package com.example.what_the_fantasy.repository
import com.example.what_the_fantasy.data.services.IServices
import okhttp3.Request
class AuthRepository {}

@ -1,64 +0,0 @@
package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.AccountCircle
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonColors
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.ui.theme.colorButtonNav
import com.example.what_the_fantasy.ui.theme.colorNavBar
@Composable
fun BackBar(navBack : () ->Unit ,
content : @Composable ()-> Unit ){
Column(
modifier = Modifier
.fillMaxSize()
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(70.dp)
.background(colorNavBar),
Arrangement.SpaceBetween,
verticalAlignment = Alignment.Bottom
) {
IconButton(onClick = {navBack()},
modifier = Modifier
.size(60.dp)
) {
Icon(Icons.Rounded.ArrowBack,
contentDescription = "Back",
modifier = Modifier
.size(60.dp)
)
}
}
Box(modifier = Modifier.background(Color.Black).fillMaxHeight()) {
content()
}
}
}

@ -1,68 +0,0 @@
package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage
import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.ui.theme.gradienBox
@Composable
fun LittleQuoteComponent(quote : Quote){
Row(
modifier = Modifier
.fillMaxWidth(0.9f)
.clip(RoundedCornerShape(16.dp))
.background(gradienBox)
) {
val sizeTextInfoQuote = 13
val lineHeightText = 12
val sizeTextQuote = 16
AsyncImage(
model = quote.imgUrl,
contentDescription = "Quote picture",
modifier = Modifier
.size(130.dp)
.clip(RoundedCornerShape(16.dp))
)
Column(modifier = Modifier.padding(10.dp)) {
TextInfoQuote(
quote.content,
sizeTextQuote,
lineHeightText
)
SpaceHeightComponent(40)
TextInfoQuote("${stringResource(R.string.dateQuote)} : ${quote.date}", sizeTextInfoQuote, lineHeightText)
TextInfoQuote("${quote.type} : ${quote.source}", sizeTextInfoQuote, lineHeightText)
TextInfoQuote("${stringResource(R.string.CharacterQuote)}: ${quote.character}", sizeTextInfoQuote, lineHeightText)
}
}
}
@Composable
fun TextInfoQuote(text : String, fontSizeText : Int, lineHeightText : Int){
Text(text,
color = Color.White,
fontSize = fontSizeText.sp,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
lineHeight = lineHeightText.sp)
}

@ -1,16 +1,18 @@
package com.example.what_the_fantasy.ui.components package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.* import androidx.compose.material.icons.rounded.*
import androidx.compose.material3.BottomAppBar import androidx.compose.material3.BottomAppBar
@ -20,29 +22,38 @@ import androidx.compose.material3.IconButtonColors
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import coil.compose.rememberAsyncImagePainter
import coil.compose.rememberImagePainter
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun NavBar(onProfile : Boolean = false , fun NavBar(onProfile : Boolean = false,
onFavorite : Boolean = false , onFavorite : Boolean = false,
onAccueil : Boolean = false , onAccueil : Boolean = false,
onQuiz : Boolean = false , onQuiz : Boolean = false,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
navControllerProfil: () -> Unit = {}, navControllerProfil: () -> Unit = {},
navControllerFavorite:() -> Unit = {}, navControllerFavorite:() -> Unit= {},
navControllerAccueil: () -> Unit = {}, navControllerAccueil: () -> Unit= {},
navControllerQuiz: () -> Unit = {}, navControllerQuiz: () -> Unit= {},
navControllerSearch: () -> Unit = {}, navControllerSearch: () -> Unit = {},
content : @Composable ()-> Unit ) { content : @Composable ()-> Unit ) {
Column( Column(
@ -60,11 +71,9 @@ fun NavBar(onProfile : Boolean = false ,
Arrangement.SpaceBetween, Arrangement.SpaceBetween,
verticalAlignment = Alignment.Bottom verticalAlignment = Alignment.Bottom
) { ) {
ButtonIconVector(Icons.Rounded.AccountCircle,stringResource(R.string.NavProfile),navControllerProfil,onProfile) ButtonIconVectorInt(currentUserState.imagePath,"Profile",navControllerProfil,onProfile)
ButtonIconVector(Icons.Rounded.Search,stringResource(R.string.NavSearch),navControllerSearch,false) ButtonIconVector(Icons.Rounded.Search,stringResource(R.string.NavSearch),navControllerSearch,false)
} }
} }
@ -105,7 +114,7 @@ fun NavBar(onProfile : Boolean = false ,
} }
@Composable @Composable
fun ButtonIconVector(img : ImageVector, name : String, nav : ()->Unit,onPage : Boolean){ fun ButtonIconVectorInt(img : String, name : String, nav : ()->Unit ,onPage : Boolean){
IconButton(onClick = {nav()}, IconButton(onClick = {nav()},
enabled = !onPage, enabled = !onPage,
colors = IconButtonColors(Color.Transparent, MaterialTheme.colorScheme.onBackground,//couleur quand il n'est pas selectionné colors = IconButtonColors(Color.Transparent, MaterialTheme.colorScheme.onBackground,//couleur quand il n'est pas selectionné
@ -113,14 +122,35 @@ fun ButtonIconVector(img : ImageVector, name : String, nav : ()->Unit,onPage : B
modifier = Modifier modifier = Modifier
.size(60.dp) .size(60.dp)
) { ) {
Icon(img,
Image(
painter = rememberAsyncImagePainter(img),
contentDescription = name, contentDescription = name,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.clip(CircleShape) // Pour rendre l'image circulaire
) )
} }
} }
@Composable
fun ButtonIconVector(img : ImageVector, name : String, nav : ()->Unit ,onPage : Boolean){
IconButton(onClick = {nav()},
enabled = !onPage,
colors = IconButtonColors(Color.Transparent, MaterialTheme.colorScheme.onBackground,//couleur quand il n'est pas selectionné
Color.Transparent, MaterialTheme.colorScheme.primary),//couleur quand il est selectionné
modifier = Modifier
.size(60.dp)
) {
Image(img,
contentDescription = name,
modifier = Modifier
.fillMaxSize()
.clip(CircleShape), // Pour rendre l'image circulaire
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary)
)
}
}
@Composable @Composable
fun ButtonIconPainter(img : Painter, name : String, nav : ()->Unit,onPage : Boolean){ fun ButtonIconPainter(img : Painter, name : String, nav : ()->Unit,onPage : Boolean){

@ -15,7 +15,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -24,8 +23,6 @@ import androidx.compose.ui.unit.sp
import coil.compose.rememberAsyncImagePainter import coil.compose.rememberAsyncImagePainter
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.model.Quote import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.ui.theme.colorBackground
import com.example.what_the_fantasy.ui.theme.gradienBox
@Composable @Composable
fun QuoteLittle(quote: Quote, modifier: Modifier = Modifier) { fun QuoteLittle(quote: Quote, modifier: Modifier = Modifier) {

@ -2,7 +2,6 @@ package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp

@ -1,15 +1,11 @@
package com.example.what_the_fantasy.ui.components package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp

@ -0,0 +1,28 @@
package com.example.what_the_fantasy.ui.components
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.example.what_the_fantasy.R
@Composable
fun VisibleIconPasswordComponent(passwordVisible : Boolean){
Icon(
painterResource(
if(passwordVisible){
R.drawable.password_visible
}
else{
R.drawable.password_no_visible
}
),
contentDescription = "visible",
modifier = Modifier
.size(20.dp),
tint = MaterialTheme.colorScheme.primary
)
}

@ -6,14 +6,21 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute import androidx.navigation.toRoute
import com.example.what_the_fantasy.data.services.ServicesStub import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.screens.* import com.example.what_the_fantasy.ui.screens.*
import com.example.what_the_fantasy.ui.theme.colorNavBar import com.example.what_the_fantasy.ui.viewModels.AuthUserViewModel
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
import com.example.what_the_fantasy.ui.viewModels.QuoteInformationUserViewModel
import com.example.what_the_fantasy.ui.viewModels.SearchViewModel
import com.example.what_the_fantasy.ui.viewModels.SignInUserViewModel
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
@ -43,8 +50,9 @@ data class QuizRandom(val userIndex: Int)
@Serializable @Serializable
data class OneQuote(val quoteId: Int, val userIndex: Int) data class OneQuote(val quoteId: Int, val userIndex: Int)
@Serializable @Serializable
data class Search(val userIndex: Int,val type : String = "contenue", val search: String = "") data class Search(val userIndex: Int,val type : String = "contenu", val search: String = "")
@Serializable @Serializable
data object SignUp data object SignUp
@ -64,11 +72,32 @@ fun AppNavigator() {
val navController = rememberNavController() val navController = rememberNavController()
val services = ServicesStub() val services = ServicesStub()
//ViewModel pour l'authentification
val authUserVM : AuthUserViewModel = viewModel()
val authState by authUserVM.userState.collectAsState()
//ViewModel pour l'inscription
val signInUserVM : SignInUserViewModel = viewModel()
val signInState by signInUserVM.userState.collectAsState()
//ViewModel pour l'utilisateur
val currentUserVM : CurrentUserViewModel = viewModel()
val currentUserState by currentUserVM.currentUserState.collectAsState()
//ViewModel pour la recherche
val searchVM : SearchViewModel = viewModel()
val searchState by searchVM.searchState.collectAsState()
//ViewModel pour les commentaires et likes des citations
val quoteInformationUserVM : QuoteInformationUserViewModel = viewModel()
val quoteInformationUserState by quoteInformationUserVM.quoteState.collectAsState()
Scaffold( Scaffold(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
containerColor = MaterialTheme.colorScheme.onPrimary containerColor = MaterialTheme.colorScheme.onPrimary
) { paddingValues -> ) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) { Box(modifier = Modifier.padding(paddingValues)) {
NavHost(navController, startDestination = Login) { NavHost(navController, startDestination = Login) {
composable<Login> { composable<Login> {
LoginPage( LoginPage(
@ -78,75 +107,100 @@ fun AppNavigator() {
popUpTo(Login) { inclusive = true } popUpTo(Login) { inclusive = true }
} }
}, },
services = services authUserVM = authUserVM,
authState = authState,
initialierCurrentUser ={currentUserVM.initialiseCurrentUser(it)}
) )
} }
composable<Accueil> { composable<Accueil> {
val accueil: Accueil = it.toRoute() //val accueil: Accueil = it.toRoute()
AccueilPage( AccueilPage(
index = accueil.userIndex, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(accueil.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(accueil.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navProfil = { navController.navigate(Profil(accueil.userIndex)) }, navQuote = { quoteId ->
navQuote = { quoteId -> navController.navigate(OneQuote(quoteId,accueil.userIndex)) }, navController.navigate(
navSearch = { navController.navigate(Search(accueil.userIndex))}, OneQuote(
services = services quoteId,
currentUserState.id
)
)
},
navSearch = { navController.navigate(Search(currentUserState.id))},
services = services,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
composable<Favorite> { composable<Favorite> {
val favorite: Favorite = it.toRoute() //val favorite: Favorite = it.toRoute()
FavoritePage( FavoritePage(
index = favorite.userIndex, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navAccueil = { navController.navigate(Accueil(favorite.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(favorite.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navProfil = { navController.navigate(Profil(favorite.userIndex)) }, navQuote = { quoteId ->
navQuote = { quoteId -> navController.navigate(OneQuote(quoteId,favorite.userIndex)) }, navController.navigate(
navSearch = { navController.navigate(Search(favorite.userIndex))}, OneQuote(
services = services quoteId,
currentUserState.id
)
)
},
navSearch = { navController.navigate(Search(currentUserState.id))},
services = services,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
composable<Profil> { composable<Profil> {
val profil: Profil = it.toRoute() val profil: Profil = it.toRoute()
ProfilPage( ProfilPage(
index = profil.userIndex, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(profil.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navAccueil = { navController.navigate(Accueil(profil.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(profil.userIndex)) }, navSubmitQuote = { navController.navigate(SubmitQuote(currentUserState.id)) },
navSubmitQuote = { navController.navigate(SubmitQuote(profil.userIndex)) },
navUnLog = { navUnLog = {
navController.navigate(Login) { navController.navigate(Login) {
popUpTo(profil) { inclusive = true } popUpTo(profil) { inclusive = true }
} }
}, },
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navSearch = { navController.navigate(Search(profil.userIndex))}, navSearch = { navController.navigate(Search(profil.userIndex))},
services = services
) )
} }
composable<OneQuote> { composable<OneQuote> {
val quote: OneQuote = it.toRoute() val quote: OneQuote = it.toRoute()
QuotePage( QuotePage(
quoteId = quote.quoteId, quoteId = quote.quoteId,
navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navProfil = { navController.navigate(Profil(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
service = services, service = services,
index = quote.userIndex, currentUserVM = currentUserVM,
navAccueil = { navController.navigate(Accueil(quote.userIndex)) }, currentUserState = currentUserState,
navQuiz = { navController.navigate(QuizMenu(quote.userIndex)) }, navSearch = { navController.navigate(Search(currentUserState.id))},
navProfil = { navController.navigate(Profil(quote.userIndex)) }, quoteInformationUserVM = quoteInformationUserVM,
navFavorite = { navController.navigate(Favorite(quote.userIndex)) }, quoteInformationUserState = quoteInformationUserState,
navSearch = { navController.navigate(Search(quote.userIndex))}
) )
} }
composable<Search> { composable<Search> {
val search: Search = it.toRoute() val search: Search = it.toRoute()
SearchPage( SearchPage(
navAccueil = { navController.navigate(Accueil(search.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(search.userIndex)) }, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(search.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navProfil = { navController.navigate(Profil(search.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navQuote = { quoteId -> navController.navigate(OneQuote(quoteId,search.userIndex)) }, navQuote = { quoteId -> navController.navigate(OneQuote(quoteId,currentUserState.id)) },
navSearch = {type,newSearch -> navController.navigate(Search(search.userIndex,type,newSearch))}, navSearch = {type,newSearch -> navController.navigate(Search(currentUserState.id,type,newSearch))},
services = services,
type = search.type, type = search.type,
search = search.search search = search.search,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
searchVM = searchVM,
searchState = searchState
) )
} }
composable<SignUp> { composable<SignUp> {
@ -156,68 +210,77 @@ fun AppNavigator() {
popUpTo(Login) { inclusive = true } popUpTo(Login) { inclusive = true }
} }
}, },
services = services signInUserVM = signInUserVM,
signInState = signInState
) )
} }
composable<SubmitQuote> { composable<SubmitQuote> {
val submitQuote: SubmitQuote = it.toRoute() //val submitQuote: SubmitQuote = it.toRoute()
SubmitQuotePage( SubmitQuotePage(
navAccueil = { navController.navigate(Accueil(submitQuote.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(submitQuote.userIndex)) }, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navProfil = { navController.navigate(Profil(submitQuote.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(submitQuote.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navRecap = { quoteContent, character, source -> navRecap = { quoteContent, character, source ->
navController.navigate( navController.navigate(
RecapSubmit( RecapSubmit(
submitQuote.userIndex, currentUserState.id,
quoteContent, quoteContent,
character, character,
source source
) )
) )
} },
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
composable<RecapSubmit> { composable<RecapSubmit> {
val recapSubmit: RecapSubmit = it.toRoute() val recapSubmit: RecapSubmit = it.toRoute()
RecapSubmitPage( RecapSubmitPage(
index = recapSubmit.userIndex,
quoteContent = recapSubmit.quoteContent, quoteContent = recapSubmit.quoteContent,
character = recapSubmit.character, character = recapSubmit.character,
source = recapSubmit.source, source = recapSubmit.source,
navAccueil = { navController.navigate(Accueil(recapSubmit.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(recapSubmit.userIndex)) }, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navProfil = { navController.navigate(Profil(recapSubmit.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navSearch = { navController.navigate(Search(recapSubmit.userIndex))}, navSearch = { navController.navigate(Search(currentUserState.id))},
navQuiz = { navController.navigate(QuizMenu(recapSubmit.userIndex)) } navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
composable<QuizMenu> { composable<QuizMenu> {
val quizMenu: QuizMenu = it.toRoute() //val quizMenu: QuizMenu = it.toRoute()
QuizMenu( QuizMenu(
navAccueil = { navController.navigate(Accueil(quizMenu.userIndex)) }, currentUserVM = currentUserVM,
navFavorite = { navController.navigate(Favorite(quizMenu.userIndex)) }, currentUserState = currentUserState,
navProfil = { navController.navigate(Profil(quizMenu.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navSearch = { navController.navigate(Search(quizMenu.userIndex))}, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navProfil = { navController.navigate(Profil(currentUserState.id)) },
navSearch = { navController.navigate(Search(currentUserState.id))},
navControllerQuiz = { idQuiz -> navControllerQuiz = { idQuiz ->
navController.navigate(Quiz(quizMenu.userIndex, idQuiz)) navController.navigate(Quiz(currentUserState.id, idQuiz))
}, },
navControllerRandomQuiz = { navController.navigate(QuizRandom(quizMenu.userIndex)) } navControllerRandomQuiz = { navController.navigate(QuizRandom(currentUserState.id)) }
) )
} }
composable<Quiz> { composable<Quiz> {
val quiz: Quiz = it.toRoute() val quiz: Quiz = it.toRoute()
QuizPage( QuizPage(
navAccueil = { navController.navigate(Accueil(quiz.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(quiz.userIndex)) }, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navProfil = { navController.navigate(Profil(quiz.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(quiz.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navControllerQuizEnd = { idQuiz, pts -> navControllerQuizEnd = { idQuiz, pts ->
navController.navigate(QuizEnd(quiz.userIndex, idQuiz, pts)) navController.navigate(QuizEnd(currentUserState.id, idQuiz, pts))
}, },
navSearch = { navController.navigate(Search(quiz.userIndex))}, navSearch = { navController.navigate(Search(currentUserState.id))},
idQuiz = quiz.idQuiz idQuiz = quiz.idQuiz,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
composable<QuizEnd> { composable<QuizEnd> {
@ -225,11 +288,13 @@ fun AppNavigator() {
QuizEndPage( QuizEndPage(
idQuiz = quizEnd.idQuiz, idQuiz = quizEnd.idQuiz,
points = quizEnd.pts, points = quizEnd.pts,
navAccueil = { navController.navigate(Accueil(quizEnd.userIndex)) }, navAccueil = { navController.navigate(Accueil(currentUserState.id)) },
navFavorite = { navController.navigate(Favorite(quizEnd.userIndex)) }, navFavorite = { navController.navigate(Favorite(currentUserState.id)) },
navProfil = { navController.navigate(Profil(quizEnd.userIndex)) }, navProfil = { navController.navigate(Profil(currentUserState.id)) },
navQuiz = { navController.navigate(QuizMenu(quizEnd.userIndex)) }, navQuiz = { navController.navigate(QuizMenu(currentUserState.id)) },
navSearch = { navController.navigate(Search(quizEnd.userIndex))} navSearch = { navController.navigate(Search(currentUserState.id))},
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
@ -244,6 +309,8 @@ fun AppNavigator() {
navControllerQuizEnd = { idQuiz, pts -> navControllerQuizEnd = { idQuiz, pts ->
navController.navigate(QuizEnd(quizRandom.userIndex, idQuiz, pts)) navController.navigate(QuizEnd(quizRandom.userIndex, idQuiz, pts))
}, },
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) )
} }
} }

@ -12,7 +12,6 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -23,47 +22,49 @@ import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.services.IServices import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.components.QuoteLittle import com.example.what_the_fantasy.ui.components.QuoteLittle
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
import com.example.what_the_fantasy.ui.theme.colorBackground import com.example.what_the_fantasy.ui.theme.colorBackground
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@Composable @Composable
fun AccueilPage( fun AccueilPage(
index: Int,
navFavorite: () -> Unit, navFavorite: () -> Unit,
navQuiz: () -> Unit, navQuiz: () -> Unit,
navProfil: () -> Unit, navProfil: () -> Unit,
navSearch: () -> Unit,
navQuote: (Int) -> Unit, navQuote: (Int) -> Unit,
services: IServices navSearch: () -> Unit,
services: IServices,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
val dailyQuote = DailyQuoteStub.dailyQuote val dailyQuote = DailyQuoteStub.dailyQuote
val user = services.getUserById(index) ?: return
val titleDalyQuote = stringResource(R.string.TitleHomeDailyQuote) val titleDalyQuote = stringResource(R.string.TitleHomeDailyQuote)
val titleSuggestion = stringResource(R.string.TitleHomeSuggestion) val titleSuggestion = stringResource(R.string.TitleHomeSuggestion)
val page = remember { mutableStateOf(1) } val page = remember { mutableIntStateOf(1) }
val quotes = remember { mutableStateListOf<Quote>() } val quotes = remember { mutableStateListOf<Quote>() }
val state = rememberLazyListState() val state = rememberLazyListState()
val layoutInfo = state.layoutInfo val layoutInfo = remember { derivedStateOf { state.layoutInfo } }
val isLoading = remember { mutableStateOf(false) } val isLoading = remember { mutableStateOf(false) }
val visibleItemsInfo = layoutInfo.visibleItemsInfo val visibleItemsInfo = layoutInfo.value.visibleItemsInfo
val fullyVisibleItemsInfo = visibleItemsInfo.toMutableList() val fullyVisibleItemsInfo = visibleItemsInfo.toMutableList()
val lastItem = if (fullyVisibleItemsInfo.isNotEmpty()) fullyVisibleItemsInfo.last() else null val lastItem = if (fullyVisibleItemsInfo.isNotEmpty()) fullyVisibleItemsInfo.last() else null
LaunchedEffect(page.value) { LaunchedEffect(page.intValue) {
if (!isLoading.value) { if (!isLoading.value) {
isLoading.value = true isLoading.value = true
delay(500) delay(500)
val newQuotes = services.getSomeQuotes(15, page.value) val newQuotes = services.getSomeQuotes(15, page.intValue)
val uniqueQuotes = newQuotes.filterNot { new -> quotes.any { it.id == new.id } } val uniqueQuotes = newQuotes.filterNot { new -> quotes.any { it.id == new.id } }
if (uniqueQuotes.isNotEmpty()) { if (uniqueQuotes.isNotEmpty()) {
quotes.addAll(uniqueQuotes) quotes.addAll(uniqueQuotes)
} else { } else {
println("Aucune nouvelle quote à la page ${page.value}, stop pagination.") println("Aucune nouvelle quote à la page ${page.intValue}, stop pagination.")
} }
isLoading.value = false isLoading.value = false
} }
@ -73,8 +74,9 @@ fun AccueilPage(
NavBar( NavBar(
onAccueil = true, onAccueil = true,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = { },
navControllerProfil = navProfil, navControllerProfil = navProfil,
navControllerQuiz = navQuiz, navControllerQuiz = navQuiz,
navControllerSearch = navSearch navControllerSearch = navSearch
@ -111,7 +113,7 @@ fun AccueilPage(
} }
items(quotes) { quote -> items(quotes) { quote ->
if (quote.language == user.langage) { if (quote.language == currentUserState.langage) {
Column(Modifier.clickable { navQuote(quote.id ) }) { Column(Modifier.clickable { navQuote(quote.id ) }) {
QuoteLittle(quote) QuoteLittle(quote)
Spacer(modifier = Modifier.height(16.dp)) Spacer(modifier = Modifier.height(16.dp))
@ -130,11 +132,11 @@ fun AccueilPage(
CircularProgressIndicator() CircularProgressIndicator()
} }
} else { } else {
LaunchedEffect(remember { derivedStateOf { state.firstVisibleItemIndex } }, state.layoutInfo.totalItemsCount) { LaunchedEffect(remember { derivedStateOf { state.firstVisibleItemIndex } }, remember { derivedStateOf { state.layoutInfo } }.value.totalItemsCount) {
if (!isLoading.value && state.layoutInfo.visibleItemsInfo.isNotEmpty()) { if (!isLoading.value && state.layoutInfo.visibleItemsInfo.isNotEmpty()) {
val lastVisibleItem = state.layoutInfo.visibleItemsInfo.last() val lastVisibleItem = state.layoutInfo.visibleItemsInfo.last()
if (lastVisibleItem.index >= state.layoutInfo.totalItemsCount - 1) { if (lastVisibleItem.index >= state.layoutInfo.totalItemsCount - 1) {
page.value++ page.intValue++
} }
} }
} }

@ -18,23 +18,30 @@ import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.services.IServices import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.components.QuoteLittle import com.example.what_the_fantasy.ui.components.QuoteLittle
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.theme.colorBackground
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun FavoritePage( fun FavoritePage(
index: Int,
navAccueil: () -> Unit, navAccueil: () -> Unit,
navQuiz: () -> Unit, navQuiz: () -> Unit,
navProfil: () -> Unit, navProfil: () -> Unit,
navSearch: () -> Unit,
navQuote: (Int) -> Unit, navQuote: (Int) -> Unit,
services: IServices navSearch: () -> Unit,
services: IServices,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
val user = services.getUserById(index) ?: return val user = services.getUserById(currentUserState.id) ?: return
val quotes = services.getFavorite(user) val quotes = services.getFavorite(user)
val titlePage = stringResource(R.string.TitleFavorite) val titlePage = stringResource(R.string.TitleFavorite)
NavBar(onFavorite = true, NavBar(onFavorite = true,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = { },
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,
navControllerQuiz = navQuiz, navControllerQuiz = navQuiz,

@ -1,5 +1,6 @@
package com.example.what_the_fantasy.ui.screens package com.example.what_the_fantasy.ui.screens
import android.util.Log
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -16,6 +17,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -30,20 +32,26 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.Logs.LogsUsers import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.what_the_fantasy.logs.LogsUsers
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.model.User 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.IServices
import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent 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.SpaceHeightComponent
import com.example.what_the_fantasy.ui.components.TitlePageComponent import com.example.what_the_fantasy.ui.components.TitlePageComponent
import com.example.what_the_fantasy.ui.components.hashPassword import com.example.what_the_fantasy.data.services.hashPassword
import com.example.what_the_fantasy.ui.theme.colorBackground import com.example.what_the_fantasy.ui.components.VisibleIconPasswordComponent
import com.example.what_the_fantasy.ui.theme.gradienBox import com.example.what_the_fantasy.ui.states.AuthUserState
import com.example.what_the_fantasy.ui.viewModels.AuthUserViewModel
@Composable @Composable
fun LoginPage(navControllerSignUp: () -> Unit, navControllerProfil: (Int) -> Unit, services : IServices) { fun LoginPage(navControllerSignUp: () -> Unit,
val users = services.getAllUsers() navControllerProfil: (Int) -> Unit,
authUserVM : AuthUserViewModel,
authState : AuthUserState,
initialierCurrentUser : (Int) -> Unit) {
Box( Box(
modifier = Modifier modifier = Modifier
@ -63,7 +71,15 @@ fun LoginPage(navControllerSignUp: () -> Unit, navControllerProfil: (Int) -> Uni
TitlePageComponent(R.string.titleLogin, MaterialTheme.colorScheme.primary) TitlePageComponent(R.string.titleLogin, MaterialTheme.colorScheme.primary)
SpaceHeightComponent(20) SpaceHeightComponent(20)
ConnexionButtonLogin(users,IdentifiantTextField(R.string.IdentifiantLogin), PassWdTextField(R.string.PasswdLogin), R.string.ButtonLogin,18, Color.White, Color.Black,navControllerProfil)
ConnexionButtonLogin(authUserVM,
IdentifiantTextField(R.string.IdentifiantLogin, authState.username){
authUserVM.setUsername(it)
}, PassWdTextField(R.string.PasswdLogin, authState.password){
authUserVM.setPassword(it)
}, R.string.ButtonLogin,18,navControllerProfil){
initialierCurrentUser(it)
}
SpaceHeightComponent(16) SpaceHeightComponent(16)
CreateAccountButton(R.string.ButtonCreateLogin,12, MaterialTheme.colorScheme.primary, navControllerSignUp) CreateAccountButton(R.string.ButtonCreateLogin,12, MaterialTheme.colorScheme.primary, navControllerSignUp)
} }
@ -72,13 +88,13 @@ fun LoginPage(navControllerSignUp: () -> Unit, navControllerProfil: (Int) -> Uni
@Composable @Composable
fun IdentifiantTextField(textIdentifiantResId : Int) : String{ fun IdentifiantTextField(textIdentifiantResId : Int, username : String, onValueChange: (String) -> Unit ) : String{
val textIdentifiant = stringResource(id = textIdentifiantResId) val textIdentifiant = stringResource(id = textIdentifiantResId)
var identifiant by remember { mutableStateOf("") }
Column(modifier = Modifier.padding(top = 16.dp)) { Column(modifier = Modifier.padding(top = 16.dp)) {
OutlinedTextField( OutlinedTextField(
value = identifiant, value = username,
onValueChange = { identifiant = it }, onValueChange = onValueChange,
label = { Text(textIdentifiant) }, label = { Text(textIdentifiant) },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -88,18 +104,18 @@ fun IdentifiantTextField(textIdentifiantResId : Int) : String{
shape = RoundedCornerShape(16.dp) shape = RoundedCornerShape(16.dp)
) )
} }
return identifiant; return username;
} }
@Composable @Composable
fun PassWdTextField(textpasswdResId : Int) : String{ fun PassWdTextField(textpasswdResId : Int, password : String, onValueChange: (String) -> Unit) : String{
val textpasswd = stringResource(id = textpasswdResId) val textpasswd = stringResource(id = textpasswdResId)
var passwd by remember { mutableStateOf("") }
var passwordVisible by remember { mutableStateOf(false) } var passwordVisible by remember { mutableStateOf(false) }
Column(modifier = Modifier.padding(top = 10.dp, bottom = 30.dp)) { Column(modifier = Modifier.padding(top = 10.dp, bottom = 30.dp)) {
OutlinedTextField( OutlinedTextField(
value = passwd, value = password,
onValueChange = { passwd = it }, onValueChange = onValueChange,
label = { Text(textpasswd) }, label = { Text(textpasswd) },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -109,21 +125,22 @@ fun PassWdTextField(textpasswdResId : Int) : String{
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = { trailingIcon = {
IconButton(onClick = { passwordVisible = !passwordVisible }) { IconButton(onClick = { passwordVisible = !passwordVisible }) {
VisibleIconPasswordComponent(passwordVisible)
} }
}, },
shape = RoundedCornerShape(16.dp) shape = RoundedCornerShape(16.dp)
) )
} }
return passwd; return password;
} }
@Composable @Composable
fun ConnexionButtonLogin(userStub : List<User>, id : String, passwd : String, titleResId : Int, size : Int, colorButton : Color, colorText : Color, navController: (Int) -> Unit){ fun ConnexionButtonLogin(authUserVM : AuthUserViewModel, username : String, passwd : String, titleResId : Int, size : Int, navController: (Int) -> Unit, initialierCurrentUser : (Int) -> Unit){
val title = stringResource(id = titleResId) val title = stringResource(id = titleResId)
var showError by remember { mutableStateOf(false) } var showError by remember { mutableStateOf(false) }
Button( Button(
onClick = { showError = !validLogin(id, passwd, userStub, navController) onClick = { showError = !authUserVM.validLogin(username, passwd, navController, initialierCurrentUser)
}, },
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background),
modifier = Modifier modifier = Modifier
@ -138,19 +155,6 @@ fun ConnexionButtonLogin(userStub : List<User>, id : String, passwd : String, ti
} }
fun validLogin(identifiant : String, passwd : String, users : List<User>, navController: (Int) -> Unit): Boolean {
val logsUser = LogsUsers() //gestion des logs pour les utilisateurs
users.forEachIndexed { index, user ->
val hashPassWd = hashPassword(passwd)
if (user.username == identifiant && user.password == hashPassWd) {
navController(index)
logsUser.logInformationUserConnect(user, "UserConnect")
return true
}
}
return false
}
@Composable @Composable
fun CreateAccountButton(titleResId : Int, size : Int, color : Color, navController: () -> Unit) { fun CreateAccountButton(titleResId : Int, size : Int, color : Color, navController: () -> Unit) {

@ -1,5 +1,6 @@
package com.example.what_the_fantasy.ui.screens package com.example.what_the_fantasy.ui.screens
import android.util.Log
import android.util.Patterns import android.util.Patterns
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -12,10 +13,12 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CheckCircle import androidx.compose.material.icons.filled.CheckCircle
import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Edit
@ -45,29 +48,30 @@ import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.example.what_the_fantasy.Logs.LogsUsers import com.example.what_the_fantasy.logs.LogsUsers
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.model.User
import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.components.SpaceHeightComponent 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.TitlePageComponent
import com.example.what_the_fantasy.ui.theme.gradienBox import com.example.what_the_fantasy.ui.components.VisibleIconPasswordComponent
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun ProfilPage(index: Int, fun ProfilPage(navFavorite: () -> Unit,
navFavorite: () -> Unit,
navAccueil: () -> Unit, navAccueil: () -> Unit,
navQuiz: () -> Unit, navQuiz: () -> Unit,
navSearch: () -> Unit,
navUnLog: () -> Unit, navUnLog: () -> Unit,
navSubmitQuote: () -> Unit, navSubmitQuote: () -> Unit,
services: IServices navSearch: () -> Unit,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
val user = services.getUserById(index) ?: return
NavBar(onProfile = true, NavBar(onProfile = true,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerQuiz = navQuiz, navControllerQuiz = navQuiz,
@ -77,7 +81,8 @@ fun ProfilPage(index: Int,
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(MaterialTheme.colorScheme.background), .background(MaterialTheme.colorScheme.background)
.verticalScroll(rememberScrollState()),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Column( Column(
@ -95,24 +100,24 @@ fun ProfilPage(index: Int,
SpaceHeightComponent(16) SpaceHeightComponent(16)
// Image de profil // Image de profil
ImageProfil(user.imgUrl, 120) ImageProfil(120, currentUserState.id, currentUserVM,currentUserState)
SpaceHeightComponent(16) SpaceHeightComponent(16)
EditUsername(user.username, index, services)// Édition du Username EditUsername(currentUserState.username, currentUserState.id, currentUserVM)// Édition du Username
SpaceHeightComponent(16) SpaceHeightComponent(16)
EditEmail(user.email,index, services)// Édition du Email EditEmail(currentUserState.email,currentUserState.id, currentUserVM)// Édition du Email
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
EditPasswd(index, services) EditPasswd(currentUserState.id, currentUserVM)
SpaceHeightComponent(16) SpaceHeightComponent(16)
// Bouton // Bouton
ButtonProfile(R.string.ButtonAddQuoteprofile, 18, MaterialTheme.colorScheme.primary, MaterialTheme.colorScheme.background,navSubmitQuote) // Pas encore de navigation definie ButtonProfile(R.string.ButtonAddQuoteprofile, 18, MaterialTheme.colorScheme.onBackground,MaterialTheme.colorScheme.background,navSubmitQuote) // Pas encore de navigation definie
SpaceHeightComponent(16) SpaceHeightComponent(16)
ButtonLanguage(R.string.ButtonLanguageprofile, 18, MaterialTheme.colorScheme.primary, MaterialTheme.colorScheme.background,services, user) ButtonLanguage(R.string.ButtonLanguageprofile, 18, MaterialTheme.colorScheme.onBackground,MaterialTheme.colorScheme.background,currentUserVM, currentUserState)
SpaceHeightComponent(16) SpaceHeightComponent(16)
ButtonUnLog(R.string.ButtonUnlogprofile, 18, MaterialTheme.colorScheme.primary, MaterialTheme.colorScheme.background,navUnLog) ButtonUnLog(R.string.ButtonUnlogprofile, 18,MaterialTheme.colorScheme.onBackground, MaterialTheme.colorScheme.background, navUnLog,currentUserVM)
@ -123,26 +128,30 @@ fun ProfilPage(index: Int,
@Composable @Composable
fun ImageProfil(imgProfil : String, size :Int){ fun ImageProfil(size :Int,index: Int, currentUserVM: CurrentUserViewModel, currentUserState: CurrentUserState){
AsyncImage( AsyncImage(
model = imgProfil, model = currentUserState.imagePath,
contentDescription = "Photo de profil", contentDescription = "Photo de profil",
modifier = Modifier modifier = Modifier
.size(size.dp) .size(size.dp)
.clip(CircleShape) .clip(CircleShape)
.clickable{currentUserVM.editImage(index)}
) )
} }
@Composable @Composable
fun EditEmail(userEmail: String, index: Int, service: IServices) { fun EditEmail(emailState: String, index: Int, currentUserVM: CurrentUserViewModel) {
var email by remember { mutableStateOf(userEmail) } var email by remember { mutableStateOf(emailState) }
var originalEmail by remember { mutableStateOf(emailState) }
var isEditingEmail by remember { mutableStateOf(false) } var isEditingEmail by remember { mutableStateOf(false) }
var emailError by remember { mutableStateOf(false) } var emailError by remember { mutableStateOf(false) }
fun onDoneEditing() { fun onDoneEditing() {
isEditingEmail =!service.EditEmail(email, index) if (email != originalEmail) {
isEditingEmail = !currentUserVM.editEmail(email, index)
} else {
isEditingEmail = false
}
} }
if (isEditingEmail) { if (isEditingEmail) {
@ -150,7 +159,7 @@ fun EditEmail(userEmail: String, index: Int, service: IServices) {
email = email, email = email,
onEmailChange = { newEmail -> onEmailChange = { newEmail ->
email = newEmail email = newEmail
emailError = !Patterns.EMAIL_ADDRESS.matcher(newEmail).matches() // Validation email emailError = !Patterns.EMAIL_ADDRESS.matcher(newEmail).matches()
}, },
onDone = { onDone = {
if (!emailError) { if (!emailError) {
@ -197,7 +206,6 @@ fun EmailEditingField(
} }
} }
@Composable @Composable
fun DisplayEmail(email: String, onEdit: () -> Unit) { fun DisplayEmail(email: String, onEdit: () -> Unit) {
Row( Row(
@ -208,7 +216,7 @@ fun DisplayEmail(email: String, onEdit: () -> Unit) {
text = email, text = email,
fontSize = 18.sp, fontSize = 18.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary color = MaterialTheme.colorScheme.onBackground
) )
Icon( Icon(
imageVector = Icons.Default.Edit, imageVector = Icons.Default.Edit,
@ -221,20 +229,26 @@ fun DisplayEmail(email: String, onEdit: () -> Unit) {
@Composable @Composable
fun EditUsername(userName: String, index: Int, service : IServices) { fun EditUsername(usernameState: String, index: Int, currentUserVM: CurrentUserViewModel) {
var username by remember { mutableStateOf(userName) } var username by remember { mutableStateOf(usernameState) }
var originalUsername by remember { mutableStateOf(usernameState) }
var isEditingUsername by remember { mutableStateOf(false) } var isEditingUsername by remember { mutableStateOf(false) }
fun onDoneEditing() { fun onDoneEditing() {
isEditingUsername= !service.EditUsername(username, index) if (username != originalUsername) {
isEditingUsername = !currentUserVM.editUsername(username, index)
} else {
isEditingUsername = false
}
} }
if (isEditingUsername) { if (isEditingUsername) {
UsernameEditingField( UsernameEditingField(
username = username, username = username,
onUsernameChange = { username = it }, onUsernameChange = { username = it },
onDone = { onDoneEditing() } onDone = { onDoneEditing() },
) )
} else { } else {
DisplayUsername(username = username, onEdit = { isEditingUsername = true }) DisplayUsername(username = username, onEdit = { isEditingUsername = true })
@ -277,7 +291,7 @@ fun DisplayUsername(username: String, onEdit: () -> Unit) {
text = username, text = username,
fontSize = 18.sp, fontSize = 18.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary color = MaterialTheme.colorScheme.onBackground
) )
Icon( Icon(
imageVector = Icons.Default.Edit, imageVector = Icons.Default.Edit,
@ -290,9 +304,9 @@ fun DisplayUsername(username: String, onEdit: () -> Unit) {
@Composable @Composable
fun EditPasswd(index: Int, service: IServices) { fun EditPasswd(index: Int, currentUserVM: CurrentUserViewModel) {
var password by remember { mutableStateOf("*******") } // Mot de passe actuel (affiché comme un masque)
var isEditingPassword by remember { mutableStateOf(false) } var isEditingPassword by remember { mutableStateOf(false) }
var newPassword by remember { mutableStateOf("") } var newPassword by remember { mutableStateOf("") }
var confirmPassword by remember { mutableStateOf("") } var confirmPassword by remember { mutableStateOf("") }
@ -302,7 +316,7 @@ fun EditPasswd(index: Int, service: IServices) {
// Fonction pour finaliser l'édition du mot de passe et appeler la méthode EditPasswd2 // Fonction pour finaliser l'édition du mot de passe et appeler la méthode EditPasswd2
fun onDoneEditing() { fun onDoneEditing() {
// Appeler EditPasswd pour mettre à jour le mot de passe de l'utilisateur // Appeler EditPasswd pour mettre à jour le mot de passe de l'utilisateur
service.EditPasswd(newPassword, index) currentUserVM.editPassword(newPassword, index)
isEditingPassword = false isEditingPassword = false
} }
@ -315,18 +329,20 @@ fun EditPasswd(index: Int, service: IServices) {
confirmPassword = it confirmPassword = it
passwordError = newPassword != it // Vérifier si les mots de passe correspondent passwordError = newPassword != it // Vérifier si les mots de passe correspondent
}, },
passwordVisible = passwordVisible, passwordVisible = passwordVisible,
onPasswordVisibilityChange = { passwordVisible = it }, onPasswordVisibilityChange = { passwordVisible = it },
passwordError = passwordError, passwordError = passwordError,
onDone = { onDone = {
if (!passwordError && newPassword.isNotEmpty()) { if (!passwordError && newPassword.isNotEmpty()) {
onDoneEditing() // Appeler la fonction onDoneEditing() pour mettre à jour le mot de passe onDoneEditing() // pour mettre à jour le mot de passe
} }
} }
) )
} else { } else {
DisplayPassword(onEdit = { isEditingPassword = true }) // Afficher l'option pour modifier le mot de passe DisplayPassword(onEdit = { isEditingPassword = true }) // pour modifier le mot de passe
} }
} }
@Composable @Composable
@ -400,7 +416,7 @@ fun PasswordTextField(
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = { trailingIcon = {
IconButton(onClick = { onPasswordVisibilityChange(!passwordVisible) }) { IconButton(onClick = { onPasswordVisibilityChange(!passwordVisible) }) {
// Ajout d'une icône pour montrer/masquer le mot de passe VisibleIconPasswordComponent(passwordVisible)
} }
}, },
isError = isError isError = isError
@ -411,13 +427,13 @@ fun PasswordTextField(
fun SaveButton(onClick: () -> Unit) { fun SaveButton(onClick: () -> Unit) {
Button( Button(
onClick = onClick, onClick = onClick,
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.onPrimary), colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.background),
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ) {
val text = stringResource(id = R.string.ButtonSaveprofile) val text = stringResource(id = R.string.ButtonSaveprofile)
Text(text, Text(text,
fontSize = 18.sp, fontSize = 18.sp,
color = MaterialTheme.colorScheme.primary) color = MaterialTheme.colorScheme.onBackground)
} }
} }
@ -431,7 +447,7 @@ fun DisplayPassword(onEdit: () -> Unit) {
text = "*****", text = "*****",
fontSize = 18.sp, fontSize = 18.sp,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary color = MaterialTheme.colorScheme.onBackground
) )
Icon( Icon(
imageVector = Icons.Default.Edit, imageVector = Icons.Default.Edit,
@ -443,14 +459,16 @@ fun DisplayPassword(onEdit: () -> Unit) {
} }
@Composable @Composable
fun ButtonUnLog(textResId : Int, size :Int, colorTexte : Color, colorButton : Color,navController: () -> Unit){ fun ButtonUnLog(textResId : Int, size :Int, colorTexte : Color,colorButton : Color, navController: () -> Unit, currentUserVM: CurrentUserViewModel){
val text = stringResource(id = textResId) val text = stringResource(id = textResId)
val logsUser = LogsUsers() //gestion des logs pour les utilisateurs val logsUser = LogsUsers() //gestion des logs pour les utilisateurs
Button( Button(
onClick = { onClick = {
currentUserVM.clearCurrentUser()
navController() navController()
logsUser.unlogInformationUserConnect("UserUnLog") logsUser.unlogInformationUserConnect("UserUnLog")
}, },
colors = ButtonDefaults.buttonColors(containerColor = colorButton), colors = ButtonDefaults.buttonColors(containerColor = colorButton),
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
@ -460,23 +478,22 @@ fun ButtonUnLog(textResId : Int, size :Int, colorTexte : Color, colorButton : Co
} }
@Composable @Composable
fun ButtonLanguage(textResId : Int, size :Int, colorTexte : Color, colorButton : Color, service: IServices, user : User){ fun ButtonLanguage(textResId : Int, size :Int,colorTexte : Color, colorButton : Color, currentUserVM: CurrentUserViewModel, currentUserState : CurrentUserState){
val text = stringResource(id = textResId) val text = stringResource(id = textResId)
val currentLangage = remember { mutableStateOf(user.langage) }
Button( Button(
onClick = { onClick = {
service.ChangeLangage(user) currentUserVM.editLangue(currentUserState.id)
currentLangage.value = user.langage
}, },
colors = ButtonDefaults.buttonColors(containerColor = colorButton), colors = ButtonDefaults.buttonColors(containerColor = colorButton),
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) { ) {
Text("${text} (${currentLangage.value})", fontSize = size.sp, color = colorTexte) Text("${text} (${currentUserState.langage})", fontSize = size.sp, color = colorTexte)
} }
} }
@Composable @Composable
fun ButtonProfile(textResId : Int, size :Int, colorTexte : Color, colorButton : Color,navController: () -> Unit){ fun ButtonProfile(textResId : Int, size :Int,colorTexte : Color, colorButton : Color,navController: () -> Unit){
val text = stringResource(id = textResId) val text = stringResource(id = textResId)
Button( Button(

@ -16,9 +16,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.data.local.QuestionStub
import com.example.what_the_fantasy.data.local.QuizStub import com.example.what_the_fantasy.data.local.QuizStub
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
val gradient = Brush.linearGradient( val gradient = Brush.linearGradient(
colors = listOf(Color(0xFF7B1FA2), Color(0xFF311B92)), colors = listOf(Color(0xFF7B1FA2), Color(0xFF311B92)),
@ -35,8 +36,12 @@ fun QuizEndPage(
navProfil:() -> Unit, navProfil:() -> Unit,
navQuiz: () -> Unit, navQuiz: () -> Unit,
navSearch: () -> Unit, navSearch: () -> Unit,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
NavBar( NavBar(
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,

@ -33,17 +33,24 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.data.local.QuizStub import com.example.what_the_fantasy.data.local.QuizStub
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun QuizMenu( fun QuizMenu(
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
navFavorite: () -> Unit, navFavorite: () -> Unit,
navAccueil: () -> Unit, navAccueil: () -> Unit,
navProfil:() -> Unit, navProfil:() -> Unit,
navSearch: () -> Unit,
navControllerQuiz: (Int) -> Unit, navControllerQuiz: (Int) -> Unit,
navSearch: () -> Unit,
navControllerRandomQuiz:() -> Unit navControllerRandomQuiz:() -> Unit
) { ) {
NavBar(onQuiz = true, NavBar(onQuiz = true,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,

@ -19,9 +19,13 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.data.local.QuizStub import com.example.what_the_fantasy.data.local.QuizStub
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun QuizPage( fun QuizPage(
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
navFavorite: () -> Unit, navFavorite: () -> Unit,
navAccueil: () -> Unit, navAccueil: () -> Unit,
navProfil:() -> Unit, navProfil:() -> Unit,
@ -57,6 +61,8 @@ fun QuizPage(
else navControllerQuizEnd(idQuiz, pts) // Retour menu else navControllerQuizEnd(idQuiz, pts) // Retour menu
} }
NavBar( NavBar(
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,

@ -20,6 +20,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.data.local.QuestionStub import com.example.what_the_fantasy.data.local.QuestionStub
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun QuizRandom( fun QuizRandom(
@ -29,6 +31,8 @@ fun QuizRandom(
navQuiz: () -> Unit, navQuiz: () -> Unit,
navSearch: () -> Unit, navSearch: () -> Unit,
navControllerQuizEnd: (Int, Int) -> Unit, navControllerQuizEnd: (Int, Int) -> Unit,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
val questions = QuestionStub.shuffleRandomQuestions val questions = QuestionStub.shuffleRandomQuestions
var idCurrentQuestion by remember { mutableIntStateOf(0) } var idCurrentQuestion by remember { mutableIntStateOf(0) }
@ -66,7 +70,9 @@ fun QuizRandom(
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,
navControllerQuiz = navQuiz, navControllerQuiz = navQuiz,
navControllerSearch = navSearch navControllerSearch = navSearch,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
){ ){
Column ( Column (
modifier = Modifier.fillMaxSize().background(Color(0xFF100C1B)) modifier = Modifier.fillMaxSize().background(Color(0xFF100C1B))

@ -2,6 +2,7 @@ package com.example.what_the_fantasy.ui.screens
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.util.Log
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
@ -9,6 +10,7 @@ import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -16,21 +18,19 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.icons.filled.MailOutline
import androidx.compose.material.icons.filled.Share import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -45,10 +45,10 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@ -56,13 +56,14 @@ import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.example.what_the_fantasy.data.model.Comment import com.example.what_the_fantasy.data.model.Comment
import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.services.IServices import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.logs.LogsUsers
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.theme.colorBackground import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.theme.gradienBox import com.example.what_the_fantasy.ui.states.QuoteInformationUserState
import com.example.what_the_fantasy.ui.theme.iconText import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
import com.example.what_the_fantasy.ui.theme.likeIcon import com.example.what_the_fantasy.ui.viewModels.QuoteInformationUserViewModel
import com.example.what_the_fantasy.ui.theme.whiteBackcgroundText
var isCommentVisible by mutableStateOf(false) var isCommentVisible by mutableStateOf(false)
@ -70,20 +71,29 @@ var isCommentVisible by mutableStateOf(false)
fun QuotePage( fun QuotePage(
quoteId : Int, quoteId : Int,
service : IServices, service : IServices,
index : Int,
navAccueil: () -> Unit, navAccueil: () -> Unit,
navFavorite:() -> Unit, navFavorite:() -> Unit,
navQuiz: () -> Unit, navQuiz: () -> Unit,
navProfil:() -> Unit,
navSearch: () -> Unit, navSearch: () -> Unit,
navProfil:() -> Unit) currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
quoteInformationUserVM : QuoteInformationUserViewModel,
quoteInformationUserState : QuoteInformationUserState
)
{ {
// utiliser ViewModel // utiliser ViewModel
val quote = service.getQuote(quoteId) ?: return val quote = service.getQuote(quoteId) ?: return
val context = LocalContext.current val context = LocalContext.current
val user = service.getUserById(index) ?: return val favorite by remember { mutableStateOf(service.isFavorite(
val favorite by remember { mutableStateOf(service.isFavorite(id = quoteId, user = user)) } idQuote = quoteId,
iduser = currentUserState.id)) }
NavBar( NavBar(
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,
@ -93,7 +103,8 @@ fun QuotePage(
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(MaterialTheme.colorScheme.background), .background(MaterialTheme.colorScheme.background)
.verticalScroll(rememberScrollState()),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) { ) {
Column(modifier = Modifier Column(modifier = Modifier
@ -111,10 +122,12 @@ fun QuotePage(
FunctionalIcon( FunctionalIcon(
isFavorite = favorite, isFavorite = favorite,
userId = index, userId = currentUserState.id,
id = quoteId, quoteId = quoteId,
context = context, context = context,
service = service quoteInformationUserVM = quoteInformationUserVM,
quoteInformationUserState = quoteInformationUserState,
quote = quote
) )
QuoteText( QuoteText(
text = '"' + quote.content + '"' text = '"' + quote.content + '"'
@ -133,13 +146,25 @@ fun QuotePage(
nameId = R.string.charac, nameId = R.string.charac,
text = quote.character text = quote.character
) )
InfoQuoteText(
nameId = R.string.date,
text = quote.date.toString()
)
InfoQuoteText(
nameId = R.string.type,
text = quote.type.toString()
)
Row( Row(
modifier = Modifier modifier = Modifier
.padding(top = 10.dp) .padding(top = 10.dp)
.align(alignment = Alignment.End) .align(alignment = Alignment.End)
) { ) {
LikeInfo( LikeInfo(
likes = quote.likes likes = quote.likes,
quoteInformationUserVM
) )
} }
} }
@ -156,9 +181,12 @@ fun QuotePage(
), ),
exit = slideOutVertically() + shrinkVertically() + fadeOut() exit = slideOutVertically() + shrinkVertically() + fadeOut()
) { ) {
Box(modifier = Modifier.fillMaxWidth().background(MaterialTheme.colorScheme.primary).fillMaxSize()){ Box(modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.primary)
.fillMaxSize()){
Column { Column {
AddComment(index, service) AddComment(currentUserState.id, service, quoteInformationUserState, quoteInformationUserVM)
LstComment(service.getComment(quoteId)) LstComment(service.getComment(quoteId))
} }
} }
@ -191,7 +219,16 @@ fun ImageQuote(imageUrl : String){
} }
@Composable @Composable
fun FunctionalIcon(isFavorite: Boolean, userId : Int, id : Int, context : Context, service: IServices){ fun FunctionalIcon(isFavorite: Boolean,
userId : Int,
quoteId : Int,
context : Context,
quoteInformationUserVM : QuoteInformationUserViewModel,
quoteInformationUserState : QuoteInformationUserState,
quote : Quote
){
val logsUsers = LogsUsers()
Row(modifier = Modifier Row(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
) { ) {
@ -201,9 +238,10 @@ fun FunctionalIcon(isFavorite: Boolean, userId : Int, id : Int, context : Contex
val sendIntent = Intent().apply { val sendIntent = Intent().apply {
action = Intent.ACTION_SEND action = Intent.ACTION_SEND
// lien a changer quand le site sra deployer // lien a changer quand le site sra deployer
putExtra(Intent.EXTRA_TEXT, "http://wfWebsite/quote/$id") putExtra(Intent.EXTRA_TEXT, "http://wfWebsite/quote/$quoteId")
type = "text/plain" type = "text/plain"
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
logsUsers.shareInformationUser("ShareQuote", quoteId, userId)
} }
val shareIntent = Intent.createChooser(sendIntent, null) val shareIntent = Intent.createChooser(sendIntent, null)
@ -213,6 +251,7 @@ fun FunctionalIcon(isFavorite: Boolean, userId : Int, id : Int, context : Contex
}, },
modifier = Modifier.padding(start = 15.dp) modifier = Modifier.padding(start = 15.dp)
) { ) {
Icon( Icon(
Icons.Default.Share, Icons.Default.Share,
contentDescription = stringResource(R.string.share), contentDescription = stringResource(R.string.share),
@ -225,16 +264,23 @@ fun FunctionalIcon(isFavorite: Boolean, userId : Int, id : Int, context : Contex
}, },
modifier = Modifier.padding(start = 20.dp) modifier = Modifier.padding(start = 20.dp)
){ ){
Icon( Image(
Icons.Default.MailOutline, painter = painterResource(id = R.drawable.message),
contentDescription = stringResource(R.string.comment), contentDescription ="message",
tint = MaterialTheme.colorScheme.onPrimary, modifier = Modifier.size(30.dp),
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onPrimary)
) )
} }
if(isFavorite){ if(isFavorite){
IconButton( IconButton(
onClick = { service.SupFav(userId = userId, QuoteId = id)}, //sup fav onClick = {
quoteInformationUserVM.supFav(userId = userId, idQuote = quoteId)
quote.likes = quoteInformationUserState.like
//Log.e("Like", "Coeur ${quote.likes} ${quoteInformationUserState.like}")
logsUsers.favoriteInformationUserFalse("Favorite", quoteId, userId)
}, //sup fav
modifier = Modifier.padding(start = 20.dp) modifier = Modifier.padding(start = 20.dp)
){ ){
Icon( Icon(
@ -247,7 +293,11 @@ fun FunctionalIcon(isFavorite: Boolean, userId : Int, id : Int, context : Contex
} }
else{ else{
IconButton( IconButton(
onClick = { service.AddFav(userId = userId, QuoteId = id)}, //add fav onClick = {
quoteInformationUserVM.addFav(userId = userId, idQuote = quoteId)
quote.likes = quoteInformationUserState.like
logsUsers.favoriteInformationUserTrue("Favorite", quoteId, userId)
}, //add fav
modifier = Modifier.padding(start = 50.dp) modifier = Modifier.padding(start = 50.dp)
){ ){
Icon( Icon(
@ -286,7 +336,10 @@ fun InfoQuoteText(nameId : Int, text : String){
} }
@Composable @Composable
fun LikeInfo(likes : Int){ fun LikeInfo(likes : Int,
quoteInformationUserVM : QuoteInformationUserViewModel){
quoteInformationUserVM.setLike(likes)
//Log.e("Like", "LikeInfo => Nb Like : ${likes}")
Text( Text(
text = likes.toString(), text = likes.toString(),
color = MaterialTheme.colorScheme.onPrimary color = MaterialTheme.colorScheme.onPrimary
@ -299,8 +352,11 @@ fun LikeInfo(likes : Int){
} }
@Composable @Composable
fun AddComment(userId: Int, service: IServices) { fun AddComment(userId: Int,
var text by remember { mutableStateOf("") } service: IServices,
quoteInformationUserState: QuoteInformationUserState,
quoteInformationUserVM: QuoteInformationUserViewModel) {
// var text by remember { mutableStateOf(quoteInformationUserState.comment) }
Row( Row(
modifier = Modifier modifier = Modifier
@ -318,8 +374,8 @@ fun AddComment(userId: Int, service: IServices) {
) )
} }
TextField( TextField(
value = text, value = quoteInformationUserState.comment,
onValueChange = { text = it }, onValueChange = { quoteInformationUserVM.setComment(it) },
label = { Text(stringResource(R.string.comment)) }, label = { Text(stringResource(R.string.comment)) },
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
@ -347,8 +403,6 @@ fun AddComment(userId: Int, service: IServices) {
) )
} }
} }
@Composable @Composable
fun LstComment(lst: List<Comment>) { fun LstComment(lst: List<Comment>) {
LazyColumn( LazyColumn(
@ -391,5 +445,3 @@ fun LstComment(lst: List<Comment>) {
} }
} }
} }

@ -1,6 +1,5 @@
package com.example.what_the_fantasy.ui.screens package com.example.what_the_fantasy.ui.screens
import android.content.Context
import android.content.Intent
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -8,18 +7,10 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material.icons.filled.FavoriteBorder
import androidx.compose.material.icons.filled.MailOutline
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
@ -40,21 +31,26 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import com.example.what_the_fantasy.data.model.Character import com.example.what_the_fantasy.data.model.Character
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun RecapSubmitPage( fun RecapSubmitPage(
index: Int,
navFavorite: () -> Unit, navFavorite: () -> Unit,
navAccueil: () -> Unit, navAccueil: () -> Unit,
navProfil:() -> Unit, navProfil:() -> Unit,
navQuiz: () -> Unit,
navSearch: () -> Unit, navSearch: () -> Unit,
navQuiz : () -> Unit,
quoteContent : String, quoteContent : String,
character: String, character: String,
source: String source: String,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
NavBar( NavBar(onQuiz = true,
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,

@ -1,5 +1,7 @@
package com.example.what_the_fantasy.ui.screens package com.example.what_the_fantasy.ui.screens
import android.util.Log
import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@ -16,6 +18,8 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
@ -23,13 +27,20 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.model.Quote import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.services.IServices import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.components.QuoteLittle import com.example.what_the_fantasy.ui.components.QuoteLittle
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.states.SearchState
import com.example.what_the_fantasy.ui.viewModels.AuthUserViewModel
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
import com.example.what_the_fantasy.ui.viewModels.SearchViewModel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@Composable @Composable
fun SearchPage( fun SearchPage(
navFavorite: () -> Unit, navFavorite: () -> Unit,
@ -38,24 +49,34 @@ fun SearchPage(
navQuiz: () -> Unit, navQuiz: () -> Unit,
navQuote: (Int) -> Unit, navQuote: (Int) -> Unit,
navSearch: (String, String) -> Unit, navSearch: (String, String) -> Unit,
services: IServices,
type: String, type: String,
search: String search: String,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
searchVM : SearchViewModel,
searchState : SearchState,
) { ) {
var newSearch by remember { mutableStateOf(search) }
val filtre = listOf("contenue", "personnage", "titre")
val textQuoteSearch = stringResource(id = R.string.QuoteSearch)
val textTitleSearch = stringResource(id = R.string.TitleQuoteSearch)
val textCharacterSearch = stringResource(id = R.string.character)
val textSearch = stringResource(id = R.string.Search)
val filtre = listOf("contenu", "personnage", "titre")
//val filtre = listOf(textQuoteSearch, textCharacterSearch, textTitleSearch)
val (newFiltre, onFiltreSelected) = remember { mutableStateOf(type) } val (newFiltre, onFiltreSelected) = remember { mutableStateOf(type) }
val page = remember { mutableStateOf(1) } val page = remember { mutableIntStateOf(1) }
val quotes = remember { mutableStateListOf<Quote>() } val quotes = remember { mutableStateListOf<Quote>() }
val isLoading = remember { mutableStateOf(false) } val isLoading = remember { mutableStateOf(false) }
val state = rememberLazyListState() val state = rememberLazyListState()
LaunchedEffect(page.value, type, search) { LaunchedEffect(page.intValue, type, search) {
if (!isLoading.value) { if (!isLoading.value) {
isLoading.value = true isLoading.value = true
delay(500) delay(500)
val newQuotes = services.search(type, search, page.value * 15) val newQuotes = searchVM.search(type, search, page.intValue * 15)
val uniqueQuotes = newQuotes.filterNot { new -> quotes.any { it.id == new.id } } val uniqueQuotes = newQuotes.filterNot { new -> quotes.any { it.id == new.id } }
if (uniqueQuotes.isNotEmpty()) { if (uniqueQuotes.isNotEmpty()) {
quotes.addAll(uniqueQuotes) quotes.addAll(uniqueQuotes)
@ -70,7 +91,11 @@ fun SearchPage(
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,
navControllerQuiz = navQuiz, navControllerQuiz = navQuiz,
navControllerSearch = { navSearch("contenue", "") } navControllerSearch = { navSearch("contenu", "") },
currentUserVM = currentUserVM,
currentUserState = currentUserState,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@ -88,29 +113,33 @@ fun SearchPage(
) )
Column(horizontalAlignment = Alignment.CenterHorizontally) { Column(horizontalAlignment = Alignment.CenterHorizontally) {
OutlinedTextField( OutlinedTextField(
value = newSearch, value = searchState.search,
onValueChange = { newSearch = it }, onValueChange = {
searchVM.setSearch(it)
},
textStyle = TextStyle(color = MaterialTheme.colorScheme.onBackground), textStyle = TextStyle(color = MaterialTheme.colorScheme.onBackground),
label = { Text(textSearch) },
modifier = Modifier modifier = Modifier
.padding(top = 2.dp) .padding(top = 2.dp)
.fillMaxWidth() .fillMaxWidth()
.height(50.dp), .height(70.dp),
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text),
maxLines = 1, maxLines = 1,
shape = CircleShape, shape = CircleShape,
trailingIcon = { trailingIcon = {
IconButton( IconButton(
onClick = { navSearch(newFiltre, newSearch) }, onClick = { navSearch(newFiltre, searchState.search) },
modifier = Modifier modifier = Modifier
.size(50.dp) .size(50.dp)
.clip(CircleShape) .clip(CircleShape)
) { ) {
Icon(
Icons.Rounded.Search, Image(
contentDescription = stringResource(R.string.TitleSearch), painter = painterResource(id = R.drawable.search),
Modifier contentDescription = "search",
.fillMaxSize() modifier = Modifier
.background(MaterialTheme.colorScheme.primary, CircleShape) .size(30.dp),
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary)
) )
} }
} }
@ -148,13 +177,15 @@ fun SearchPage(
) { ) {
items(quotes) { quote -> items(quotes) { quote ->
Column(Modifier.clickable { navQuote(quote.id) }) { Column(Modifier.clickable { navQuote(quote.id) }) {
if(quote.language == currentUserState.langage) { // affiche les suggestions de citation dans la bonne langue
QuoteLittle(quote) QuoteLittle(quote)
} }
} }
}
item { item {
if (state.layoutInfo.visibleItemsInfo.lastOrNull()?.index == quotes.size - 1 && !isLoading.value) { if (state.layoutInfo.visibleItemsInfo.lastOrNull()?.index == quotes.size - 1 && !isLoading.value) {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
page.value++ page.intValue++
} }
Box( Box(
modifier = Modifier modifier = Modifier

@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
@ -21,6 +22,7 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@ -29,27 +31,26 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.example.what_the_fantasy.R import com.example.what_the_fantasy.R
import com.example.what_the_fantasy.data.services.IServices import com.example.what_the_fantasy.data.model.Image
import com.example.what_the_fantasy.ui.components.SpaceHeightComponent 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.TitlePageComponent
import com.example.what_the_fantasy.ui.theme.colorBackground
import com.example.what_the_fantasy.ui.theme.gradienBox
import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent import com.example.what_the_fantasy.ui.components.ErrorMessageProfileComponent
import com.example.what_the_fantasy.ui.components.VisibleIconPasswordComponent
import com.example.what_the_fantasy.ui.states.SignInUserState
import com.example.what_the_fantasy.ui.viewModels.SignInUserViewModel
@Composable @Composable
fun SignUpPage(navControllerLogin: () -> Unit, services : IServices) { fun SignUpPage(navControllerLogin: () -> Unit, signInUserVM :SignInUserViewModel,signInState : SignInUserState) {
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) }
Box( Box(
modifier = Modifier modifier = Modifier
@ -68,23 +69,35 @@ fun SignUpPage(navControllerLogin: () -> Unit, services : IServices) {
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
TitlePageComponent(R.string.titleSignUp,MaterialTheme.colorScheme.onBackground) TitlePageComponent(R.string.titleSignUp,MaterialTheme.colorScheme.onBackground) // Page Title
IdentifiantTextFieldSign(R.string.IdentifiantLogin,identifiant = username,onValueChange = { username = it })
EmailTextFieldSign(R.string.EmailSignUp, email, onValueChange = { email = it }) IdentifiantTextFieldSign(R.string.IdentifiantLogin,signInState.username){ // Username
PassWdTextFieldSign(R.string.PasswdLogin,password, onValueChange = { password = it },passwordVisible,onPasswordVisibilityChange = { passwordVisible = !passwordVisible }) signInUserVM.setUsername(it)
PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp,confirmPassword,onValueChange = { confirmPassword = it },passwordVisible,onPasswordVisibilityChange = { passwordVisible = !passwordVisible }) }
EmailTextFieldSign(R.string.EmailSignUp, signInState.email){ // Email
signInUserVM.setEmail(it)
}
PassWdTextFieldSign(R.string.PasswdLogin,signInState.password){ // Password
signInUserVM.setPassword(it)
}
PassWdConfirmTextFieldSign(R.string.ConfirmPassWdSignUp,signInState.confirmPassword){ // confirm Password
signInUserVM.setConfirmPassword(it)
}
SpaceHeightComponent(16) SpaceHeightComponent(16)
ConnexionButtonSign(R.string.ButtonSignUp,18, MaterialTheme.colorScheme.background, MaterialTheme.colorScheme.onBackground, username, email, password, confirmPassword, services, navControllerLogin)
ConnexionButtonSign(R.string.ButtonSignUp,18, Color.White, Color.Black, signInState.username, signInState.email, signInState.password, signInState.confirmPassword, signInUserVM, navControllerLogin)
SpaceHeightComponent(16) SpaceHeightComponent(16)
ReturnLogin(R.string.ButtonLogin,12, MaterialTheme.colorScheme.primary, navController = navControllerLogin)
ReturnLogin(R.string.ButtonLogin,12, Color.White, navController = navControllerLogin)
} }
} }
} }
@Composable @Composable
fun IdentifiantTextFieldSign(textIdentifiantResId : Int, identifiant: String, onValueChange: (String) -> Unit){ fun IdentifiantTextFieldSign(textIdentifiantResId : Int, identifiant: String, onValueChange: (String) -> Unit){
val textIdentifiant = stringResource(id = textIdentifiantResId) val textIdentifiant = stringResource(id = textIdentifiantResId)
@ -121,8 +134,10 @@ fun EmailTextFieldSign(textIdentifiantResId: Int, email: String, onValueChange:
} }
@Composable @Composable
fun PassWdTextFieldSign(textpasswdResId : Int, passwd: String, onValueChange: (String) -> Unit, passwordVisible: Boolean, onPasswordVisibilityChange: () -> Unit){ fun PassWdTextFieldSign(textpasswdResId : Int, passwd: String, onValueChange: (String) -> Unit){
val textpasswd = stringResource(id = textpasswdResId) val textpasswd = stringResource(id = textpasswdResId)
var passwordVisible by remember { mutableStateOf(false) }
Column(modifier = Modifier.padding(top = 10.dp)) { Column(modifier = Modifier.padding(top = 10.dp)) {
OutlinedTextField( OutlinedTextField(
value = passwd, value = passwd,
@ -134,8 +149,10 @@ fun PassWdTextFieldSign(textpasswdResId : Int, passwd: String, onValueChange: (S
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = { trailingIcon = {
IconButton(onClick = onPasswordVisibilityChange) { IconButton(onClick = {
Icon(imageVector = Icons.Default.Check, contentDescription = "Valider") passwordVisible = !passwordVisible
}) {
VisibleIconPasswordComponent(passwordVisible)
} }
}, },
shape = RoundedCornerShape(16.dp) shape = RoundedCornerShape(16.dp)
@ -144,8 +161,10 @@ fun PassWdTextFieldSign(textpasswdResId : Int, passwd: String, onValueChange: (S
} }
@Composable @Composable
fun PassWdConfirmTextFieldSign(textpasswdResId : Int,confirmPassword: String, onValueChange: (String) -> Unit, passwordVisible: Boolean, onPasswordVisibilityChange: () -> Unit){ fun PassWdConfirmTextFieldSign(textpasswdResId : Int,confirmPassword: String, onValueChange: (String) -> Unit){
val textpasswd = stringResource(id = textpasswdResId) val textpasswd = stringResource(id = textpasswdResId)
var passwordVisible by remember { mutableStateOf(false) }
Column(modifier = Modifier.padding(top = 10.dp)) { Column(modifier = Modifier.padding(top = 10.dp)) {
OutlinedTextField( OutlinedTextField(
value = confirmPassword, value = confirmPassword,
@ -157,8 +176,8 @@ fun PassWdConfirmTextFieldSign(textpasswdResId : Int,confirmPassword: String, on
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password),
visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
trailingIcon = { trailingIcon = {
IconButton(onClick = onPasswordVisibilityChange) { IconButton(onClick = {passwordVisible = !passwordVisible}) {
Icon(imageVector = Icons.Default.Check, contentDescription = "Valider") VisibleIconPasswordComponent(passwordVisible)
} }
}, },
shape = RoundedCornerShape(16.dp) shape = RoundedCornerShape(16.dp)
@ -188,7 +207,7 @@ fun ConnexionButtonSign(
email: String, email: String,
password: String, password: String,
confirmPassword: String, confirmPassword: String,
service: IServices, viewModel: SignInUserViewModel,
navController: ()-> Unit navController: ()-> Unit
) { ) {
val title = stringResource(id = titleResId) val title = stringResource(id = titleResId)
@ -208,7 +227,7 @@ fun ConnexionButtonSign(
passwordErrorEmpty = password.isBlank() || confirmPassword.isBlank() passwordErrorEmpty = password.isBlank() || confirmPassword.isBlank()
if (!emailError && !passwordError && !usernameError && !passwordErrorEmpty) { if (!emailError && !passwordError && !usernameError && !passwordErrorEmpty) {
usernameErrorExist = !service.CreateUser(username, email, password, service) usernameErrorExist = !viewModel.createUser(username, email, password)
if(!usernameErrorExist){ if(!usernameErrorExist){
navController() // retour à la page login navController() // retour à la page login
} }

@ -2,7 +2,6 @@ package com.example.what_the_fantasy.ui.screens
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -35,8 +34,10 @@ import com.example.what_the_fantasy.ui.components.ErrorMessageSubmitQuoteCompone
import com.example.what_the_fantasy.ui.components.NavBar import com.example.what_the_fantasy.ui.components.NavBar
import com.example.what_the_fantasy.ui.components.SpaceHeightComponent 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.TitlePageComponent
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.theme.colorBackground import com.example.what_the_fantasy.ui.theme.colorBackground
import com.example.what_the_fantasy.ui.theme.gradienBox import com.example.what_the_fantasy.ui.theme.gradienBox
import com.example.what_the_fantasy.ui.viewModels.CurrentUserViewModel
@Composable @Composable
fun SubmitQuotePage( fun SubmitQuotePage(
@ -44,9 +45,13 @@ fun SubmitQuotePage(
navAccueil: () -> Unit, navAccueil: () -> Unit,
navProfil:() -> Unit, navProfil:() -> Unit,
navQuiz: () -> Unit, navQuiz: () -> Unit,
navRecap: (String, String, String) -> Unit navRecap: (String, String, String) -> Unit,
currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState,
) { ) {
NavBar( NavBar(
currentUserVM = currentUserVM,
currentUserState = currentUserState,
navControllerFavorite = navFavorite, navControllerFavorite = navFavorite,
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,

@ -0,0 +1,9 @@
package com.example.what_the_fantasy.ui.states
import com.example.what_the_fantasy.data.model.SrcLanguage
import com.example.what_the_fantasy.data.model.User
data class AuthUserState (
val username : String = "",
val password: String = "",
)

@ -0,0 +1,13 @@
package com.example.what_the_fantasy.ui.states
import com.example.what_the_fantasy.data.model.SrcLanguage
data class CurrentUserState (
var id : Int = -1,
val imagePath : String ="",
var username :String="",
var email : String="",
var password : String="",
var confirmPassword : String="",
val langage : SrcLanguage = SrcLanguage.vo
)

@ -0,0 +1,7 @@
package com.example.what_the_fantasy.ui.states
data class QuoteInformationUserState (
val comment : String ="",
val isFavorite : Boolean = false,
val like : Int = 0
)

@ -0,0 +1,5 @@
package com.example.what_the_fantasy.ui.states
data class SearchState (
var search : String = ""
)

@ -0,0 +1,8 @@
package com.example.what_the_fantasy.ui.states
data class SignInUserState (
val username : String ="",
val email : String ="",
val password : String ="",
val confirmPassword : String ="",
)

@ -0,0 +1,30 @@
package com.example.what_the_fantasy.ui.viewModels
import android.util.Log
import androidx.lifecycle.ViewModel
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.states.AuthUserState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class AuthUserViewModel : ViewModel(){
private val services = ServicesStub() // faire repository qui gère les services Stub et API
private val _userState = MutableStateFlow(AuthUserState())
val userState : StateFlow<AuthUserState> = _userState.asStateFlow()
fun setUsername(username : String){
_userState.update { it.copy(username=username) }
}
fun setPassword(password : String){
_userState.update { it.copy(password=password) }
}
fun validLogin(username : String, passwd : String, navController: (Int) -> Unit, initialierCurrentUser : (Int) -> Unit) : Boolean{
return services.validLogin(username,passwd, navController, initialierCurrentUser)
}
}

@ -0,0 +1,94 @@
package com.example.what_the_fantasy.ui.viewModels
import android.util.Log
import androidx.lifecycle.ViewModel
import com.example.what_the_fantasy.data.model.SrcLanguage
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.states.CurrentUserState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class CurrentUserViewModel : ViewModel(){
private val services = ServicesStub() // faire repository qui gère les services Stub et API
private val _currentUserState = MutableStateFlow(CurrentUserState())
var currentUserState : StateFlow<CurrentUserState> = _currentUserState.asStateFlow()
fun initialiseCurrentUser(index : Int){
services.getUserById(index)?.let {
setId(it.id)
setUsername(it.username)
setEmail(it.email)
setPassword(it.password)
setLangue(it.langage)
setImage(it.imgUrl)
}
}
fun clearCurrentUser(){
_currentUserState.value = CurrentUserState()
}
fun setId(id : Int){
_currentUserState.update {it.copy(id = id)}
}
fun setUsername(username : String){
_currentUserState.update {it.copy(username = username)}
}
fun setEmail(email : String){
_currentUserState.update {it.copy(email = email)}
}
fun setPassword(password : String){
_currentUserState.update {it.copy(password = password)}
}
fun setLangue(langue : SrcLanguage){
_currentUserState.update {it.copy(langage = langue)}
}
fun setImage(imagePath : String){
_currentUserState.update {it.copy(imagePath = imagePath)}
}
fun editUsername(username : String, index : Int) : Boolean{
_currentUserState.update {it.copy(username = username)}
return services.EditUsername(username, index)
}
fun editEmail(email : String, index : Int) : Boolean{
_currentUserState.update {
it.copy(email = email)
}
return services.EditEmail(email, index)
}
fun editPassword(password : String, index : Int){
services.EditPasswd(password, index)
}
fun editLangue(index : Int){
val langage = services.ChangeLangage(index)
_currentUserState.update {
it.copy(langage = langage)
}
}
fun editImage(index : Int){
val image = services.EditImage(index)
_currentUserState.update {
it.copy(imagePath = image)
}
}
}

@ -0,0 +1,43 @@
package com.example.what_the_fantasy.ui.viewModels
import android.util.Log
import androidx.lifecycle.ViewModel
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.states.QuoteInformationUserState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class QuoteInformationUserViewModel: ViewModel() {
private val services = ServicesStub() // faire repository qui gère les services Stub et API
private val _quoteState = MutableStateFlow(QuoteInformationUserState())
val quoteState : StateFlow<QuoteInformationUserState> = _quoteState.asStateFlow()
fun setComment(comment : String){
_quoteState.update { it.copy(comment=comment) }
}
fun setFavorite(isFavorite : Boolean){
_quoteState.update { it.copy(isFavorite=isFavorite) }
}
fun setLike(like : Int){
if(like >= 0) {
_quoteState.update { it.copy(like=like) }
}
}
fun addFav(userId: Int, idQuote: Int) {
services.AddFav(userId, idQuote)
setLike(quoteState.value.like + 1)
setFavorite(true)
}
fun supFav(userId: Int, idQuote: Int) {
services.SupFav(userId, idQuote)
setLike(quoteState.value.like - 1)
setFavorite(false)
//Log.e("Like", "Service ${quoteState.value.like}")
}
}

@ -0,0 +1,27 @@
package com.example.what_the_fantasy.ui.viewModels
import androidx.lifecycle.ViewModel
import com.example.what_the_fantasy.data.model.Quote
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.states.CurrentUserState
import com.example.what_the_fantasy.ui.states.SearchState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class SearchViewModel : ViewModel() {
private val services = ServicesStub() // faire repository qui gère les services Stub et API
private val _searchState = MutableStateFlow(SearchState())
var searchState : StateFlow<SearchState> = _searchState.asStateFlow()
fun setSearch(search : String){
_searchState.update {it.copy(search = search)}
}
fun search(type : String ,search:String ,indexCount: Int): List<Quote>{
return services.search(type,search,indexCount)
}
}

@ -0,0 +1,35 @@
package com.example.what_the_fantasy.ui.viewModels
import androidx.lifecycle.ViewModel
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.ui.states.SignInUserState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
class SignInUserViewModel: ViewModel() {
private val services = ServicesStub() // faire repository qui gère les services Stub et API
private val _userState = MutableStateFlow(SignInUserState())
val userState : StateFlow<SignInUserState> = _userState.asStateFlow()
fun createUser(username: String, email: String, passwd: String) : Boolean{
return services.CreateUser(username, email, passwd)
}
fun setUsername(username : String){
_userState.update { it.copy(username=username) }
}
fun setEmail(email : String){
_userState.update { it.copy(email=email) }
}
fun setPassword(password : String){
_userState.update { it.copy(password=password) }
}
fun setConfirmPassword(confirmPassword : String){
_userState.update { it.copy(confirmPassword=confirmPassword) }
}
}

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="39dp"
android:height="19dp"
android:viewportWidth="39"
android:viewportHeight="19">
<path
android:pathData="M25.655,1.196H11.58C9.495,1.196 7.6,2.098 6.226,3.55C4.852,5.003 4,7.006 4,9.212C4,11.416 4.852,13.42 6.226,14.872C7.6,16.325 9.495,17.226 11.58,17.226H24.79C26.263,18.341 28.065,19 30.003,19H30.015C32.486,19 34.734,17.931 36.361,16.21C37.988,14.489 39,12.114 39,9.5C39,6.887 37.99,4.51 36.359,2.792C34.73,1.07 32.483,0 30.015,0H30.003C28.43,0 26.946,0.435 25.655,1.196ZM30.482,8.22L30.512,8.226C30.568,7.977 30.705,7.779 30.925,7.637C31.143,7.493 31.371,7.451 31.609,7.51L31.616,7.479C31.379,7.42 31.192,7.274 31.057,7.043C30.922,6.81 30.882,6.57 30.938,6.32L30.908,6.312C30.852,6.563 30.715,6.761 30.496,6.904C30.277,7.047 30.048,7.089 29.811,7.029L29.804,7.06C30.042,7.12 30.228,7.266 30.364,7.497C30.5,7.728 30.538,7.968 30.482,8.22ZM33.003,9.432L33.039,9.441C33.109,9.126 33.282,8.878 33.557,8.699C33.832,8.519 34.118,8.466 34.416,8.541L34.425,8.503C34.127,8.428 33.893,8.246 33.723,7.954C33.553,7.663 33.503,7.36 33.573,7.046L33.537,7.037C33.467,7.352 33.294,7.599 33.019,7.779C32.744,7.959 32.457,8.012 32.16,7.937L32.151,7.976C32.449,8.05 32.683,8.232 32.852,8.523C33.023,8.814 33.073,9.118 33.003,9.432ZM30.351,5.022C29.279,5.577 28.507,6.703 28.417,8.053C28.283,10.068 29.719,11.816 31.625,11.958C32.529,12.025 33.377,11.718 34.032,11.161C34.357,10.885 34.693,11.128 34.551,11.476C33.777,13.386 31.923,14.66 29.852,14.505C27.235,14.311 25.263,11.91 25.446,9.143C25.622,6.491 27.724,4.458 30.212,4.481C30.67,4.486 30.767,4.807 30.351,5.022ZM30.003,1.123H30.015C34.373,1.123 37.939,4.892 37.939,9.5C37.939,14.108 34.369,17.878 30.015,17.878H30.003C25.65,17.878 22.08,14.108 22.08,9.5C22.08,4.892 25.645,1.123 30.003,1.123Z"
android:fillColor="#ffffff"/>
</vector>

@ -1,10 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="39dp"
android:height="19dp"
android:viewportWidth="39"
android:viewportHeight="19">
<path
android:pathData="M9.752,0H9.765C11.443,0 13.028,0.42 14.412,1.158H30.437C32.79,1.158 34.931,2.096 36.483,3.609C38.036,5.12 39,7.206 39,9.5C39,11.795 38.036,13.88 36.485,15.392L36.453,15.42C34.903,16.916 32.775,17.842 30.437,17.842H14.415C13.031,18.579 11.446,19 9.765,19H9.752C7.07,19 4.631,17.931 2.864,16.21C1.098,14.489 0,12.114 0,9.5C0,6.886 1.097,4.51 2.863,2.789L2.933,2.728C4.696,1.043 7.106,0 9.752,0ZM9.298,4.038C9.298,3.894 9.359,3.762 9.457,3.667C9.665,3.462 10.01,3.463 10.22,3.667L10.231,3.678C10.325,3.776 10.378,3.904 10.378,4.038V4.999C10.378,5.144 10.318,5.276 10.22,5.371C10.01,5.575 9.666,5.575 9.457,5.371C9.407,5.322 9.367,5.264 9.34,5.201C9.312,5.137 9.298,5.068 9.298,4.999V4.038ZM9.759,6.351C10.652,6.351 11.459,6.704 12.044,7.274C12.628,7.844 12.991,8.631 12.991,9.5C12.991,10.37 12.629,11.156 12.044,11.726C11.459,12.296 10.652,12.649 9.759,12.649C8.866,12.649 8.059,12.296 7.473,11.726C6.889,11.156 6.526,10.37 6.526,9.5C6.526,8.63 6.889,7.844 7.473,7.274C8.059,6.705 8.867,6.351 9.759,6.351ZM5.468,5.955C5.368,5.856 5.311,5.723 5.311,5.583C5.311,5.294 5.553,5.057 5.851,5.057C5.989,5.057 6.127,5.108 6.232,5.211L6.929,5.891C6.98,5.939 7.019,5.997 7.047,6.061C7.074,6.125 7.088,6.193 7.088,6.262C7.088,6.396 7.034,6.531 6.929,6.634C6.879,6.683 6.82,6.722 6.754,6.748C6.689,6.775 6.619,6.789 6.548,6.788C6.411,6.788 6.273,6.737 6.167,6.635L5.468,5.955ZM4.152,9.948C4.004,9.948 3.868,9.889 3.771,9.794C3.56,9.591 3.561,9.254 3.771,9.051L3.782,9.041C3.882,8.948 4.014,8.897 4.152,8.897H5.138C5.209,8.897 5.279,8.91 5.345,8.937C5.41,8.963 5.47,9.002 5.52,9.051C5.57,9.099 5.61,9.158 5.637,9.221C5.664,9.285 5.678,9.354 5.678,9.423C5.678,9.568 5.617,9.7 5.52,9.795C5.419,9.893 5.281,9.948 5.138,9.948H4.152ZM6.119,13.679C6.069,13.728 6.01,13.767 5.944,13.793C5.879,13.819 5.809,13.833 5.738,13.833C5.44,13.833 5.198,13.599 5.198,13.308C5.198,13.173 5.25,13.039 5.356,12.936L6.065,12.246C6.165,12.154 6.297,12.102 6.435,12.102C6.578,12.102 6.716,12.158 6.817,12.257C6.918,12.355 6.975,12.489 6.975,12.629C6.975,12.761 6.923,12.896 6.817,12.999L6.119,13.679ZM10.219,14.962C10.219,15.106 10.158,15.239 10.06,15.333C9.851,15.538 9.506,15.538 9.297,15.333L9.287,15.322C9.192,15.225 9.139,15.096 9.139,14.962V14.001C9.139,13.856 9.2,13.725 9.297,13.63C9.507,13.426 9.851,13.426 10.061,13.63C10.162,13.728 10.218,13.862 10.219,14.001V14.962ZM14.048,13.046C14.099,13.094 14.138,13.152 14.165,13.216C14.192,13.28 14.206,13.348 14.206,13.417C14.206,13.706 13.964,13.943 13.667,13.943C13.529,13.943 13.39,13.892 13.285,13.79L12.587,13.11C12.486,13.011 12.429,12.877 12.43,12.738C12.43,12.448 12.672,12.212 12.969,12.212C13.106,12.212 13.244,12.264 13.35,12.366L14.048,13.046ZM15.365,9.052C15.512,9.052 15.649,9.112 15.746,9.206C15.957,9.41 15.956,9.746 15.746,9.95L15.735,9.96C15.635,10.052 15.503,10.104 15.365,10.104H14.379C14.23,10.104 14.094,10.045 13.997,9.95C13.787,9.746 13.787,9.41 13.997,9.206C14.047,9.157 14.107,9.118 14.172,9.092C14.238,9.065 14.308,9.052 14.379,9.052H15.365ZM13.398,5.321C13.499,5.222 13.636,5.167 13.779,5.167C14.076,5.167 14.32,5.404 14.32,5.693C14.32,5.827 14.267,5.962 14.162,6.064L13.452,6.755C13.352,6.847 13.219,6.898 13.082,6.898C12.784,6.898 12.542,6.662 12.542,6.372C12.542,6.239 12.595,6.104 12.7,6.001L13.398,5.321ZM16.001,2.214C16.226,2.397 16.443,2.59 16.65,2.792C18.419,4.51 19.517,6.886 19.517,9.5C19.517,12.114 18.418,14.489 16.653,16.21C16.446,16.411 16.23,16.604 16.005,16.786H30.437C32.48,16.786 34.34,15.977 35.694,14.672L35.718,14.646C37.074,13.325 37.916,11.503 37.916,9.5C37.916,7.497 37.074,5.675 35.718,4.354C34.365,3.033 32.494,2.214 30.437,2.214H16.001ZM9.752,1.122H9.765C14.495,1.122 18.364,4.892 18.364,9.5C18.364,14.108 14.49,17.878 9.765,17.878H9.752C5.027,17.878 1.152,14.108 1.152,9.5C1.152,4.892 5.022,1.122 9.752,1.122Z"
android:fillColor="#000000"
android:fillType="evenOdd"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="256"
android:viewportHeight="256">
<path
android:pathData="M115.8,18C90.7,20.2 67,29.2 47.6,43.8c-4.7,3.6 -13.8,12.4 -17.5,17C7.9,88.2 3.8,123.2 19.2,154c4.9,9.8 9.9,16.6 19,26c9.9,10.3 9.8,9.8 10.1,32.1l0.2,17.3l1.2,2.1c2.8,4.7 6.9,7.1 12.1,7.1c2.3,0 3.9,-0.3 5.3,-1c1.2,-0.5 9.1,-5.4 17.7,-10.9c8.6,-5.5 16.7,-10.4 18.2,-10.9c5.1,-1.9 8.2,-2.2 20.1,-2c12.5,0.3 20,-0.2 29.8,-2c12.8,-2.3 24,-6 35.5,-11.8c42.5,-21.2 64.2,-60.6 55.8,-101.5c-6,-29.3 -29.2,-55.7 -61.4,-69.7C162.2,19.8 138.5,16 115.8,18zM145.3,32.4c14.3,1.9 25.6,5.2 37.8,11.1c28.9,14 46.2,37.4 48.7,66.1c1.5,16.2 -2.8,33.1 -11.9,47.1c-13.1,20.1 -36.5,35 -63.8,40.6c-10.9,2.3 -13.4,2.5 -30.3,2.6c-17,0.1 -19.2,0.3 -25.8,2.4c-5.3,1.7 -7.1,2.7 -23.3,13l-14.5,9.3l-0.2,-15.6l-0.2,-15.5l-1.7,-4.8c-2.5,-7.1 -5.3,-11.3 -11.9,-18c-13.7,-13.9 -20.1,-25.2 -23.2,-41.2c-1.3,-6.8 -1.4,-19.4 -0.2,-26.4c4.6,-25.5 21.7,-46.8 48,-59.5c12.7,-6.1 25.8,-9.8 39.7,-11.2c2.8,-0.3 5.8,-0.6 6.7,-0.7C122.5,31.2 140.4,31.8 145.3,32.4z"
android:fillColor="#000000"/>
</vector>

@ -0,0 +1,18 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="96dp"
android:height="96dp"
android:viewportWidth="96"
android:viewportHeight="96">
<path
android:pathData="M45.6,45.8c-38,38.1 -40.4,41 -35.2,42 1.3,0.3 5,-2.8 12.1,-9.8l10.2,-10.2 4.3,2.8c3.7,2.5 5.4,2.9 11,2.9 5.5,-0 7.3,-0.4 10.7,-2.7 6.3,-4.1 8.8,-9 8.8,-16.9 0,-5.5 -0.4,-7.2 -2.9,-10.9l-2.8,-4.3 4.4,-4.3 4.3,-4.4 4.6,3.8c6.1,5 10.6,10.9 13.5,17.9 1.9,4.7 2.7,5.8 4.6,5.8 2,-0 2.3,-0.5 2.1,-3.3 -0.2,-5.8 -5.2,-14.3 -12.8,-21.8l-7.3,-7.2 6.5,-6.3c4.3,-4.3 6.3,-7.1 6.1,-8.4 -0.8,-5.5 -4,-2.9 -42.2,35.3zM60,47.2c7.6,12.4 -9,27.1 -20.1,17.9l-2.4,-2 2.6,-2.6c2.3,-2.3 2.8,-2.5 5.2,-1.4 5.4,2.5 10.5,-2.9 7.7,-8.1 -1,-1.8 -0.8,-2.6 1.1,-4.6 2.9,-3.1 3.5,-3 5.9,0.8z"
android:fillColor="#000000"
android:strokeColor="#00000000"/>
<path
android:pathData="M36,19.6c-9.3,2.5 -16.2,6.4 -23.1,13.3 -10.1,10.2 -15.8,24.1 -10.1,24.9 1.4,0.2 2.4,-0.3 2.8,-1.5 7.1,-21 25.4,-33.7 46,-31.9 6.6,0.5 7.3,0.4 9.3,-1.8l2.3,-2.4 -5.2,-1.1c-6.8,-1.5 -15.3,-1.3 -22,0.5z"
android:fillColor="#000000"
android:strokeColor="#00000000"/>
<path
android:pathData="M41.2,35.1c-6.6,1.9 -14.3,12.8 -13,18.4 0.2,0.7 4.9,-3.3 10.7,-9.1 10.8,-10.9 11,-11.8 2.3,-9.3z"
android:fillColor="#000000"
android:strokeColor="#00000000"/>
</vector>

@ -0,0 +1,14 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="96dp"
android:height="96dp"
android:viewportWidth="96"
android:viewportHeight="96">
<path
android:pathData="M36,19.6c-9.3,2.5 -16.2,6.4 -23.1,13.3 -10.1,10.2 -15.8,24.1 -10.1,24.9 1.4,0.2 2.4,-0.3 2.8,-1.5 2.4,-7.2 6.8,-14.6 11.2,-19 22.4,-22.4 59.9,-14.8 71.8,14.6 1.9,4.5 2.7,5.6 4.6,5.6 5.9,-0 -0.1,-14.5 -10.1,-24.5 -12.9,-12.7 -30.6,-17.8 -47.1,-13.4z"
android:fillColor="#000000"
android:strokeColor="#00000000"/>
<path
android:pathData="M40.5,35.9c-12.5,5.8 -15.5,20.7 -6.1,30.9 11.1,12.2 32.6,3.5 32.6,-13.2 0,-2.5 -0.5,-5.7 -1.1,-7.3 -2.4,-6.4 -10.9,-12.3 -17.9,-12.3 -1.9,-0 -5.3,0.9 -7.5,1.9zM53.5,41.4c10.4,4.4 9.8,20 -1,24.1 -4.5,1.8 -8.8,1.2 -12.5,-1.8 -7.5,-5.8 -6.2,-18.6 2.3,-22.2 4.1,-1.8 6.9,-1.8 11.2,-0.1z"
android:fillColor="#000000"
android:strokeColor="#00000000"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="256dp"
android:height="256dp"
android:viewportWidth="256"
android:viewportHeight="256">
<path
android:pathData="M96.1,10.5c-18.4,1.9 -36,9.2 -50.7,21.1c-4.1,3.3 -12.3,11.7 -15.2,15.5c-3.9,5 -7.8,11.4 -10.4,16.6C3.7,96.9 7.6,135 30.2,164.6c2.9,3.9 11.2,12.3 15.2,15.5c34.5,27.8 82.4,28.8 117.6,2.4l5.2,-3.9l33.4,33.4c36.3,36.2 34.3,34.5 38.6,33.7c2.2,-0.4 5.1,-3.4 5.5,-5.5c0.8,-4.2 2.4,-2.3 -33.7,-38.6l-33.4,-33.4l3.9,-5.2c26.4,-35.2 25.4,-83.2 -2.4,-117.6c-3.3,-4.1 -11.7,-12.3 -15.5,-15.2C144.7,15 120.4,8 96.1,10.5zM116,25.4c9.6,1.2 17.5,3.6 25.9,7.9c40,20 56.4,68.8 36.5,108.5c-14,27.7 -42,45.1 -72.6,45.1c-27,0 -52.4,-13.7 -67.6,-36.5C18.7,121.3 20.7,82 42.9,54.7c2.7,-3.3 9.4,-9.9 12.7,-12.5C72.2,28.9 95,22.6 116,25.4z"
android:fillColor="#000000"/>
</vector>

@ -14,6 +14,8 @@
<string name="like">Likes</string> <string name="like">Likes</string>
<string name="profilePict">Image de profil</string> <string name="profilePict">Image de profil</string>
<string name="send">Envoyer</string> <string name="send">Envoyer</string>
<string name="type">Type</string>
<string name="date">Date</string>
//Page Login //Page Login
<string name="titleLogin">Connexion au compte</string> <string name="titleLogin">Connexion au compte</string>
@ -79,6 +81,9 @@
//Page Search //Page Search
<string name="TitleSearch">Recherche</string> <string name="TitleSearch">Recherche</string>
<string name="QuoteSearch">Citation</string>
<string name="TitleQuoteSearch">Titre</string>
<string name="Search">Recherche…</string>
</resources> </resources>

@ -13,6 +13,8 @@
<string name="like">Likes</string> <string name="like">Likes</string>
<string name="profilePict">Profile picture</string> <string name="profilePict">Profile picture</string>
<string name="send">Send</string> <string name="send">Send</string>
<string name="type">Type</string>
<string name="date">Date</string>
//Page Login //Page Login
<string name="titleLogin">Account login</string> <string name="titleLogin">Account login</string>
@ -75,6 +77,9 @@
//Page Search //Page Search
<string name="TitleSearch">Search</string> <string name="TitleSearch">Search</string>
<string name="QuoteSearch">Quote</string>
<string name="TitleQuoteSearch">Title</string>
<string name="Search">To research…</string>
</resources> </resources>

@ -1,17 +0,0 @@
package com.example.what_the_fantasy
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

@ -0,0 +1,161 @@
package com.example.what_the_fantasy
import org.junit.Assert.assertEquals
import org.junit.Test
import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.data.services.ServicesStub
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
class UnitTestQuote {
private val services : IServices = ServicesStub()
@Test
fun testGetQuote_OK(){
val quote = services.getQuote(1)
assertEquals("All we have to decide is what to do with the time that is given us.",quote?.content)
}
@Test
fun testGetQuote_Fake(){
val quote = services.getQuote(-1)
assertEquals(null,quote?.content)
}
@Test
fun testGetSomeQuote_OK(){
val quote = services.getSomeQuotes(4,1)
assertEquals(4,quote.size)
}
@Test
fun testGetSomeQuoteIndexNegatif(){
val quote = services.getSomeQuotes(-1,1)
assertEquals(1,quote.size)
}
@Test
fun testGetSomeQuotePageNegatif(){
val quote = services.getSomeQuotes(1,-1)
assertEquals(1,quote.size)
}
@Test
fun testGetSomeQuoteIndex0(){
val quote = services.getSomeQuotes(0,1)
assertEquals(0,quote.size)
}
@Test
fun testSearchByFullQuote(){
val quote = services.search("contenu","I am no man.",1)
assertEquals("I am no man.",quote[0].content)
}
@Test
fun testSearchByHalfQuote(){
val quote = services.search("contenu","I am no",1)
assertEquals("I am no man.",quote[0].content)
}
@Test
fun testSearchByFullQuoteWithUpperCase(){
val quote = services.search("contenu","I aM nO MaN",1)
assertEquals("I am no man.",quote[0].content)
}
@Test
fun testSearchByHalfQuoteWithUpperCase(){
val quote = services.search("contenu","I aM nO",1)
assertEquals("I am no man.",quote[0].content)
}
@Test
fun testSearchByFullQuoteBad(){
val quote = services.search("contenu","I am no Man bad",1)
assertEquals(0,quote.size)
}
@Test
fun testSearchByFullCharacter(){
val quote = services.search("personnage","Arwen",1)
assertEquals("Arwen",quote[0].character)
}
@Test
fun testSearchByHalfCharacter(){
val quote = services.search("personnage","Arw",1)
assertEquals("Arwen",quote[0].character)
}
@Test
fun testSearchByFullCharacterWithUpperCase(){
val quote = services.search("personnage","ArwEn",1)
assertEquals("Arwen",quote[0].character)
}
@Test
fun testSearchByHalfCharacterWithUpperCase(){
val quote = services.search("personnage","Arw",1)
assertEquals("Arwen",quote[0].character)
}
@Test
fun testSearchByFullCharacterBad(){
val quote = services.search("personnage","Arwen bad",1)
assertEquals(0,quote.size)
}
@Test
fun testSearchByFullTitle(){
val quote = services.search("titre","Star Wars",1)
assertEquals("Star Wars",quote[0].source)
}
@Test
fun testSearchByHalfTitle(){
val quote = services.search("titre","Star",1)
assertEquals("Star Wars",quote[0].source)
}
@Test
fun testSearchByFullTitleWithUpperCase(){
val quote = services.search("titre","StAr WaRs",1)
assertEquals("Star Wars",quote[0].source)
}
@Test
fun testSearchByHalfTitleWithUpperCase(){
val quote = services.search("titre","StAr",1)
assertEquals("Star Wars",quote[0].source)
}
@Test
fun testSearchByTitleBad(){
val quote = services.search("titre","Star Wars bad",1)
assertEquals(0,quote.size)
}
@Test
fun testIsFavorite_OK(){
assertTrue(services.isFavorite(1,10))
}
@Test
fun testIsFavorite_FakeQuote(){
assertFalse(services.isFavorite(-1,10))
}
@Test
fun testIsFavorite_FakeUser(){
assertFalse(services.isFavorite(1,-1))
}
}

@ -0,0 +1,158 @@
package com.example.what_the_fantasy
import androidx.compose.runtime.Composable
import androidx.navigation.compose.rememberNavController
import com.example.what_the_fantasy.data.model.SrcLanguage
import org.junit.Assert.assertEquals
import org.junit.Test
import com.example.what_the_fantasy.data.services.IServices
import com.example.what_the_fantasy.data.services.ServicesStub
import com.example.what_the_fantasy.data.services.hashPassword
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
class UnitTestUser {
private val services : IServices = ServicesStub()
@Test
fun testCreateUser_OK(){
assertTrue(services.CreateUser("username", "email", "passwd")
)
}
@Test
fun testCreateUserSameUsername(){
services.CreateUser("username2", "email2", "passwd")
assertFalse(services.CreateUser("username2", "emai", "passwd"))
}
@Test
fun testCreateUserSameEmail(){
services.CreateUser("username3", "email3", "passwd")
assertFalse(services.CreateUser("usernam", "email3", "passwd")
)
}
@Test
fun testCreateUserEmptyUsername(){
assertFalse(services.CreateUser("", "email", "passwd")
)
}
@Test
fun testCreateUserEmptyEmail(){
assertFalse(services.CreateUser("usernameEmptyEmail", "", "passwd")
)
}
@Test
fun testCreateUserEmptyPassword(){
assertFalse(services.CreateUser("usernameEmptyPassword", "email", "")
)
}
@Test
fun testUserEditUsername_OK(){
services.CreateUser("username4", "email4", "passwd")
assertTrue(services.EditUsername("newUsername",11))
}
@Test
fun testUserEditUsernameSameUsernameWithAnotherUsername(){
services.CreateUser("username5", "email5", "passwd")
assertFalse(services.EditUsername("dev",10))
}
@Test
fun testUserEditEmail_OK(){
services.CreateUser("username6", "email6", "passwd")
assertTrue(services.EditEmail("newEmail",11))
}
@Test
fun testUserEditEmailSameUsernameWithAnotherEmail(){
services.CreateUser("username7", "email7", "passwd")
assertFalse(services.EditEmail("testeur@example.com",10))
}
@Test
fun testUserEditPassword_OK(){
services.CreateUser("username8", "email8", "passwd")
services.EditPasswd("newPassword",11)
assertEquals(hashPassword("newPassword"), services.getUserById(11)?.password)
}
@Test
fun testUserChangeLangueVoAtVf(){
services.CreateUser("username9", "email9", "passwd")
services.ChangeLangage(11)
assertEquals(SrcLanguage.vf, services.getUserById(11)?.langage)
}
@Test
fun testUserChangeLangueVfAtVo(){
services.CreateUser("username10", "email10", "passwd")
services.ChangeLangage(11)
services.ChangeLangage(11)
assertEquals(SrcLanguage.vo, services.getUserById(11)?.langage)
}
@Test
fun testUserExist_OK(){
assertTrue(services.isUsernameExist("dev"))
}
@Test
fun testUserNotExist_OK(){
assertFalse(services.isUsernameExist("devNotExist"))
}
@Test
fun testEmailExist_OK(){
assertTrue(services.isEmailExist("testeur@example.com"))
}
@Test
fun testEmailNotExist_OK(){
assertFalse(services.isUsernameExist("email@example.com"))
}
@Test
fun TestUserValidLogin_OK() {
val navControllerMock: (Int) -> Unit = {}
val initialiserCurrentUserMock: (Int) -> Unit = {}
assertTrue(services.validLogin("dev", "1234", navControllerMock, initialiserCurrentUserMock))
}
@Test
fun TestUserValidLoginBadUsername() {
val navControllerMock: (Int) -> Unit = {}
val initialiserCurrentUserMock: (Int) -> Unit = {}
assertFalse(services.validLogin("devBad", "1234", navControllerMock, initialiserCurrentUserMock))
}
@Test
fun TestUserValidLoginBadPassword() {
val navControllerMock: (Int) -> Unit = {}
val initialiserCurrentUserMock: (Int) -> Unit = {}
assertFalse(services.validLogin("dev", "5678", navControllerMock, initialiserCurrentUserMock))
}
@Test
fun testGetUserById(){
val user = services.getUserById(10)
assertEquals("dev", user?.username)
}
@Test
fun testGetFavorite_User_Dev(){
val user = services.getAllUsers()[10]
val quotes = services.getFavorite(user)
assertEquals(3, quotes.size)
}
}

@ -14,6 +14,7 @@ composeBom = "2024.04.01"
navigationCompose = "2.8.6" navigationCompose = "2.8.6"
navigationCommonAndroid = "2.9.0-alpha05" navigationCommonAndroid = "2.9.0-alpha05"
engageCore = "1.5.6" engageCore = "1.5.6"
lifecycle = "2.8.0"
[libraries] [libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -37,6 +38,8 @@ androidx-navigation-compose = { group = "androidx.navigation", name = "navigatio
androidx-navigation-common-android = { group = "androidx.navigation", name = "navigation-common-android", version.ref = "navigationCommonAndroid" } androidx-navigation-common-android = { group = "androidx.navigation", name = "navigation-common-android", version.ref = "navigationCommonAndroid" }
engage-core = { group = "com.google.android.engage", name = "engage-core", version.ref = "engageCore" } engage-core = { group = "com.google.android.engage", name = "engage-core", version.ref = "engageCore" }
android-lifecycle-viewmodel ={ group = "androidx.lifecycle", name ="lifecycle-viewmodel-compose", version.ref ="lifecycle"}
android-lifecycle-viewmodel-runtime-ktx ={ group = "androidx.lifecycle", name ="lifecycle-viewmodel-ktx", version.ref ="lifecycle"}
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }

Loading…
Cancel
Save