From 871c29d487c8493728cf86e6c743ebcd6c40c682 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Thu, 4 Jan 2024 00:51:02 +0100 Subject: [PATCH] feat: set modification --- .../memorisationapplication/HomeScreen.kt | 6 +- .../memorisationapplication/MainActivity.kt | 9 +- .../ModifySetScreen.kt | 208 +++++++++++++++++- .../memorisationapplication/Routes.kt | 1 + .../memorisationapplication/data/MemoDao.kt | 13 ++ .../memorisationapplication/data/Question.kt | 4 +- .../ui/ActionModifySet.kt | 5 + .../ui/ModifySetViewModel.kt | 65 ++++++ app/src/main/res/values/strings.xml | 3 + 9 files changed, 305 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ActionModifySet.kt create mode 100644 app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt index 7638cfe..e5f7646 100644 --- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/HomeScreen.kt @@ -151,6 +151,8 @@ private fun DeleteRow( @Composable private fun ActionRow(context: Context, model: HomeViewModel, navController: NavController) { + val selection by model.selected + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { Button(onClick = { (model::doAction)(ActionHome.CREATION) }) { Text(text = context.getString(R.string.main_button_create)) @@ -158,7 +160,9 @@ private fun ActionRow(context: Context, model: HomeViewModel, navController: Nav Spacer(modifier = Modifier.padding(2.dp)) - Button(onClick = { navController.navigate(MODIFY_SET) }) { + Button( + enabled = selection != null, + onClick = { navController.navigate("$MODIFY_SET/${selection?.idSet}") }) { Text(text = context.getString(R.string.main_button_modify)) } diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt index 2b1c4ad..5c00dfd 100644 --- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/MainActivity.kt @@ -67,7 +67,14 @@ fun MainScreen() { modifier = Modifier.padding(padding) ) { composable(HOME) { HomeScreen(padding, navController) } - composable(MODIFY_SET) { ModifySetScreen(padding, navController) } + composable("$MODIFY_SET/{$MODIFY_SET_ARGS}") { + it.arguments?.getString(MODIFY_SET_ARGS)?.let { idSet -> + ModifySetScreen( + padding, + idSet.toInt() + ) + } + } composable(PLAY) { PlayScreen(padding, navController) } } } diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt index b613792..948e5bf 100644 --- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ModifySetScreen.kt @@ -1,14 +1,212 @@ package fr.uparis.diamantkennel.memorisationapplication -import android.widget.Toast +import android.content.res.Resources +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext -import androidx.navigation.NavController +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import fr.uparis.diamantkennel.memorisationapplication.data.Question +import fr.uparis.diamantkennel.memorisationapplication.ui.ActionModifySet +import fr.uparis.diamantkennel.memorisationapplication.ui.ModifySetViewModel +import kotlin.text.Typography.ellipsis + @Composable -fun ModifySetScreen(padding: PaddingValues, navController: NavController) { +fun ModifySetScreen( + padding: PaddingValues, + idSet: Int, + model: ModifySetViewModel = viewModel() +) { + // First update the list and set ID + model.setId.value = idSet + model.updateQuestionList(idSet) + val context = LocalContext.current - - Toast.makeText(context, "Modify", Toast.LENGTH_SHORT).show() + val currentSelection by model.selection + val questions by model.questions.collectAsState(listOf()) + var action by model.action + + if (action == ActionModifySet.AJOUT || action == ActionModifySet.MODIFICATION) { + AjoutModifDialog(action, currentSelection, model::ajoutQuestion) + { action = ActionModifySet.AUCUN } + } + + if (action == ActionModifySet.SUPPRIMER) { + RemoveDialog(model::removeQuestion) + { action = ActionModifySet.AUCUN } + } + + Column( + modifier = Modifier.padding(padding), + horizontalAlignment = Alignment.CenterHorizontally + ) { + showList(model, questions, currentSelection) + + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + Button( + enabled = currentSelection != null, + onClick = { action = ActionModifySet.MODIFICATION }) { + Text(text = context.getString(R.string.modify_button_modify)) + } + + Spacer(modifier = Modifier.padding(2.dp)) + + Button(onClick = { action = ActionModifySet.AJOUT }) { + Text(text = context.getString(R.string.modify_button_add)) + } + + Spacer(modifier = Modifier.padding(2.dp)) + + Button( + enabled = currentSelection != null, + onClick = { action = ActionModifySet.SUPPRIMER }) { + Text(text = context.getString(R.string.modify_button_delete)) + } + } + } } + +@Composable +fun showList(model: ModifySetViewModel, questions: List, currentSelection: Question?) { + LazyColumn( + Modifier.fillMaxHeight(0.6f) + ) { + itemsIndexed(questions) { index, item -> + listItem(index, item, currentSelection, model::updateSelection) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun listItem( + index: Int, + question: Question, + currentSelection: Question?, + updateSelection: (Question) -> Unit +) { + + val maxLength = Resources.getSystem().displayMetrics.widthPixels / 33 + + val containerColor = when { + currentSelection == question -> colorResource(id = R.color.selected) + index % 2 == 0 -> colorResource(id = R.color.list_alternate) + else -> colorResource(id = R.color.list) + } + + Card( + onClick = { updateSelection(question) }, + Modifier.fillMaxSize(), + colors = CardDefaults.cardColors(containerColor) + ) { + Row( + modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly + ) { + Text( + question.enonce.take(maxLength) + .let { if (question.enonce.length > maxLength) it + ellipsis else it }, + modifier = Modifier.padding(2.dp) + ) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AjoutModifDialog( + type: ActionModifySet, + selection: Question?, + confirm: (String, String) -> Unit, + dismiss: () -> Unit +) { + var enonce by remember { + mutableStateOf( + if (type == ActionModifySet.MODIFICATION) { + selection?.enonce!! + } else { + "" + } + ) + } + var reponse by remember { + mutableStateOf( + if (type == ActionModifySet.MODIFICATION) { + selection?.reponse!! + } else { + "" + } + ) + } + + AlertDialog(onDismissRequest = dismiss, + title = { + Text( + text = if (selection != null) { + "Mettre à jour la question" + } else { + "Ajouter une question" + } + ) + }, + text = { + Column { + Row { + OutlinedTextField( + value = enonce, + onValueChange = { enonce = it }, + label = { Text(text = "Question") }) + } + + Row { + OutlinedTextField( + value = reponse, + onValueChange = { reponse = it }, + label = { Text(text = "Réponse") }) + } + } + }, + confirmButton = { + Button(onClick = { + confirm(enonce, reponse) + dismiss() + }) { Text(text = "Ok") } + }) +} + +@Composable +fun RemoveDialog(confirm: () -> Unit, dismiss: () -> Unit) = + AlertDialog(onDismissRequest = dismiss, + title = { Text(text = "Supprimer la question") }, + text = { Text(text = "Voulez-vous supprimer la question ?") }, + confirmButton = { + Button(onClick = { + confirm() + dismiss() + }) { Text(text = "Ok") } + }) diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/Routes.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/Routes.kt index 7b1262d..23513f6 100644 --- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/Routes.kt +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/Routes.kt @@ -2,4 +2,5 @@ package fr.uparis.diamantkennel.memorisationapplication const val HOME = "home" const val MODIFY_SET = "modify_set" +const val MODIFY_SET_ARGS = "id_set" const val PLAY = "play" diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/MemoDao.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/MemoDao.kt index 0a074b3..5abf402 100644 --- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/MemoDao.kt +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/MemoDao.kt @@ -4,6 +4,7 @@ import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert import androidx.room.Query +import androidx.room.Update import kotlinx.coroutines.flow.Flow @Dao @@ -14,12 +15,24 @@ interface MemoDao { @Insert suspend fun insertQuestion(question: Question) + @Update + fun updateQuestion(question: Question) + @Query("SELECT * FROM SetQuestions") fun loadAllSets(): Flow> + @Query("SELECT * FROM Question WHERE setId = :idSet") + fun loadQuestions(idSet: Int): Flow> + + @Query("SELECT * FROM SetQuestions WHERE idSet = :requestedId") + fun getSet(requestedId: Int): SetOfQuestions + @Query("DELETE FROM SetQuestions") fun deleteTable() @Delete fun delete(set: SetQuestions) + + @Delete + fun deleteQuestion(question: Question) } diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/Question.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/Question.kt index 888b2ff..fec7837 100644 --- a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/Question.kt +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/data/Question.kt @@ -15,6 +15,6 @@ import androidx.room.PrimaryKey data class Question( @PrimaryKey(autoGenerate = true) val idQuestion: Int = 0, val setId: Int, // Foreign key linking to SetQuestions - val enonce: String, - val reponse: String + var enonce: String, + var reponse: String ) diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ActionModifySet.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ActionModifySet.kt new file mode 100644 index 0000000..cd93da9 --- /dev/null +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ActionModifySet.kt @@ -0,0 +1,5 @@ +package fr.uparis.diamantkennel.memorisationapplication.ui + +enum class ActionModifySet { + AJOUT, AUCUN, MODIFICATION, SUPPRIMER +} diff --git a/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt new file mode 100644 index 0000000..75b3d8f --- /dev/null +++ b/app/src/main/java/fr/uparis/diamantkennel/memorisationapplication/ui/ModifySetViewModel.kt @@ -0,0 +1,65 @@ +package fr.uparis.diamantkennel.memorisationapplication.ui + +import android.app.Application +import androidx.compose.runtime.mutableStateOf +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.viewModelScope +import fr.uparis.diamantkennel.memorisationapplication.MemoApplication +import fr.uparis.diamantkennel.memorisationapplication.data.Question +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class ModifySetViewModel(application: Application) : AndroidViewModel(application) { + private val dao = (application as MemoApplication).database.memoDao() + + var setId = mutableStateOf(-1) + var questions = dao.loadQuestions(setId.value) + var selection = mutableStateOf(null) + var action = mutableStateOf(ActionModifySet.AUCUN) + + fun updateQuestionList(setId: Int) { + viewModelScope.launch(Dispatchers.IO) { + questions = dao.loadQuestions(setId) + } + } + + fun updateSelection(question: Question) { + if (selection.value == question) { + selection.value = null + } else { + selection.value = question + } + } + + fun ajoutQuestion(enonce: String, reponse: String) { + when (action.value) { + ActionModifySet.AJOUT -> viewModelScope.launch(Dispatchers.IO) { + dao.insertQuestion( + Question( + setId = setId.value, + enonce = enonce, + reponse = reponse + ) + ) + } + + ActionModifySet.MODIFICATION -> viewModelScope.launch(Dispatchers.IO) { + val question = selection.value!! + question.enonce = enonce + question.reponse = reponse + + dao.updateQuestion(question) + } + + else -> { + /* Ce cas n'arrivera jamais */ + } + } + } + + fun removeQuestion() { + viewModelScope.launch(Dispatchers.IO) { + dao.deleteQuestion(selection.value!!) + } + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 90c6639..9f5b0cf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9,4 +9,7 @@ Lancer Erreur : entrée invalide Erreur : doublon + Ajouter + Modifier + Supprimer