Merge pull request 'Changement de l'image de profil' (#53) from ViewModelSearch into master

Reviewed-on: #53
pull/54/head
Leni BEAULATON 3 weeks ago
commit aa498b8ccc

@ -18,7 +18,7 @@ interface IServices {
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(index : Int): SrcLanguage fun ChangeLangage(index : Int): SrcLanguage
fun AddFav(userId: Int, QuoteId : Int) fun AddFav(userId: Int, QuoteId : Int)
@ -30,8 +30,6 @@ interface IServices {
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(id : Int, user: User): Boolean

@ -70,8 +70,8 @@ class ServicesStub : IServices {
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(index : Int) : SrcLanguage{ override fun ChangeLangage(index : Int) : SrcLanguage{
@ -135,9 +135,6 @@ class ServicesStub : IServices {
return (users.find { it.id == id }) 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 })
@ -157,7 +154,23 @@ class ServicesStub : IServices {
} }
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())
}
else -> {
it.content.uppercase().contains(search.uppercase())
}
}
}.take(indexCount))
}
//------------------------------------------------------ //------------------------------------------------------
@SuppressLint("NewApi") @SuppressLint("NewApi")
@ -198,21 +211,5 @@ class ServicesStub : IServices {
return false return false
} }
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())
}
else -> {
it.content.uppercase().contains(search.uppercase())
}
}
}.take(indexCount))
}
} }

@ -5,23 +5,35 @@ import com.example.what_the_fantasy.data.model.User
class LogsUsers{ class LogsUsers{
fun logDebugAllUsers(users : List<User>, titleLog : String){ fun logDebugAllUsers(users : List<User>, titleLog : String){
for(user in users){ for(user in users){
Log.e(titleLog, "User created: ${user.username} => ${user.email} => ${user.imgUrl} => ${user.langage}") Log.d(titleLog, "User created: ${user.username} => ${user.email} => ${user.imgUrl} => ${user.langage}")
} }
} }
fun logDebugUserEmail(user : User?, titleLog : String){ fun logDebugUserEmail(user : User?, titleLog : String){
Log.e(titleLog, "User created: ${user?.username} => ${user?.email}") Log.d(titleLog, "User created: ${user?.username} => ${user?.email}")
} }
fun logDebugUserLangage(user : User?, titleLog : String){ fun logDebugUserLangage(user : User?, titleLog : String){
Log.e(titleLog, "User Change: ${user?.username} => ${user?.langage}") Log.d(titleLog, "User Change: ${user?.username} => ${user?.langage}")
} }
fun logInformationUserConnect(user : User?, titleLog : String){ fun logInformationUserConnect(user : User?, titleLog : String){
Log.e(titleLog, "${user?.username} logged in") Log.i(titleLog, "${user?.username} logged in")
} }
fun unlogInformationUserConnect(titleLog : String){ fun unlogInformationUserConnect(titleLog : String){
Log.e(titleLog, "Logged out") 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")
} }
} }

@ -29,6 +29,7 @@ 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.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
@ -145,7 +146,8 @@ fun ButtonIconVector(img : ImageVector, name : String, nav : ()->Unit ,onPage :
contentDescription = name, contentDescription = name,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.clip(CircleShape) // Pour rendre l'image circulaire .clip(CircleShape), // Pour rendre l'image circulaire
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.primary)
) )
} }
} }

@ -18,6 +18,7 @@ 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.viewModels.AuthUserViewModel 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.CurrentUserViewModel
import com.example.what_the_fantasy.ui.viewModels.SearchViewModel
import com.example.what_the_fantasy.ui.viewModels.SignInUserViewModel import com.example.what_the_fantasy.ui.viewModels.SignInUserViewModel
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@ -48,8 +49,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
@ -81,6 +83,9 @@ fun AppNavigator() {
val currentUserVM : CurrentUserViewModel = viewModel() val currentUserVM : CurrentUserViewModel = viewModel()
val currentUserState by currentUserVM.currentUserState.collectAsState() val currentUserState by currentUserVM.currentUserState.collectAsState()
//ViewModel pour la recherche
val searchVM : SearchViewModel = viewModel()
val searchState by searchVM.searchState.collectAsState()
Scaffold( Scaffold(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
containerColor = MaterialTheme.colorScheme.onPrimary containerColor = MaterialTheme.colorScheme.onPrimary
@ -176,17 +181,18 @@ fun AppNavigator() {
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, currentUserVM = currentUserVM,
currentUserState = currentUserState, currentUserState = currentUserState,
searchVM = searchVM,
searchState = searchState
) )
} }
composable<SignUp> { composable<SignUp> {

@ -13,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
@ -79,7 +81,8 @@ fun ProfilPage(navFavorite: () -> Unit,
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(
@ -97,7 +100,7 @@ fun ProfilPage(navFavorite: () -> Unit,
SpaceHeightComponent(16) SpaceHeightComponent(16)
// Image de profil // Image de profil
ImageProfil(currentUserState.imagePath, 120) ImageProfil(120, currentUserState.id, currentUserVM,currentUserState)
SpaceHeightComponent(16) SpaceHeightComponent(16)
EditUsername(currentUserState.username, currentUserState.id, currentUserVM)// Édition du Username EditUsername(currentUserState.username, currentUserState.id, currentUserVM)// Édition du Username
@ -110,11 +113,11 @@ fun ProfilPage(navFavorite: () -> Unit,
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,currentUserVM, currentUserState) 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,currentUserVM) ButtonUnLog(R.string.ButtonUnlogprofile, 18,MaterialTheme.colorScheme.onBackground, MaterialTheme.colorScheme.background, navUnLog,currentUserVM)
@ -125,14 +128,14 @@ fun ProfilPage(navFavorite: () -> Unit,
@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)}
) )
} }
@ -210,7 +213,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,
@ -236,7 +239,8 @@ fun EditUsername(usernameState: String, index: Int, currentUserVM : CurrentUserV
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 })
@ -279,7 +283,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,
@ -294,7 +298,6 @@ fun DisplayUsername(username: String, onEdit: () -> Unit) {
@Composable @Composable
fun EditPasswd(index: Int, currentUserVM: CurrentUserViewModel) { 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("") }
@ -421,7 +424,7 @@ fun SaveButton(onClick: () -> Unit) {
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)
} }
} }
@ -435,7 +438,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,

@ -9,6 +9,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
@ -20,7 +21,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
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
@ -43,7 +46,9 @@ 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.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
@ -52,6 +57,7 @@ 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.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.states.CurrentUserState 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
@ -93,7 +99,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
@ -112,7 +119,7 @@ fun QuotePage(
FunctionalIcon( FunctionalIcon(
isFavorite = favorite, isFavorite = favorite,
userId = currentUserState.id, userId = currentUserState.id,
id = quoteId, quoteId = quoteId,
context = context, context = context,
service = service service = service
) )
@ -133,6 +140,17 @@ 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)
@ -191,7 +209,9 @@ 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, service: IServices){
val logsUsers = LogsUsers()
Row(modifier = Modifier Row(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
) { ) {
@ -201,9 +221,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 +234,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 +247,21 @@ 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 = {
service.SupFav(userId = userId, QuoteId = quoteId)
logsUsers.favoriteInformationUserFalse("Favorite", quoteId, userId)
}, //sup fav
modifier = Modifier.padding(start = 20.dp) modifier = Modifier.padding(start = 20.dp)
){ ){
Icon( Icon(
@ -247,7 +274,10 @@ fun FunctionalIcon(isFavorite: Boolean, userId : Int, id : Int, context : Contex
} }
else{ else{
IconButton( IconButton(
onClick = { service.AddFav(userId = userId, QuoteId = id)}, //add fav onClick = {
service.AddFav(userId = userId, QuoteId = quoteId)
logsUsers.favoriteInformationUserTrue("Favorite", quoteId, userId)
}, //add fav
modifier = Modifier.padding(start = 50.dp) modifier = Modifier.padding(start = 50.dp)
){ ){
Icon( Icon(

@ -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,15 +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.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.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,
@ -40,26 +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, currentUserVM : CurrentUserViewModel,
currentUserState : CurrentUserState, 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)
@ -74,10 +91,11 @@ fun SearchPage(
navControllerAccueil = navAccueil, navControllerAccueil = navAccueil,
navControllerProfil = navProfil, navControllerProfil = navProfil,
navControllerQuiz = navQuiz, navControllerQuiz = navQuiz,
navControllerSearch = { navSearch("contenue", "") }, navControllerSearch = { navSearch("contenu", "") },
currentUserVM = currentUserVM, currentUserVM = currentUserVM,
currentUserState = currentUserState, currentUserState = currentUserState,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
@ -95,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)
) )
} }
} }
@ -155,13 +177,15 @@ fun SearchPage(
) { ) {
items(quotes) { quote -> items(quotes) { quote ->
Column(Modifier.clickable { navQuote(quote.id) }) { Column(Modifier.clickable { navQuote(quote.id) }) {
QuoteLittle(quote) if(quote.language == currentUserState.langage) { // affiche les suggestions de citation dans la bonne langue
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

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

@ -48,9 +48,6 @@ class CurrentUserViewModel : ViewModel(){
_currentUserState.update {it.copy(password = password)} _currentUserState.update {it.copy(password = password)}
} }
fun setConfirmPassword(password : String){
_currentUserState.update {it.copy(confirmPassword = password)}
}
fun setLangue(langue : SrcLanguage){ fun setLangue(langue : SrcLanguage){
_currentUserState.update {it.copy(langage = langue)} _currentUserState.update {it.copy(langage = langue)}
@ -86,4 +83,12 @@ class CurrentUserViewModel : ViewModel(){
it.copy(langage = langage) it.copy(langage = langage)
} }
} }
fun editImage(index : Int){
val image = services.EditImage(index)
_currentUserState.update {
it.copy(imagePath = image)
}
}
} }

@ -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)
}
}

@ -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>
Loading…
Cancel
Save